name: Windows Build Test on: workflow_dispatch: inputs: version: description: "Version for SignPath parameter (e.g., 1.0.0-test.1)" required: false default: "dev" permissions: contents: read actions: read jobs: windows-build-sign: runs-on: windows-latest steps: - name: Checkout code uses: actions/checkout@v6 with: fetch-depth: 0 - name: Setup pnpm uses: pnpm/action-setup@v4 - name: Setup Node.js uses: actions/setup-node@v6 with: node-version: "24" cache: "pnpm" - name: Install dependencies run: pnpm install - name: Download uv binaries for Windows run: pnpm run uv:download:win - name: Build Windows run: pnpm run package:win - name: Validate unsigned Windows artifacts before SignPath shell: pwsh run: | $unsignedExeFiles = Get-ChildItem -Path "release" -Filter *.exe -File if (-not $unsignedExeFiles) { throw "No unsigned .exe files found in release/ before SignPath upload" } $unsignedCount = $unsignedExeFiles.Count "UNSIGNED_EXE_COUNT=$unsignedCount" | Out-File -FilePath $env:GITHUB_ENV -Append Write-Host "Found $unsignedCount unsigned .exe file(s):" $unsignedExeFiles | ForEach-Object { Write-Host " - $($_.Name)" } # Required by SignPath Trusted Build: artifact must exist on GitHub first. - name: Upload unsigned Windows artifacts for SignPath id: upload-unsigned-windows-artifact uses: actions/upload-artifact@v4 with: name: unsigned-win-exe-${{ github.run_id }}-${{ github.run_attempt }} path: release/*.exe retention-days: 1 - name: Sign Windows artifacts via SignPath id: signpath-sign-windows uses: signpath/github-action-submit-signing-request@v2 with: api-token: ${{ secrets.SIGNPATH_API_TOKEN }} organization-id: "78e37079-23df-4800-b41c-33312ad7c1e3" project-slug: "ValueCell" signing-policy-slug: "ValueCell-sign" github-artifact-id: ${{ steps.upload-unsigned-windows-artifact.outputs.artifact-id }} wait-for-completion: true output-artifact-directory: release/signed - name: Replace unsigned executables with signed ones shell: pwsh run: | Write-Host "SignPath GitHub artifact ID: ${{ steps.upload-unsigned-windows-artifact.outputs.artifact-id }}" $signedExeFiles = Get-ChildItem -Path "release/signed" -Filter *.exe -File -Recurse if (-not $signedExeFiles) { throw "No signed .exe files found in release/signed" } $signedCount = $signedExeFiles.Count if ($env:UNSIGNED_EXE_COUNT -and ($signedCount -ne [int]$env:UNSIGNED_EXE_COUNT)) { throw "Signed .exe count ($signedCount) does not match unsigned count ($env:UNSIGNED_EXE_COUNT)" } foreach ($file in $signedExeFiles) { Copy-Item -Path $file.FullName -Destination "release/$($file.Name)" -Force } $finalExeFiles = Get-ChildItem -Path "release" -Filter *.exe -File if ($env:UNSIGNED_EXE_COUNT -and ($finalExeFiles.Count -ne [int]$env:UNSIGNED_EXE_COUNT)) { throw "Final release .exe count ($($finalExeFiles.Count)) does not match unsigned count ($env:UNSIGNED_EXE_COUNT)" } Write-Host "Signed executables copied to release/ ($($finalExeFiles.Count) file(s))" - name: Upload signed Windows artifacts uses: actions/upload-artifact@v4 with: name: signed-win-exe-${{ github.run_id }}-${{ github.run_attempt }} path: | release/*.exe release/latest*.yml retention-days: 7