Uh oh!
There was an error while loading. Please reload this page.
fix(release): publish before syncing main, and stop racing the merge - #296
Conversation
promote.yml ran the main-sync before the two steps that actually ship the release. The sync opens a PR and merges it ~3s later, which races GitHub's asynchronous mergeability computation and has failed every time since v1.7.0: v1.9.0 got "This branch can't be rebased" 2.9s after create, v1.8.0 "has merge conflicts" after 1.7s. Neither was a real conflict — both PRs were rebase-merged by hand, unchanged, minutes later. Because the step had no continue-on-error and nothing below it was if: always(), each failure silently skipped "Trigger build workflow" and "Announce stable on Discord". v1.7.0, v1.8.0 and v1.9.0 all shipped with the build dispatched by hand and no #releases announcement. Two changes, independent on purpose: - Order. Build trigger and Discord announce now run right after the stable tag is pushed, before the sync. They depend on nothing the sync produces — the build is dispatched with --ref on the stable tag, not on main — so a stuck PR can no longer suppress the release. - Reliability. The sync polls mergeStateStatus until it leaves UNKNOWN, then retries the merge up to 5 times. MERGED is set only by a successful merge: a bare `&& break` loop exits 0 after five failures and reports a merge that never happened. The step is continue-on-error since the release is already out by then, and the job summary says so when it fails rather than letting it pass unnoticed.
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe promotion workflow dispatches the stable-tag build and announces the release before main synchronization. Synchronization waits for mergeability, retries up to five times, and reports incomplete work without blocking publishing. ChangesRelease promotion flow
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant GitHub Actions
participant Stable-tag build
participant Discord
participant Sync PR
participant GitHub mergeability
GitHub Actions->>Stable-tag build: dispatch stable-tag build
GitHub Actions->>Discord: announce release
GitHub Actions->>Sync PR: locate synchronization PR
GitHub Actions->>GitHub mergeability: poll mergeability
GitHub Actions->>Sync PR: retry rebase merge up to five times
GitHub Actions->>GitHub Actions: report incomplete synchronization
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/promote.yml:
- Around line 173-175: Update the no-PR branch in the synchronization step of
promote.yml to re-check whether main contains the release branch before exiting.
Return status 0 only when main is confirmed up to date; otherwise emit the
existing synchronization warning and exit 1 so sync_main fails when main remains
behind.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
Uh oh!
There was an error while loading. Please reload this page.
L'échec de `gh pr create` est converti en echo, donc la branche « aucune PR ouverte » couvrait aussi le cas où la création avait échoué pour une autre raison. Elle sortait alors en 0 alors que le test d'ascendance du haut venait d'établir que main ne contient pas la branche : sync_main était reporté en succès et l'avertissement de fin sautait. On re-teste l'ascendance plutôt que de supposer — quelqu'un a pu merger la synchro à la main entre-temps — et on sort en 1 sinon. Exercé avec git et gh stubbés sur les quatre chemins : création échouée avec main en retard sort bien en 1, création échouée avec main à jour en 0, et les deux chemins nominaux ne régressent pas.
Uh oh!
There was an error while loading. Please reload this page.
Summary
promote.ymlhas failed on every run since v1.7.0. Last success:28734947685(2026-07-05).gh pr create31029721368GraphQL: This branch can't be rebased (mergePullRequest)30873203114Pull Request has merge conflicts29706639667/29702095523These are not real conflicts. PR #288 (v1.9.0's sync PR) was rebase-merged by hand 24 minutes later, base and head SHAs unchanged, and
gh api .../pulls/288/commitsshows a linear chain whose first parent is exactlybase.sha— a head that descends directly from its base cannot conflict.allow_rebase_mergeistrue, so it is not a repo setting either. What it is: GitHub computesmergeable/mergeStateStatusasynchronously, and the mutation fails while the state is stillUNKNOWN.The expensive part is not the race, it is where the step sits. "Merge release branch into main" ran before "Trigger build workflow" and "Announce stable on Discord", with no
continue-on-errorand noif: always()below it. So every failure skipped both:Consequences, verified: v1.7.0, v1.8.0 and v1.9.0 were all built by a manual
workflow_dispatch(e.g. run31029970478, dispatched 2 min 32 s after promote died), and #releases has had no announcement since v1.6.0 — while #rc-testing keeps working, becauseprerelease.ymlputs its announce step last.What changed
Order. Build trigger and Discord announce now run immediately after the stable tag is pushed. They depend on nothing the sync produces — the build is dispatched with
--refon the stable tag, not on main, so the checkout gets the released snapshot whatever main looks like. Publishing no longer depends on a PR round-trip.Reliability. The sync now polls
mergeStateStatus(30 × 5 s) until it leavesUNKNOWN, then retriesgh pr mergeup to 5 times with a 15 s backoff.Failure handling. The sync is
continue-on-error: true— the release is already out by the time it runs, so a stuck PR should not redden a successful release. To keep that from hiding anything, the job summary emits a warning block naming the outstanding-syncbranch whensteps.sync_main.outcome != 'success'.Related issue
No issue — found while auditing the Linux build/packaging chain. Same family as #148 (winget publishing broken), which this does not fix.
Type of change
Release impact
Desktop impact
Screenshots / video
n/a
Testing
CI-only change; the workflow can only be exercised by a real promotion. What I verified locally:
yaml.safe_load→ step 6Trigger build workflow, 7Announce stable on Discord, 8Merge release branch into mainwithid: sync_main,continue-on-error: True).gh pr merge … && break; sleep 15form exits 0 after five failed attempts and reports a merge that never happened. Simulated with a merge that always fails →::error::then exit 1.set -euo pipefailwhen the state staysUNKNOWNfor all 30 iterations (if … then break; fi, not[[ … ]] && break).The next promotion is the real test. If the race still bites, the sync now fails alone and the release goes out regardless — which is the point.
🤖 Generated with Claude Code
Summary by CodeRabbit