name: Windows Package on: push: branches: - master - maint - next tags: - "v*" pull_request: workflow_dispatch: env: CARGO_TERM_COLOR: always jobs: determine-versioning: runs-on: windows-latest outputs: package_version: ${{ steps.version.outputs.package_version }} steps: - uses: actions/checkout@v6 with: fetch-depth: 0 - name: Derive package version id: version shell: pwsh run: | $cargoToml = Get-Content Cargo.toml -Raw if ($cargoToml -match 'version\s*=\s*"([^"]+)"') { $baseVersion = $Matches[1] } else { throw "Could not determine version from Cargo.toml" } if ($env:GITHUB_REF -like "refs/tags/*") { $version = $env:GITHUB_REF_NAME -replace '^v', '' } else { $branch = $env:GITHUB_REF_NAME -replace '[^A-Za-z0-9]', '.' -replace '\.\.+', '.' -replace '^\.|\.$$', '' $height = git rev-list --count HEAD $hash = git rev-parse --short HEAD if (-not $branch) { $branch = "ref" } $version = "$baseVersion+$branch.$height.$hash" } echo "package_version=$version" >> $env:GITHUB_OUTPUT build: name: Build Windows package runs-on: windows-latest needs: determine-versioning steps: - uses: actions/checkout@v6 with: fetch-depth: 0 - name: Set SOURCE_DATE_EPOCH from git shell: pwsh run: | $epoch = git log -1 --format=%ct echo "SOURCE_DATE_EPOCH=$epoch" >> $env:GITHUB_ENV - name: Install Rust toolchain uses: actions-rust-lang/setup-rust-toolchain@v1 with: cache: false rustflags: '' - name: Cache Cargo registry + build uses: actions/cache@v5 with: path: | ~/.cargo/registry ~/.cargo/git target key: windows-release-x86_64-${{ hashFiles('**/Cargo.lock') }} restore-keys: | windows-release-x86_64- - name: Build release binaries run: cargo build --release - name: Build Windows package shell: pwsh run: | powershell -File packaging/windows/build-zip.ps1 ` -Version "${{ needs.determine-versioning.outputs.package_version }}" ` -NoBuild - name: Verify ZIP structural correctness shell: pwsh run: | $zip = Get-ChildItem deploy\fips-*-windows-*.zip | Select-Object -First 1 if (-not $zip) { Write-Error "No ZIP artifact found in deploy\"; exit 1 } Write-Host "Verifying: $($zip.Name)" $extractDir = "verify-extract" if (Test-Path $extractDir) { Remove-Item -Recurse -Force $extractDir } Expand-Archive -Path $zip.FullName -DestinationPath $extractDir # Expected top-level files (flat ZIP, no wrapper directory). # Source of truth: packaging/windows/build-zip.ps1 $expected = @( "fips.exe", "fipsctl.exe", "fipstop.exe", "fips.yaml", "hosts", "install-service.ps1", "uninstall-service.ps1", "README.txt" ) $missing = @() foreach ($f in $expected) { $path = Join-Path $extractDir $f if (Test-Path -LiteralPath $path -PathType Leaf) { Write-Host "PASS: $f" } else { Write-Host "FAIL: $f" $missing += $f } } Write-Host "" Write-Host "ZIP contents:" Get-ChildItem -Path $extractDir -Recurse | ForEach-Object { Write-Host " $($_.FullName.Substring((Resolve-Path $extractDir).Path.Length + 1))" } if ($missing.Count -gt 0) { Write-Error "Missing expected files: $($missing -join ', ')" exit 1 } Write-Host "" Write-Host "All expected files present." - name: SHA-256 hash shell: pwsh run: | Write-Host "==> Windows release asset:" Get-ChildItem deploy\fips-*-windows-*.zip | ForEach-Object { Get-FileHash $_.FullName -Algorithm SHA256 | Format-Table -AutoSize } - name: Upload artifact uses: actions/upload-artifact@v7 with: name: fips_${{ needs.determine-versioning.outputs.package_version }}_x86_64_windows path: deploy/fips-*-windows-*.zip retention-days: 30 - name: Build summary shell: pwsh run: | $pkg = Get-ChildItem deploy\fips-*-windows-*.zip | Select-Object -First 1 Write-Host "Build Summary for Windows/x86_64:" Write-Host " Package: $($pkg.Name)" Write-Host " Size: $([math]::Round($pkg.Length / 1MB, 2)) MB" release: name: Publish Windows assets to GitHub Release runs-on: ubuntu-latest needs: build if: startsWith(github.ref, 'refs/tags/') permissions: contents: write steps: - name: Download Windows artifacts uses: actions/download-artifact@v8 with: path: dist merge-multiple: true - name: Generate Windows release checksums run: | cd dist find . -maxdepth 1 -type f -name '*.zip' -printf '%P\n' \ | LC_ALL=C sort \ | xargs sha256sum \ > checksums-windows.txt - name: Wait for tag release env: GH_TOKEN: ${{ github.token }} run: | for attempt in $(seq 1 20); do if gh release view "${GITHUB_REF_NAME}" --repo "${GITHUB_REPOSITORY}" >/dev/null 2>&1; then exit 0 fi echo "Release ${GITHUB_REF_NAME} not available yet; waiting..." sleep 15 done echo "Timed out waiting for release ${GITHUB_REF_NAME}" >&2 exit 1 - name: Upload Windows assets env: GH_TOKEN: ${{ github.token }} run: | gh release upload "${GITHUB_REF_NAME}" \ dist/*.zip \ dist/checksums-windows.txt \ --clobber \ --repo "${GITHUB_REPOSITORY}"