Skip to content

Bump notarization deadline to 2 hours #13

Bump notarization deadline to 2 hours

Bump notarization deadline to 2 hours #13

Workflow file for this run

name: Release
on:
push:
tags:
- "release-[0-9]+.[0-9]+.[0-9]+*"
permissions:
contents: write
jobs:
build-cli:
strategy:
matrix:
include:
- target: aarch64-apple-darwin
os: macos-latest
artifact: ralph-macos-arm64
- target: x86_64-apple-darwin
os: macos-latest
artifact: ralph-macos-x86_64
- target: x86_64-pc-windows-msvc
os: windows-latest
artifact: ralph-windows-x86_64
- target: aarch64-pc-windows-msvc
os: windows-latest
artifact: ralph-windows-arm64
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
artifact: ralph-linux-x86_64
- target: aarch64-unknown-linux-gnu
os: ubuntu-latest
artifact: ralph-linux-arm64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Install cross-compilation tools (Linux ARM64)
if: matrix.target == 'aarch64-unknown-linux-gnu'
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu
echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
- name: Build
run: cargo build --release --target ${{ matrix.target }} -p ralph-cli
- name: Prepare artifact (Unix)
if: runner.os != 'Windows'
run: |
cp target/${{ matrix.target }}/release/ralph ${{ matrix.artifact }}
chmod +x ${{ matrix.artifact }}
- name: Prepare artifact (Windows)
if: runner.os == 'Windows'
run: cp target/${{ matrix.target }}/release/ralph.exe ${{ matrix.artifact }}.exe
- name: Sign and notarize (macOS)
if: runner.os == 'macOS'
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }}
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
APPLE_API_KEY_BASE64: ${{ secrets.APPLE_API_KEY_BASE64 }}
ARTIFACT: ${{ matrix.artifact }}
run: |
set -euo pipefail
# Create a temporary keychain and import the signing certificate
KEYCHAIN_PATH="$RUNNER_TEMP/signing.keychain-db"
KEYCHAIN_PASSWORD=$(uuidgen)
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
CERT_PATH="$RUNNER_TEMP/cert.p12"
echo "$APPLE_CERTIFICATE" | base64 --decode > "$CERT_PATH"
security import "$CERT_PATH" -k "$KEYCHAIN_PATH" -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security list-keychains -d user -s "$KEYCHAIN_PATH" $(security list-keychains -d user | tr -d '"')
# Sign the binary with hardened runtime and a secure timestamp
codesign --force --options runtime --timestamp \
--sign "$APPLE_SIGNING_IDENTITY" "$ARTIFACT"
codesign --verify --verbose "$ARTIFACT"
# Notarize: zip the binary and submit to the notary service.
# Bare binaries can't be stapled, so Gatekeeper does an online check
# on first run instead.
export APPLE_API_KEY_PATH="$RUNNER_TEMP/AuthKey.p8"
echo "$APPLE_API_KEY_BASE64" | base64 --decode > "$APPLE_API_KEY_PATH"
ZIP_PATH="$RUNNER_TEMP/$ARTIFACT.zip"
/usr/bin/ditto -c -k --keepParent "$ARTIFACT" "$ZIP_PATH"
./scripts/notarize.sh "$ZIP_PATH"
# Cleanup
security delete-keychain "$KEYCHAIN_PATH"
rm -f "$CERT_PATH" "$APPLE_API_KEY_PATH" "$ZIP_PATH"
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact }}
path: ${{ matrix.artifact }}${{ runner.os == 'Windows' && '.exe' || '' }}
build-desktop:
strategy:
matrix:
include:
- os: macos-latest
target: aarch64-apple-darwin
artifact: ralph-desktop-macos-arm64
- os: windows-latest
target: x86_64-pc-windows-msvc
artifact: ralph-desktop-windows-x86_64
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
artifact: ralph-desktop-linux-x86_64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 22
- name: Install frontend dependencies
run: npm ci
- name: Install Linux dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
- name: Build Tauri app
id: tauri
uses: tauri-apps/tauri-action@v0
env:
# Signing only — notarization is done manually in the next step
# because Tauri's built-in notarization uses `notarytool --wait`
# which hangs on transient network errors in CI.
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
KEYCHAIN_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
with:
args: --target ${{ matrix.target }}
includeUpdaterJson: false
- name: Notarize and staple DMG (macOS)
if: runner.os == 'macOS'
env:
APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }}
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
APPLE_API_KEY_BASE64: ${{ secrets.APPLE_API_KEY_BASE64 }}
run: |
set -euo pipefail
export APPLE_API_KEY_PATH="$RUNNER_TEMP/AuthKey.p8"
echo "$APPLE_API_KEY_BASE64" | base64 --decode > "$APPLE_API_KEY_PATH"
DMG=$(ls target/${{ matrix.target }}/release/bundle/dmg/*.dmg | head -n1)
echo "Notarizing $DMG"
./scripts/notarize.sh "$DMG"
xcrun stapler staple "$DMG"
xcrun stapler validate "$DMG"
rm -f "$APPLE_API_KEY_PATH"
- name: Upload desktop artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact }}
path: |
target/${{ matrix.target }}/release/bundle/dmg/*.dmg
target/${{ matrix.target }}/release/bundle/nsis/*.exe
target/${{ matrix.target }}/release/bundle/msi/*.msi
target/${{ matrix.target }}/release/bundle/deb/*.deb
target/${{ matrix.target }}/release/bundle/appimage/*.AppImage
release:
needs: [build-cli, build-desktop]
runs-on: ubuntu-latest
steps:
- name: Extract version from tag
id: version
run: echo "version=${GITHUB_REF_NAME#release-}" >> $GITHUB_OUTPUT
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
name: v${{ steps.version.outputs.version }}
generate_release_notes: true
body: |
## macOS notes
The desktop app (`.dmg`) and CLI binaries are signed and notarized
with a Developer ID. macOS will check Apple's notary service
online on first launch — no manual `xattr` workaround needed.
files: artifacts/**/*