From 18da62d8658e35cb26630032634289ca62d5baa5 Mon Sep 17 00:00:00 2001 From: Paul Mulligan Date: Tue, 7 Jul 2026 16:33:45 -0400 Subject: [PATCH] ci(gui): stop pnpm side-effects cache poisoning of Electron installs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The gui (lint/typecheck) job installs with ELECTRON_SKIP_BINARY_DOWNLOAD=1, and pnpm's side-effects cache (default on) records that binary-less Electron postinstall in the pnpm store. setup-node caches the store keyed only on OS + lockfile hash, and the fast job wins the immutable cache save — so the smoke job (and the Linux release build) restores the poisoned store, pnpm replays the recorded postinstall instead of running it, node_modules/electron never gets dist/, and electron.launch dies with "Electron failed to install correctly". Pass --config.side-effects-cache=false at all three install sites: the gui job stops writing the poisoned entry, and the smoke/release installs stop trusting any existing one (the already-saved cache entry is immutable until the lockfile changes, so fixing only the producer would not unbreak CI). Verified with a local repro on pnpm 9.15.0: a fake package whose postinstall skips its binary under the env var; a second env-free install through the same store silently replayed the skip, and the flag made it really run. Co-Authored-By: Claude Fable 5 --- .github/workflows/gui-release.yml | 7 ++++++- .github/workflows/gui.yml | 14 ++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/.github/workflows/gui-release.yml b/.github/workflows/gui-release.yml index cbd624f..73886b2 100644 --- a/.github/workflows/gui-release.yml +++ b/.github/workflows/gui-release.yml @@ -38,7 +38,12 @@ jobs: cache: pnpm - name: Install dependencies - run: pnpm install --frozen-lockfile + # side-effects-cache=false: the Linux runner shares the lockfile-keyed + # pnpm store cache with gui.yml, whose lint/typecheck job installs with + # ELECTRON_SKIP_BINARY_DOWNLOAD=1. Replaying that recorded postinstall + # would yield an Electron install with no binary, breaking the smoke + # test and packaging. Force postinstalls to really run. + run: pnpm install --frozen-lockfile --config.side-effects-cache=false - name: Install Electron runtime libraries + Xvfb (Linux) if: runner.os == 'Linux' diff --git a/.github/workflows/gui.yml b/.github/workflows/gui.yml index d02d3f7..2343939 100644 --- a/.github/workflows/gui.yml +++ b/.github/workflows/gui.yml @@ -38,9 +38,14 @@ jobs: - name: Install dependencies # Skip the ~100 MB Electron binary download — typecheck needs only the # bundled types and the core tests never launch Electron. + # side-effects-cache=false: pnpm would otherwise record this *skipped* + # Electron postinstall in the pnpm store (which setup-node caches, keyed + # on the lockfile — shared with the smoke job), and any later install + # restoring that cache would replay it and never get a binary + # ("Electron failed to install correctly"). env: ELECTRON_SKIP_BINARY_DOWNLOAD: '1' - run: pnpm install --frozen-lockfile + run: pnpm install --frozen-lockfile --config.side-effects-cache=false - name: Lint run: pnpm --filter @vespasian/gui lint @@ -68,7 +73,12 @@ jobs: - name: Install dependencies # No ELECTRON_SKIP here — the smoke needs the real Electron binary. - run: pnpm install --frozen-lockfile + # side-effects-cache=false: don't replay postinstall results from the + # restored store cache — an install that ran with + # ELECTRON_SKIP_BINARY_DOWNLOAD=1 records a binary-less Electron build, + # and replaying it here is what breaks electron.launch. This forces + # Electron's postinstall to really run (and really download). + run: pnpm install --frozen-lockfile --config.side-effects-cache=false - name: Install Electron runtime libraries + Xvfb run: |