Skip to content

ci: skip the electron binary download on typecheck and lint - #380

Merged
Zaldaryon merged 2 commits into
devfrom
ci/skip-electron-binary-on-check-jobs
Sep 6, 2026
Merged

ci: skip the electron binary download on typecheck and lint#380
Zaldaryon merged 2 commits into
devfrom
ci/skip-electron-binary-on-check-jobs

Conversation

@Pixnop

@Pixnop Pixnop commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Closes #377.

Run 33969911703 on #369, a pure rebase with no source change, failed its typecheck job inside npm ci: the postinstall script (electron-builder install-app-deps && node scripts/fix-native-deps.js) noticed the Electron binary was missing and tried to download it from the mirror, and the mirror answered TypeError: fetch failed. The job's only work is tsc --noEmit, which reads electron.d.ts from the npm tarball and needs no binary. Same exposure for lint. Every rebase of every open PR was one mirror hiccup away from a reviewer round trip.

What changes

  • .github/workflows/ci.yml: ELECTRON_SKIP_BINARY_DOWNLOAD: 1 in the env of the typecheck and lint jobs only, with a comment saying why. The build, test-matrix, sonarcloud and macOS jobs are untouched and keep downloading. Job keys are byte-identical to dev, so the five required contexts still report under their own names.
  • scripts/fix-native-deps.js: an early return at the top of ensureElectronBinaryIsDownloaded() when that variable is set, logging one line. The guard has to live here: node_modules/electron 44.1.1 ships no scripts in its package.json, so npm ci itself never fetches the binary, and neither @electron/get 5.1.0 nor Electron's own install.js reads ELECTRON_SKIP_BINARY_DOWNLOAD any more (the string appears in neither package). Setting the variable in the workflow alone would have changed nothing; CI: typecheck and lint fail when the Electron binary download hiccups, though they never run Electron #377's premise said otherwise and has been corrected there.
  • tests/config/electron-binary-download-skip.test.ts: pins that the two check jobs carry the variable, that the download jobs do not, that the script honours it when set, and that it falls through to the installer when unset. The job-block parser starts below the jobs: line, so the top-level on: keys are not mistaken for jobs.

Behaviour matrix, old script against new, mirror pointed at a dead port

State Old New
binary present, variable unset exit 0, silent exit 0, silent
binary missing, variable unset exit 1, fetch failed identical
binary present, variable set exit 0, silent exit 0, skip line
binary missing, variable set exit 1, tries the download exit 0, skip line, no dist

CI evidence, run 33983272184 on 13de23a

typecheck and lint both log during npm ci:

  ELECTRON_SKIP_BINARY_DOWNLOAD: 1
[fix-native-deps] ELECTRON_SKIP_BINARY_DOWNLOAD is set, skipping the electron binary download

test-matrix (ubuntu-latest) on the same run still logs [fix-native-deps] electron binary missing, running node_modules/electron/install.js. All eight checks pass.

Mutants

Guard removed from the script: red on the skip case. env block removed from the lint job: red on the workflow case.

Two more after review, on the rebased tree:

  • ELECTRON_SKIP_BINARY_DOWNLOAD written into a comment under on:, next to workflow_dispatch:. The old parser reported ["lint", "typecheck", "workflow_dispatch"] and its assertion failed; the new one reported ["lint", "typecheck"] and the file stayed green.
  • Guard condition inverted to if (!process.env.ELECTRON_SKIP_BINARY_DOWNLOAD). Red, 2 of 4: the new unset case, which no longer sees the installer run, and the existing set case, which no longer sees the skip line.

Left for a follow-up

Caching ~/.cache/electron on the jobs that download. actions/cache is not used anywhere in ci.yml today, so it would be a new block in four jobs with a Windows path to verify; it deserves its own PR and its own run.

Testing

  • npm run typecheck: passed (node, web, tests), with no Electron binary in the tree.
  • npm run lint:ci: 0 errors, 15 pre-existing React Hooks warnings.
  • npm run format:check: passed.
  • npm run test:coverage: 167 files, 2150 passed, 2 skipped; 93.52 / 90.27 / 93.06 / 95.09 against floors 87 / 85 / 85 / 89.
  • npm run build:unpack: passed, Electron 44.1.1 Linux.

