ci: publish the desktop release atomically and stop the create race - #102
Conversation
The two platform jobs each called electron-builder's getOrCreateRelease, which lists the releases and creates one when no tag matches. That is a check-then-act with no lock, so both decided to create: one won and the other failed with 'Published releases must have a valid tag'. A prepare job now creates the release once, as a draft, which every platform job then finds and reuses. Publishing moves to a final job that runs only after both platforms uploaded and that names each expected artifact before flipping the draft. A failed platform now leaves a draft nobody can download rather than a live release missing an operating system. Both platform jobs set EP_GH_IGNORE_TIME, since electron-builder otherwise refuses to upload to a release published more than two hours ago by logging 'skipped publishing' and exiting zero.
|
Warning Review limit reached
Next review available in: 4 minutes Limit details: You’ve used all 3 included reviews currently available under your plan. Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
Comment |
commit: |
|
@coderabbitai review |
|
Related Issue
No issue. The first real desktop release (
desktop-v0.1.3) exposed the problems described below; both were diagnosed from the run logs and from electron-builder's own source.Problem
The two platform jobs race to create the release. electron-builder's
getOrCreateRelease(packages/electron-publish/src/gitHubPublisher.ts) lists the releases, looks for one whose tag matches, and callscreateRelease()when none does. That is a check-then-act with no lock. The macOS and Windows jobs start together, both see no release, and bothPOST /releases. One wins; the other gets422 Validation Failed: Published releases must have a valid tag. electron-builder'sdoesErrorMeanAlreadyExistsguard covers only asset upload conflicts, so the create path has no retry at all.That is exactly what happened on
desktop-v0.1.3: Windows created the release at04:02:42Z, macOS failed one second later.Publishing per platform leaves half a release. Because the winner publishes immediately, the failed macOS job left a live, published
v0.1.3containing the Windows installer, a stray.dmg.blockmap, and no.dmgat all. Anyone landing on it during that window got a release with no macOS build.A re-run can silently ship nothing. For a non-draft release published more than two hours ago,
getOrCreateReleasereturnsnull, anddoUploadthen logsskipped publishingand returns normally — the job goes green having uploaded no assets. The macOS re-run only worked because it landed inside the two-hour window.What changed
preparecreates the release once, before either platform job. It is created as a draft deliberately: a draft needs no valid git tag, so this step cannot hit the same 422, andgetOrCreateReleasereturns an existing draft before it consults either the release type or the two-hour rule. It is idempotent — an existing release, draft or published, is left untouched.macandwindowsnowneeds: prepare, so they find the draft and reuse it instead of creating anything. Both setEP_GH_IGNORE_TIMEso a re-run cannot silently upload nothing.publishruns only after both platforms succeed. It names each expected artifact —.dmg,-mac.zip,latest-mac.yml,-Setup.exe,latest.yml— and flips the draft only when all five are present. A count check would not do: the half-release that shipped had four assets.A platform failure now leaves a draft that no one can download and that is fixed by re-running that one job, instead of a live release missing an operating system.
Verification
run:block passesbash -n.v0.1.3asset list (publishes) and the exact broken list that shipped (stays a draft, naming the three missing macOS artifacts)..dmg$correctly rejects.dmg.blockmap.EP_GH_IGNORE_TIMEwas read from electron-builder's source rather than from docs, and the spelling matchesisEnvTrue(process.env.EP_GH_IGNORE_TIME).Not verified end to end. Exercising this needs a real release, and cutting one only to test a workflow change is not worth it. The first genuine exercise is the next desktop tag.
Note for reviewers
The App token is now minted in four jobs per release rather than two.
Checklist
gen-changesetsskill, or this PR needs no changeset. — CI-only change under.github/, nothing enters a package artifact.gen-docsskill, or this PR needs no doc update.