Public/Get-ChangedFiles.ps1
|
function Get-ChangedFiles { <# .SYNOPSIS Get list of changed files using native git .DESCRIPTION Detects changed files matching specified extensions in the current branch compared to a base branch. Auto-detects PR context in Azure DevOps pipelines. .PARAMETER BaseBranch Base branch for comparison (default: origin/master). Only used outside a PR merge commit (three-dot, merge-base). In a PR build the base is the merge commit's first parent; see Resolve-DiffRange. .PARAMETER FileExtensions Array of file extensions to filter on. Each extension should include the leading dot. .EXAMPLE Get-ChangedFiles -FileExtensions @('.al', '.yml', '.ps1', '.json') Returns all changed .al and .yml files compared to origin/master .EXAMPLE Get-ChangedFiles -FileExtensions @('.al') Returns only changed .al files .EXAMPLE Get-ChangedFiles -BaseBranch "origin/development" -FileExtensions @('.al', '.yml', '.json') Compare against specific branch and filter on multiple extensions .OUTPUTS System.String[] - Array of file paths relative to repository root .NOTES Author: waldo Version: 2.1.0 #> [CmdletBinding()] param( [Parameter(Mandatory = $false)] [string]$BaseBranch = "origin/master", [Parameter(Mandatory = $true)] [string[]]$FileExtensions ) begin { Write-Verbose "Starting $($MyInvocation.MyCommand.Name)" } process { try { # Build regex pattern from extensions (e.g. "\.al$|\.yml$") $extPattern = ($FileExtensions | ForEach-Object { [regex]::Escape($_) + '$' }) -join '|' $extDisplay = $FileExtensions -join ', ' # One shared resolution for the file list and the per-file diffs (Resolve-DiffRange). # PR build: the merge commit's first parent, never the target branch as it is now. $range = Resolve-DiffRange -BaseBranch $BaseBranch -Fetch if ($range.Skip) { Write-Host "##[warning]AI Code Review skipped: $($range.Reason). Not reviewing against another commit." return @() } Write-Host "Current HEAD: $(git rev-parse HEAD 2>&1)" Write-Host "Compare commit: $($range.Compare)" Write-Host "Base commit: $($range.Base) ($($range.Label))" Write-Host "" Write-Verbose "Getting changed files ($extDisplay): git diff $($range.Base) $($range.Compare)" $gitOutput = git diff --name-only --diff-filter=ACMR $range.Base $range.Compare 2>&1 # Check if git command failed if ($LASTEXITCODE -ne 0) { Write-Error "Git diff failed with exit code $LASTEXITCODE" Write-Error "Git output: $gitOutput" throw "Git diff command failed" } $allChanged = @($gitOutput | Where-Object { $_ }) Write-Host "Changed files: $($allChanged.Count) in total" $changedFiles = $allChanged | Where-Object { $_ -match $extPattern } if (-not $changedFiles) { Write-Host "No matching files changed (extensions: $extDisplay)" Write-Host "" Write-Host "Debug: All changed files:" if ($allChanged) { $allChanged | ForEach-Object { Write-Host " $_" } } else { Write-Host " (no files changed)" } Write-Host "" Write-Host "✅ No matching files changed - skipping review" return @() } $changedFiles = @($changedFiles) # Ensure array Write-Host "✅ Found $($changedFiles.Count) changed file(s) (extensions: $extDisplay):" foreach ($file in $changedFiles) { Write-Host " - $file" } return $changedFiles } catch { Write-Error "Error in $($MyInvocation.MyCommand.Name): $_" throw } } end { Write-Verbose "Completed $($MyInvocation.MyCommand.Name)" } } |