Files
openscreen/.github/workflows/build.yml
T
Siddharth 6a6caf618b fix build
2026-05-05 20:29:53 -07:00

254 lines
9.9 KiB
YAML

name: Build Electron App
on:
workflow_dispatch:
inputs:
arch:
description: 'Architecture to build'
required: true
default: 'both'
type: choice
options:
- arm64
- x64
- both
jobs:
build-windows:
runs-on: windows-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '22'
- name: Install dependencies
run: npm ci
- name: Build Windows app
run: npm run build:win
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload Windows build
uses: actions/upload-artifact@v4
with:
name: windows-installer
path: release/**/*.exe
retention-days: 30
build-macos:
runs-on: macos-latest
strategy:
matrix:
arch: ${{ github.event.inputs.arch == 'both' && fromJSON('["arm64", "x64"]') || fromJSON(format('["{0}"]', github.event.inputs.arch)) }}
steps:
# ─── Checkout ─────────────────────────────────────────────
- name: Checkout code
uses: actions/checkout@v4
# ─── Setup Node.js ────────────────────────────────────────
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
# ─── Setup Python (needed by some native deps) ────────────
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
# ─── Install Dependencies ─────────────────────────────────
- name: Install dependencies
run: npm ci
# ─── Import Code Signing Certificate ──────────────────────
# This is the KEY step that makes CI signing work.
# We create a temporary keychain, import the .p12 cert into it,
# and set it as the default so codesign can find it.
- name: Import code signing certificate
env:
MAC_CERTIFICATE_P12: ${{ secrets.MAC_CERTIFICATE_P12 }}
MAC_CERTIFICATE_PASSWORD: ${{ secrets.MAC_CERTIFICATE_PASSWORD }}
run: |
# Create a temporary keychain
KEYCHAIN_PATH=$RUNNER_TEMP/build.keychain-db
KEYCHAIN_PASSWORD=$(openssl rand -base64 32)
# Create and configure keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
# Decode and import certificate
echo "$MAC_CERTIFICATE_P12" | base64 --decode > $RUNNER_TEMP/certificate.p12
security import $RUNNER_TEMP/certificate.p12 \
-k "$KEYCHAIN_PATH" \
-P "$MAC_CERTIFICATE_PASSWORD" \
-T /usr/bin/codesign \
-T /usr/bin/security
# Allow codesign to access the keychain without UI prompt
security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
# Add to keychain search path (makes it the default)
security list-keychains -d user -s "$KEYCHAIN_PATH" $(security list-keychains -d user | tr -d '"')
# Verify the identity is available
security find-identity -v -p codesigning "$KEYCHAIN_PATH"
# Clean up the .p12 file
rm -f $RUNNER_TEMP/certificate.p12
# ─── Build Vite + Electron ────────────────────────────────
- name: Build Vite + Electron
run: npx tsc && npx vite build
# ─── Package with electron-builder ────────────────────────
# electron-builder handles deep codesigning the .app bundle
# "notarize: false" in electron-builder.json5 prevents it from
# trying its own notarization flow
- name: Package .app bundle
run: npx electron-builder --mac --${{ matrix.arch }} --dir
env:
CSC_NAME: "Samir Patil (N26FZ4GW28)"
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# ─── Read version from package.json ───────────────────────
- name: Get version
id: version
run: echo "version=$(node -p 'require(\"./package.json\").version')" >> $GITHUB_OUTPUT
# ─── Locate the .app bundle ───────────────────────────────
- name: Find .app bundle
id: find_app
run: |
VERSION="${{ steps.version.outputs.version }}"
echo "=== Release directory contents ==="
ls -laR "release/${VERSION}/" || echo "release/${VERSION}/ not found"
echo "=== Searching for .app bundle ==="
APP_BUNDLE=$(find "release/${VERSION}" -maxdepth 4 -name "*.app" -type d | head -n1)
if [ -z "$APP_BUNDLE" ]; then
echo "::error::No .app bundle found in release/${VERSION}/"
exit 1
fi
echo "app_bundle=$APP_BUNDLE" >> $GITHUB_OUTPUT
echo "Found: $APP_BUNDLE"
# ─── Verify .app signature ────────────────────────────────
- name: Verify .app code signature
run: codesign --verify --deep --strict "${{ steps.find_app.outputs.app_bundle }}"
# ─── Create DMG ───────────────────────────────────────────
- name: Create DMG
id: dmg
run: |
VERSION="${{ steps.version.outputs.version }}"
ARCH="${{ matrix.arch }}"
DMG_NAME="Openscreen-Mac-${ARCH}-${VERSION}.dmg"
RELEASE_DIR="release/${VERSION}"
DMG_OUTPUT="${RELEASE_DIR}/${DMG_NAME}"
STAGING="${RELEASE_DIR}/dmg-staging"
mkdir -p "$STAGING"
cp -R "${{ steps.find_app.outputs.app_bundle }}" "$STAGING/"
ln -s /Applications "$STAGING/Applications"
hdiutil create \
-srcfolder "$STAGING" \
-volname "Openscreen" \
-fs HFS+ \
-fsargs "-c c=64,a=16,e=16" \
-format UDBZ \
"$DMG_OUTPUT"
rm -rf "$STAGING"
echo "dmg_path=$DMG_OUTPUT" >> $GITHUB_OUTPUT
echo "dmg_name=$DMG_NAME" >> $GITHUB_OUTPUT
# ─── Sign DMG ─────────────────────────────────────────────
- name: Sign DMG
run: |
codesign --force \
--sign "Developer ID Application: Samir Patil (N26FZ4GW28)" \
--timestamp \
"${{ steps.dmg.outputs.dmg_path }}"
# ─── Notarize DMG ────────────────────────────────────────
# On CI we can't use keychain profiles for notarytool, so we
# pass credentials directly via env vars / flags
- name: Notarize DMG
run: |
xcrun notarytool submit "${{ steps.dmg.outputs.dmg_path }}" \
--apple-id "${{ secrets.APPLE_ID }}" \
--team-id "${{ secrets.APPLE_TEAM_ID }}" \
--password "${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}" \
--wait
timeout-minutes: 15
# ─── Staple ───────────────────────────────────────────────
- name: Staple notarization ticket
run: xcrun stapler staple "${{ steps.dmg.outputs.dmg_path }}"
# ─── Validate ─────────────────────────────────────────────
- name: Validate stapled DMG
run: |
xcrun stapler validate "${{ steps.dmg.outputs.dmg_path }}"
spctl -a -vv -t install "${{ steps.dmg.outputs.dmg_path }}"
# ─── Upload Artifact ──────────────────────────────────────
- name: Upload notarized DMG
uses: actions/upload-artifact@v4
with:
name: openscreen-mac-${{ matrix.arch }}
path: ${{ steps.dmg.outputs.dmg_path }}
retention-days: 30
# ─── Cleanup Keychain ─────────────────────────────────────
- name: Cleanup keychain
if: always()
run: security delete-keychain $RUNNER_TEMP/build.keychain-db || true
build-linux:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '22'
- name: Install dependencies
run: npm ci
# bsdtar (from libarchive-tools) is required by fpm to build pacman
# packages. AppImage and deb don't need it; ubuntu-latest doesn't ship it.
- name: Install pacman build dependencies
run: sudo apt-get update && sudo apt-get install -y libarchive-tools
- name: Build Linux app
run: npm run build:linux
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload Linux build
uses: actions/upload-artifact@v4
with:
name: linux-installer
path: |
release/**/*.AppImage
release/**/*.zsync
release/**/*.deb
release/**/*.pacman
retention-days: 30