scripts/run.ps1
scripts/run.ps1Browse 4 files
1,640 tokens
6,476 bytes
Token encoding: o200k_base
Snapshot 1d17ca4
← Back to SKILL.md
1Set-StrictMode -Version Latest2$ErrorActionPreference = "Stop"3 4$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition5$repoRoot = $null6 7try {8 $repoRoot = (& git -C $scriptDir rev-parse --show-toplevel 2>$null)9} catch {10 $repoRoot = $null11}12 13if (-not $repoRoot) {14 $repoRoot = (Resolve-Path (Join-Path $scriptDir "..\\..\\..\\..")).Path15} else {16 $repoRoot = ([string]$repoRoot).Trim()17}18 19Set-Location $repoRoot20 21$logDir = Join-Path ([System.IO.Path]::GetTempPath()) ("code-change-verification-" + [System.Guid]::NewGuid().ToString("N"))22New-Item -ItemType Directory -Path $logDir | Out-Null23 24$steps = New-Object System.Collections.Generic.List[object]25$heartbeatIntervalSeconds = 1026if ($env:CODE_CHANGE_VERIFICATION_HEARTBEAT_SECONDS) {27 $heartbeatIntervalSeconds = [int]$env:CODE_CHANGE_VERIFICATION_HEARTBEAT_SECONDS28}29 30function Resolve-MakeInvocation {31 $command = Get-Command make -ErrorAction Stop32 33 while ($command.CommandType -eq [System.Management.Automation.CommandTypes]::Alias) {34 $command = $command.ResolvedCommand35 }36 37 if ($command.CommandType -in @(38 [System.Management.Automation.CommandTypes]::Application,39 [System.Management.Automation.CommandTypes]::ExternalScript40 )) {41 $commandPath = if ($command.Path) { $command.Path } else { $command.Source }42 return [PSCustomObject]@{43 FilePath = $commandPath44 ArgumentList = @()45 }46 }47 48 if ($command.CommandType -eq [System.Management.Automation.CommandTypes]::Function) {49 $shellPath = (Get-Process -Id $PID).Path50 if (-not $shellPath) {51 throw "Unable to resolve the current PowerShell executable for make wrapper launches."52 }53 54 $wrapperPath = Join-Path $logDir "invoke-make.ps1"55 $escapedRepoRoot = $repoRoot -replace "'", "''"56 $wrapperTemplate = @'57Set-StrictMode -Version Latest58$ErrorActionPreference = "Stop"59Set-Location -LiteralPath '{0}'60function global:make {{61{1}62}}63& make @args64exit $LASTEXITCODE65'@66 $wrapperScript = $wrapperTemplate -f $escapedRepoRoot, $command.Definition.TrimEnd()67 Set-Content -Path $wrapperPath -Value $wrapperScript -Encoding UTF868 69 return [PSCustomObject]@{70 FilePath = $shellPath71 ArgumentList = @("-NoLogo", "-NoProfile", "-File", $wrapperPath)72 }73 }74 75 throw "code-change-verification: make must resolve to an application, script, alias, or function."76}77 78$script:MakeInvocation = Resolve-MakeInvocation79 80function Invoke-MakeStep {81 param(82 [Parameter(Mandatory = $true)][string]$Step83 )84 85 Write-Host "Running make $Step..."86 & $script:MakeInvocation.FilePath @($script:MakeInvocation.ArgumentList + $Step)87 88 if ($LASTEXITCODE -ne 0) {89 Write-Host "code-change-verification: make $Step failed with exit code $LASTEXITCODE."90 return $LASTEXITCODE91 }92 93 return 094}95 96function Start-MakeStep {97 param(98 [Parameter(Mandatory = $true)][string]$Step99 )100 101 $stdoutLogPath = Join-Path $logDir "$Step.stdout.log"102 $stderrLogPath = Join-Path $logDir "$Step.stderr.log"103 Write-Host "Running make $Step..."104 $process = Start-Process -FilePath $script:MakeInvocation.FilePath -ArgumentList @($script:MakeInvocation.ArgumentList + $Step) -RedirectStandardOutput $stdoutLogPath -RedirectStandardError $stderrLogPath -PassThru105 $steps.Add([PSCustomObject]@{106 Name = $Step107 Process = $process108 StdoutLogPath = $stdoutLogPath109 StderrLogPath = $stderrLogPath110 StartTime = Get-Date111 })112}113 114function Stop-RunningSteps {115 foreach ($step in $steps) {116 if ($null -eq $step.Process) {117 continue118 }119 120 & taskkill /PID $step.Process.Id /T /F *> $null121 }122 123 foreach ($step in $steps) {124 if ($null -eq $step.Process) {125 continue126 }127 128 try {129 $step.Process.WaitForExit()130 } catch {131 }132 }133}134 135function Wait-ForParallelSteps {136 $pending = New-Object System.Collections.Generic.List[object]137 foreach ($step in $steps) {138 $pending.Add($step)139 }140 $nextHeartbeatAt = (Get-Date).AddSeconds($heartbeatIntervalSeconds)141 142 while ($pending.Count -gt 0) {143 foreach ($step in @($pending)) {144 $step.Process.Refresh()145 if (-not $step.Process.HasExited) {146 continue147 }148 149 $duration = [int]((Get-Date) - $step.StartTime).TotalSeconds150 if ($step.Process.ExitCode -eq 0) {151 Write-Host "make $($step.Name) passed in ${duration}s."152 [void]$pending.Remove($step)153 continue154 }155 156 Write-Host "code-change-verification: make $($step.Name) failed with exit code $($step.Process.ExitCode) after ${duration}s."157 if (Test-Path $step.StderrLogPath) {158 Write-Host "--- $($step.Name) stderr log (last 80 lines) ---"159 Get-Content $step.StderrLogPath -Tail 80160 }161 if (Test-Path $step.StdoutLogPath) {162 Write-Host "--- $($step.Name) stdout log (last 80 lines) ---"163 Get-Content $step.StdoutLogPath -Tail 80164 }165 166 Stop-RunningSteps167 return $step.Process.ExitCode168 }169 170 if ($pending.Count -gt 0) {171 if ((Get-Date) -ge $nextHeartbeatAt) {172 $running = @()173 foreach ($step in $pending) {174 $elapsed = [int]((Get-Date) - $step.StartTime).TotalSeconds175 $running += "$($step.Name) (${elapsed}s)"176 }177 Write-Host ("code-change-verification: still running: " + ($running -join ", ") + ".")178 $nextHeartbeatAt = (Get-Date).AddSeconds($heartbeatIntervalSeconds)179 }180 Start-Sleep -Seconds 1181 }182 }183 184 return 0185}186 187$exitCode = 0188 189try {190 $exitCode = Invoke-MakeStep -Step "format"191 if ($exitCode -eq 0) {192 Write-Host "Running make lint, make typecheck, and make tests in parallel..."193 Start-MakeStep -Step "lint"194 Start-MakeStep -Step "typecheck"195 Start-MakeStep -Step "tests"196 197 $exitCode = Wait-ForParallelSteps198 }199} finally {200 Stop-RunningSteps201 Remove-Item $logDir -Recurse -Force -ErrorAction SilentlyContinue202}203 204if ($exitCode -ne 0) {205 exit $exitCode206}207 208Write-Host "code-change-verification: all commands passed."209