SignPath test #5
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
| # SignPath OSS signing test — Windows binaries via SignPath. | |
| # | |
| # This workflow is the SignPath trial run: it signs the Windows binaries with | |
| # the OSS organization's self-signed TEST certificate. It does NOT touch the | |
| # Certum SimplySign release flow (release.yml) yet — once SignPath is proven | |
| # and the production certificate is imported, the release workflow will switch. | |
| # | |
| # Prerequisites (one-time, see code-signing/signpath/README.md): | |
| # * SignPath portal: project + signing policy + 'GitHub.com' trusted build | |
| # system + artifact configurations 'mercury-windows' and 'mercury-setup' | |
| # (XML in code-signing/signpath/artifact-configs/). | |
| # * Repo secret SIGNPATH_API_TOKEN (SignPath API token of a submitter user). | |
| # * Replace the d1c3b645-94b2-48ac-95fa-b72a652f3578, mercury and test-signing | |
| # placeholders below with the real portal values. | |
| name: SignPath test | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| build_installer: | |
| description: 'Also build + sign the Windows installer (Wine + Inno)' | |
| required: false | |
| default: false | |
| type: boolean | |
| jobs: | |
| # ---- Build unsigned Windows binaries (GitHub-hosted agent) ---- | |
| build: | |
| name: Build unsigned binaries | |
| runs-on: ubuntu-latest | |
| container: debian:trixie | |
| timeout-minutes: 20 | |
| outputs: | |
| artifact-id: ${{ steps.upload.outputs.artifact-id }} | |
| steps: | |
| - name: Install deps | |
| run: | | |
| apt-get update && apt-get install -y --no-install-recommends \ | |
| ca-certificates build-essential git golang-go \ | |
| gcc-mingw-w64-x86-64 mingw-w64-x86-64-dev mingw-w64-common zip | |
| - uses: actions/checkout@v4 | |
| with: { fetch-depth: 1 } | |
| - name: Git config | |
| run: git config --global --add safe.directory /__w/mercury/mercury | |
| - name: Build binaries | |
| run: | | |
| make windows | |
| make fyne-ui-windows | |
| mkdir -p dist | |
| cp mercury.exe dist/ | |
| cp windows-installer/mercury-ui.exe dist/ | |
| - name: Upload unsigned binaries | |
| id: upload | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: signpath-unsigned | |
| path: | | |
| dist/mercury.exe | |
| dist/mercury-ui.exe | |
| # ---- Submit to SignPath (test certificate) ---- | |
| sign: | |
| name: Sign via SignPath | |
| needs: build | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Submit signing request | |
| uses: signpath/github-action-submit-signing-request@v2 | |
| with: | |
| api-token: '${{ secrets.SIGNPATH_API_TOKEN }}' | |
| organization-id: 'd1c3b645-94b2-48ac-95fa-b72a652f3578' | |
| project-slug: 'mercury' | |
| signing-policy-slug: 'test-signing' | |
| artifact-configuration-slug: 'mercury-windows' | |
| github-artifact-id: '${{ needs.build.outputs.artifact-id }}' | |
| wait-for-completion: true | |
| output-artifact-directory: signed | |
| - name: Verify signatures | |
| run: | | |
| sudo apt-get update && sudo apt-get install -y --no-install-recommends osslsigncode | |
| for f in signed/mercury.exe signed/mercury-ui.exe; do | |
| [ -f "$f" ] || { echo "::error::missing signed file $f"; exit 1; } | |
| # Chain validation fails for the self-signed OSS test cert, but the | |
| # signature itself is cryptographically verified: osslsigncode | |
| # reports "Number of verified signatures: 1" for a valid one. | |
| OUT="$(osslsigncode verify "$f" 2>&1 || true)" | |
| printf '%s\n' "$OUT" | |
| if printf '%s\n' "$OUT" | grep -q "Number of verified signatures: 1"; then | |
| echo "OK: valid Authenticode signature present in $f" | |
| else | |
| echo "::error::no valid signature found in $f" | |
| exit 1 | |
| fi | |
| if printf '%s\n' "$OUT" | grep -q "self-signed certificate"; then | |
| echo "::warning::self-signed test certificate (expected until production cert)" | |
| fi | |
| done | |
| - name: Upload signed binaries | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: signpath-signed | |
| path: | | |
| signed/mercury.exe | |
| signed/mercury-ui.exe | |
| # ---- Installer: build with SIGNED payloads, then sign the Setup.exe ---- | |
| installer: | |
| name: Build installer from signed payloads | |
| if: ${{ inputs.build_installer }} | |
| needs: sign | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| outputs: | |
| artifact-id: ${{ steps.upload-setup.outputs.artifact-id }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: { fetch-depth: 1 } | |
| - name: Download signed binaries | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: signpath-signed | |
| - name: Install Inno Setup (Wine) | |
| env: | |
| INNO_URL: https://wiki.hermes.radio/reports/inno-setup-6.7.3-wine.tar.gz | |
| INNO_SHA256: 4c9c92249663f201a33bf194c0cd37e01c60540e299c771f3626411ef463c884 | |
| run: | | |
| set -eu | |
| # ISCC.exe is 32-bit; wine on the runner ships without i386, so | |
| # enable multiarch and pull wine32 to get syswow64 working. | |
| sudo dpkg --add-architecture i386 | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends wine wine32:i386 ca-certificates curl zip | |
| curl -fsSLo /tmp/inno.tar.gz "$INNO_URL" | |
| echo "${INNO_SHA256} /tmp/inno.tar.gz" | sha256sum -c - | |
| wineboot -i | |
| PF="$HOME/.wine/drive_c/Program Files (x86)" | |
| mkdir -p "$PF" | |
| tar xzf /tmp/inno.tar.gz -C "$PF/" | |
| ISCC_PATH="$PF/Inno Setup 6/ISCC.exe" | |
| [ -f "$ISCC_PATH" ] || { echo "::error::Inno Setup tree missing ISCC.exe"; exit 1; } | |
| echo "ISCC_PATH=$ISCC_PATH" >> "$GITHUB_ENV" | |
| - name: Stage signed payloads and build installer | |
| run: | | |
| set -eu | |
| # Payloads here are the SIGNED binaries from the previous job; | |
| # windows-installer-stage only copies, it does not rebuild. | |
| # upload-artifact v4 strips the common base dir, so the signed | |
| # payloads arrive either at the root or under signed/; handle both. | |
| if [ -f mercury.exe ]; then SRC=.; else SRC=signed; fi | |
| cp "$SRC/mercury.exe" windows-installer/ | |
| cp "$SRC/mercury-ui.exe" windows-installer/ | |
| cp mercury.ini.example windows-installer/mercury.ini | |
| sed -i 's/ui_enabled = false/ui_enabled = true/g' windows-installer/mercury.ini | |
| sed -i 's/sound_system = auto/sound_system = wasapi/g' windows-installer/mercury.ini | |
| wine "$ISCC_PATH" windows-installer/installer.iss | |
| SETUP=$(ls Mercury_*_Setup.exe | head -1) | |
| [ -n "$SETUP" ] || { echo "::error::ISCC produced no installer"; exit 1; } | |
| cp "$SETUP" mercury-setup.exe | |
| - name: Upload unsigned installer | |
| id: upload-setup | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: signpath-setup-unsigned | |
| path: mercury-setup.exe | |
| # ---- Sign the installer via SignPath ---- | |
| sign-setup: | |
| name: Sign installer via SignPath | |
| if: ${{ inputs.build_installer }} | |
| needs: installer | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Submit signing request (installer) | |
| uses: signpath/github-action-submit-signing-request@v2 | |
| with: | |
| api-token: '${{ secrets.SIGNPATH_API_TOKEN }}' | |
| organization-id: 'd1c3b645-94b2-48ac-95fa-b72a652f3578' | |
| project-slug: 'mercury' | |
| signing-policy-slug: 'test-signing' | |
| artifact-configuration-slug: 'mercury-setup' | |
| github-artifact-id: '${{ needs.installer.outputs.artifact-id }}' | |
| wait-for-completion: true | |
| output-artifact-directory: signed-setup | |
| - name: Verify installer signature | |
| run: | | |
| sudo apt-get update && sudo apt-get install -y --no-install-recommends osslsigncode | |
| f=signed-setup/mercury-setup.exe | |
| [ -f "$f" ] || { echo "::error::missing signed installer"; exit 1; } | |
| OUT="$(osslsigncode verify "$f" 2>&1 || true)" | |
| printf '%s\n' "$OUT" | |
| if printf '%s\n' "$OUT" | grep -q "Number of verified signatures: 1"; then | |
| echo "OK: valid Authenticode signature present in installer" | |
| else | |
| echo "::error::no valid signature found in installer" | |
| exit 1 | |
| fi | |
| if printf '%s\n' "$OUT" | grep -q "self-signed certificate"; then | |
| echo "::warning::self-signed test certificate (expected until production cert)" | |
| fi | |
| - name: Upload signed installer | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: signpath-setup-signed | |
| path: signed-setup/mercury-setup.exe |