diff --git a/.github/workflows/staged-release.yml b/.github/workflows/staged-release.yml index d78c2656..e5ffd1f5 100644 --- a/.github/workflows/staged-release.yml +++ b/.github/workflows/staged-release.yml @@ -7,6 +7,7 @@ on: env: CARGO_TERM_COLOR: always + TAURI_TARGET: aarch64-apple-darwin jobs: release: @@ -14,6 +15,7 @@ jobs: runs-on: macos-latest permissions: contents: write + id-token: write steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 @@ -27,8 +29,10 @@ jobs: key: staged-release-aarch64-apple-darwin - name: Validate tag matches staged versions + id: version run: | TAG_VERSION="${GITHUB_REF#refs/tags/staged/v}" + echo "value=${TAG_VERSION}" >> "${GITHUB_OUTPUT}" PACKAGE_VERSION="$(node -p "require('./apps/staged/package.json').version")" TAURI_VERSION="$(node -p "require('./apps/staged/src-tauri/tauri.conf.json').version")" CARGO_VERSION="$(grep '^version' apps/staged/src-tauri/Cargo.toml | head -1 | sed 's/version = "//;s/"//')" @@ -43,24 +47,16 @@ jobs: STAGED_UPDATER_PUBLIC_KEY: ${{ secrets.STAGED_UPDATER_PUBLIC_KEY }} TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} - APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} - APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} - APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} - APPLE_ID: ${{ secrets.APPLE_ID }} - APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} - APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + OSX_CODESIGN_ROLE: ${{ secrets.OSX_CODESIGN_ROLE }} + CODESIGN_S3_BUCKET: ${{ secrets.CODESIGN_S3_BUCKET }} run: | missing=() for name in \ STAGED_UPDATER_PUBLIC_KEY \ TAURI_SIGNING_PRIVATE_KEY \ TAURI_SIGNING_PRIVATE_KEY_PASSWORD \ - APPLE_CERTIFICATE \ - APPLE_CERTIFICATE_PASSWORD \ - APPLE_SIGNING_IDENTITY \ - APPLE_ID \ - APPLE_PASSWORD \ - APPLE_TEAM_ID; do + OSX_CODESIGN_ROLE \ + CODESIGN_S3_BUCKET; do if [ -z "${!name}" ]; then missing+=("$name") fi @@ -81,30 +77,64 @@ jobs: env: STAGED_UPDATER_PUBLIC_KEY: ${{ secrets.STAGED_UPDATER_PUBLIC_KEY }} STAGED_UPDATER_ENDPOINT: https://github.com/${{ github.repository }}/releases/download/staged-latest/latest.json - APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} run: pnpm run tauri:release:config - - name: Build and publish staged release - uses: tauri-apps/tauri-action@fce9c6108b31ea247710505d3aaaa893ee6768d4 # v0 + - name: Build unsigned Tauri app + working-directory: apps/staged env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} - TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} - APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} - APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} - APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} - APPLE_ID: ${{ secrets.APPLE_ID }} - APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} - APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} VITE_UPDATER_ENABLED: 'true' + run: pnpm tauri build --no-sign --target "$TAURI_TARGET" --config src-tauri/tauri.release.conf.json + + - name: Codesign and Notarize + id: codesign + uses: block/apple-codesign-action@v1.1.0 with: - projectPath: apps/staged - tagName: ${{ github.ref_name }} - releaseName: Staged ${{ github.ref_name }} - releaseBody: See the assets to download and install this version. - releaseDraft: false - prerelease: false - args: --target aarch64-apple-darwin --config src-tauri/tauri.release.conf.json + osx-codesign-role: ${{ secrets.OSX_CODESIGN_ROLE }} + codesign-s3-bucket: ${{ secrets.CODESIGN_S3_BUCKET }} + unsigned-artifact-path: apps/staged/src-tauri/target/aarch64-apple-darwin/release/bundle/dmg/Staged_${{ steps.version.outputs.value }}_aarch64.dmg + artifact-name: staged-${{ github.sha }}-${{ github.run_id }}-arm64 + + - name: Replace DMG and rebuild updater artifacts + working-directory: apps/staged + env: + SIGNED_DMG: ${{ steps.codesign.outputs.signed-dmg-path }} + SIGNED_APP_ZIP: ${{ steps.codesign.outputs.signed-artifact-path }} + TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} + TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} + run: | + set -euo pipefail + + BUNDLE_DIR="src-tauri/target/${TAURI_TARGET}/release/bundle" + VERSION="$(node -p "require('./src-tauri/tauri.conf.json').version")" + + # Replace DMG with signed version + cp "$SIGNED_DMG" "${BUNDLE_DIR}/dmg/Staged_${VERSION}_aarch64.dmg" + + # Extract signed .app and rebuild updater artifacts + extract_dir="${RUNNER_TEMP}/signed-app-extract" + mkdir -p "$extract_dir" + ditto -x -k "$SIGNED_APP_ZIP" "$extract_dir" + + app_dir="${BUNDLE_DIR}/macos" + rm -rf "${app_dir}/Staged.app" + cp -R "${extract_dir}/Staged.app" "${app_dir}/Staged.app" + + # Recreate updater archive and re-sign with Tauri updater key + rm -f "${app_dir}/Staged.app.tar.gz" "${app_dir}/Staged.app.tar.gz.sig" + (cd "$app_dir" && tar -czf Staged.app.tar.gz Staged.app) + pnpm tauri signer sign "${app_dir}/Staged.app.tar.gz" + + - name: Create GitHub Release + env: + GH_TOKEN: ${{ github.token }} + run: | + if gh release view "$GITHUB_REF_NAME" >/dev/null 2>&1; then + echo "Release $GITHUB_REF_NAME already exists; skipping creation." + else + gh release create "$GITHUB_REF_NAME" \ + --title "Staged $GITHUB_REF_NAME" \ + --notes "See the assets to download and install this version." + fi - name: Publish staged updater alias working-directory: apps/staged