Repository navigation
v2.11.1 — Two distinct cart glyphs so "add to your To-order list" (ca… #133
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: Build & Release | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| permissions: | |
| contents: write | |
| jobs: | |
| # ───────────────────────────────────────────────────────────────── | |
| # Runs FIRST — creates the draft release for this tag and fills its | |
| # body with the CHANGELOG.md section, BEFORE any platform build runs. | |
| # The three build jobs then just attach their assets to this already- | |
| # described draft, so none of them races to write (or accidentally | |
| # blank) the release body. | |
| # ───────────────────────────────────────────────────────────────── | |
| prepare-release: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Build release notes from CHANGELOG.md | |
| run: node scripts/extract-changelog.mjs "${{ github.ref_name }}" > release-notes.md | |
| # Release NAME is the version without the leading "v" (e.g. tag v2.0.0 → "2.0.0"), | |
| # matching the historical naming. softprops defaults the name to the tag otherwise. | |
| - name: Release version (strip leading v) | |
| id: ver | |
| run: echo "num=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" | |
| - name: Create draft release with description | |
| uses: softprops/action-gh-release@v3 | |
| with: | |
| tag_name: ${{ github.ref_name }} | |
| name: ${{ steps.ver.outputs.num }} | |
| draft: true | |
| body_path: release-notes.md | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| build: | |
| needs: prepare-release | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: macos-latest | |
| platform: mac | |
| - os: windows-latest | |
| platform: win | |
| - os: ubuntu-latest | |
| platform: linux | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-node@v5 | |
| with: | |
| node-version: 24 | |
| - name: Install Linux system dependencies | |
| if: matrix.os == 'ubuntu-latest' | |
| run: | | |
| sudo apt-get update -y | |
| sudo apt-get install -y \ | |
| libpcsclite-dev \ | |
| libusb-1.0-0-dev \ | |
| libudev-dev \ | |
| build-essential \ | |
| python3 \ | |
| rpm \ | |
| fakeroot | |
| - run: npm ci | |
| # --- macOS only: decode the App Store Connect API Key (.p8) into a file so notarytool can read it --- | |
| - name: Decode App Store Connect API Key (.p8) | |
| if: matrix.os == 'macos-latest' | |
| env: | |
| APPLE_API_KEY_BASE64: ${{ secrets.APPLE_API_KEY_BASE64 }} | |
| APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }} | |
| run: | | |
| mkdir -p ~/private_keys | |
| echo -n "$APPLE_API_KEY_BASE64" | base64 --decode > ~/private_keys/AuthKey_${APPLE_API_KEY_ID}.p8 | |
| chmod 600 ~/private_keys/AuthKey_${APPLE_API_KEY_ID}.p8 | |
| # Export the resolved path for the next step | |
| echo "APPLE_API_KEY=$HOME/private_keys/AuthKey_${APPLE_API_KEY_ID}.p8" >> "$GITHUB_ENV" | |
| # ───────────────────────────────────────────────────────────────── | |
| # macOS / Linux — build & publish in one step (no post-build signing). | |
| # Windows is handled in the next 4 steps so we can SIGN the .exe with | |
| # Microsoft Trusted Signing (Azure) BEFORE publishing it to the Release. | |
| # ───────────────────────────────────────────────────────────────── | |
| - name: Build & publish (macOS / Linux) | |
| if: matrix.os != 'windows-latest' | |
| run: npm run build:${{ matrix.platform }} | |
| env: | |
| # GitHub Releases publish (electron-builder reads GH_TOKEN automatically) | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| # macOS code signing — electron-builder reads CSC_LINK (base64 .p12) + CSC_KEY_PASSWORD | |
| CSC_LINK: ${{ secrets.MACOS_CERTIFICATE }} | |
| CSC_KEY_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }} | |
| # macOS notarization via App Store Connect API Key (preferred over Apple ID + password) | |
| # APPLE_API_KEY is set in the previous step via GITHUB_ENV (path to decoded .p8) | |
| APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }} | |
| APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }} | |
| APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | |
| # Google Desktop OAuth — Touch ID / loopback sign-in | |
| TIGERTAG_GOOGLE_DESKTOP_CLIENT_ID: ${{ secrets.TIGERTAG_GOOGLE_DESKTOP_CLIENT_ID }} | |
| TIGERTAG_GOOGLE_DESKTOP_CLIENT_SECRET: ${{ secrets.TIGERTAG_GOOGLE_DESKTOP_CLIENT_SECRET }} | |
| # ───────────────────────────────────────────────────────────────── | |
| # Windows path — split into: | |
| # 1. Build .exe locally with --publish never (so we can sign first) | |
| # 2. Check whether Trusted Signing secrets are configured in repo | |
| # 3. Sign .exe artifacts via Microsoft Trusted Signing (skipped | |
| # gracefully when secrets are absent → unsigned build still ships) | |
| # 4. Upload .exe (+ .blockmap + latest.yml) to the GitHub Release | |
| # ───────────────────────────────────────────────────────────────── | |
| - name: Build Windows (no publish — sign first, publish after) | |
| if: matrix.os == 'windows-latest' | |
| run: npm run build:win:nopublish | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| # Google Desktop OAuth — Touch ID / loopback sign-in | |
| TIGERTAG_GOOGLE_DESKTOP_CLIENT_ID: ${{ secrets.TIGERTAG_GOOGLE_DESKTOP_CLIENT_ID }} | |
| TIGERTAG_GOOGLE_DESKTOP_CLIENT_SECRET: ${{ secrets.TIGERTAG_GOOGLE_DESKTOP_CLIENT_SECRET }} | |
| - name: Check Trusted Signing secrets availability | |
| id: check_signing | |
| if: matrix.os == 'windows-latest' | |
| shell: bash | |
| env: | |
| AZ_TENANT: ${{ secrets.AZURE_TENANT_ID }} | |
| AZ_CLIENT: ${{ secrets.AZURE_CLIENT_ID }} | |
| AZ_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} | |
| CERT_PROFILE: ${{ vars.TRUSTED_SIGNING_CERT_PROFILE }} | |
| run: | | |
| if [ -n "$AZ_TENANT" ] && [ -n "$AZ_CLIENT" ] && [ -n "$AZ_SECRET" ] && [ -n "$CERT_PROFILE" ]; then | |
| echo "ready=true" >> "$GITHUB_OUTPUT" | |
| echo "✓ Trusted Signing secrets present — Windows artifacts will be signed under cert profile '$CERT_PROFILE'." | |
| else | |
| echo "ready=false" >> "$GITHUB_OUTPUT" | |
| echo "⚠ Trusted Signing secrets / cert profile missing — Windows artifacts will be UNSIGNED for this run." | |
| echo " Configure secrets AZURE_TENANT_ID / AZURE_CLIENT_ID / AZURE_CLIENT_SECRET and repo variable TRUSTED_SIGNING_CERT_PROFILE to enable signing." | |
| fi | |
| - name: Sign Windows artifacts (Microsoft Trusted Signing) | |
| if: matrix.os == 'windows-latest' && steps.check_signing.outputs.ready == 'true' | |
| uses: azure/trusted-signing-action@v0.5.1 | |
| with: | |
| azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }} | |
| azure-client-id: ${{ secrets.AZURE_CLIENT_ID }} | |
| azure-client-secret: ${{ secrets.AZURE_CLIENT_SECRET }} | |
| endpoint: https://neu.codesigning.azure.net/ | |
| trusted-signing-account-name: TigerTagStudioSigning | |
| certificate-profile-name: ${{ vars.TRUSTED_SIGNING_CERT_PROFILE }} | |
| files-folder: dist | |
| files-folder-filter: exe | |
| files-folder-recurse: false | |
| file-digest: SHA256 | |
| timestamp-rfc3161: http://timestamp.acs.microsoft.com | |
| timestamp-digest: SHA256 | |
| # Signing changes the .exe (the authenticode signature is embedded into | |
| # the PE binary), which invalidates the SHA-512 + size that | |
| # electron-builder wrote into dist/latest.yml. Without this regen step, | |
| # auto-updater clients would download the new signed .exe, hash-check it | |
| # against the stale latest.yml, mismatch, and refuse the update. | |
| - name: Regenerate dist/latest.yml after signing | |
| if: matrix.os == 'windows-latest' && steps.check_signing.outputs.ready == 'true' | |
| run: node scripts/regen-latest-yml.mjs | |
| - name: Release version (strip leading v) | |
| if: matrix.os == 'windows-latest' | |
| id: verwin | |
| shell: bash # windows runner defaults to PowerShell; force bash for ${VAR#v} | |
| run: echo "num=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" | |
| - name: Publish Windows artifacts to GitHub Release | |
| if: matrix.os == 'windows-latest' | |
| # v3.0.0 (2026-04-12) moved the action runtime from Node 20 to | |
| # Node 24, silencing the GitHub Actions deprecation warning that | |
| # v2.6.2 emits. Same inputs/outputs, no breaking API changes. | |
| # | |
| # `draft: true` matches the `releaseType: "draft"` set in | |
| # package.json so electron-builder (mac/linux) and softprops | |
| # (windows) agree on the same release type. With a mismatch, | |
| # the second tool to fire either skips its uploads or creates | |
| # a duplicate release. The release stays in draft until manually | |
| # promoted via the GitHub UI — that's how we want it: lets us | |
| # verify all artifacts are present + spot a broken build | |
| # before the auto-updater picks the new version. | |
| uses: softprops/action-gh-release@v3 | |
| with: | |
| tag_name: ${{ github.ref_name }} | |
| name: ${{ steps.verwin.outputs.num }} | |
| draft: true | |
| files: | | |
| dist/*.exe | |
| dist/*.exe.blockmap | |
| dist/latest.yml | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |