2828 # Only Electron is launched here, never Playwright's bundled browsers, so
2929 # skip their download during yarn install (faster, fewer network flakes).
3030 PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD : ' 1'
31+ # electron's postinstall (extract-zip) intermittently drops files from dist
32+ # on CI runners, so skip it and install the binary deterministically below.
33+ ELECTRON_SKIP_BINARY_DOWNLOAD : ' 1'
3134 steps :
3235 - uses : actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
3336 - uses : actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5
@@ -37,52 +40,27 @@ jobs:
3740 node-version : ' 24.x'
3841 cache : ' yarn'
3942 - run : yarn install --frozen-lockfile
40- # The electron postinstall (extract-zip) intermittently leaves dist without
41- # the binary on CI runners (it happens on macOS too, not just Linux), so
42- # launch fails with "Electron failed to install correctly". Run install.js
43- # explicitly on every OS to fetch and extract the binary.
43+ # Install the Electron binary deterministically instead of relying on the
44+ # flaky extract-zip postinstall. Resolve the cached zip with @electron/get
45+ # (electron's own download dep, same call on every OS) and extract it with
46+ # the system tool: macOS needs ditto to keep the Electron Framework
47+ # symlinks that plain unzip mangles; Linux uses unzip. Then point path.txt
48+ # at the binary and confirm require('electron') resolves.
4449 - name : Install the Electron binary
45- run : node node_modules/electron/install.js
46- # On Linux, if extract-zip still dropped the binary, fall back to system
47- # unzip (the zip is the linux-x64 build, binary at dist/electron).
48- - name : Repair the Electron binary on Linux if needed
49- if : matrix.os == 'ubuntu-latest'
50+ shell : bash
5051 run : |
5152 set -euo pipefail
52- if [ ! -x node_modules/ electron/dist/electron ]; then
53- echo "linux electron binary missing, repairing from the cached zip"
54- zip=$(ls ~/.cache/electron/*/electron-*-linux-x64.zip | head -1)
55- rm -rf node_modules/electron/dist
56- mkdir -p node_modules/electron/ dist
57- unzip -q -o "$zip" -d node_modules/electron/dist
58- printf 'electron' > node_modules/electron/path.txt
53+ zip=$(node -e "const {downloadArtifact}=require('@ electron/get');const {version}=require('electron/package.json');downloadArtifact({version,artifactName:'electron'}). then(p=>process.stdout.write(p)).catch(e=>{console.error(e);process.exit(1)})")
54+ dist=node_modules/ electron/dist
55+ rm -rf "$dist" && mkdir -p "$dist"
56+ if [ "$RUNNER_OS" = "macOS" ]; then
57+ ditto -x -k "$zip" "$ dist"
58+ printf 'Electron.app/Contents/MacOS/Electron' > node_modules/electron/path.txt
59+ test -f "$dist/Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Electron Framework"
5960 else
60- echo "linux electron binary present, no repair needed"
61+ unzip -q -o "$zip" -d "$dist"
62+ printf 'electron' > node_modules/electron/path.txt
6163 fi
62- test -x node_modules/electron/dist/electron
63- # extract-zip produces a broken Electron.app on the macOS runner: the
64- # launcher at Contents/MacOS/Electron is present but Contents/Frameworks/
65- # Electron Framework.framework is incomplete, so dyld fails with "Library
66- # not loaded" at launch, and path.txt is never written either. Re-extract
67- # the cached darwin zip with ditto, which reproduces a complete .app
68- # (framework binary plus the Versions/Current symlinks plain unzip mangles)
69- # locally, then write path.txt (its macOS value is constant) and verify
70- # both the launcher and the framework binary are in place.
71- - name : Repair the Electron install on macOS
72- if : matrix.os == 'macos-latest'
73- run : |
74- set -euo pipefail
75- # Ask @electron/get (electron's own download dep) for the cached zip,
76- # fetching it if absent. It stores the zip under a content-hash subdir,
77- # so globbing the cache root misses it; let the library resolve the path.
78- zip=$(node -e "const {downloadArtifact}=require('@electron/get');const {version}=require('electron/package.json');downloadArtifact({version,artifactName:'electron',platform:'darwin',arch:process.arch}).then(p=>process.stdout.write(p)).catch(e=>{console.error(e);process.exit(1)})")
79- echo "re-extracting electron from $zip"
80- rm -rf node_modules/electron/dist
81- mkdir -p node_modules/electron/dist
82- ditto -x -k "$zip" node_modules/electron/dist
83- printf 'Electron.app/Contents/MacOS/Electron' > node_modules/electron/path.txt
84- test -x "node_modules/electron/dist/Electron.app/Contents/MacOS/Electron"
85- test -f "node_modules/electron/dist/Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Electron Framework"
8664 node -e "console.log('resolved electron:', require('electron'))"
8765 - run : yarn build
8866 # Electron needs system libraries; xvfb provides a display on the headless
0 commit comments