Skip to content

Commit 6aa147f

Browse files
chrfalchmeta-codesync[bot]
authored andcommitted
feat(iOS): ReactNativeDependenciesHeaders sidecar + pure-RN ReactNativeHeaders, published to Maven (#57442)
Summary: Step 2 of the prebuilt-deps roadmap: ship the deps headers as a **SwiftPM-ready, self-contained artifact** and make every header namespace have exactly **one physical home**. 1. **New artifact: `ReactNativeDependenciesHeaders.xcframework`** — the binary `ReactNativeDependencies.xcframework` is framework-type, so its root `Headers/` is invisible to SwiftPM binaryTargets (`HeadersPath` is rejected on framework entries; verified empirically). The deps prebuild now emits a headers-only library-type sidecar (stub archives + per-slice `Headers/` + `HeadersPath` — the exact `ReactNativeHeaders` recipe, factored into a shared `headers-xcframework.js` emitter) carrying all seven deps namespaces incl. SocketRocket, with slice parity derived from the binary artifact's Info.plist. Ships inside the deps tarball *and* standalone. 2. **`ReactNativeHeaders` goes pure-RN** — the R2 relocation of deps namespaces (and the `DEPS_NAMESPACES_NOT_RELOCATED` SocketRocket exclusion list) is deleted. Relocated copies are what enabled the SocketRocket dual-copy regression (duplicate `interface` / poisoned module graph under `use_frameworks!`); that bug class is now structurally impossible. Headers gate flipped: deps namespaces must be **absent** from RNH; the sidecar emitter enforces set-equality with `DEPS_NAMESPACES` fail-closed in both directions. On the CocoaPods side, a new `ReactNativeDependenciesUtils.configure_aggregate_xcconfig` injects the deps pod's `Headers/` globally (aggregate + every pod target), mirroring the rncore injection — this replaces the folly/glog resolution pods previously got via the flattened `React-Core-prebuilt/Headers`. 3. **CI: prebuilt + dynamic-frameworks lane** — the regression's exact config had no coverage (the `test-ios-rntester` action hard-coupled `use-frameworks:true` to source builds). New `use-prebuilds` input; `test_ios_rntester`'s dynamic cells now consume the workflow-built prebuilt artifacts. 4. **Maven publishing** — `ReactNativeHeaders` and `ReactNativeDependenciesHeaders` publish standalone on `react-native-artifacts` (classifiers `reactnative-headers-*`, `reactnative-dependencies-headers-*`); `verifyArtifactsAreOnMaven` now HEAD-checks every classifier tarball instead of only the POM. Stacked on #57440. The SwiftPM preview (#57332) rebases on top and wires the sidecar as its 5th binaryTarget. ## Changelog: [IOS] [CHANGED] - Prebuilt artifacts: ReactNativeHeaders is pure-RN; third-party deps headers ship in the new ReactNativeDependenciesHeaders.xcframework sidecar (and the ReactNativeDependencies pod), published standalone to Maven Pull Request resolved: #57442 Test Plan: - Headers gate: include-health, structural (deps absent from RNH, byte-matched module maps), and compile smokes (React module + 14 namespace modules + Expo-shape ObjC++/Swift fixtures vs the deps include path) — ALL PASSED - jest: 33/33 (`scripts/ios-prebuild/__tests__`, incl. new sidecar set-equality tests) - ESLint (`--max-warnings 0`), Prettier, Flow (`yarn flow-check`): clean - E2E (locally built artifacts): rn-tester prebuilt static ✅, prebuilt `USE_FRAMEWORKS=dynamic` ✅ (the regression config — verified `React-Core-prebuilt/Headers` contains no deps namespaces and the deps pod serves all seven), helloworld static ✅, source-core + prebuilt-deps ✅ (React compiled from source resolves folly via the deps pod), source-mode control with unchanged dependency graph ✅ - Sidecar inspected: per-slice `HeadersPath`, 7 namespaces, slice parity with the binary - Publication validated end-to-end with `publishReleasePublicationToMavenLocal`: all 12 files + POM land with the expected classifier names 🤖 Generated with [Claude Code](https://claude.com/claude-code) Reviewed By: fabriziocucci Differential Revision: D111449462 Pulled By: cipolleschi fbshipit-source-id: e1217d14c0588d00a207622d346c9e6f4705a95d
1 parent a8156ac commit 6aa147f

25 files changed

Lines changed: 975 additions & 254 deletions

.github/actions/build-npm-package/action.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ runs:
3131
pattern: ReactCore*
3232
path: ./packages/react-native/ReactAndroid/external-artifacts/artifacts
3333
merge-multiple: true
34+
# ReactNativeDependenciesHeaders* is already covered by the
35+
# ReactNativeDependencies* pattern above; ReactNativeHeaders* needs its own.
36+
- name: Download ReactNativeHeaders artifacts
37+
if: ${{ inputs.skip-apple-prebuilts != 'true' }}
38+
uses: actions/download-artifact@v7
39+
with:
40+
pattern: ReactNativeHeaders*
41+
path: ./packages/react-native/ReactAndroid/external-artifacts/artifacts
42+
merge-multiple: true
3443
- name: Print Artifacts Directory
3544
if: ${{ inputs.skip-apple-prebuilts != 'true' }}
3645
shell: bash

.github/actions/test-ios-rntester/action.yml

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,18 @@ inputs:
1515
required: false
1616
default: false
1717
use-frameworks:
18-
description: Whether we have to build with Dynamic Frameworks. If this is set to true, it builds from source
18+
description: Whether we have to build with Dynamic Frameworks.
1919
required: false
2020
default: false
21+
use-prebuilds:
22+
description: >-
23+
Whether to consume the prebuilt ReactCore/ReactNativeDependencies
24+
artifacts. 'auto' (default) keeps the historical coupling: prebuilds for
25+
static, source for dynamic frameworks. Pass 'true' with
26+
use-frameworks:true for the prebuilt + dynamic-frameworks lane (the
27+
config of the 2026-07-03 SocketRocket dual-copy regression).
28+
required: false
29+
default: auto
2130

2231
runs:
2332
using: composite
@@ -41,33 +50,53 @@ runs:
4150
- name: Prepare IOS Tests
4251
if: ${{ inputs.run-unit-tests == 'true' }}
4352
uses: ./.github/actions/prepare-ios-tests
53+
- name: Resolve prebuilds mode
54+
id: prebuilds
55+
shell: bash
56+
run: |
57+
if [[ "${{ inputs.use-prebuilds }}" == "auto" ]]; then
58+
# Historical coupling: prebuilds for static, source for dynamic frameworks.
59+
if [[ "${{ inputs.use-frameworks }}" == "true" ]]; then
60+
echo "enabled=false" >> "$GITHUB_OUTPUT"
61+
else
62+
echo "enabled=true" >> "$GITHUB_OUTPUT"
63+
fi
64+
elif [[ "${{ inputs.use-prebuilds }}" == "true" ]]; then
65+
echo "enabled=true" >> "$GITHUB_OUTPUT"
66+
elif [[ "${{ inputs.use-prebuilds }}" == "false" ]]; then
67+
echo "enabled=false" >> "$GITHUB_OUTPUT"
68+
else
69+
# Don't silently treat a typo as 'disabled' — surface it.
70+
echo "::warning::Unexpected use-prebuilds value '${{ inputs.use-prebuilds }}' (expected auto/true/false); treating as disabled."
71+
echo "enabled=false" >> "$GITHUB_OUTPUT"
72+
fi
4473
- name: Download ReactNativeDependencies
45-
if: ${{ inputs.use-frameworks == 'false' }}
74+
if: ${{ steps.prebuilds.outputs.enabled == 'true' }}
4675
uses: actions/download-artifact@v7
4776
with:
4877
name: ReactNativeDependencies${{ inputs.flavor }}.xcframework.tar.gz
4978
path: /tmp/third-party/
5079
- name: Print third-party folder
51-
if: ${{ inputs.use-frameworks == 'false' }}
80+
if: ${{ steps.prebuilds.outputs.enabled == 'true' }}
5281
shell: bash
5382
run: ls -lR /tmp/third-party
5483
- name: Download React Native Prebuilds
55-
if: ${{ inputs.use-frameworks == 'false' }}
84+
if: ${{ steps.prebuilds.outputs.enabled == 'true' }}
5685
uses: actions/download-artifact@v7
5786
with:
5887
name: ReactCore${{ inputs.flavor }}.xcframework.tar.gz
5988
path: /tmp/ReactCore
6089
- name: Print ReactCore folder
61-
if: ${{ inputs.use-frameworks == 'false' }}
90+
if: ${{ steps.prebuilds.outputs.enabled == 'true' }}
6291
shell: bash
6392
run: ls -lR /tmp/ReactCore
6493
- name: Install CocoaPods dependencies
6594
shell: bash
6695
run: |
6796
if [[ ${{ inputs.use-frameworks }} == "true" ]]; then
6897
export USE_FRAMEWORKS=dynamic
69-
else
70-
# If use-frameworks is false, let's use prebuilds
98+
fi
99+
if [[ "${{ steps.prebuilds.outputs.enabled }}" == "true" ]]; then
71100
export RCT_USE_LOCAL_RN_DEP="/tmp/third-party/ReactNativeDependencies${{ inputs.flavor }}.xcframework.tar.gz"
72101
export RCT_TESTONLY_RNCORE_TARBALL_PATH="/tmp/ReactCore/ReactCore${{ inputs.flavor }}.xcframework.tar.gz"
73102
fi

.github/workflow-scripts/__tests__/verifyArtifactsAreOnMaven-test.js

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,47 @@ jest.mock('../utils.js', () => ({
2222
process.exit = mockExit;
2323
global.fetch = mockFetch;
2424

25+
const BASE_URL =
26+
'https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts';
27+
28+
// The verifier HEAD-checks the POM plus every classifier tarball attached to
29+
// the react-native-artifacts publication (external-artifacts/build.gradle.kts).
30+
const expectedUrls = version => [
31+
`${BASE_URL}/${version}/react-native-artifacts-${version}.pom`,
32+
...[
33+
'reactnative-core-debug',
34+
'reactnative-core-release',
35+
'reactnative-dependencies-debug',
36+
'reactnative-dependencies-release',
37+
'reactnative-headers-debug',
38+
'reactnative-headers-release',
39+
'reactnative-dependencies-headers-debug',
40+
'reactnative-dependencies-headers-release',
41+
].map(
42+
classifier =>
43+
`${BASE_URL}/${version}/react-native-artifacts-${version}-${classifier}.tar.gz`,
44+
),
45+
];
46+
2547
describe('#verifyArtifactsAreOnMaven', () => {
2648
beforeEach(jest.clearAllMocks);
2749

2850
it('waits for the packages to be published on maven when version has no v', async () => {
2951
mockSleep.mockReturnValueOnce(Promise.resolve()).mockImplementation(() => {
3052
throw new Error('Should not be called again!');
3153
});
54+
// First attempt: the POM is not there yet. Second attempt: every URL is.
3255
mockFetch
3356
.mockReturnValueOnce(Promise.resolve({status: 404}))
34-
.mockReturnValueOnce(Promise.resolve({status: 200}));
57+
.mockReturnValue(Promise.resolve({status: 200}));
3558

3659
const version = '0.78.1';
3760
await verifyArtifactsAreOnMaven(version);
3861

3962
expect(mockSleep).toHaveBeenCalledTimes(1);
40-
expect(mockFetch).toHaveBeenCalledWith(
41-
'https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.78.1/react-native-artifacts-0.78.1.pom',
42-
);
63+
for (const url of expectedUrls('0.78.1')) {
64+
expect(mockFetch).toHaveBeenCalledWith(url, {method: 'HEAD'});
65+
}
4366
});
4467

4568
it('waits for the packages to be published on maven, when version starts with v', async () => {
@@ -48,27 +71,46 @@ describe('#verifyArtifactsAreOnMaven', () => {
4871
});
4972
mockFetch
5073
.mockReturnValueOnce(Promise.resolve({status: 404}))
51-
.mockReturnValueOnce(Promise.resolve({status: 200}));
74+
.mockReturnValue(Promise.resolve({status: 200}));
5275

5376
const version = 'v0.78.1';
5477
await verifyArtifactsAreOnMaven(version);
5578

5679
expect(mockSleep).toHaveBeenCalledTimes(1);
57-
expect(mockFetch).toHaveBeenCalledWith(
58-
'https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.78.1/react-native-artifacts-0.78.1.pom',
59-
);
80+
for (const url of expectedUrls('0.78.1')) {
81+
expect(mockFetch).toHaveBeenCalledWith(url, {method: 'HEAD'});
82+
}
6083
});
6184

6285
it('passes immediately if packages are already on Maven', async () => {
63-
mockFetch.mockReturnValueOnce(Promise.resolve({status: 200}));
86+
mockFetch.mockReturnValue(Promise.resolve({status: 200}));
6487

6588
const version = '0.78.1';
6689
await verifyArtifactsAreOnMaven(version);
6790

6891
expect(mockSleep).toHaveBeenCalledTimes(0);
69-
expect(mockFetch).toHaveBeenCalledWith(
70-
'https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.78.1/react-native-artifacts-0.78.1.pom',
71-
);
92+
// All nine URLs (POM + 8 classifier tarballs) are verified in one pass.
93+
expect(mockFetch).toHaveBeenCalledTimes(9);
94+
for (const url of expectedUrls('0.78.1')) {
95+
expect(mockFetch).toHaveBeenCalledWith(url, {method: 'HEAD'});
96+
}
97+
});
98+
99+
it('waits when a classifier artifact is missing even though the POM exists', async () => {
100+
mockSleep.mockReturnValueOnce(Promise.resolve()).mockImplementation(() => {
101+
throw new Error('Should not be called again!');
102+
});
103+
// First attempt: POM ok, first classifier missing. Second attempt: all ok.
104+
mockFetch
105+
.mockReturnValueOnce(Promise.resolve({status: 200}))
106+
.mockReturnValueOnce(Promise.resolve({status: 404}))
107+
.mockReturnValue(Promise.resolve({status: 200}));
108+
109+
const version = '0.78.1';
110+
await verifyArtifactsAreOnMaven(version);
111+
112+
expect(mockSleep).toHaveBeenCalledTimes(1);
113+
expect(mockExit).not.toHaveBeenCalled();
72114
});
73115

74116
it('tries 90 times and then exits', async () => {
@@ -82,6 +124,7 @@ describe('#verifyArtifactsAreOnMaven', () => {
82124
expect(mockExit).toHaveBeenCalledWith(1);
83125
expect(mockFetch).toHaveBeenCalledWith(
84126
'https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.78.1/react-native-artifacts-0.78.1.pom',
127+
{method: 'HEAD'},
85128
);
86129
});
87130
});

.github/workflow-scripts/verifyArtifactsAreOnMaven.js

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* @format
88
*/
99

10+
// @flow
1011
const {log, sleep} = require('./utils');
1112

1213
const SLEEP_S = 60; // 1 minute
@@ -15,23 +16,64 @@ const ARTIFACT_URL =
1516
'https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/';
1617
const ARTIFACT_NAME = 'react-native-artifacts-';
1718

18-
async function verifyArtifactsAreOnMaven(version, retries = MAX_RETRIES) {
19+
// The primary xcframework classifier tarballs attached to the
20+
// react-native-artifacts publication (external-artifacts/build.gradle.kts).
21+
// The 4 dSYM classifiers (core/deps dSYM debug+release) are intentionally
22+
// excluded — they are debug-symbol sidecars, not consumed at install time.
23+
// The POM check alone would pass even when a classifier artifact never made
24+
// it to Maven.
25+
const ARTIFACT_CLASSIFIERS = [
26+
'reactnative-core-debug',
27+
'reactnative-core-release',
28+
'reactnative-dependencies-debug',
29+
'reactnative-dependencies-release',
30+
'reactnative-headers-debug',
31+
'reactnative-headers-release',
32+
'reactnative-dependencies-headers-debug',
33+
'reactnative-dependencies-headers-release',
34+
];
35+
36+
async function verifyArtifactsAreOnMaven(
37+
version: string,
38+
retries: number = MAX_RETRIES,
39+
): Promise<void> {
1940
if (version.startsWith('v')) {
2041
version = version.substring(1);
2142
}
2243

23-
const artifactUrl = `${ARTIFACT_URL}${version}/${ARTIFACT_NAME}${version}.pom`;
44+
const urls = [
45+
`${ARTIFACT_URL}${version}/${ARTIFACT_NAME}${version}.pom`,
46+
...ARTIFACT_CLASSIFIERS.map(
47+
classifier =>
48+
`${ARTIFACT_URL}${version}/${ARTIFACT_NAME}${version}-${classifier}.tar.gz`,
49+
),
50+
];
2451
for (let currentAttempt = 1; currentAttempt <= retries; currentAttempt++) {
25-
const response = await fetch(artifactUrl);
26-
27-
if (response.status !== 200) {
28-
log(
29-
`${currentAttempt}) Artifact's for version ${version} are not on maven yet.\nURL: ${artifactUrl}\nLet's wait a minute and try again.\n`,
30-
);
31-
await sleep(SLEEP_S);
32-
} else {
52+
let missingUrl = null;
53+
for (const url of urls) {
54+
try {
55+
const response = await fetch(url, {method: 'HEAD'});
56+
if (response.status === 200) {
57+
continue;
58+
}
59+
log(`Got status ${response.status} while checking ${url}`);
60+
} catch (error) {
61+
const message = error instanceof Error ? error.message : String(error);
62+
log(`Network error while checking ${url}: ${message}`);
63+
missingUrl = url;
64+
break;
65+
}
66+
missingUrl = url;
67+
break;
68+
}
69+
70+
if (missingUrl == null) {
3371
return;
3472
}
73+
log(
74+
`${currentAttempt}) Artifact's for version ${version} are not on maven yet.\nURL: ${missingUrl}\nLet's wait a minute and try again.\n`,
75+
);
76+
await sleep(SLEEP_S);
3577
}
3678

3779
log(

.github/workflows/prebuild-ios-core.yml

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ jobs:
133133
uses: actions/cache/restore@v5
134134
with:
135135
path: packages/react-native/.build/output/xcframeworks
136-
key: v2-ios-core-xcframework-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift', 'packages/react-native/scripts/ios-prebuild/*.js', 'packages/react-native/scripts/ios-prebuild.js', 'packages/react-native/React/**/*', 'packages/react-native/ReactCommon/**/*', 'packages/react-native/Libraries/**/*') }}
136+
key: v3-ios-core-xcframework-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift', 'packages/react-native/scripts/ios-prebuild/*.js', 'packages/react-native/scripts/ios-prebuild.js', 'packages/react-native/React/**/*', 'packages/react-native/ReactCommon/**/*', 'packages/react-native/Libraries/**/*') }}
137137
- name: Setup node.js
138138
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
139139
uses: ./.github/actions/setup-node
@@ -167,9 +167,11 @@ jobs:
167167
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
168168
shell: bash
169169
run: |
170-
# ReactNativeHeaders.xcframework (built by the compose step) folds in
171-
# the third-party deps namespaces (folly/glog/boost/...), so the deps
172-
# headers must be staged here too — not just in build-slices.
170+
# ReactNativeHeaders.xcframework is pure-RN (the deps namespaces ship
171+
# in the ReactNativeDependenciesHeaders sidecar built by the deps
172+
# prebuild), but the headers-verify compile gates still need the deps
173+
# headers on their include path (folly/glog/... reached from RN's
174+
# public headers), so the deps artifact is staged here too.
173175
tar -xzf /tmp/third-party/ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz -C /tmp/third-party/
174176
mkdir -p packages/react-native/third-party/
175177
mv /tmp/third-party/packages/react-native/third-party/ReactNativeDependencies.xcframework packages/react-native/third-party/ReactNativeDependencies.xcframework
@@ -212,6 +214,15 @@ jobs:
212214
run: |
213215
cd packages/react-native/.build/output/xcframeworks/${{matrix.flavor}}/Symbols
214216
tar -cz -f ../../ReactCore${{ matrix.flavor }}.framework.dSYM.tar.gz .
217+
- name: Rename ReactNativeHeaders XCFramework tarball
218+
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
219+
run: |
220+
# The compose step already tars ReactNativeHeaders.xcframework standalone;
221+
# published as its own Maven artifact (classifier reactnative-headers-*)
222+
# so SwiftPM consumers can wire it as a separate binaryTarget. It also
223+
# ships inside the ReactCore tarball for the CocoaPods pod.
224+
cp packages/react-native/.build/output/xcframeworks/${{matrix.flavor}}/ReactNativeHeaders.xcframework.tar.gz \
225+
packages/react-native/.build/output/xcframeworks/ReactNativeHeaders${{matrix.flavor}}.xcframework.tar.gz
215226
- name: Upload XCFramework Artifact
216227
uses: actions/upload-artifact@v6
217228
with:
@@ -222,11 +233,17 @@ jobs:
222233
with:
223234
name: ReactCore${{ matrix.flavor }}.framework.dSYM.tar.gz
224235
path: packages/react-native/.build/output/xcframeworks/ReactCore${{matrix.flavor}}.framework.dSYM.tar.gz
236+
- name: Upload ReactNativeHeaders XCFramework Artifact
237+
uses: actions/upload-artifact@v6
238+
with:
239+
name: ReactNativeHeaders${{ matrix.flavor }}.xcframework.tar.gz
240+
path: packages/react-native/.build/output/xcframeworks/ReactNativeHeaders${{matrix.flavor}}.xcframework.tar.gz
225241
- name: Save cache if present
226242
if: ${{ github.ref == 'refs/heads/main' }} # To avoid that the cache explode
227243
uses: actions/cache/save@v5
228244
with:
229245
path: |
230246
packages/react-native/.build/output/xcframeworks/ReactCore${{matrix.flavor}}.xcframework.tar.gz
231247
packages/react-native/.build/output/xcframeworks/ReactCore${{matrix.flavor}}.framework.dSYM.tar.gz
232-
key: v2-ios-core-xcframework-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift', 'packages/react-native/scripts/ios-prebuild/*.js', 'packages/react-native/scripts/ios-prebuild.js', 'packages/react-native/React/**/*', 'packages/react-native/ReactCommon/**/*', 'packages/react-native/Libraries/**/*') }}
248+
packages/react-native/.build/output/xcframeworks/ReactNativeHeaders${{matrix.flavor}}.xcframework.tar.gz
249+
key: v3-ios-core-xcframework-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift', 'packages/react-native/scripts/ios-prebuild/*.js', 'packages/react-native/scripts/ios-prebuild.js', 'packages/react-native/React/**/*', 'packages/react-native/ReactCommon/**/*', 'packages/react-native/Libraries/**/*') }}

.github/workflows/prebuild-ios-dependencies.yml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ jobs:
130130
with:
131131
path: |
132132
packages/react-native/third-party/
133-
key: v3-ios-dependencies-xcframework-${{ matrix.flavor }}-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js') }}
133+
key: v5-ios-dependencies-xcframework-${{ matrix.flavor }}-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js', 'scripts/releases/ios-prebuild/compose-framework.js', 'packages/react-native/scripts/ios-prebuild/headers-xcframework.js', 'packages/react-native/scripts/ios-prebuild/headers-spec.js') }}
134134
# If cache hit, we already have our binary. We don't need to do anything.
135135
- name: Yarn Install
136136
if: steps.restore-xcframework.outputs.cache-hit != 'true'
@@ -164,7 +164,13 @@ jobs:
164164
if: steps.restore-xcframework.outputs.cache-hit != 'true'
165165
run: |
166166
tar -cz -f packages/react-native/third-party/ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz \
167-
packages/react-native/third-party/ReactNativeDependencies.xcframework
167+
packages/react-native/third-party/ReactNativeDependencies.xcframework \
168+
packages/react-native/third-party/ReactNativeDependenciesHeaders.xcframework
169+
- name: Compress Headers Sidecar XCFramework
170+
if: steps.restore-xcframework.outputs.cache-hit != 'true'
171+
run: |
172+
tar -cz -f packages/react-native/third-party/ReactNativeDependenciesHeaders${{ matrix.flavor }}.xcframework.tar.gz \
173+
packages/react-native/third-party/ReactNativeDependenciesHeaders.xcframework
168174
- name: Show Symbol folder content
169175
if: steps.restore-xcframework.outputs.cache-hit != 'true'
170176
run: ls -lR packages/react-native/third-party/Symbols
@@ -179,6 +185,11 @@ jobs:
179185
with:
180186
name: ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz
181187
path: packages/react-native/third-party/ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz
188+
- name: Upload Headers Sidecar XCFramework Artifact
189+
uses: actions/upload-artifact@v6
190+
with:
191+
name: ReactNativeDependenciesHeaders${{ matrix.flavor }}.xcframework.tar.gz
192+
path: packages/react-native/third-party/ReactNativeDependenciesHeaders${{ matrix.flavor }}.xcframework.tar.gz
182193
- name: Upload dSYM Artifact
183194
uses: actions/upload-artifact@v6
184195
with:
@@ -191,5 +202,6 @@ jobs:
191202
with:
192203
path: |
193204
packages/react-native/third-party/ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz
205+
packages/react-native/third-party/ReactNativeDependenciesHeaders${{ matrix.flavor }}.xcframework.tar.gz
194206
packages/react-native/third-party/ReactNativeDependencies${{ matrix.flavor }}.framework.dSYM.tar.gz
195-
key: v3-ios-dependencies-xcframework-${{ matrix.flavor }}-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js') }}
207+
key: v5-ios-dependencies-xcframework-${{ matrix.flavor }}-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js', 'scripts/releases/ios-prebuild/compose-framework.js', 'packages/react-native/scripts/ios-prebuild/headers-xcframework.js', 'packages/react-native/scripts/ios-prebuild/headers-spec.js') }}

0 commit comments

Comments
 (0)