diff --git a/.github/workflows/electron-build.yml b/.github/workflows/electron-build.yml new file mode 100644 index 00000000..b800a718 --- /dev/null +++ b/.github/workflows/electron-build.yml @@ -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