Feature/3d plotting v2 (#4) #11
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release Packaging | |
| on: | |
| push: | |
| tags: | |
| - "v*.*.*" | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| jobs: | |
| package: | |
| runs-on: windows-latest | |
| env: | |
| # Opt into Node.js 24 for all JavaScript actions ahead of the June 2026 forced migration. | |
| # Remove once all actions used here ship native Node.js 24 support. | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" | |
| # Update these toolchain pins when the runner image changes or when a dependency upgrade | |
| # is required. Keep WiX major version aligned with packaging/build-packages.ps1 checks. | |
| DOTNET_VERSION: "9.0.x" | |
| PYTHON_VERSION: "3.12" | |
| WIX_VERSION: "6.0.2" | |
| BUILD_CONFIGURATION: "Release" | |
| BUILD_PLATFORM: "x64" | |
| MSVC_PLATFORM_TOOLSET: "v143" | |
| # Signing is optional and intentionally disabled by default so the pipeline keeps working | |
| # before a code-signing certificate is configured. | |
| ENABLE_CODESIGN: "false" | |
| # GitHub Actions does not allow direct secrets.* references inside step `if:` expressions. | |
| # Compute a boolean once in job env and reference that in the conditional step below. | |
| HAS_CODESIGN_SECRETS: ${{ secrets.WINDOWS_CODESIGN_PFX_BASE64 != '' && secrets.WINDOWS_CODESIGN_PFX_PASSWORD != '' }} | |
| # Override via GitHub variable WINDOWS_CODESIGN_TIMESTAMP_URL if your CA requires another URL. | |
| CODE_SIGN_TIMESTAMP_URL: "http://timestamp.digicert.com" | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup MSBuild | |
| uses: microsoft/setup-msbuild@v2 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| # Optional signing bootstrap. This step only runs when BOTH secrets exist: | |
| # - WINDOWS_CODESIGN_PFX_BASE64 | |
| # - WINDOWS_CODESIGN_PFX_PASSWORD | |
| # To keep unsigned behavior, do nothing (leave secrets unset). | |
| # | |
| # When you later enable signing, no pipeline logic changes are required; just add secrets | |
| # (and optionally the WINDOWS_CODESIGN_TIMESTAMP_URL variable). | |
| - name: Prepare Optional Code Signing | |
| if: env.HAS_CODESIGN_SECRETS == 'true' | |
| shell: pwsh | |
| env: | |
| TIMESTAMP_URL_OVERRIDE: ${{ vars.WINDOWS_CODESIGN_TIMESTAMP_URL }} | |
| run: | | |
| $ErrorActionPreference = "Stop" | |
| $pfxPath = Join-Path $env:RUNNER_TEMP "binxray-codesign.pfx" | |
| [System.IO.File]::WriteAllBytes( | |
| $pfxPath, | |
| [Convert]::FromBase64String("${{ secrets.WINDOWS_CODESIGN_PFX_BASE64 }}") | |
| ) | |
| $signtoolCmd = Get-Command signtool.exe -ErrorAction SilentlyContinue | |
| $signtoolPath = $null | |
| if ($signtoolCmd) { | |
| $signtoolPath = $signtoolCmd.Source | |
| } else { | |
| $candidate = Get-ChildItem "C:\Program Files (x86)\Windows Kits\10\bin" -Recurse -Filter signtool.exe -ErrorAction SilentlyContinue | | |
| Where-Object { $_.FullName -match "\\x64\\signtool\.exe$" } | | |
| Sort-Object FullName -Descending | | |
| Select-Object -First 1 | |
| if ($candidate) { | |
| $signtoolPath = $candidate.FullName | |
| } | |
| } | |
| if (-not $signtoolPath) { | |
| throw "signtool.exe not found on runner." | |
| } | |
| $timestampUrl = $env:CODE_SIGN_TIMESTAMP_URL | |
| if (-not [string]::IsNullOrWhiteSpace($env:TIMESTAMP_URL_OVERRIDE)) { | |
| $timestampUrl = $env:TIMESTAMP_URL_OVERRIDE | |
| } | |
| "ENABLE_CODESIGN=true" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append | |
| "CODE_SIGN_PFX=$pfxPath" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append | |
| "CODE_SIGN_PWD=${{ secrets.WINDOWS_CODESIGN_PFX_PASSWORD }}" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append | |
| "SIGNTOOL_EXE=$signtoolPath" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append | |
| "CODE_SIGN_TIMESTAMP_URL=$timestampUrl" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append | |
| Write-Host "Optional Authenticode signing enabled." | |
| Write-Host "Using SignTool: $signtoolPath" | |
| - name: Show MSBuild Version | |
| shell: pwsh | |
| run: | | |
| msbuild -version | |
| - name: Install WiX CLI | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = "Stop" | |
| $PSNativeCommandUseErrorActionPreference = $true | |
| $globalTools = dotnet tool list --global | |
| if ($globalTools -match '(^|\s)wix(\s|$)') { | |
| dotnet tool update --global wix --version $env:WIX_VERSION | |
| } | |
| else { | |
| dotnet tool install --global wix --version $env:WIX_VERSION | |
| } | |
| $extensions = "" | |
| $PSNativeCommandUseErrorActionPreference = $false | |
| try { | |
| $extensions = wix extension list --global 2>$null | |
| if ($extensions -match 'WixToolset\.Bal\.wixext') { | |
| wix extension remove --global WixToolset.Bal.wixext 2>$null | |
| } | |
| } | |
| finally { | |
| $PSNativeCommandUseErrorActionPreference = $true | |
| } | |
| wix extension add --global "WixToolset.Bal.wixext/$env:WIX_VERSION" | |
| $wixVersion = (wix --version).Trim() | |
| if (-not $wixVersion.StartsWith("6.")) { | |
| throw "Expected WiX 6.x but found '$wixVersion'." | |
| } | |
| Write-Host "Using WiX $wixVersion" | |
| - name: Read App Version | |
| id: version | |
| shell: pwsh | |
| run: | | |
| $version = python scripts/get_version.py | |
| if (-not $version) { throw "Failed to read version from Version.h" } | |
| "app_version=$version" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append | |
| - name: Validate Tag Matches Version | |
| if: startsWith(github.ref, 'refs/tags/') | |
| shell: pwsh | |
| run: | | |
| $expected = "v${{ steps.version.outputs.app_version }}" | |
| $actual = "${{ github.ref_name }}" | |
| if ($actual -ne $expected) { | |
| throw "Tag '$actual' does not match Version.h ('$expected')." | |
| } | |
| - name: Build Release Binary | |
| shell: pwsh | |
| run: | | |
| $solutionDir = Join-Path $env:GITHUB_WORKSPACE "src\" | |
| $repoUrl = "${{ github.server_url }}/${{ github.repository }}" | |
| $branch = "${{ github.ref_name }}" | |
| $commit = "${{ github.sha }}" | |
| $buildVersion = "${{ steps.version.outputs.app_version }}" | |
| Write-Host "Building with Configuration=$env:BUILD_CONFIGURATION Platform=$env:BUILD_PLATFORM PlatformToolset=$env:MSVC_PLATFORM_TOOLSET" | |
| Write-Host "Build metadata: repo=$repoUrl branch=$branch commit=$commit version=$buildVersion" | |
| msbuild src\BinXray\BinXray.vcxproj /t:Build /m ` | |
| /p:Configuration=$env:BUILD_CONFIGURATION ` | |
| /p:Platform=$env:BUILD_PLATFORM ` | |
| /p:PlatformToolset=$env:MSVC_PLATFORM_TOOLSET ` | |
| /p:BxrBuildRepoUrl="$repoUrl" ` | |
| /p:BxrBuildBranch="$branch" ` | |
| /p:BxrBuildCommit="$commit" ` | |
| /p:BxrBuildVersion="$buildVersion" ` | |
| /p:SolutionDir="$solutionDir" ` | |
| /p:IntDir="$env:GITHUB_WORKSPACE\build\obj\" ` | |
| /p:OutDir="$env:GITHUB_WORKSPACE\build\bin\" | |
| # Packaging script supports both unsigned and signed modes. | |
| # IMPORTANT signing-order constraint (handled in packaging/build-packages.ps1): | |
| # sign app EXE -> build MSI -> sign MSI -> build bundle -> sign bundle | |
| # Do not move MSI signing after bundle creation. | |
| - name: Build MSI and Setup EXE Packages | |
| shell: pwsh | |
| run: | | |
| if ($env:ENABLE_CODESIGN -eq "true") { | |
| Write-Host "Packaging with optional Authenticode signing enabled." | |
| .\packaging\build-packages.ps1 ` | |
| -AppExePath "$env:GITHUB_WORKSPACE\build\bin\BinXray.exe" ` | |
| -Version "${{ steps.version.outputs.app_version }}" ` | |
| -RequiredWixVersion "$env:WIX_VERSION" ` | |
| -OutputDir "artifacts\release" ` | |
| -SignArtifacts ` | |
| -SignToolPath "$env:SIGNTOOL_EXE" ` | |
| -CodeSignPfxPath "$env:CODE_SIGN_PFX" ` | |
| -CodeSignPfxPassword "$env:CODE_SIGN_PWD" ` | |
| -TimestampUrl "$env:CODE_SIGN_TIMESTAMP_URL" | |
| } | |
| else { | |
| .\packaging\build-packages.ps1 ` | |
| -AppExePath "$env:GITHUB_WORKSPACE\build\bin\BinXray.exe" ` | |
| -Version "${{ steps.version.outputs.app_version }}" ` | |
| -RequiredWixVersion "$env:WIX_VERSION" ` | |
| -OutputDir "artifacts\release" | |
| } | |
| # Verification is optional and only meaningful in signed mode. | |
| # Keep this step after packaging and before upload/publish so failures block releases. | |
| - name: Verify Authenticode Signatures (Optional) | |
| shell: pwsh | |
| run: | | |
| if ($env:ENABLE_CODESIGN -ne "true") { | |
| Write-Host "Skipping signature verification (no signing certificate configured)." | |
| return | |
| } | |
| $ErrorActionPreference = "Stop" | |
| $targets = @( | |
| "$env:GITHUB_WORKSPACE\build\bin\BinXray.exe", | |
| "$env:GITHUB_WORKSPACE\artifacts\release\*.exe", | |
| "$env:GITHUB_WORKSPACE\artifacts\release\*.msi" | |
| ) | |
| foreach ($pattern in $targets) { | |
| Get-ChildItem $pattern -ErrorAction SilentlyContinue | ForEach-Object { | |
| $sig = Get-AuthenticodeSignature $_.FullName | |
| $subject = if ($sig.SignerCertificate) { $sig.SignerCertificate.Subject } else { "<none>" } | |
| Write-Host "$($_.Name): $($sig.Status) / $subject" | |
| if ($sig.Status -ne "Valid") { | |
| throw "Invalid signature on '$($_.FullName)': $($sig.Status)" | |
| } | |
| } | |
| } | |
| # Upload is unchanged for signed/unsigned mode. Artifact filenames remain stable. | |
| - name: Upload Packaging Artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: binxray-packages-${{ steps.version.outputs.app_version }} | |
| path: artifacts/release/* | |
| # Tag pushes publish to GitHub Releases. workflow_dispatch builds artifacts only unless the | |
| # run is manually attached/published through another process. | |
| - name: Publish GitHub Release Assets | |
| if: startsWith(github.ref, 'refs/tags/') | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| files: | | |
| artifacts/release/*.exe | |
| artifacts/release/*.msi |