Patch macOS Release #1
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: Patch macOS Release | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: "Release version to rebuild and replace (for example 0.0.1 or v0.0.1)" | |
| required: true | |
| type: string | |
| ref: | |
| description: "Git ref to rebuild from (defaults to the release tag)" | |
| required: false | |
| default: "" | |
| type: string | |
| permissions: | |
| contents: write | |
| id-token: write | |
| jobs: | |
| resolve_release: | |
| name: Resolve Release Version | |
| runs-on: ubuntu-24.04 | |
| outputs: | |
| version: ${{ steps.release_meta.outputs.version }} | |
| tag: ${{ steps.release_meta.outputs.tag }} | |
| checkout_ref: ${{ steps.release_meta.outputs.checkout_ref }} | |
| steps: | |
| - id: release_meta | |
| name: Resolve release version | |
| shell: bash | |
| run: | | |
| raw="${{ github.event.inputs.version }}" | |
| checkout_ref="${{ github.event.inputs.ref }}" | |
| version="${raw#v}" | |
| if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+([.-][0-9A-Za-z.-]+)?$ ]]; then | |
| echo "Invalid release version: $raw" >&2 | |
| exit 1 | |
| fi | |
| echo "version=$version" >> "$GITHUB_OUTPUT" | |
| echo "tag=v$version" >> "$GITHUB_OUTPUT" | |
| if [[ -z "$checkout_ref" ]]; then | |
| checkout_ref="refs/tags/v$version" | |
| fi | |
| echo "checkout_ref=$checkout_ref" >> "$GITHUB_OUTPUT" | |
| build_macos_arm64: | |
| name: Build macOS arm64 Assets | |
| needs: resolve_release | |
| runs-on: macos-14 | |
| timeout-minutes: 45 | |
| steps: | |
| - name: Checkout release source | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ needs.resolve_release.outputs.checkout_ref }} | |
| fetch-depth: 0 | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version-file: package.json | |
| - name: Setup Node | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version-file: package.json | |
| - name: Cache Bun and Turbo | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.bun/install/cache | |
| .turbo | |
| key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }}-${{ hashFiles('turbo.json', 'apps/*/turbo.jsonc') }} | |
| restore-keys: | | |
| ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }}- | |
| - name: Cache Electron builder artifacts | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cache/electron | |
| ~/.cache/electron-builder | |
| key: ${{ runner.os }}-electron-builder-${{ hashFiles('bun.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-electron-builder- | |
| - name: Install dependencies | |
| run: bun install --frozen-lockfile | |
| - name: Align package versions to release version | |
| run: node scripts/update-release-package-versions.ts "${{ needs.resolve_release.outputs.version }}" | |
| - name: Build macOS arm64 artifacts | |
| shell: bash | |
| env: | |
| CSC_LINK: ${{ secrets.CSC_LINK }} | |
| CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} | |
| APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }} | |
| APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }} | |
| APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }} | |
| run: | | |
| has_all() { | |
| for value in "$@"; do | |
| if [[ -z "$value" ]]; then | |
| return 1 | |
| fi | |
| done | |
| return 0 | |
| } | |
| args=( | |
| --platform mac | |
| --target dmg | |
| --arch arm64 | |
| --build-version "${{ needs.resolve_release.outputs.version }}" | |
| --verbose | |
| ) | |
| if has_all "$CSC_LINK" "$CSC_KEY_PASSWORD" "$APPLE_API_KEY" "$APPLE_API_KEY_ID" "$APPLE_API_ISSUER"; then | |
| key_path="$RUNNER_TEMP/AuthKey_${APPLE_API_KEY_ID}.p8" | |
| printf '%s' "$APPLE_API_KEY" > "$key_path" | |
| export APPLE_API_KEY="$key_path" | |
| args+=(--signed) | |
| fi | |
| bun run dist:desktop:artifact -- "${args[@]}" | |
| bun run dist:desktop:artifact -- "${args[@]/dmg/zip}" | |
| - name: Collect patched macOS arm64 assets | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| mkdir -p release-publish | |
| shopt -s nullglob | |
| for pattern in \ | |
| "release/*arm64.dmg" \ | |
| "release/*arm64.zip" \ | |
| "release/*arm64*.blockmap" \ | |
| "release/latest-mac.yml"; do | |
| for file in $pattern; do | |
| cp "$file" release-publish/ | |
| done | |
| done | |
| shopt -u nullglob | |
| ls -la release-publish | |
| - name: Upload macOS arm64 assets | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: patch-macos-arm64 | |
| path: release-publish/* | |
| if-no-files-found: error | |
| build_macos_x64: | |
| name: Build macOS x64 Assets | |
| needs: resolve_release | |
| runs-on: macos-15-intel | |
| timeout-minutes: 45 | |
| steps: | |
| - name: Checkout release source | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ needs.resolve_release.outputs.checkout_ref }} | |
| fetch-depth: 0 | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version-file: package.json | |
| - name: Setup Node | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version-file: package.json | |
| - name: Cache Bun and Turbo | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.bun/install/cache | |
| .turbo | |
| key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }}-${{ hashFiles('turbo.json', 'apps/*/turbo.jsonc') }} | |
| restore-keys: | | |
| ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }}- | |
| - name: Cache Electron builder artifacts | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cache/electron | |
| ~/.cache/electron-builder | |
| key: ${{ runner.os }}-electron-builder-${{ hashFiles('bun.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-electron-builder- | |
| - name: Install dependencies | |
| run: bun install --frozen-lockfile | |
| - name: Align package versions to release version | |
| run: node scripts/update-release-package-versions.ts "${{ needs.resolve_release.outputs.version }}" | |
| - name: Build macOS x64 artifacts | |
| shell: bash | |
| env: | |
| CSC_LINK: ${{ secrets.CSC_LINK }} | |
| CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} | |
| APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }} | |
| APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }} | |
| APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }} | |
| run: | | |
| has_all() { | |
| for value in "$@"; do | |
| if [[ -z "$value" ]]; then | |
| return 1 | |
| fi | |
| done | |
| return 0 | |
| } | |
| args=( | |
| --platform mac | |
| --target dmg | |
| --arch x64 | |
| --build-version "${{ needs.resolve_release.outputs.version }}" | |
| --verbose | |
| ) | |
| if has_all "$CSC_LINK" "$CSC_KEY_PASSWORD" "$APPLE_API_KEY" "$APPLE_API_KEY_ID" "$APPLE_API_ISSUER"; then | |
| key_path="$RUNNER_TEMP/AuthKey_${APPLE_API_KEY_ID}.p8" | |
| printf '%s' "$APPLE_API_KEY" > "$key_path" | |
| export APPLE_API_KEY="$key_path" | |
| args+=(--signed) | |
| fi | |
| bun run dist:desktop:artifact -- "${args[@]}" | |
| bun run dist:desktop:artifact -- "${args[@]/dmg/zip}" | |
| - name: Collect patched macOS x64 assets | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| mkdir -p release-publish | |
| shopt -s nullglob | |
| for pattern in \ | |
| "release/*x64.dmg" \ | |
| "release/*x64.zip" \ | |
| "release/*x64*.blockmap" \ | |
| "release/latest-mac.yml"; do | |
| for file in $pattern; do | |
| cp "$file" release-publish/ | |
| done | |
| done | |
| if [[ -f release-publish/latest-mac.yml ]]; then | |
| mv release-publish/latest-mac.yml release-publish/latest-mac-x64.yml | |
| fi | |
| shopt -u nullglob | |
| ls -la release-publish | |
| - name: Upload macOS x64 assets | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: patch-macos-x64 | |
| path: release-publish/* | |
| if-no-files-found: error | |
| publish_macos_release: | |
| name: Upload Patched macOS Assets | |
| needs: [resolve_release, build_macos_arm64, build_macos_x64] | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Checkout release source | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ needs.resolve_release.outputs.checkout_ref }} | |
| fetch-depth: 0 | |
| - name: Setup Node | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version-file: package.json | |
| - name: Download patched macOS assets | |
| uses: actions/download-artifact@v5 | |
| with: | |
| pattern: patch-macos-* | |
| path: release-assets | |
| merge-multiple: true | |
| - name: Merge macOS update manifests | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| if [[ -f release-assets/latest-mac.yml && -f release-assets/latest-mac-x64.yml ]]; then | |
| node scripts/merge-mac-update-manifests.ts \ | |
| release-assets/latest-mac.yml \ | |
| release-assets/latest-mac-x64.yml | |
| fi | |
| - name: Upload patched macOS assets to existing release | |
| shell: bash | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| gh release upload "${{ needs.resolve_release.outputs.tag }}" release-assets/* --clobber |