Files
Zack SheppardandClaude Opus 5.5 4a300ed5fa Let electron-builder find the signing identity in signed Mac builds (#5)
CSC_IDENTITY_AUTO_DISCOVERY=false was set for every Mac build. With it,
electron-builder imports CSC_LINK into its keychain but won't look the
identity up, so the v0.0.3 build skipped signing and failed the signature
check. It's now set only for unsigned builds.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 23:01:44 +01:00

186 lines
6.9 KiB
YAML

name: Build
# Every push to main and every pull request: check the code, then build installers for each
# platform and attach them to the run as artifacts. The release workflow calls
# this same file with a version to stamp into the app.
on:
# Pushes to main, plus pull requests. Branch pushes aren't built separately, so a
# pull request's commits run once (as pull_request), not twice.
push:
branches: [main]
pull_request:
workflow_call:
inputs:
version:
description: Version to stamp into the app (e.g. 1.2.3). Empty keeps package.json's.
type: string
default: ""
ref:
description: Commit to build.
type: string
default: ""
sign_mac:
description: Sign and notarize the macOS build (needs the release-signing environment).
type: boolean
default: false
concurrency:
group: build-${{ github.workflow }}-${{ inputs.ref || github.ref }}
cancel-in-progress: ${{ github.event_name != 'workflow_call' && !inputs.version }}
permissions:
contents: read
jobs:
check:
name: Typecheck, test, build site
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.ref || github.sha }}
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm typecheck
- run: pnpm test
- run: pnpm build:web
- uses: actions/upload-artifact@v4
with:
name: website
path: apps/web/dist
if-no-files-found: error
package:
name: Package (${{ matrix.name }})
needs: check
strategy:
fail-fast: false
matrix:
include:
- name: Windows
os: windows-latest
args: --win --x64
- name: Linux x64
os: ubuntu-latest
args: --linux --x64
- name: Linux arm64
os: ubuntu-24.04-arm
args: --linux --arm64
system_fpm: true
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.ref || github.sha }}
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Stamp version
if: inputs.version != ''
run: node scripts/version.mjs set "${{ inputs.version }}"
- name: Install fpm (arm64 Linux has no prebuilt one)
if: matrix.system_fpm
run: |
sudo apt-get update
sudo apt-get install -y ruby ruby-dev build-essential rpm
sudo gem install --no-document fpm
- name: Build installers
working-directory: apps/desktop
shell: bash
env:
USE_SYSTEM_FPM: ${{ matrix.system_fpm && 'true' || '' }}
# Builds are unsigned for now; don't go looking for certificates.
CSC_IDENTITY_AUTO_DISCOVERY: "false"
run: |
pnpm build
pnpm exec electron-builder --config electron-builder.config.cjs ${{ matrix.args }} --publish never
- uses: actions/upload-artifact@v4
with:
name: frameloader-${{ matrix.os }}
path: |
apps/desktop/release/*.dmg
apps/desktop/release/*.zip
apps/desktop/release/*.exe
apps/desktop/release/*.AppImage
apps/desktop/release/*.deb
if-no-files-found: error
# macOS is its own job so release builds can run inside the protected
# release-signing environment (approval required, v* tags only), which holds
# the Developer ID certificate and the notarization key. Pushes and pull
# requests never touch it and produce ad-hoc signed builds.
package-mac:
name: Package (macOS${{ inputs.sign_mac && ', signed' || '' }})
needs: check
runs-on: macos-latest
environment: ${{ inputs.sign_mac && 'release-signing' || '' }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.ref || github.sha }}
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Stamp version
if: inputs.version != ''
run: node scripts/version.mjs set "${{ inputs.version }}"
# Signing secrets live only in this step's environment, never in GITHUB_ENV, so no
# later step or action (artifact upload, post steps) can read them. They're exported
# only for signed builds: electron-builder treats an empty CSC_LINK as a file path.
- name: Build installers
working-directory: apps/desktop
env:
SIGN_MAC: ${{ inputs.sign_mac }}
SIGN_CSC_LINK: ${{ secrets.CSC_LINK }}
SIGN_CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
SIGN_APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }}
SIGN_APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
SIGN_APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
run: |
if [ "$SIGN_MAC" = "true" ]; then
for name in SIGN_CSC_LINK SIGN_CSC_KEY_PASSWORD SIGN_APPLE_API_KEY SIGN_APPLE_API_KEY_ID SIGN_APPLE_API_ISSUER; do
if [ -z "${!name}" ]; then
echo "::error::release-signing secret ${name#SIGN_} is missing. See README → Signing."
exit 1
fi
done
key_file="$RUNNER_TEMP/notary.p8"
printf '%s' "$SIGN_APPLE_API_KEY" > "$key_file"
trap 'rm -f "$key_file"' EXIT
export CSC_LINK="$SIGN_CSC_LINK" CSC_KEY_PASSWORD="$SIGN_CSC_KEY_PASSWORD"
export APPLE_API_KEY="$key_file" APPLE_API_KEY_ID="$SIGN_APPLE_API_KEY_ID" APPLE_API_ISSUER="$SIGN_APPLE_API_ISSUER"
else
# Unsigned (ad-hoc) build: don't let electron-builder look for a certificate.
# Not set for signed builds: with it, electron-builder imports CSC_LINK but then
# won't look the identity up, and silently skips signing.
export CSC_IDENTITY_AUTO_DISCOVERY=false
fi
unset SIGN_CSC_LINK SIGN_CSC_KEY_PASSWORD SIGN_APPLE_API_KEY SIGN_APPLE_API_KEY_ID SIGN_APPLE_API_ISSUER
pnpm build
pnpm exec electron-builder --config electron-builder.config.cjs --mac --arm64 --x64 --publish never
- name: Check signature
if: inputs.sign_mac
working-directory: apps/desktop
run: |
app="release/mac-arm64/Frameloader.app"
codesign --verify --deep --strict --verbose=2 "$app"
spctl --assess --type execute --verbose=2 "$app"
xcrun stapler validate "$app"
- uses: actions/upload-artifact@v4
with:
name: frameloader-macos
path: |
apps/desktop/release/*.dmg
apps/desktop/release/*.zip
if-no-files-found: error