fix(capgo): give every OTA upload a unique bundle version - #2795
Conversation
Closes #2638 `package.json`'s version only moves on a native release, so every OTA upload after the first reused the same bundle version. Capgo failed those uploads loudly until #2636 added `--version-exists-ok`, which turned them into silent no-ops: green check, nothing shipped. The obvious fix — appending the short SHA — is the one shape that must not be used, and is what the workflow does today for every non-production lane. `1.0.53-abc1234` is a semver prerelease and sorts BELOW plain `1.0.53`. Capgo's update endpoint rejects any bundle sorting under the device's native version (`disable_auto_update_under_native`, on by default), so those uploads succeed, appear on the dashboard, and are refused by every device on the shipped binary. - `scripts/capgo-bundle-version.mjs` prints `<major>.<minor>` from `package.json` plus the git commit count (today: `1.0.10175`). Anchoring major/minor to `package.json` keeps the version above the native floor when a native release bumps it; the commit count makes it unique per commit. It refuses a shallow clone (would emit `1.0.1`), a prerelease override, and any `CAPGO_BUNDLE_VERSION` override below the native version. - `capgo-deploy.yml` gains `fetch-depth: 0` and a "Resolve bundle version" step. The tag-derived production version is unchanged: `ota-1.0.48` is already plain and above the native floor, and `ota-1.0.48-hotfix1` is a deliberate prerelease that still sorts above it, so production does not go through the script — which refuses prereleases by design. Every other lane now derives the commit-count version instead of suffixing the SHA. - A post-upload step asserts the channel actually serves the version the run just built. `--version-exists-ok` stays, but now only covers a re-run of the same commit; any other no-op leaves the channel stale and turns the job red. - `capgo:upload:dev|staging` get the same derived version — same collision. 6 new jest tests, including a real shallow-clone repo. The verification step was simulated under `bash -e` for match / stale-channel / CLI-error; it is green only on a real match. Before the first release: check on the Capgo dashboard that the channels' update policy is not `patch` — that setting blocks any patch-differing bundle, i.e. all OTA, regardless of the version scheme. Note also that a native release which overrides `versionName` without bumping `package.json` would strand OTA bundles under the shipped binary.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
@coderabbitai review |
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 29 minutes Limit details: You’ve used all 3 included reviews currently available. Your 49 included PR review attempts over the past 7 days set your current allowance at 3 reviews per hour. You’re in a promotional period — use the checkbox below to run this review for free:
On-demand reviews are free for the next 29 days. After that, they cost $0.25 per reviewed file. How can I continue?Run this review now using the option above, or comment You can also wait for the limit to reset, then comment An organization admin can change what happens after included review limits in Billing. How do review limits work?CodeRabbit enforces per-developer PR review limits within each organization. For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
Comment |
|
Code-analysis diffPainscore total: 7322.72 → 7322.72 (0) |
🧪 UI test report — ✅ all greenSuites
📊 Coverage (unit)
⏱ 10 slowest test cases
|
Closes #2638. Replaces #2708 — same change, rebuilt on current
dev(see Why a new PR below).Problem
package.json's version only moves on a native release, so every OTA upload after the first reused the same bundle version. Capgo failed those uploads loudly until #2636 added--version-exists-ok, which turned them into silent no-ops: green check, nothing shipped.The fix that must not be used — and is currently in
devAppending the short SHA looks equivalent and is not.
1.0.53-abc1234is a semver prerelease and sorts below plain1.0.53. Capgo's update endpoint rejects any bundle that sorts under the device's native version (disable_auto_update_under_native, on by default — update.ts). So the upload succeeds, the dashboard shows a new bundle, and every device on the shipped binary refuses it.capgo-deploy.ymlondevdoes exactly this for every non-production lane today.Changes
scripts/capgo-bundle-version.mjs— prints<major>.<minor>frompackage.json+ the git commit count (today:1.0.10175). Anchoring major/minor topackage.jsonkeeps the version above the native floor when a native release bumps it; the commit count makes it unique per commit. It refuses a shallow clone (would emit1.0.1), a prerelease override, and anyCAPGO_BUNDLE_VERSIONoverride below the native version.capgo-deploy.yml—fetch-depth: 0, a "Resolve bundle version" step,--bundle <version>on the upload, and a post-upload assertion thatchannel currentBundleactually serves the version the run just built.--version-exists-okstays, but now only covers a re-run of the same commit; any other no-op leaves the channel stale and turns the job red. That check is Capgo OTA: --version-exists-ok greens the check but ships nothing (version never bumped) #2638's "verify when fixed" criterion, enforced in CI.ota-1.0.48is already plain and above the native floor, andota-1.0.48-hotfix1is an intentional prerelease that still sorts above it. Production keeps its tag-derived version and does not go through the script, which refuses prereleases by design.capgo:upload:dev|stagingpackage scripts get the same derived version — they had the identical collision.Verification
scripts/__tests__/capgo-bundle-version.test.js), including a real shallow-clone repo.bash -efor match / stale-channel / CLI-error; it is green only on a real match.prettier --checkclean on the touched files; the workflow parses.Why a new PR
#2708 was cut on 2026-08-17. Since then
devdeletedcapgo-deploy-ios.yml(folded intocapgo-deploy.yml), moved production ontoota-*tags, and added the SHA-suffix scheme above — so #2708 conflicted. It could not be fixed in place: mergingdevinto that branch drags in 7 pre-2026-08-18 unsignedsrc/contentbumps and the "All branches" ruleset rejects the push (GH013), whilenon_fast_forwardblocks the rebase escape hatch. Same content, rebuilt ondev, reconciled with dev's consolidated lane. #2708 is closed in favour of this.Before the first release
Check on the Capgo dashboard that the channels' update policy is not
patch— that setting blocks any patch-differing bundle, i.e. all OTA, regardless of the version scheme. Also note a native release that overridesversionNamewithout bumpingpackage.jsonwould strand OTA bundles under the shipped binary.