Related issues

Type

  • Bug fix
  • Feature
  • Performance
  • Refactor or cleanup
  • Tests only
  • Docs or build

Checklist

  • Targets dev, not main.
  • npm run typecheck passes.
  • npm run lint:ci passes.
  • npm run format:check passes.
  • npm run test:coverage passes, coverage at or above the floor in vitest.config.ts.
  • npm run build:unpack passes.

@Zaldaryon Zaldaryon left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change itself is sound. node_modules/electron 44.1.1 ships no scripts in its package.json, so npm ci alone never fetches the platform binary, and the only downloader in the repo is the postinstall calling scripts/fix-native-deps.js, which is exactly where the guard sits. electron's own install.js never reads ELECTRON_SKIP_BINARY_DOWNLOAD, so the comment is right that nothing downstream would honour it. tsc reads electron.d.ts from the npm tarball and .eslintrc.cjs needs nothing from Electron, so neither guarded job loses anything. The five required checks are green on 13de23a, and the npm ci log in the CI evidence section shows the skip firing on both jobs. Local gate here is green too: typecheck, lint:ci (0 errors, 15 pre-existing hook warnings), format:check, test:coverage at 93.45% statements above the 87 floor, build:unpack.

The blocker is the description. It is #385's body, word for word: it describes the Manage Mods bulk-action filter scope, the backup failure cause, and the window-open spread check, and it lists Closes #357, Closes #358, Closes #378, none of which this PR touches. This PR is the #377 CI change. Please replace the body with a description of what this PR does and set Closes #377. dev is not the default branch so nothing auto-closes on merge, but the record should still be right, and a reader arriving here from #377 currently finds a page about three other issues.

One non-blocking note on tests/config/electron-binary-download-skip.test.ts: the ^ {2}(\S+):$ job-block parser also matches push:, pull_request: and workflow_dispatch: under on:, and folds every line between workflow_dispatch: and typecheck:, the new comment block included, into a pseudo-job named workflow_dispatch. It passes today only because that comment does not contain the literal ELECTRON_SKIP_BINARY_DOWNLOAD. Starting the collection after the jobs: line would make it robust, and a second case pinning the negative (variable unset, the download is attempted) would catch an inverted condition.

@Pixnop

Pixnop commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

You are right, and it was our slip: the body was #385's, pasted onto the wrong PR. Replaced with a description of this change, Closes #377, the behaviour matrix and the CI evidence. The parser note and the negative case are coming in a commit on this branch.

The typecheck and lint jobs run tsc, eslint and prettier. Neither launches
Electron, yet `npm ci` fetched the platform binary for them anyway, so one
hiccup on the download mirror failed a job whose only work is static
analysis. Run 33969911703 lost typecheck that way while the six other jobs
on the same commit passed.

Both jobs now set ELECTRON_SKIP_BINARY_DOWNLOAD and fix-native-deps.js
returns early when it sees it, logging one line. The guard has to live in
the script: electron 44's install.js dropped its own check on that variable
and @electron/get 5 never had one, so nothing downstream would honour it.

test-matrix, build and sonarcloud are untouched and keep the download.

Closes #377
The job-block parser walked the whole workflow, so the top-level `on:` keys
matched `^ {2}(\S+):$` too and `workflow_dispatch` became a pseudo-job holding
every line up to `typecheck:`, the `jobs:` comment block included. It only
passed because that comment does not spell out ELECTRON_SKIP_BINARY_DOWNLOAD.
Collection now starts below `jobs:`.

Added the negative case: with the variable unset the script must fall through
to the installer. The repo's own node_modules already has the binary, so the
script is copied into a sandbox with a stub install.js, which shows the guard
falling through without touching the download mirror.
@Pixnop
Pixnop force-pushed the ci/skip-electron-binary-on-check-jobs branch from 13de23a to 82d6a3e Compare September 5, 2026 21:47
@Pixnop

