Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
f8d6810
feat: add phase-2 trusted release consumption platform
svelderrainruiz Feb 26, 2026
589b7f8
fix(release): align release manifest repro asset with published name
svelderrainruiz Feb 26, 2026
fb51fa2
Merge pull request #1 from LabVIEW-Community-CI-CD/feature/phase2-rel…
svelderrainruiz Feb 26, 2026
1890b54
ci(release): fail fast when no eligible self-hosted runner is online
svelderrainruiz Feb 26, 2026
e4b0934
Merge pull request #2 from LabVIEW-Community-CI-CD/hardening/release-…
svelderrainruiz Feb 26, 2026
0039a58
feat(ops): add autonomous release control plane and ops hardening (#3)
svelderrainruiz Feb 26, 2026
8d657f5
feat(ops): add local docker release-control-plane harness
svelderrainruiz Feb 26, 2026
294d6cb
Merge pull request #4 from LabVIEW-Community-CI-CD/feature/release-co…
svelderrainruiz Feb 27, 2026
dac281c
feat(ops): publish runtime image to ghcr
svelderrainruiz Feb 27, 2026
a8e4295
Merge pull request #5 from LabVIEW-Community-CI-CD/feature/publish-op…
svelderrainruiz Feb 27, 2026
7f281d8
feat: add container NSIS self-test and linux parity image publish (#6)
svelderrainruiz Feb 27, 2026
49698f2
feat: add windows NSIS parity image publish with silent self-test gat…
svelderrainruiz Feb 27, 2026
de6521f
fix: correct windows parity publish workflow YAML tag parsing (#8)
svelderrainruiz Feb 27, 2026
17fa7bd
fix: auto-resolve Windows docker context for publish workflow (#9)
svelderrainruiz Feb 27, 2026
72927f1
fix: harden windows publish context resolution error handling (#10)
svelderrainruiz Feb 27, 2026
ae3f98e
Lock CI to hosted runners and fix Windows publish pwsh shell (#11)
svelderrainruiz Feb 27, 2026
bb52969
Use bundled cdev-cli to execute Windows container installer smoke (#12)
svelderrainruiz Feb 27, 2026
1f4eb0a
Pass cdev-cli installer args via CommandArgs in container smoke (#13)
svelderrainruiz Feb 27, 2026
621d4cc
Invoke cdev-cli script directly in Windows container self-test (#14)
svelderrainruiz Feb 27, 2026
05a7eef
Handle cdev-cli installer report-path collision in container smoke (#15)
svelderrainruiz Feb 27, 2026
98033fb
Stabilize container smoke with cdev-cli installer execution (#16)
svelderrainruiz Feb 27, 2026
fe5d661
Decouple control-plane health gate and pin ops runtime base
svelderrainruiz Feb 27, 2026
13b62d4
Merge pull request #17 from LabVIEW-Community-CI-CD/feature/control-p…
svelderrainruiz Feb 27, 2026
c1a8037
Fix runner-label argument passing for control-plane workflows
svelderrainruiz Feb 27, 2026
1658538
Merge pull request #19 from LabVIEW-Community-CI-CD/fix/control-plane…
svelderrainruiz Feb 27, 2026
89f20a7
Add Scope A control-plane hardening gates and incident lifecycle
svelderrainruiz Feb 27, 2026
e4b58c0
Fix Scope A reason-code binding for empty list paths
svelderrainruiz Feb 27, 2026
1437a22
Merge pull request #20 from LabVIEW-Community-CI-CD/feature/scope-a-c…
svelderrainruiz Feb 27, 2026
6002cd2
Add Scope 2 bounded self-healing for SLO and rollback gates
svelderrainruiz Feb 27, 2026
51835a1
Merge pull request #23 from LabVIEW-Community-CI-CD/feature/scope2-co…
svelderrainruiz Feb 27, 2026
39708e6
Fix workflow dispatch input binding for self-healing paths
svelderrainruiz Feb 27, 2026
09f878e
Merge pull request #24 from LabVIEW-Community-CI-CD/fix/self-heal-dis…
svelderrainruiz Feb 27, 2026
d0df22f
Flatten workflow dispatch input args for gh CLI
svelderrainruiz Feb 27, 2026
32cd1bd
Merge pull request #25 from LabVIEW-Community-CI-CD/fix/dispatch-inpu…
svelderrainruiz Feb 27, 2026
b6b4062
Fix release preflight runner labels argument binding
svelderrainruiz Feb 27, 2026
09cdcc3
Merge pull request #26 from LabVIEW-Community-CI-CD/fix/release-prefl…
svelderrainruiz Feb 27, 2026
0dc8310
Handle runner preflight 403 with deterministic warning path
svelderrainruiz Feb 27, 2026
65fff2b
Merge pull request #27 from LabVIEW-Community-CI-CD/fix/release-runne…
svelderrainruiz Feb 27, 2026
e3e62ba
Introduce composite runner preflight action
svelderrainruiz Feb 27, 2026
d166153
Merge pull request #28 from LabVIEW-Community-CI-CD/feature/composite…
svelderrainruiz Feb 27, 2026
ae7b1c6
Allow rollback self-heal for missing release assets
svelderrainruiz Feb 27, 2026
72bb0fb
Merge pull request #29 from LabVIEW-Community-CI-CD/fix/rollback-self…
svelderrainruiz Feb 27, 2026
930e01d
Add checkout before local runner-preflight action
svelderrainruiz Feb 27, 2026
d808a5c
Merge pull request #30 from LabVIEW-Community-CI-CD/fix/runner-prefli…
svelderrainruiz Feb 27, 2026
6de1ba9
Fix immutable release publish path for new tags
svelderrainruiz Feb 27, 2026
a650d98
Merge pull request #31 from LabVIEW-Community-CI-CD/fix/release-immut…
svelderrainruiz Feb 27, 2026
557bd93
Add dual-mode SemVer migration for release tags and hygiene
svelderrainruiz Feb 27, 2026
ec5ac9c
Merge pull request #32 from LabVIEW-Community-CI-CD/feature/semver-du…
svelderrainruiz Feb 27, 2026
6211ac5
Quote release tag descriptions to restore workflow dispatch parsing
svelderrainruiz Feb 27, 2026
d80b99a
Merge pull request #33 from LabVIEW-Community-CI-CD/fix/release-workf…
svelderrainruiz Feb 27, 2026
b910d88
feat(control-plane): cut over rollout orchestration to semver tags
svelderrainruiz Feb 27, 2026
d785052
Merge pull request #34 from LabVIEW-Community-CI-CD/feature/control-p…
svelderrainruiz Feb 27, 2026
463d191
fix(control-plane): bootstrap semver canary planning and add semver g…
svelderrainruiz Feb 27, 2026
d140eaa
Merge pull request #35 from LabVIEW-Community-CI-CD/fix/control-plane…
svelderrainruiz Feb 27, 2026
410e567
fix(control-plane): serialize prerelease dispatch input deterministic…
svelderrainruiz Feb 27, 2026
25b8bf5
Merge pull request #36 from LabVIEW-Community-CI-CD/fix/control-plane…
svelderrainruiz Feb 27, 2026
da6cb05
feat(control-plane): harden canary with release verification and mapp…
svelderrainruiz Feb 27, 2026
d67d45b
Merge pull request #37 from LabVIEW-Community-CI-CD/hardening/canary-…
svelderrainruiz Feb 27, 2026
6535c5a
fix(control-plane): suppress child stdout in execution report path
svelderrainruiz Feb 27, 2026
75b54b9
Merge pull request #38 from LabVIEW-Community-CI-CD/fix/control-plane…
svelderrainruiz Feb 27, 2026
d38ce2c
feat(control-plane): harden promotion lineage verification paths
svelderrainruiz Feb 27, 2026
1d6b076
Merge pull request #39 from LabVIEW-Community-CI-CD/hardening/promoti…
svelderrainruiz Feb 27, 2026
a528de5
Harden stable promotion window policy and audited override
svelderrainruiz Feb 27, 2026
ac13469
Merge pull request #40 from LabVIEW-Community-CI-CD/hardening/stable-…
svelderrainruiz Feb 27, 2026
7b58e38
Harden stable override governance and audit artifacts
svelderrainruiz Feb 27, 2026
b06f3cd
Merge pull request #41 from LabVIEW-Community-CI-CD/hardening/stable-…
svelderrainruiz Feb 27, 2026
00fdbac
Fix stable override audit extraction for hashtable reports
svelderrainruiz Feb 27, 2026
27f464d
Merge pull request #43 from LabVIEW-Community-CI-CD/hotfix/stable-ove…
svelderrainruiz Feb 27, 2026
eb5117e
Harden release concurrency and SemVer collision retries
svelderrainruiz Feb 27, 2026
0564c3a
Merge pull request #44 from LabVIEW-Community-CI-CD/hardening/release…
svelderrainruiz Feb 27, 2026
794fcdd
Add release race-hardening drill workflow and contracts
svelderrainruiz Feb 27, 2026
117459f
Harden race drill for optional dispatch fields
svelderrainruiz Feb 27, 2026
8d8e469
Promote race drill to enforcement gate with incident lifecycle
svelderrainruiz Feb 27, 2026
237a86a
Add race-hardening gate and branch-protection drift controls
svelderrainruiz Feb 27, 2026
f5feb3d
Fix branch-protection apply/verify runtime edge cases
svelderrainruiz Feb 27, 2026
f692951
Merge pull request #45 from LabVIEW-Community-CI-CD/hardening/release…
svelderrainruiz Feb 27, 2026
d1d73f7
Add autonomous release guardrails self-healing lane
svelderrainruiz Feb 27, 2026
4091b2b
Merge pull request #47 from LabVIEW-Community-CI-CD/feature/release-g…
svelderrainruiz Feb 27, 2026
412d82c
Use WORKFLOW_BOT_TOKEN fallback for guardrails workflows
svelderrainruiz Feb 27, 2026
67d7438
Merge pull request #49 from LabVIEW-Community-CI-CD/fix/guardrails-wo…
svelderrainruiz Feb 27, 2026
bf13b5f
Harden autonomous guardrails token and auth reason mapping
svelderrainruiz Feb 27, 2026
7bfbfc7
Align governance contract checks with branch-protection baseline
svelderrainruiz Feb 27, 2026
4973cfa
Make governance PR-review enforcement opt-in
svelderrainruiz Feb 27, 2026
87fe73c
Merge pull request #50 from LabVIEW-Community-CI-CD/feature/scope1-au…
svelderrainruiz Feb 27, 2026
bb8eef1
Scope1: add token drill and SLO alert threshold guardrails
svelderrainruiz Feb 27, 2026
14e7d53
Merge pull request #51 from LabVIEW-Community-CI-CD/feature/scope1-st…
svelderrainruiz Feb 27, 2026
4d6cd8b
Fix workflow bot token drill repository-name resolution
svelderrainruiz Feb 27, 2026
439505c
Merge pull request #53 from LabVIEW-Community-CI-CD/fix/workflow-bot-…
svelderrainruiz Feb 27, 2026
c3cf8a0
Harden control-plane watch timeout and race-drill traceability
svelderrainruiz Feb 27, 2026
835238c
Merge pull request #54 from LabVIEW-Community-CI-CD/hardening/scope1-…
svelderrainruiz Feb 27, 2026
e577815
feat(control-plane): add GA policy state machine, rollback orchestrat…
svelderrainruiz Feb 27, 2026
8930131
feat(control-plane): add deterministic decision-trail artifact contract
svelderrainruiz Feb 27, 2026
8c56fc0
Merge pull request #57 from LabVIEW-Community-CI-CD/feature/control-p…
svelderrainruiz Feb 27, 2026
b8c90d3
fix(control-plane): tolerate optional stable-window decision fields
svelderrainruiz Feb 27, 2026
9ae83f2
Merge pull request #58 from LabVIEW-Community-CI-CD/hotfix/decision-t…
svelderrainruiz Feb 27, 2026
1859a38
feat(drill): add deterministic forced control-plane timeout mode
svelderrainruiz Feb 27, 2026
d221e07
Merge pull request #59 from LabVIEW-Community-CI-CD/feature/race-dril…
svelderrainruiz Feb 27, 2026
69e65c7
fix(guardrails): emit invalid_input report on workflow input guard fa…
svelderrainruiz Feb 27, 2026
e46a684
Merge pull request #60 from LabVIEW-Community-CI-CD/feature/guardrail…
svelderrainruiz Feb 27, 2026
98855c5
Merge remote-tracking branch 'upstream/main' into align/upstream-main…
svelderrainruiz Feb 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions .github/actions/runner-preflight/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
name: runner-preflight
description: Deterministic self-hosted runner availability preflight with 403 visibility fallback.

inputs:
repository:
description: owner/repo target for runner visibility.
required: true
required_labels_csv:
description: Comma-delimited required runner labels.
required: true
report_path:
description: Absolute path to write preflight JSON report.
required: true

outputs:
reason_code:
description: ok | runner_unavailable | runner_visibility_unavailable
value: ${{ steps.check.outputs.reason_code }}
report_path:
description: Output JSON report path.
value: ${{ steps.check.outputs.report_path }}

runs:
using: composite
steps:
- id: check
name: Evaluate runner availability gate
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'

$repo = [string]'${{ inputs.repository }}'
if ([string]::IsNullOrWhiteSpace($repo)) {
throw 'repository_required'
}

$requiredLabels = @(
[string]'${{ inputs.required_labels_csv }}'.Split(',') |
ForEach-Object { ([string]$_).Trim() } |
Where-Object { -not [string]::IsNullOrWhiteSpace($_) }
)
if ($requiredLabels.Count -eq 0) {
throw 'required_labels_empty'
}

$reportPath = [string]'${{ inputs.report_path }}'
if ([string]::IsNullOrWhiteSpace($reportPath)) {
throw 'report_path_required'
}

$runnersJson = & gh api "repos/$repo/actions/runners?per_page=100" 2>&1
$runnerApiExitCode = if ($null -eq $LASTEXITCODE) { 0 } else { [int]$LASTEXITCODE }
$runnerVisibility = 'available'
$runnerQueryError = ''
if ($runnerApiExitCode -ne 0) {
$runnerQueryError = [string]::Join("`n", @($runnersJson))
if ($runnerQueryError -match 'Resource not accessible by integration' -or $runnerQueryError -match 'HTTP 403') {
$runnerVisibility = 'forbidden'
} else {
throw "Failed to list runners for '$repo'. $runnerQueryError"
}
}

$onlineRunners = @()
$eligibleRunners = @()
if ($runnerVisibility -eq 'available') {
$runnerPayload = $runnersJson | ConvertFrom-Json -ErrorAction Stop
foreach ($runner in @($runnerPayload.runners)) {
if ([string]$runner.status -ne 'online') {
continue
}

$onlineRunners += [string]$runner.name
$runnerLabels = @{}
foreach ($label in @($runner.labels)) {
$runnerLabels[[string]$label.name.ToLowerInvariant()] = $true
}

$missingLabels = @($requiredLabels | Where-Object { -not $runnerLabels.ContainsKey($_) })
if ($missingLabels.Count -eq 0) {
$eligibleRunners += [ordered]@{
name = [string]$runner.name
labels = @($runner.labels | ForEach-Object { [string]$_.name })
}
}
}
}

$status = 'fail'
$reasonCode = 'runner_unavailable'
$remediation = 'Register at least one online self-hosted runner with the required labels.'
if ($runnerVisibility -eq 'forbidden') {
$status = 'warn'
$reasonCode = 'runner_visibility_unavailable'
$remediation = 'Grant token access to list self-hosted runners, or run an out-of-band runner availability check.'
} elseif ($eligibleRunners.Count -gt 0) {
$status = 'pass'
$reasonCode = 'ok'
$remediation = ''
}

$report = [ordered]@{
schema_version = '1.0'
repository = $repo
generated_at_utc = (Get-Date).ToUniversalTime().ToString('o')
required_labels = $requiredLabels
runner_visibility = $runnerVisibility
runner_query_error = $runnerQueryError
online_runners = $onlineRunners
eligible_runners = $eligibleRunners
status = $status
reason_code = $reasonCode
remediation = $remediation
}

$report | ConvertTo-Json -Depth 20 | Set-Content -LiteralPath $reportPath -Encoding utf8

"reason_code=$reasonCode" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
"report_path=$reportPath" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8

if ($status -eq 'pass') {
Write-Host "Runner preflight passed. Eligible runners: $($eligibleRunners.Count)."
exit 0
}

if ($status -eq 'warn') {
Write-Warning "[runner_visibility_unavailable] Runner list API is not accessible with current token. Continuing without fail-fast runner gate."
exit 0
}

throw "[runner_unavailable] No online runner matched required labels ($($requiredLabels -join ', ')). Remediation: $remediation"
58 changes: 50 additions & 8 deletions .github/scripts/Invoke-GovernanceContract.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,54 @@ if ([string]::IsNullOrWhiteSpace($env:GH_TOKEN)) {
throw 'GH token is required. Set GH_ADMIN_TOKEN (preferred) or WORKFLOW_BOT_TOKEN/GH_TOKEN/GITHUB_TOKEN.'
}

$requiredContexts = @(
'CI Pipeline',
'Workspace Installer Contract',
'Reproducibility Contract',
'Provenance Contract'
)
function ConvertTo-BoolOrDefault {
param(
[Parameter()][AllowNull()][string]$Value = '',
[Parameter()][bool]$Default = $false
)

if ([string]::IsNullOrWhiteSpace([string]$Value)) {
return $Default
}

try {
return [System.Convert]::ToBoolean([string]$Value)
} catch {
$normalized = ([string]$Value).Trim().ToLowerInvariant()
if (@('1', 'yes', 'y', 'on') -contains $normalized) {
return $true
}
if (@('0', 'no', 'n', 'off') -contains $normalized) {
return $false
}
return $Default
}
}

$enableSelfHostedContracts = ConvertTo-BoolOrDefault -Value ([string]$env:ENABLE_SELF_HOSTED_CONTRACTS) -Default $false
$requirePullRequestReviews = ConvertTo-BoolOrDefault -Value ([string]$env:GOVERNANCE_REQUIRE_PR_REVIEWS) -Default $false
$requiredContexts = [System.Collections.Generic.List[string]]::new()
foreach ($context in @(
'CI Pipeline',
'Integration Gate',
'Release Race Hardening Drill'
)) {
if (-not $requiredContexts.Contains([string]$context)) {
[void]$requiredContexts.Add([string]$context)
}
}

if ($enableSelfHostedContracts) {
foreach ($context in @(
'Workspace Installer Contract',
'Reproducibility Contract',
'Provenance Contract'
)) {
if (-not $requiredContexts.Contains([string]$context)) {
[void]$requiredContexts.Add([string]$context)
}
}
}

$endpoint = "repos/$RepoSlug/branches/$([uri]::EscapeDataString($Branch))/protection"
$response = & gh api $endpoint 2>&1
Expand All @@ -68,13 +110,13 @@ if ($null -ne $protection.required_status_checks -and $null -ne $protection.requ
$actualContexts = @($protection.required_status_checks.contexts)
}

foreach ($context in $requiredContexts) {
foreach ($context in @($requiredContexts)) {
if ($actualContexts -notcontains $context) {
$issues += "missing required status context: $context"
}
}

if ($null -eq $protection.required_pull_request_reviews) {
if ($requirePullRequestReviews -and $null -eq $protection.required_pull_request_reviews) {
$issues += 'required_pull_request_reviews is not enabled'
}

Expand Down
Loading
Loading