diff --git a/.github/workflows/build-windows-installer.yml b/.github/workflows/build-windows-installer.yml new file mode 100644 index 000000000..3fc4f2b07 --- /dev/null +++ b/.github/workflows/build-windows-installer.yml @@ -0,0 +1,100 @@ +name: Build Windows Installer + +on: + workflow_dispatch: + +permissions: + contents: read + +jobs: + # Gate: workflow_dispatch is already restricted to users with write access, + # but we want ADMIN-only. Explicitly check the triggering actor's repo + # permission via the API and fail fast for anyone below admin. + authorize: + name: Authorize (admins only) + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Check actor is a repo admin + env: + GH_TOKEN: ${{ github.token }} + ACTOR: ${{ github.actor }} + run: | + set -euo pipefail + perm=$(gh api \ + "repos/${{ github.repository }}/collaborators/${ACTOR}/permission" \ + --jq '.permission') + echo "Actor '${ACTOR}' has permission: ${perm}" + if [ "${perm}" != "admin" ]; then + echo "::error::'${ACTOR}' is not a repo admin (permission=${perm}). Refusing to build/sign." + exit 1 + fi + echo "Authorized: '${ACTOR}' is an admin." + + build: + name: Hermes-Setup.exe + needs: authorize + runs-on: windows-latest + timeout-minutes: 30 + permissions: + contents: read + # Required for OIDC auth to Azure (azure/login federated credentials). + id-token: write + + steps: + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Setup Node.js + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version: 22 + cache: npm + + - name: Install npm dependencies + run: npm ci + + - name: Setup Rust + uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable + + - name: Cache Rust targets + uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 + with: + workspaces: apps/bootstrap-installer/src-tauri + + - name: Build installer + run: npm run tauri:build + working-directory: apps/bootstrap-installer + + - name: Azure login (OIDC) + uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - name: Sign Hermes-Setup.exe with Azure Artifact Signing + uses: azure/artifact-signing-action@c7ab2a863ab5f9a846ddb8265964877ef296ee82 # v2 + with: + endpoint: ${{ vars.AZURE_SIGNING_ENDPOINT }} + signing-account-name: ${{ vars.AZURE_SIGNING_ACCOUNT_NAME }} + certificate-profile-name: ${{ vars.AZURE_SIGNING_CERTIFICATE_PROFILE }} + # Sign both the raw exe and the bundled NSIS installer. + files-folder: ${{ github.workspace }}\apps\bootstrap-installer\src-tauri\target\release + files-folder-filter: exe + files-folder-recurse: true + file-digest: SHA256 + timestamp-rfc3161: http://timestamp.acs.microsoft.com + timestamp-digest: SHA256 + + - name: Upload NSIS installer + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: Hermes-Setup-installer + path: apps/bootstrap-installer/src-tauri/target/release/bundle/nsis/*.exe + + - name: Upload raw exe + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: Hermes-Setup-exe + path: apps/bootstrap-installer/src-tauri/target/release/Hermes-Setup.exe