Pixnop commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

Body replaced, and I took the test note too. Rebased on current dev (4e4dfbd), pushed as 82d6a3e.

Two changes in tests/config/electron-binary-download-skip.test.ts:

  • The job-block loop now runs over the slice below ^jobs:$ instead of the whole file, so push:, pull_request: and workflow_dispatch: are out of reach of ^ {2}(\S+):$ and nothing between them and typecheck: gets folded into a pseudo-job.
  • New case for the variable unset. The repo's own node_modules already has the binary, so running the real script there fast-exits at the path.txt check and proves nothing. The test copies the script into a mkdtempSync sandbox with a stub node_modules/electron/install.js, then asserts the script logs electron binary missing, running node_modules/electron/install.js, that the stub actually ran, and that the skip line is absent. No mirror traffic.

Mutants for both, on the rebased tree:

  • Parser. I put ELECTRON_SKIP_BINARY_DOWNLOAD into a comment under on:, right after workflow_dispatch:, then ran both parsers over the mutated file. Old: ["lint","typecheck","workflow_dispatch"], assertion failed. New: ["lint","typecheck"], assertion passed, and the real file stayed 4 of 4 green with the mutant in place. Throwaway script, not committed; the workflow was restored with git checkout and git status was clean before the gates.
  • Negative case. Guard inverted to if (!process.env.ELECTRON_SKIP_BINARY_DOWNLOAD). Red, 2 of 4. The new unset case dies on the missing installer line, and the existing set case dies too since it no longer sees the skip line. Worth saying plainly: the inversion is caught twice, so the negative case is not the sole killer of that specific mutant. What it does add is the other direction, a guard that swallows the download when the variable is unset, which nothing pinned before.

Gates on the rebased tree, all local:

  • npm run typecheck: passed, node, web and tests.
  • npm run lint:ci: 0 errors, 15 warnings, all the pre-existing react-hooks/exhaustive-deps ones.
  • npm run format:check: passed.
  • npm run test:coverage: 167 files, 2150 passed, 2 skipped. 93.52 statements, 90.27 branches, 93.06 functions, 95.09 lines, against floors 87 / 85 / 85 / 89.
  • npm run build:unpack: passed, Electron 44.1.1 Linux.

Body figures updated to match, and the mutant section now carries these two. Nothing in ci.yml or scripts/fix-native-deps.js changed in this push, the diff is the test file alone.

@Pixnop
Pixnop requested a review from Zaldaryon September 5, 2026 21:48

@Zaldaryon Zaldaryon left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both points from the last round are addressed.

The description is now this PR's: it explains the #369 rebase run that hit the mirror, Closes #377, and it names the two ci.yml jobs and the guard in scripts/fix-native-deps.js with the reason the guard has to live there. The behaviour matrix and the note that #377's own premise was corrected are a good touch.

The new commit 82d6a3e closes the two test gaps. The job-block parser now slices from below jobs:, so the top-level on: keys are no longer mistaken for jobs, and the added "runs the electron installer when the variable is not set" case builds a sandbox with a stub install.js, unsets the variable, and asserts the guard falls through to the installer without touching the mirror. The ci.yml and fix-native-deps.js changes themselves are byte-identical to the head I reviewed before (git range-diff confirms).

Full local gate on 82d6a3e is green: typecheck, lint:ci (0 errors, 15 pre-existing hook warnings), format:check, test:coverage at 93.52% statements and 90.27% branches above the 87/85 floors, build:unpack on Electron 44.1.1. npx vitest run tests/config/electron-binary-download-skip.test.ts: 4 passing. The five required GitHub contexts pass on the head, and the npm ci log shows the skip firing on both guarded jobs.

Approving.

@Zaldaryon
Zaldaryon merged commit 22b167c into dev Sep 6, 2026
9 checks passed
@Zaldaryon
Zaldaryon deleted the ci/skip-electron-binary-on-check-jobs branch September 6, 2026 00:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants