chore: retry and cache the Electron zip download during CI builds - #34585
Open
mschile wants to merge 2 commits into
Open
chore: retry and cache the Electron zip download during CI builds#34585mschile wants to merge 2 commits into
mschile wants to merge 2 commits into
Conversation
The "Build packages" step fails intermittently on every branch when the
Electron zip download from GitHub's release CDN is reset mid-stream:
RequestError: socket hang up ... code: 'ECONNRESET'
url: .../download/v37.6.0/electron-v37.6.0-linux-x64.zip
@electron/packager fetches that zip through @electron/get, which downloads
via got.stream(). got does not retry streams — its retry config is present
but inert there — so a single reset becomes an unhandled rejection that
kills the build. @electron/get exposes no retry option of its own.
Call downloadArtifact() directly so the download can be retried with
backoff, then hand the file to the packager via electronZipDir so it skips
its own download. The retry also covers the SHASUMS256.txt fetch, which
@electron/get re-requests on every run even on a cache hit.
Also cache the download across builds. @electron/get's default cache root
is platform-specific, so the build job pins it via electron_config_cache
(the same variable the electron package's own installer honors) to keep a
single save_cache path valid on all five platform executors. The cache key
tracks the pinned Electron version, so it invalidates on an upgrade.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 288b5b3. Configure here.
The health-check job flagged @electron/get as an unused devDependency in
packages/electron. It is used, but through `require(`@${e}/get`)` — the
same computed-string form already used for @electron/packager, which keeps
the module undiscoverable by mksnapshot since it is build-only. knip cannot
resolve that statically.
Add it alongside the existing @electron/packager entry in the package's
ignoreDependencies rather than making the require a plain literal, which
would expose a build dependency to the v8 snapshot.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
cypress
|
||||||||||||||||||||||||||||||||||||||||
| Project |
cypress
|
| Branch Review |
mschile/confident-hopper-b1c094
|
| Run status |
|
| Run duration | 16m 06s |
| Commit |
|
| Committer | Matthew Schile |
| View all properties for this run ↗︎ | |
| Test results | |
|---|---|
|
|
0
|
|
|
14
|
|
|
1135
|
|
|
0
|
|
|
27874
|
| View all changes introduced in this branch ↗︎ | |
UI Coverage
67.61%
|
|
|---|---|
|
|
23
|
|
|
48
|
Accessibility
98.99%
|
|
|---|---|
|
|
0 critical
3 serious
1 moderate
0 minor
|
|
|
18
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Additional details
The
buildjob's "Build packages" step has been failing intermittently across all branches (internal-pr-build,linux-arm64-build, and the develop platform builds) while downloading the Electron zip:Why a single reset kills the build.
@electron/packagerfetches that zip through@electron/get, whoseGotDownloaderdownloads viagot.stream(). got does not retry streams — theretryblock visible in the error dump (limit: 2, withECONNRESETinerrorCodes) is present but never consulted, which is what makes this failure look so confusing. Confirmed empirically against the installed got 14.4.7, using a local server that resets every connection:This is deliberate on got's part: on a stream failure it emits a
retryevent with acreateRetryStreamcallback and expects the caller to re-create the request, since it can't know whether bytes were already piped to a destination.@electron/getnever listens for that event, and exposes no retry option of its own — its full option surface isunsafelyDisableChecksums,checksums,cacheRoot,downloadOptions,mirrorOptions,downloader,tempDirectory,cacheMode,platform,arch,artifactSuffix,isGeneric. So there is no option to pass; the only supported extension point is supplying a whole customDownloaderclass, which is strictly more code for the same result.The change.
@packages/electronnow callsdownloadArtifact()itself with backoff retries (2s/4s/8s/16s/32s), then hands the file to the packager viaelectronZipDirso the packager skips its own download entirely. Same library, same URL, same cache as before — the only difference is that the call is now ours, which is what makes it retryable. The retry also covers theSHASUMS256.txtrequest that@electron/getre-issues on every run, including cache hits (it passescacheMode: Bypassfor checksums), so caching alone could not have closed this.Caching. The build job now also caches the download between runs.
@electron/get's default cache root is platform-specific (~/.cache/electron,~/Library/Caches/electron,%LOCALAPPDATA%), and thebuildjob is shared by five executors (docker, Linux ARM VM, two macOS VMs, Windows VM), so a singlesave_cachepath would not have covered them. The step pins the root viaelectron_config_cache— the same variable theelectronnpm package's own installer honors (node_modules/electron/install.js) — and@packages/electronforwards it ascacheRoot. The cache key tracks the pinned Electron version, so an Electron upgrade invalidates it with no manual coordination. On a warm cache the ~110MB transfer disappears entirely.Note that the
Lerna (powered by Nx) The task graph has a circular dependencynotice appearing above these failures is unrelated and benign — it is nx's warn branch (lerna passesnxIgnoreCycles, nx callsmakeAcyclic()and continues), and the same logs go on to reportSuccessfully ran target build for 44 projects. The fatal variant reads "Could not execute command because the task graph has a circular dependency". No change was made there.Note
Low Risk
Changes are limited to CI and Electron binary packaging; no runtime, API, or user-facing behavior is affected.
Overview
Addresses intermittent CI failures when downloading the Electron release zip (
ECONNRESET/ socket hang up) by owning the download instead of relying on@electron/packager→@electron/get, which does not retry streamed downloads.@packages/electronnow callsdownloadArtifact()with exponential backoff (2s–32s, five retries), honorselectron_config_cachefor the cache root, then passeselectronZipDirso the packager skips its own fetch.@electron/getis added as a dev dependency (dynamic require preserved for mksnapshot).CircleCI
build-and-persistrestores and saves~/.electron-cachekeyed by platform and pinned Electron version, and setselectron_config_cacheduringyarn buildso all executors share one cache path.Reviewed by Cursor Bugbot for commit d8b3152. Bugbot is set up for automated code reviews on this repo. Configure here.
Steps to test
CI itself is the primary test — the
buildjob should now logRestore Electron download cache/Save Electron download cachearound "Build packages", and a second run on the same Electron version should hit the cache.Locally, from the repo root:
Retry path — force every download to fail and confirm the backoff fires and then propagates:
Expect five
Electron download failed (...), retrying in Nslines at 2/4/8/16/32s, then the error.Cache path — run twice against a scratch cache root:
First run logs
Cache missand leaves the zip in/tmp/ci-electron-cache; the second logsCache hitwith no zip transfer. Both package the binary successfully.Normal path —
yarn workspace @packages/electron build-binarywith no env vars set still uses the platform-default cache root, unchanged from before.All three were run on this branch, along with
@packages/electronbuild (tscfor ESM + CJS), lint, and unit tests (30 passing), andyarn pack-ci --validate.How has the user experience changed?
No change. This affects CI build tooling only — no runtime, API, or user-visible behavior is touched, so no changelog entry is included.
PR Tasks
cypress-documentation?type definitions?