Public/Git/Test-CommitSignatures.ps1

function Test-CommitSignatures {
    <#
    .SYNOPSIS
        Tests that commits are signed (GPG or SSH)
         
    .DESCRIPTION
        Checks git commits to ensure they are properly signed with GPG or SSH.
        Can check recent commits or a specific range.
         
    .PARAMETER Count
        Number of recent commits to check (default: 1)
         
    .PARAMETER Range
        Git commit range to check (e.g., "HEAD~5..HEAD", "main..feature")
         
    .PARAMETER Branch
        Branch to check (default: current branch)
         
    .EXAMPLE
        Test-CommitSignatures
        Checks the last commit
         
    .EXAMPLE
        Test-CommitSignatures -Count 10
        Checks the last 10 commits
         
    .EXAMPLE
        Test-CommitSignatures -Range "HEAD~5..HEAD"
        Checks specific commit range
         
    .EXAMPLE
        Test-CommitSignatures -Branch main
        Checks commits on main branch
    #>

    [CmdletBinding()]
    param(
        [Parameter()]
        [int]$Count = 1,
        
        [Parameter()]
        [string]$Range,
        
        [Parameter()]
        [string]$Branch
    )

    $ErrorActionPreference = 'Stop'

    # Check if we're in a git repository
    try {
        git rev-parse --git-dir 2>&1 | Out-Null
        if ($LASTEXITCODE -ne 0) {
            throw "Not in a git repository"
        }
    }
    catch {
        Write-Error "Not in a git repository"
        return $false
    }

    Write-Host "Validating commit signatures..." -ForegroundColor Cyan

    # Check if commit signing is configured
    $commitSignEnabled = git config --get commit.gpgsign
    $signingKey = git config --get user.signingkey
    $gpgFormat = git config --get gpg.format

    # Detect signing method
    $signingMethod = if ($gpgFormat -eq 'ssh') { 'SSH' } 
                     elseif ($signingKey -like 'ssh-*') { 'SSH' }
                     else { 'GPG' }

    if ($commitSignEnabled -ne 'true') {
        Write-Warning "Commit signing is not enabled!"
        Write-Host "Enable with: git config --global commit.gpgsign true" -ForegroundColor Yellow
    }

    if (-not $signingKey) {
        Write-Warning "No signing key configured!"
        Write-Host "Configure with: git config --global user.signingkey <YOUR_KEY_ID>" -ForegroundColor Yellow
    }

    if ($signingMethod -eq 'SSH') {
        $allowedSigners = git config --get gpg.ssh.allowedSignersFile
        if (-not $allowedSigners) {
            Write-Warning "SSH signing is configured but gpg.ssh.allowedSignersFile is not set"
            Write-Host "For verification, configure with:" -ForegroundColor Yellow
            Write-Host " git config --global gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers" -ForegroundColor Gray
            Write-Host "Then add your public key:" -ForegroundColor Yellow
            Write-Host " echo `"`$(git config user.email) `$(cat ~/.ssh/id_ed25519.pub)`" >> ~/.ssh/allowed_signers" -ForegroundColor Gray
        }
    }

    # Build git log command
    $gitArgs = @('log', '--pretty=format:%H|%G?|%GS|%s')

    if ($Range) {
        $gitArgs += $Range
    }
    elseif ($Branch) {
        $gitArgs += $Branch
    }
    else {
        $gitArgs += "-$Count"
    }

    # Get commits
    $commits = git @gitArgs | ForEach-Object {
        $parts = $_ -split '\|', 4
        [PSCustomObject]@{
            Hash = $parts[0].Substring(0, 7)
            SignatureStatus = $parts[1]
            Signer = $parts[2]
            Subject = $parts[3]
        }
    }

    if (-not $commits) {
        Write-Host "No commits found to check" -ForegroundColor Yellow
        return $true
    }

    # Analyze results
    $results = foreach ($commit in $commits) {
        $status = switch ($commit.SignatureStatus) {
            'G' { 'Valid'; $true }      # Good signature
            'B' { 'Bad'; $false }        # Bad signature
            'U' { 'Unknown'; $false }    # Unknown validity
            'X' { 'Expired'; $false }    # Expired signature
            'Y' { 'Expired Key'; $false } # Expired key
            'R' { 'Revoked'; $false }    # Revoked key
            'E' { 'Error'; $false }      # Error checking
            'N' { 'Not Signed'; $false } # No signature
            default { 'Unknown'; $false }
        }
        
        $color = if ($status -eq 'Valid') { 'Green' } else { 'Red' }
        
        [PSCustomObject]@{
            Commit = $commit.Hash
            Status = $status
            Signer = $commit.Signer
            Subject = $commit.Subject
            Valid = $status -eq 'Valid'
            Color = $color
        }
    }

    # Display results
    Write-Host "`nCommit Signature Status:" -ForegroundColor Cyan
    $results | ForEach-Object {
        $statusText = "[$($_.Status)]".PadRight(15)
        Write-Host " $($_.Commit) " -NoNewline
        Write-Host $statusText -ForegroundColor $_.Color -NoNewline
        Write-Host " $($_.Subject)"
        if ($_.Signer) {
            Write-Host " Signer: $($_.Signer)" -ForegroundColor Gray
        }
    }

    # Summary
    $validCount = ($results | Where-Object Valid).Count
    $totalCount = $results.Count
    $invalidCount = $totalCount - $validCount

    Write-Host "`nSummary:" -ForegroundColor Cyan
    Write-Host " Total commits checked: $totalCount"
    Write-Host " Valid signatures: $validCount" -ForegroundColor Green
    if ($invalidCount -gt 0) {
        Write-Host " Invalid/Missing signatures: $invalidCount" -ForegroundColor Red
    }

    # Return false if any commits are not properly signed
    if ($invalidCount -gt 0) {
        Write-Host "`nValidation FAILED: Not all commits are properly signed" -ForegroundColor Red
        Write-Host "All commits must be signed" -ForegroundColor Yellow
        Write-Host "`nTo fix:" -ForegroundColor Yellow
        
        if ($signingMethod -eq 'SSH') {
            Write-Host " 1. Ensure SSH signing is configured:"
            Write-Host " git config --global gpg.format ssh"
            Write-Host " git config --global commit.gpgsign true"
            Write-Host " git config --global user.signingkey ~/.ssh/id_ed25519.pub"
            Write-Host " 2. Configure allowed signers (for verification):"
            Write-Host " git config --global gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers"
            Write-Host " echo `"`$(git config user.email) `$(cat ~/.ssh/id_ed25519.pub)`" >> ~/.ssh/allowed_signers"
            Write-Host " 3. Amend unsigned commits: git commit --amend --no-edit -S"
        }
        else {
            Write-Host " 1. Configure GPG signing: git config --global commit.gpgsign true"
            Write-Host " 2. Set your signing key: git config --global user.signingkey <KEY_ID>"
            Write-Host " 3. Amend unsigned commits: git commit --amend --no-edit -S"
        }
        return $false
    }

    Write-Host "`nValidation PASSED: All commits are properly signed" -ForegroundColor Green
    return $true
}