Skip to content

ci: download release assets into an isolated directory before signing… #169

ci: download release assets into an isolated directory before signing…

ci: download release assets into an isolated directory before signing… #169

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
permissions:
contents: read
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
validate:
runs-on: windows-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # upstream commit
with:
toolchain: 1.97.1
components: rustfmt, clippy, llvm-tools-preview
- run: cargo fmt -- --check
- run: cargo check --workspace --all-targets
- run: cargo test
- run: cargo clippy --all-targets -- -D warnings
- run: cargo build --release
- name: Install dependency policy tools
shell: pwsh
run: cargo install cargo-deny --version 0.20.2 --locked
- run: cargo deny check
- name: Install cargo-llvm-cov
shell: pwsh
run: cargo install cargo-llvm-cov --version 0.8.7 --locked
- name: Test the production coverage analyzer
shell: pwsh
run: python -m unittest discover -s tests/coverage
- name: Enforce Rust production coverage >= 80%
shell: pwsh
run: |
cargo llvm-cov --workspace --json --output-path target/llvm-cov-export.json
python scripts/rust-production-coverage.py target/llvm-cov-export.json --threshold 80 --json target/production-coverage.json
- name: Verify release build repeatability
shell: pwsh
run: ./scripts/verify-build-repeatability.ps1
powershell:
runs-on: windows-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install pinned PowerShell quality tools
shell: pwsh
run: |
Install-PSResource -Name PSScriptAnalyzer -Version 1.25.0 -Repository PSGallery -TrustRepository -Scope CurrentUser
Install-PSResource -Name Pester -Version 6.1.0 -Repository PSGallery -TrustRepository -Scope CurrentUser
- name: Parse and lint PowerShell
shell: pwsh
run: ./scripts/validate-powershell.ps1
- name: Run Pester tests with coverage gate
shell: pwsh
run: ./scripts/invoke-pester-coverage.ps1
distribution:
strategy:
fail-fast: false
matrix:
node-version: ['22', '24', '26']
name: distribution (Node ${{ matrix.node-version }})
runs-on: windows-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node-version }}
- name: Enforce version consistency across channels
# Version surfaces share one value; verify it once on the canonical
# baseline leg instead of repeating it across the whole matrix.
if: matrix.node-version == '24'
shell: pwsh
run: |
$cargoVersion = (Get-Content Cargo.toml | Select-String '^version = "([0-9.]+)"$').Matches.Groups[1].Value
$channels = @{
'powershell/DevNav.psd1' = (Test-ModuleManifest -Path powershell/DevNav.psd1).Version.ToString()
'packaging/npm/package.json' = (Get-Content packaging/npm/package.json -Raw | ConvertFrom-Json).version
'packaging/scoop/devnav.template.json' = (Get-Content packaging/scoop/devnav.template.json -Raw | ConvertFrom-Json).version
}
foreach ($file in $channels.GetEnumerator()) {
if ($file.Value -ne $cargoVersion) {
throw "Version mismatch: Cargo.toml has $cargoVersion but $($file.Key) has $($file.Value). All channels must share one version."
}
}
- name: Run the npm bootstrap unit tests
# The canonical Node 24 leg also enforces the coverage gate; the
# 22/26 legs only check compatibility with the plain test run.
if: matrix.node-version != '24'
run: node --test "tests/npm/**/*.test.mjs"
- name: Run the npm bootstrap tests with coverage gate
if: matrix.node-version == '24'
shell: pwsh
run: ./scripts/invoke-npm-coverage.ps1
- name: Validate the npm tarball allow-list
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'
$stage = Join-Path $env:RUNNER_TEMP 'devnav-pack-check'
New-Item -ItemType Directory -Path "$stage\payload" -Force | Out-Null
Copy-Item packaging\npm\package.json, packaging\npm\README.md, LICENSE $stage
Copy-Item packaging\npm\bin $stage -Recurse
Set-Content "$stage\payload\DevNavSetup-x64.exe" 'CI placeholder x64'
Set-Content "$stage\payload\DevNavSetup-arm64.exe" 'CI placeholder arm64'
$artifacts = [ordered]@{}
foreach ($name in @('installer-x64', 'installer-arm64')) {
$file = "DevNavSetup-$($name -replace 'installer-', '').exe"
$artifacts[$name] = @{
file = $file
sha256 = (Get-FileHash (Join-Path "$stage\payload" $file) -Algorithm SHA256).Hash.ToLowerInvariant()
}
}
$packageVersion = (Get-Content packaging\npm\package.json -Raw | ConvertFrom-Json).version
[ordered]@{ schemaVersion = 1; version = $packageVersion; artifacts = $artifacts } |
ConvertTo-Json -Depth 5 | Set-Content "$stage\release-manifest.json"
Push-Location $stage
try {
$dryRun = npm pack --dry-run --json | ConvertFrom-Json
$files = @($dryRun[0].files | ForEach-Object { $_.path }) | Sort-Object
$expected = @(
'LICENSE', 'README.md', 'bin/devnav.mjs', 'package.json',
'payload/DevNavSetup-arm64.exe', 'payload/DevNavSetup-x64.exe',
'release-manifest.json'
) | Sort-Object
$extra = @($files | Where-Object { $_ -notin $expected })
$missing = @($expected | Where-Object { $_ -notin $files })
if ($files.Count -ne $expected.Count -or $extra.Count -gt 0 -or $missing.Count -gt 0) {
throw "Tarball layout mismatch. Got [$($files -join ', ')]. Extra: $($extra -join ', '). Missing: $($missing -join ', ')."
}
Write-Host "Tarball allow-list verified: $($files.Count) files match exactly."
}
finally {
Pop-Location
}
installer-smoke:
name: installer smoke (${{ matrix.architecture }})
strategy:
fail-fast: false
matrix:
include:
- runner: windows-latest
architecture: x64
- runner: windows-11-arm
architecture: arm64
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Prepare safe compiler payload
shell: pwsh
run: |
New-Item -ItemType Directory -Path release-assets -Force | Out-Null
Set-Content -Path release-assets\dev.exe -Value 'CI compiler smoke payload'
- name: Compile installer with verified Inno Setup
shell: pwsh
run: ./scripts/invoke-inno-compiler.ps1 -Architecture '${{ matrix.architecture }}' -Version '0.12.0'