mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-24 20:53:06 +00:00
1dd4a477c5
The gates were attached to publishing: they ran only as the first job of the script publish. Holding that publish back with GitHub's skip-actions marker dropped them together with CI, CodeQL and zizmor. The stable agent release published the same scripts without them, the MSI build signed the loader without them, and no gate page ever showed a run. - pester.yml, shown as "Bootstrap script gates", runs on pushes to main as well as pull requests, with one list of every input of the checks. - publish-scripts.yml: a push whose commit message carries the skip-publish marker (spelled out in the workflow) runs neither job and uploads nothing; every check of the push still runs. - build-agent.yml: a publish_as_stable release waits for the gates, which run next to the build and are skipped otherwise. - build-msi.yml: nothing is signed before the gates pass. The loader's own parse/ASCII step goes, since the gates cover it. - The reusable workflow is named "Bootstrap script gates (reusable)", since its runs show under the caller only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
94 lines
4.1 KiB
YAML
94 lines
4.1 KiB
YAML
name: Bootstrap script gates (reusable)
|
|
|
|
# Quality gate for the customer-facing PowerShell scripts, factored out so it exists
|
|
# once and every caller runs the identical checks. Its runs show under the caller:
|
|
# * pester.yml -- every pull request and push to main that changes an input
|
|
# of these checks (reports, does not block the merge button)
|
|
# * publish-scripts.yml -- BLOCKS the upload to the download alias
|
|
# * build-agent.yml -- BLOCKS a stable release, which publishes the scripts too
|
|
# * build-msi.yml -- BLOCKS signing the loader the MSI embeds
|
|
# Devices execute these scripts as SYSTEM during enrollment, so a red suite must never
|
|
# ship: every job that signs or uploads them waits for this workflow.
|
|
|
|
on:
|
|
workflow_call:
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
gates:
|
|
name: Bootstrap guard tests (PS 5.1, ${{ matrix.os }})
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
# Folder permissions and Windows PowerShell 5.1 come with the OS, so both server images.
|
|
os: [windows-2022, windows-2025]
|
|
runs-on: ${{ matrix.os }}
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
# For all users: the SYSTEM pass below runs Pester as SYSTEM.
|
|
- name: Install Pester 5+
|
|
shell: powershell
|
|
run: |
|
|
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Scope AllUsers | Out-Null
|
|
Install-Module Pester -Scope AllUsers -Force -SkipPublisherCheck -MinimumVersion 5.5.0
|
|
|
|
# Windows PowerShell 5.1 on purpose: that is the runtime IME uses to execute
|
|
# platform scripts, so guard/relax logic is verified without resetting a device.
|
|
# The runner is elevated, so the integration tests use the real folder permissions.
|
|
- name: Run Pester
|
|
shell: powershell
|
|
run: |
|
|
Import-Module Pester -MinimumVersion 5.5.0
|
|
$c = New-PesterConfiguration
|
|
$c.Run.Path = 'scripts/Bootstrap'
|
|
$c.Run.Exit = $true
|
|
$c.Output.Verbosity = 'Detailed'
|
|
Invoke-Pester -Configuration $c
|
|
|
|
# On a device the bootstrap runs as SYSTEM: the integration tests once more as SYSTEM.
|
|
- name: Integration tests as SYSTEM
|
|
shell: powershell
|
|
run: ./.github/scripts/Invoke-BootstrapSystemPass.ps1
|
|
|
|
- name: Folder permissions against a real standard user
|
|
shell: powershell
|
|
run: ./.github/scripts/Test-BootstrapAttacker.ps1
|
|
|
|
- name: Guard scripts stay pure ASCII
|
|
shell: powershell
|
|
run: |
|
|
$failed = $false
|
|
Get-ChildItem 'scripts/Bootstrap' -Filter '*.ps1' -Recurse | ForEach-Object {
|
|
$bytes = [System.IO.File]::ReadAllBytes($_.FullName)
|
|
for ($i = 0; $i -lt $bytes.Length; $i++) {
|
|
if ($bytes[$i] -gt 127) {
|
|
Write-Host "::error file=scripts/Bootstrap/$($_.Name)::Non-ASCII byte 0x$('{0:X2}' -f $bytes[$i]) at offset $i. PS 5.1 (IME) reads BOM-less files as ANSI and corrupts multi-byte chars."
|
|
$failed = $true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if ($failed) { exit 1 }
|
|
Write-Host 'All bootstrap scripts are pure ASCII.'
|
|
|
|
- uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
|
with:
|
|
dotnet-version: '10.0.x'
|
|
|
|
# The names and log lines the scripts share with the agent, checked against the agent's
|
|
# own code.
|
|
- name: Script contracts with the agent
|
|
run: dotnet test src/Agent/AutopilotMonitor.Agent.V2.Core.Tests --configuration Release --filter "Category=BootstrapContract" --logger "console;verbosity=normal"
|
|
|
|
# The publish chain renders the -Dev variant by literal substitution and refuses to
|
|
# ship when an anchor moved. Running it dry here surfaces that (and any drift against
|
|
# the alias) on the PR instead of on the push that would have published.
|
|
- name: Publish dry run (dev-render anchors + version-bump guard + drift)
|
|
shell: pwsh
|
|
run: ./.github/scripts/Publish-BootstrapScripts.ps1 -DryRun
|