Test-ALProject29.ps1

<#
.SYNOPSIS
Test AI Code Review against ALProject29
 
.DESCRIPTION
Runs AI code review against the specified AL project and displays output as it would appear in Azure DevOps.
 
.PARAMETER ProjectPath
Path to AL project (defaults to C:\Users\Waldo\Documents\AL\ALProject29)
 
.PARAMETER Provider
AI provider to use (github, azure, openai, anthropic)
 
.PARAMETER BaseBranch
Base branch to compare against
 
.EXAMPLE
.\Test-ALProject29.ps1
.\Test-ALProject29.ps1 -Provider github
.\Test-ALProject29.ps1 -ProjectPath "C:\Path\To\Project"
 
#>


param(
    [string]$ProjectPath = "C:\Users\Waldo\Documents\AL\ALProject29",
    [string]$Provider = "github",
    [string]$BaseBranch = "HEAD~1"
)

Write-Host "`n╔════════════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
Write-Host "║ AI Code Review Test - ALProject29 ║" -ForegroundColor Cyan
Write-Host "╚════════════════════════════════════════════════════════════════╝" -ForegroundColor Cyan
Write-Host ""

# Step 1: Verify module
Write-Host "##[section]Step 1: Verifying environment..."
if (-not (Get-Module -Name iFacto.AICodeReview -ListAvailable)) {
    Write-Host "##[error]Module not installed"
    Write-Host "Install with: Install-Module iFacto.AICodeReview -Scope CurrentUser"
    exit 1
}

Import-Module iFacto.AICodeReview -Force
Write-Host "✅ Module loaded: iFacto.AICodeReview"

# Load .env file for API keys
$envPath = Join-Path $PSScriptRoot ".env"
if (Test-Path $envPath) {
    Get-Content $envPath | ForEach-Object {
        if ($_ -match '^\s*([^#][^=]+)\s*=\s*(.+)\s*$') {
            $key = $matches[1].Trim()
            $value = $matches[2].Trim()
            [Environment]::SetEnvironmentVariable($key, $value, [System.EnvironmentVariableTarget]::Process)
        }
    }
    Write-Host "✅ Loaded environment variables from .env"
}

# Step 2: Verify project exists
Write-Host "`n##[section]Step 2: Verifying project path..."
if (-not (Test-Path $ProjectPath)) {
    Write-Host "##[error]Project path not found: $ProjectPath"
    exit 1
}

$appJsonPath = Join-Path $ProjectPath "app.json"
if (-not (Test-Path $appJsonPath)) {
    Write-Host "##[error]app.json not found at: $appJsonPath"
    exit 1
}

Write-Host "✅ Project found: $ProjectPath"

# Step 3: Check API key
Write-Host "`n##[section]Step 3: Checking API credentials..."
$apiKeyVar = switch ($Provider) {
    "github" { "GITHUB_TOKEN" }
    "azure" { "AZURE_AI_API_KEY" }
    "openai" { "OPENAI_API_KEY" }
    "anthropic" { "ANTHROPIC_API_KEY" }
}

if (-not [Environment]::GetEnvironmentVariable($apiKeyVar)) {
    Write-Host "##[error]API key not set: $apiKeyVar"
    Write-Host "Set with: `$env:$apiKeyVar = 'your-key'"
    exit 1
}

Write-Host "✅ API key configured: $apiKeyVar"

# Step 4: Change to project directory
Push-Location $ProjectPath

try {
    # Check if git repo
    Write-Host "`n##[section]Step 4: Checking git status..."
    $gitStatus = git rev-parse --is-inside-work-tree 2>&1
    if ($LASTEXITCODE -ne 0) {
        Write-Host "##[error]Not a git repository: $ProjectPath"
        Write-Host "Initialize with: git init"
        exit 1
    }
    
    Write-Host "✅ Git repository confirmed"
    
    # Get changed files
    Write-Host "`n##[section]Step 5: Finding changed AL files..."
    $changedFiles = Get-ChangedALFiles -BaseBranch $BaseBranch
    
    if (-not $changedFiles -or $changedFiles.Count -eq 0) {
        Write-Host "##[warning]No AL files changed since $BaseBranch"
        Write-Host ""
        Write-Host "Options to test with changes:"
        Write-Host " 1. Make a change to an AL file"
        Write-Host " 2. Use different base: -BaseBranch 'HEAD~2'"
        Write-Host " 3. View recent commits: git log --oneline -5"
        exit 0
    }
    
    Write-Host "✅ Found $($changedFiles.Count) changed file(s):"
    $changedFiles | ForEach-Object { Write-Host " • $_" }
    
    # Load rules
    Write-Host "`n##[section]Step 6: Loading review rules..."
    $rulesPath = Join-Path $PSScriptRoot "..\Rules"
    if (-not (Test-Path $rulesPath)) {
        Write-Host "##[warning]Rules folder not found at: $rulesPath"
        Write-Host "Will use default rules"
        $ruleFiles = @()
    } else {
        $ruleFiles = Get-ChildItem -Path $rulesPath -Filter "*.md" -File
        Write-Host "✅ Loaded $($ruleFiles.Count) rule file(s):"
        $ruleFiles | ForEach-Object { Write-Host " • $($_.Name)" }
    }
    
    # Run AI review
    Write-Host "`n##[section]═══════════════════════════════════════════════════════"
    Write-Host "##[section]STARTING AI CODE REVIEW (as it appears in DevOps)"
    Write-Host "##[section]═══════════════════════════════════════════════════════"
    Write-Host ""
    
    $result = Invoke-AICodeReview -Provider $Provider -BaseBranch $BaseBranch -RulesPath $rulesPath
    
    Write-Host "`n##[section]═══════════════════════════════════════════════════════"
    Write-Host "##[section]REVIEW COMPLETE"
    Write-Host "##[section]═══════════════════════════════════════════════════════"
    Write-Host ""
    
    # Display summary
    Write-Host "##[section]Summary"
    Write-Host "Status: $(if ($result.Success) { '✅ PASSED' } else { '❌ FAILED' })"
    Write-Host "Violations: $($result.ErrorCount) errors, $($result.WarningCount) warnings, $($result.InfoCount) info"
    Write-Host "Threshold: Fail on '$($result.SeverityThreshold)' or higher"
    Write-Host ""
    
    if (-not $result.Success) {
        Write-Host "##[error]Build would fail due to code review violations"
        exit 1
    } else {
        Write-Host "✅ Build would pass code review"
        exit 0
    }
}
finally {
    Pop-Location
}