Public/Repair-CCGitHub.ps1

function Repair-CCGitHub {
    <#
    .SYNOPSIS
        Auto-fixes GitHub configuration issues detected by Test-CCGitHub.

    .DESCRIPTION
        Applies fixes for issues that have FixAvailable = $true.
        Supports -WhatIf for previewing changes and -Force for non-interactive use.

    .PARAMETER Repository
        GitHub repository in format "owner/repo". Auto-detected if not specified.

    .PARAMETER Token
        GitHub token with admin permissions on the repository.

    .PARAMETER Fix
        Specific fix IDs to apply. If not specified, applies all available fixes.

    .PARAMETER Force
        Apply fixes without prompting for confirmation.

    .PARAMETER WhatIf
        Preview what would be fixed without making changes.

    .EXAMPLE
        Repair-CCGitHub
        # Runs audit, offers to fix all issues

    .EXAMPLE
        Repair-CCGitHub -Fix EnableBranchProtection, EnableDeleteOnMerge -Force

    .EXAMPLE
        Repair-CCGitHub -WhatIf
        # Shows what would be fixed
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter()]
        [string]$Repository,

        [Parameter()]
        [string]$Token,

        [Parameter()]
        [ValidateSet('core', 'active', 'minimal')]
        [string]$Standard = 'core',

        [Parameter()]
        [string[]]$Fix,

        [Parameter()]
        [switch]$Force
    )

    $token = Resolve-CCToken -Token $Token
    if (-not $token) { throw "No GitHub token available. Set GITHUB_TOKEN or run 'gh auth login'." }

    $repo = Resolve-CCRepository -Repository $Repository
    if (-not $repo) { throw "Cannot determine repository. Specify -Repository 'owner/repo'." }

    # Run audit first to find fixable issues
    $results = Test-CCGitHub -Repository $repo -Token $token -Standard $Standard -OutputFormat Quiet
    $fixableResults = $results | Where-Object { $_.FixAvailable -and $_.Status -in @('Fail', 'Warning') }

    if ($Fix) {
        $fixableResults = $fixableResults | Where-Object { $_.FixId -in $Fix }
    }

    if ($fixableResults.Count -eq 0) {
        Write-Host " No fixable issues found." -ForegroundColor Green
        return
    }

    Write-Host " Found $($fixableResults.Count) fixable issue(s):" -ForegroundColor Yellow
    foreach ($r in $fixableResults) {
        Write-Host " [$($r.FixId)] $($r.Message)" -ForegroundColor Gray
    }
    Write-Host ""

    $repoInfo = Invoke-CCGitHubApi -Endpoint "repos/$repo" -Token $token
    $defaultBranch = $repoInfo.default_branch

    foreach ($issue in $fixableResults) {
        $action = "Fix $($issue.FixId) on $repo"

        if (-not $Force -and -not $PSCmdlet.ShouldProcess($repo, $action)) {
            continue
        }

        try {
            switch ($issue.FixId) {
                'EnableBranchProtection' {
                    $body = @{
                        required_status_checks        = $null
                        enforce_admins                = $false
                        required_pull_request_reviews = @{
                            required_approving_review_count = 1
                            dismiss_stale_reviews           = $true
                        }
                        restrictions                  = $null
                        allow_force_pushes            = $false
                        allow_deletions               = $false
                    }
                    Invoke-CCGitHubApi -Endpoint "repos/$repo/branches/$defaultBranch/protection" -Token $token -Method Put -Body $body
                    Write-Host " + Enabled branch protection on $defaultBranch" -ForegroundColor Green
                }
                'RequireReviews' {
                    $body = @{
                        required_approving_review_count = 1
                        dismiss_stale_reviews           = $true
                    }
                    Invoke-CCGitHubApi -Endpoint "repos/$repo/branches/$defaultBranch/protection/required_pull_request_reviews" -Token $token -Method Patch -Body $body
                    Write-Host " + Configured required reviews (1 reviewer, dismiss stale)" -ForegroundColor Green
                }
                'EnableDeleteOnMerge' {
                    $body = @{ delete_branch_on_merge = $true }
                    Invoke-CCGitHubApi -Endpoint "repos/$repo" -Token $token -Method Patch -Body $body
                    Write-Host " + Enabled delete branch on merge" -ForegroundColor Green
                }
                'EnableIssues' {
                    $body = @{ has_issues = $true }
                    Invoke-CCGitHubApi -Endpoint "repos/$repo" -Token $token -Method Patch -Body $body
                    Write-Host " + Enabled issues" -ForegroundColor Green
                }
                'DisableWiki' {
                    $body = @{ has_wiki = $false }
                    Invoke-CCGitHubApi -Endpoint "repos/$repo" -Token $token -Method Patch -Body $body
                    Write-Host " + Disabled wiki" -ForegroundColor Green
                }
                'EnableVulnerabilityAlerts' {
                    Invoke-CCGitHubApi -Endpoint "repos/$repo/vulnerability-alerts" -Token $token -Method Put
                    Write-Host " + Enabled vulnerability alerts" -ForegroundColor Green
                }
                'EnableSecretScanning' {
                    $body = @{
                        security_and_analysis = @{
                            secret_scanning = @{ status = 'enabled' }
                        }
                    }
                    Invoke-CCGitHubApi -Endpoint "repos/$repo" -Token $token -Method Patch -Body $body
                    Write-Host " + Enabled secret scanning" -ForegroundColor Green
                }
                'EnablePushProtection' {
                    $body = @{
                        security_and_analysis = @{
                            secret_scanning_push_protection = @{ status = 'enabled' }
                        }
                    }
                    Invoke-CCGitHubApi -Endpoint "repos/$repo" -Token $token -Method Patch -Body $body
                    Write-Host " + Enabled push protection" -ForegroundColor Green
                }
                'EnableDependabotSecurity' {
                    $body = @{
                        security_and_analysis = @{
                            dependabot_security_updates = @{ status = 'enabled' }
                        }
                    }
                    Invoke-CCGitHubApi -Endpoint "repos/$repo" -Token $token -Method Patch -Body $body
                    Write-Host " + Enabled dependabot security updates" -ForegroundColor Green
                }
                default {
                    Write-Host " ? No auto-fix implemented for $($issue.FixId)" -ForegroundColor Gray
                }
            }
        }
        catch {
            Write-Host " x Failed to apply $($issue.FixId): $($_.Exception.Message)" -ForegroundColor Red
        }
    }
}