chore: back-merge dev → main (ships production OTA 1.6.3) - #3112
Closed
innolope-dev wants to merge 5 commits into
Closed
innolope-dev wants to merge 5 commits into
innolope-dev wants to merge 5 commits into
Conversation
Both resolvers produce a number that outranks the binary whether or not the commit contains it: `ota` lands the next bundle inside the newest native build's range, `native` returns latestBuild + 1. Neither asks about the code. A bundle numbered above the binary is accepted by every device, so an OTA published from a lagging ref is a silent downgrade of the JS that binary shipped with — and a store build in that state is worse, since only another store release undoes it. On 2026-09-10 production bundle 1.6.1 was published from ff34896, the tip of main, which did not contain the v1.6.0 release cut from dev the day before. Every install on the 1.6.0 binary took it and ran older JS. check-native-ota-surface already asserted this ancestry, but only as a precondition of its fingerprint diff — in the deploy job, after a full install and native build, reported as "v1.6.0 is not an ancestor of HEAD". A lagging ref whose native surface happened to match would have passed it outright. Both lanes now assert it before anything is built, and name the back-merge as the remedy. The native lane tolerates the first release of a new major, which has no earlier build to contain. Also recorded in docs/NATIVE-RELEASE.md: that bundle shipped through a tag push, and a push-triggered workflow runs the workflow file as it existed at the pushed ref — so it ran the long-retired capgo-deploy.yml still present at that commit, with no floor check and no surface check. Retiring a workflow does not retire it at older commits, and the same applies to `v*`.
Production is stuck on bundle 1.6.1 — JS older than the 1.6.0 binary it runs on — and every attempt to replace it fails the native-surface check. The whole drift between `dev` and v1.6.0 is two lines: the `/app` and `/app/` App Links paths d91ea7c added to AndroidManifest.xml. An intent filter cannot reach a device over the air. Those two lines were therefore inert on every shipped binary while blocking every bundle that could have fixed the fleet, so they buy nothing where they are and cost everything. Reverted byte-exact to v1.6.0 so the fingerprint matches and the OTA can ship; a comment marking the revert would itself change the bytes and fail the check, which is why the note lives in docs/NATIVE-RELEASE.md instead — at the top of "Cutting a release", where whoever cuts the next one will read it. iOS is untouched: apple-app-site-association still claims `/app` and native-routes.ts still maps `/app/*` → `/app`, so only Android `/app` deep links are missing, exactly as they already are on every install in the field.
…ve release" This reverts commit 478cd04.
Production is serving bundle 1.6.1 — JS older than the 1.6.0 binary running it — and every replacement fails check-native-ota-surface. The whole native drift between dev and v1.6.0 is d91ea7c's `/app` claim: two lines in AndroidManifest.xml, three in the AASA. v1.6.0 predates that commit, so no shipped binary and no shipped AASA ever carried the claim, and an intent filter cannot be shipped over the air. The manifest half did move the native fingerprint, which is what the surface check compares against the binary an OTA targets — so those lines blocked every bundle that could have fixed the fleet while delivering nothing to anyone. Now that the client-side store-update gate has landed, the version this unblocks matters as much as the unblocking. A native release would number its bundle 1.7.0, which the gate reads as needing a newer binary on every 1.6.0 install — pinning the fleet behind a store update that only exists in TestFlight and Play internal, invisibly on iOS where the listing is not live. 1.6.2 shares the binary's build number, so the gate passes it and the OTA lane stays open. Both platforms are reverted together. Dropping only the Android half would manufacture exactly the drift app-links.test.ts pins, so the parity and shape cases stay enforced and only the two `/app`-presence cases are `it.skip`, with the reason and the restore condition inline. docs/NATIVE-RELEASE.md carries the same note at the top of "Cutting a release", where whoever cuts the next one will read it: restore the AASA entries, the manifest entries and the two cases together, in that PR, never on dev alone.
fix(release): refuse to ship a ref that lags the newest native release
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks 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 |
Contributor
Code-analysis diffPainscore total: 8992.04 → 8992.04 (0) |
Contributor
🧪 UI test report — ✅ all greenSuites
📊 Coverage (unit)
⏱ 10 slowest test cases
|
This branch was successfully deployed
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.
Back-merge
dev→main. Merging this ships production OTA1.6.3— that is the point of it, not a side effect.Why this is the ship
mainis behinddevand is missing both halves of what unblocks the OTA:maintoday/appApp Links claim still present → surface check failsv1.6.0release-ota.ymlis dispatch-onlymain,mainonlyOnce the trigger change is on
main, the merge commit itself fires App Release OTA, which resolves1.6.3off the channel (1.6.2) and publishes it. No dispatch needed.Every gate dry-run against this tree
The surface check is the step that failed the 18:18 and 20:52 runs. It passes here.
Order of operations
dev(per-platform floors + themain-only trigger). This PR picks it up automatically.1.6.3. Watch the run.Merging this before #3111 lands still works —
mainwould get the/apprevert and the provenance guard, and1.6.3could be shipped by a manual dispatch onmain. It just would not be automatic.What
1.6.3fixes for whom1.6.1(no gate in their JS) take1.6.3freely and land on the candidate-floor logic. Healthy from then on.1.6.0binary running1.6.2:build 6 > 6is false, so they were never blocked. They take1.6.3and stay correct.1.6.0already running1.6.2cannot be reached over the air — proven, not assumed: Capgo only offers a bundle sorting above1.6.2, which forcesbuild ≥ 6, and that bundle's own gate refuses it against abuild 5binary. Android sees the store prompt and can self-rescue if a≥1.6.0build is in its Play track; iOS has no prompt (listing not live) and needs a TestFlight build.Shipping this promptly is what stops that last group growing — every device that adopts
1.6.2before1.6.3is published becomes unreachable.