fix(iOS): stamp the React Native version in the prebuild compose job#57603
fix(iOS): stamp the React Native version in the prebuild compose job#57603chrfalch wants to merge 2 commits into
Conversation
cipolleschi
left a comment
There was a problem hiding this comment.
Not a fan of this workaround, as we set the version and then we revert it.
It would be better if we can create the headers folder in one of the slice jobs and restore it here, probably.
…ders The prebuilt iOS core artifacts shipped ReactNativeVersion.h with the 1000.0.0 dev sentinel: the compose-xcframework job re-derives the shipped headers from its own fresh (unstamped) checkout, while only build-rn-slice runs set-rn-artifacts-version.js. Since the header-facades change, libraries resolve the prebuilt header instead of the stamped npm copy, so any library gating on REACT_NATIVE_VERSION_MAJOR/MINOR compiles the wrong branch (react-native-unistyles in nightly-tests). Rather than re-stamp (and then revert) the compose checkout, source just that one build-stamped header's CONTENT from the built header tree the compose job already downloads (.build/headers): stageEntries now takes an overlay dir and, for ReactNativeVersion.h only, prefers the built copy (stamped in the slice job) over the source sentinel. Header LAYOUT is still spec-derived from source, and every other header still copies from source, so a stale build tree can never ship wrong header content. Bump the compose cache key so pre-fix unstamped composed artifacts are not served. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…on sentinel Enforce the stamping above: headers-verify.js gains a --require-stamped-version gate that fails the compose verification when any ReactNativeVersion.h in the composed artifacts still contains the 1000.0.0 dev sentinel, and the workflow passes the flag whenever a version-type is set. Turns any future regression of the stamping into a red prebuild instead of silently broken community libraries. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
7af1793 to
a1830a7
Compare
|
@cipolleschi good call — dropped the set-then-revert. Reworked it to do what you were pointing at: the compose job now consumes the stamped I scoped it strictly to |
cipolleschi
left a comment
There was a problem hiding this comment.
Thanks for acting on the feedback
|
@cipolleschi has imported this pull request. If you are a Meta employee, you can view this in D113005220. |
|
@cipolleschi merged this pull request in 95df500. |
Summary
prebuild-ios-core.ymlbuilds the prebuilt iOS core in two jobs:build-rn-slicecompiles the React binary per platform slice, andcompose-xcframeworkruns afterwards in its own fresh checkout, downloads the slice artifacts, and composes the shippedReact.xcframework+ReactNativeHeaders.xcframework— re-deriving the shipped headers from that checkout.The "Set React Native version" step runs only in
build-rn-slice. So the compiled binary is stamped, but the composed headers are not: the artifact shipsReactNativeVersion.hwith the1000.0.0dev sentinel, internally inconsistent with its own binary (and with the npm package, which is stamped in its own publish job).This was latent for as long as the compose job has existed — it only started breaking consumers now because the header-facades / VFS-overlay-removal work changed which file libraries actually read. Previously header resolution (the VFS overlay, and the
Pods/Headers/Publicsymlinks of the source pods) redirected reads to the stamped npm copy, so the sentinel bytes in the tarball were never consumed. With real materialized headers, the prebuilt copy now wins the search path, and any library gating onREACT_NATIVE_VERSION_MAJOR/MINORcompiles the wrong branch. That breaks[ios] react-native-unistylesin nightly-tests: its#if REACT_NATIVE_VERSION_MINOR >= 81seesMINOR 0and picks a removed pre-0.81 path (shadowNodeFromValue).Fix — built-headers overlay (no re-stamp/revert). The
build-rn-slicejob already stamps its checkout before building and uploads.build/headers, and the compose job already downloads it — it was just unused.stageEntriesnow takes an overlay dir and, forReactNativeVersion.honly, prefers the built copy (stamped in the slice job) over the source sentinel. Header layout is still spec-derived from source (podspec inventory, collision detection, classification), and every other header still copies from source — so a stale build tree can never ship wrong header content, only the one build-generated version header is overlaid. No stamping of the compose checkout, nogit revert, no cache-key desync.The compose cache key is bumped so pre-fix (unstamped) composed artifacts cached under the old key are not served.
Guard.
headers-verify.jsgains--require-stamped-version(passed when aversion-typeis set) that hard-fails the compose verification if any composedReactNativeVersion.hstill contains the sentinel — turning any future regression into a red prebuild instead of silently broken community libraries.Changelog:
[IOS] [FIXED] - Ship a version-stamped ReactNativeVersion.h in the prebuilt iOS core artifacts instead of the 1000.0.0 dev sentinel
Test Plan
ReactNativeVersion.hseeded into.build/headersand the source tree left at the1000sentinel: all composedReactNativeVersion.hcopies come out stamped (overlay won), while a deliberately stale.build/headers/…/TraceRecordingState.his correctly ignored — the composedTraceRecordingState.h/HostTracingProfile.hcome from source, and other headers + module maps/umbrellas are unaffected (structural gate passes).verifyVersionStampthrows listing the offending files; stamped →version stamp OK (N copies checked); no effect without the flag.react-native-unistyles@3.3.0on Xcode 26.3 (prebuilt mode) and in the Expo prebuilt harness (26.3 + 26.6): stock prebuilt headers reproduce theshadowNodeFromValueerror; the stamped prebuilt header resolves it.🤖 Generated with Claude Code