diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fa7df19..87bff91 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -126,6 +126,55 @@ jobs: - name: Install dependencies run: bun install --frozen-lockfile + - name: Prepare Apple signing assets + if: runner.os == 'macOS' + shell: bash + env: + APPLE_CERT_P12_BASE64: ${{ secrets.APPLE_CERT_P12_BASE64 }} + APPLE_CERT_PASSWORD: ${{ secrets.APPLE_CERT_PASSWORD }} + APPLE_API_KEY_P8: ${{ secrets.APPLE_API_KEY_P8 }} + APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }} + APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + run: | + if [[ -z "$APPLE_CERT_P12_BASE64" ]]; then + echo "Missing required secret: APPLE_CERT_P12_BASE64" >&2 + exit 1 + fi + if [[ -z "$APPLE_CERT_PASSWORD" ]]; then + echo "Missing required secret: APPLE_CERT_PASSWORD" >&2 + exit 1 + fi + if [[ -z "$APPLE_API_KEY_P8" ]]; then + echo "Missing required secret: APPLE_API_KEY_P8" >&2 + exit 1 + fi + if [[ -z "$APPLE_API_KEY_ID" ]]; then + echo "Missing required secret: APPLE_API_KEY_ID" >&2 + exit 1 + fi + if [[ -z "$APPLE_API_ISSUER" ]]; then + echo "Missing required secret: APPLE_API_ISSUER" >&2 + exit 1 + fi + if [[ -z "$APPLE_TEAM_ID" ]]; then + echo "Missing required secret: APPLE_TEAM_ID" >&2 + exit 1 + fi + + CERT_PATH="$RUNNER_TEMP/apple-signing.p12" + API_KEY_PATH="$RUNNER_TEMP/AuthKey_${APPLE_API_KEY_ID}.p8" + + echo "$APPLE_CERT_P12_BASE64" | base64 --decode > "$CERT_PATH" + printf '%s' "$APPLE_API_KEY_P8" > "$API_KEY_PATH" + + echo "CSC_LINK=$CERT_PATH" >> "$GITHUB_ENV" + echo "CSC_KEY_PASSWORD=$APPLE_CERT_PASSWORD" >> "$GITHUB_ENV" + echo "APPLE_API_KEY=$API_KEY_PATH" >> "$GITHUB_ENV" + echo "APPLE_API_KEY_ID=$APPLE_API_KEY_ID" >> "$GITHUB_ENV" + echo "APPLE_API_ISSUER=$APPLE_API_ISSUER" >> "$GITHUB_ENV" + echo "APPLE_TEAM_ID=$APPLE_TEAM_ID" >> "$GITHUB_ENV" + - name: Build and publish release artifacts env: GH_TOKEN: ${{ github.token }} diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index aeab31c..707e0f1 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -346,7 +346,7 @@ The build pipeline is organized around three layers: - publishing the sidecar for the target runtime - packaging platform artifacts with electron-builder -electron-builder bundles the packaged Electron app, copies the published sidecar into `resources/sidecar`, produces Windows NSIS installers, macOS DMG + ZIP artifacts, and Linux AppImages, and uploads the release assets plus update metadata to GitHub Releases. The main process consumes that metadata through `electron-updater`, which checks GitHub Releases for packaged builds and can stage a restart-based update install. +electron-builder bundles the packaged Electron app, copies the published sidecar into `resources/sidecar`, produces Windows NSIS installers, macOS DMG + ZIP artifacts, and Linux AppImages, and uploads the release assets plus update metadata to GitHub Releases. Tagged macOS release jobs now materialize the certificate and App Store Connect key from repository secrets into temporary files on the runner, export the standard `electron-builder` signing and notarization environment variables from those files, and package with checked-in hardened-runtime entitlements so native modules still run correctly under code signing. The main process consumes the published metadata through `electron-updater`, which checks GitHub Releases for packaged builds and can stage a restart-based update install. Current Windows builds are unsigned, so the packaging config disables executable resource editing/signing and skips Windows update signature verification until a code-signing certificate is available. The packaging scripts also clear `release/` before each build so local packaging runs cannot accidentally mix stale artifacts with current ones. diff --git a/README.md b/README.md index 7fea53a..92bc724 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,8 @@ To publish packaged artifacts and update metadata to GitHub Releases, run: GitHub Actions runs validation on pushes and pull requests, and tagged releases now use `electron-builder` to publish Windows (NSIS), macOS (DMG + ZIP for updater metadata), and Linux (AppImage) artifacts directly to GitHub Releases. Packaged builds use `electron-updater` against those releases for in-app updates. +Tagged macOS release jobs now prepare signing assets from the GitHub secrets `APPLE_CERT_P12_BASE64`, `APPLE_CERT_PASSWORD`, `APPLE_API_KEY_P8`, `APPLE_API_KEY_ID`, `APPLE_API_ISSUER`, and `APPLE_TEAM_ID`, then export the standard `electron-builder` environment variables (`CSC_LINK`, `CSC_KEY_PASSWORD`, `APPLE_API_KEY`, `APPLE_API_KEY_ID`, `APPLE_API_ISSUER`, `APPLE_TEAM_ID`) before packaging. That same release path signs and notarizes the macOS artifacts as part of publication. + Windows builds are currently packaged without Authenticode signing, so Aryx disables `electron-updater`'s Windows signature verification until a signing certificate is configured. macOS auto-update metadata still requires a ZIP artifact alongside the DMG build. ## Current focus diff --git a/assets/entitlements.mac.inherit.plist b/assets/entitlements.mac.inherit.plist new file mode 100644 index 0000000..f2eb2ec --- /dev/null +++ b/assets/entitlements.mac.inherit.plist @@ -0,0 +1,12 @@ + + + + + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.disable-library-validation + + + diff --git a/assets/entitlements.mac.plist b/assets/entitlements.mac.plist new file mode 100644 index 0000000..f2eb2ec --- /dev/null +++ b/assets/entitlements.mac.plist @@ -0,0 +1,12 @@ + + + + + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.disable-library-validation + + + diff --git a/package.json b/package.json index e8126b5..8cd986f 100644 --- a/package.json +++ b/package.json @@ -135,7 +135,11 @@ ], "icon": "assets/icons/macos/icon.icns", "category": "public.app-category.developer-tools", - "identity": "-", + "hardenedRuntime": true, + "entitlements": "assets/entitlements.mac.plist", + "entitlementsInherit": "assets/entitlements.mac.inherit.plist", + "gatekeeperAssess": false, + "notarize": true, "artifactName": "Aryx-macos-${arch}.${ext}" }, "linux": {