Skip to content

release-rc

release-rc #7

Workflow file for this run

name: release-rc
on:
workflow_dispatch:
inputs:
channel:
description: "Release channel"
required: true
default: "internal-rc"
type: choice
options:
- internal-rc
- qa
require_signed:
description: "Fail the workflow if signing secrets are missing"
required: true
default: false
type: boolean
jobs:
build-rc-macos:
runs-on: macos-latest
permissions:
contents: read
env:
RUN_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
with:
node-version: 20
cache: npm
- uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
- run: npm ci
- run: npm run build
- name: Detect signing readiness
id: signing
shell: bash
env:
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 }}
run: |
set -euo pipefail
if [[ -n "${APPLE_CERTIFICATE}" && -n "${APPLE_CERTIFICATE_PASSWORD}" && -n "${APPLE_SIGNING_IDENTITY}" && -n "${APPLE_ID}" && -n "${APPLE_PASSWORD}" && -n "${APPLE_TEAM_ID}" ]]; then
echo "mode=signed" >> "$GITHUB_OUTPUT"
else
echo "mode=unsigned" >> "$GITHUB_OUTPUT"
fi
- name: Enforce signed mode when required
if: ${{ inputs.require_signed && steps.signing.outputs.mode != 'signed' }}
run: |
echo "Signed mode required, but one or more APPLE_* secrets are missing."
exit 1
- name: Install signing certificate
if: ${{ steps.signing.outputs.mode == 'signed' }}
shell: bash
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
run: |
set -euo pipefail
KEYCHAIN_PASSWORD="$(openssl rand -base64 24)"
KEYCHAIN_PATH="$RUNNER_TEMP/auraforge-build.keychain-db"
CERT_PATH="$RUNNER_TEMP/apple-signing-cert.p12"
echo "$APPLE_CERTIFICATE" | base64 --decode > "$CERT_PATH"
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security default-keychain -s "$KEYCHAIN_PATH"
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
security import "$CERT_PATH" -k "$KEYCHAIN_PATH" -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign -T /usr/bin/security
security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security find-identity -v -p codesigning "$KEYCHAIN_PATH"
- name: Detect hardened runtime setting
id: hardening
shell: bash
run: |
set -euo pipefail
node -e "const fs=require('fs'); const cfg=JSON.parse(fs.readFileSync('src-tauri/tauri.conf.json','utf8')); const enabled = cfg && cfg.bundle && cfg.bundle.macOS && cfg.bundle.macOS.hardenedRuntime === true; process.stdout.write('status=' + (enabled ? 'enabled' : 'disabled') + '\n');" >> "$GITHUB_OUTPUT"
- name: Build RC artifact (signed)
if: ${{ steps.signing.outputs.mode == 'signed' }}
env:
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 }}
run: npm run tauri -- build
- name: Build RC artifact (unsigned)
if: ${{ steps.signing.outputs.mode != 'signed' }}
shell: bash
run: |
set -euo pipefail
unset APPLE_CERTIFICATE APPLE_CERTIFICATE_PASSWORD APPLE_SIGNING_IDENTITY APPLE_ID APPLE_PASSWORD APPLE_TEAM_ID
npm run tauri -- build
- name: Verify macOS artifact integrity
id: verify_artifact
shell: bash
env:
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
run: |
set -euo pipefail
bash scripts/release/verify-macos-artifact.sh "src-tauri/target/release/bundle" "${{ steps.signing.outputs.mode }}"
- name: Upload RC bundle artifacts
uses: actions/upload-artifact@v4
with:
name: auraforge-${{ github.run_number }}-${{ steps.signing.outputs.mode }}-${{ inputs.channel }}
path: |
src-tauri/target/release/bundle/**
- name: Release summary
run: |
{
echo "## AuraForge RC Build"
echo ""
echo "- Channel: \`${{ inputs.channel }}\`"
echo "- Signing mode: \`${{ steps.signing.outputs.mode }}\`"
echo "- Require signed: \`${{ inputs.require_signed }}\`"
echo "- Hardened runtime: \`${{ steps.hardening.outputs.status }}\`"
echo "- Run URL: \`${RUN_URL}\`"
echo "- Artifact path: \`src-tauri/target/release/bundle/\`"
echo "- Artifact app: \`${{ steps.verify_artifact.outputs.artifact_app_path }}\`"
echo "- Artifact dmg: \`${{ steps.verify_artifact.outputs.artifact_dmg_path }}\`"
echo "- App SHA256: \`${{ steps.verify_artifact.outputs.artifact_app_sha256 }}\`"
echo "- DMG SHA256: \`${{ steps.verify_artifact.outputs.artifact_dmg_sha256 }}\`"
echo "- Signing identity: \`${{ steps.verify_artifact.outputs.signing_identity }}\`"
echo "- Codesign status: \`${{ steps.verify_artifact.outputs.codesign_status }}\`"
echo "- Gatekeeper status: \`${{ steps.verify_artifact.outputs.gatekeeper_status }}\`"
echo "- Notarization status: \`${{ steps.verify_artifact.outputs.notarization_status }}\`"
echo "- Stapler status: \`${{ steps.verify_artifact.outputs.stapler_status }}\`"
} >> "$GITHUB_STEP_SUMMARY"