ci(electron): GitHub Actions matrix build - mac/win/linux, unsigned

Phase 1 step 8 of VNCprodbuild. New workflow, additive to the existing
docker-publish*.yml/standalone-release.yml (which only ever built the
Docker image / standalone tarball, never the desktop shell).

Matrix over macos-latest/windows-latest/ubuntu-latest. Each leg: npm ci,
build:standalone, build:electron, then npm run test:electron (the Phase 1
step 2 smoke test) as a REQUIRED gate before packaging or any
artifact-upload step - a platform-specific regression fails the leg it
breaks instead of slipping through because only one OS was ever
smoke-tested. Linux needs an explicit Xvfb install first (no display
server on that runner by default); macOS/Windows runners have one.

Triggers on release-published (packages + publishes to that release via
electron-builder's --publish always, matching standalone-release.yml's
`gh release upload` precedent but through electron-builder's own GitHub
publish provider) and workflow_dispatch (packages only, uploads a build
artifact instead, --publish never).

Ships unsigned - CSC_IDENTITY_AUTO_DISCOVERY: "false" stops electron-builder
from probing for a macOS identity that doesn't exist (VNCprodbuild step 9:
no Apple Developer ID or Windows cert yet, both human-owned purchases).
Structured so signing needs no rewrite later - just add CSC_LINK/
CSC_KEY_PASSWORD (macOS) and/or WIN_CSC_LINK/WIN_CSC_KEY_PASSWORD (Windows)
as repo secrets once those exist.
This commit is contained in:
Bernd Rodler
2026-08-04 12:58:41 +02:00
parent cab43b8d06
commit 0bb098438a
+89
View File
@@ -0,0 +1,89 @@
name: Build Electron Desktop App
# Phase 1 of the VNCprodbuild rollout (~/.claude/skills/VNCprodbuild/SKILL.md
# on the machine that authored this - Phase 1 step 8). Builds the desktop
# shell (electron/) for macOS, Windows, and Linux on every release, or
# on-demand via workflow_dispatch for a one-off test build.
#
# Ships UNSIGNED. There's no Apple Developer ID or Windows code-signing cert
# yet (VNCprodbuild Phase 1 step 9 - both are human-owned purchases, not
# something CI can provide). CSC_IDENTITY_AUTO_DISCOVERY: "false" below stops
# electron-builder from probing for a macOS signing identity it won't find.
# Adding real certs later needs no rewrite here - just add CSC_LINK/
# CSC_KEY_PASSWORD (macOS) and/or WIN_CSC_LINK/WIN_CSC_KEY_PASSWORD (Windows)
# as repo secrets and electron-builder picks them up automatically.
on:
release:
types: [published]
workflow_dispatch:
permissions:
contents: write
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- name: Install dependencies
run: npm ci
- name: Build standalone Next.js server
run: npm run build:standalone
- name: Bundle Electron main/preload
run: npm run build:electron
# Only Linux runners lack a display server by default - macOS/Windows
# GitHub-hosted runners can launch a real (if headless) GUI session
# without one.
- name: Install Xvfb (Linux)
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y xvfb
# Required gate (VNCprodbuild Phase 1 step 2) before any packaging or
# artifact-upload step below, on every OS in the matrix - a
# platform-specific regression in electron/main.ts (path handling,
# spawn behavior, etc.) should fail exactly the leg it breaks, not
# slip through because only one OS was ever smoke-tested.
- name: Run Electron smoke test (Linux, via Xvfb)
if: runner.os == 'Linux'
run: xvfb-run --auto-servernum npm run test:electron
- name: Run Electron smoke test
if: runner.os != 'Linux'
run: npm run test:electron
- name: Package
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CSC_IDENTITY_AUTO_DISCOVERY: "false"
run: npx electron-builder --config electron-builder.config.js --publish ${{ github.event_name == 'release' && 'always' || 'never' }}
- name: Upload artifact (workflow_dispatch)
if: github.event_name == 'workflow_dispatch'
uses: actions/upload-artifact@v4
with:
name: vncmail-plus-desktop-${{ matrix.os }}
path: |
dist-electron-builds/*.dmg
dist-electron-builds/*.zip
dist-electron-builds/*.exe
dist-electron-builds/*.AppImage
dist-electron-builds/*.deb
retention-days: 7
if-no-files-found: ignore