diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4309ed3..ffedb7d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,6 +12,11 @@ name: CI - develop - master +# RUNNING_LOCALLY is set to 'true' by ci-cd-test-run.ps1 via act's --env flag. +# On real GitHub Actions the variable is empty, so steps gated on it run normally. +env: + RUNNING_LOCALLY: "" + jobs: validate-branch: name: Validate Branch Name @@ -60,11 +65,9 @@ jobs: --logger "trx;LogFileName=test-results-${{ matrix.framework }}.trx" - name: Upload test results uses: actions/upload-artifact@v7 - if: always() - # continue-on-error is intentionally true: when running locally via act, ACTIONS_RUNTIME_TOKEN - # is not available and upload-artifact always fails. Using env.ACT == 'true' trips actionlint - # (ACT is not a standard GitHub context variable), so we keep the unconditional true here. - continue-on-error: true + # Skipped when running locally via act (RUNNING_LOCALLY=true passed by ci-cd-test-run.ps1). + # On real GitHub Actions RUNNING_LOCALLY is empty, so the step runs and failures are fatal. + if: always() && env.RUNNING_LOCALLY == '' with: name: test-results-${{ matrix.framework }} path: "**/*.trx" diff --git a/ci-cd-test-run.ps1 b/ci-cd-test-run.ps1 index a36e6b3..14046fd 100644 --- a/ci-cd-test-run.ps1 +++ b/ci-cd-test-run.ps1 @@ -176,7 +176,7 @@ if ($Mode -in @('dry', 'all') -and $dockerAvailable -and $hasAct) { Write-Section "Dry-run $($wf.Name) workflow" Push-Location $RepoRoot try { - $actArgs = @('push', '--workflows', $wf.File, '-n') + $actArgs = @('push', '--workflows', $wf.File, '--env', 'RUNNING_LOCALLY=true', '-n') $eventPath = $null # Release workflow is gated on push to master; provide an explicit push event payload. @@ -197,12 +197,16 @@ if ($Mode -in @('dry', 'all') -and $dockerAvailable -and $hasAct) { $_ -match '(FAIL|error)' -and $_ -notmatch 'DRYRUN' -and $_ -notmatch 'upload-artifact' -and - $_ -notmatch '\.cache\\act\\actions-upload-artifact' -and - $_ -notmatch 'The system cannot find the file specified' + $_ -notmatch '\.cache\\act\\actions-upload-artifact' + # Note: 'The system cannot find the file specified' was removed — it is too + # broad and can hide unrelated failures. The specific cache path pattern above + # is the reliable signal for the known act Windows cache-cleanup bug. }) $knownArtifactCacheIssue = @($out | Where-Object { - $_ -match 'actions-upload-artifact' -or - $_ -match 'The system cannot find the file specified' + # Match only the specific known act Windows cache-cleanup issue. + # Matching on 'The system cannot find the file specified' alone was removed — + # that message can appear from unrelated failures unconnected to artifact cleanup. + $_ -match '\.cache\\act\\actions-upload-artifact' }) $dryRunLines = @($out | Where-Object { $_ -match '\*DRYRUN\* \[[^\]]+\]' }) @@ -239,10 +243,24 @@ if ($Mode -in @('ci', 'all') -and $dockerAvailable -and $hasAct) { foreach ($wf in $actWorkflows) { Write-Section "Running $($wf.Name) workflow via act" Push-Location $RepoRoot + $eventPath = $null try { - $actArgs = @($wf.Event, '--workflows', $wf.File) + $actArgs = @($wf.Event, '--workflows', $wf.File, '--env', 'RUNNING_LOCALLY=true') if ($Job) { $actArgs += @('-j', $Job) } + # Release workflow is gated on push to master; supply an explicit push event + # payload so act targets the correct branch and does not skip the workflow. + # Mirrors the same payload used in the dry-run path above. + if ($wf.Name -eq 'Release') { + $eventPath = [System.IO.Path]::GetTempFileName() + @{ + ref = 'refs/heads/master' + repository = @{ default_branch = 'master' } + head_commit = @{ id = 'local-ci-run' } + } | ConvertTo-Json -Depth 4 | Set-Content -LiteralPath $eventPath -Encoding UTF8 + $actArgs += @('-e', $eventPath) + } + # Stream output, capture for analysis $outLines = [System.Collections.Generic.List[string]]::new() & act @actArgs 2>&1 | ForEach-Object { @@ -274,6 +292,9 @@ if ($Mode -in @('ci', 'all') -and $dockerAvailable -and $hasAct) { Add-Error "$($wf.Name) workflow had job failures (see above)" } } finally { + if ($null -ne $eventPath -and (Test-Path -LiteralPath $eventPath)) { + Remove-Item -LiteralPath $eventPath -Force -ErrorAction SilentlyContinue + } Pop-Location } }