Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
68f9046
feat(ios): headers-spec layout + ReactNativeHeaders compose
chrfalch Jun 18, 2026
705b310
refactor(ios): remove clang VFS overlay, resolve headers via frameworks
chrfalch Jun 18, 2026
9ee4199
fix(ios): serve the react/ namespace as a module for SPM consumers
chrfalch Jun 21, 2026
18735a0
fix(cocoapods): install prebuilt RNCore pods as header-less facades
chrfalch Jun 22, 2026
02f3500
style: apply prettier to ios-prebuild scripts and docs
chrfalch Jun 22, 2026
977f1ae
ci(ios): include ReactNativeHeaders.xcframework in the prebuilt core …
chrfalch Jun 22, 2026
ec979d3
feat(ios): expose allowlisted private React headers in the React modu…
chrfalch Jun 23, 2026
556abab
feat(ios): emit per-namespace umbrella for React_RCTAppDelegate (R10)
chrfalch Jun 23, 2026
e53e6b2
fix(ios): re-vend RCTFabricComponentsPlugins.h from the React-RCTFabr…
chrfalch Jun 24, 2026
42d8310
fix(ios-prebuild): fail closed when a deps namespace is missing from …
chrfalch Jun 24, 2026
51d4e7e
fix(ios-prebuild): stage deps headers in compose-xcframework + sort t…
chrfalch Jun 25, 2026
7b3be97
fix(ios): harden prebuilt header layout consumption (review findings)
chrfalch Jul 3, 2026
cd67dee
feat(ios-prebuild): generator-time headers gate + drift hardening (R1…
chrfalch Jul 3, 2026
e6ab638
style: prettier-format headers-rules.md (format-check lints md too)
chrfalch Jul 3, 2026
6648f90
style: add language tags to headers-rules.md fenced blocks (markdownl…
chrfalch Jul 3, 2026
dcb5ad8
style: sort requires in headers-inventory.js (eslint sort-imports, ma…
chrfalch Jul 3, 2026
b4b1a94
fix(ios-prebuild): do not relocate SocketRocket headers into ReactNat…
chrfalch Jul 3, 2026
24a65c9
fix(ios-prebuild): address review — enforce inventory collisions, har…
chrfalch Jul 8, 2026
1e995d2
fix(ios-prebuild): sort child_process requires alphabetically (eslint…
chrfalch Jul 9, 2026
052b7f9
fix(ios-prebuild): make cp clonefile flag platform-conditional
chrfalch Jul 9, 2026
f8f5eb2
fix(ios-prebuild): execFileSync arg arrays for the stub-xcframework t…
chrfalch Jul 10, 2026
2603d7f
feat(ios-prebuild): embed React.framework's non-header resources for …
chrfalch Jun 22, 2026
6326810
fix(cocoapods): define podspec_dir in RNCoreFacades.generate
chrfalch Jun 25, 2026
0c7a28a
fix(ios-prebuild): address review on prebuilt framework resources
chrfalch Jul 8, 2026
1d64d26
fix(ios-prebuild): resolve Flow errors in framework-resources.js
chrfalch Jul 9, 2026
7b29638
fix(ios-prebuild): use platform-conditional cp flags for the i18n bun…
chrfalch Jul 9, 2026
3aa78b0
fix(ios): warn in dev when RCTI18nStrings.bundle cannot be resolved
chrfalch Jul 10, 2026
c337763
fix(ios-prebuild): allowlist + drift gate for React.framework privacy…
chrfalch Jul 10, 2026
d2a7841
fix(cocoapods): harden prebuilt-deps header search paths and artifact…
chrfalch Jul 6, 2026
31a1929
feat(cocoapods): dependency-only facades for third-party pods in preb…
chrfalch Jul 6, 2026
620c59a
feat(ios-prebuild): SocketRocket privacy manifest + Xcode 26 header l…
chrfalch Jul 6, 2026
a59d1b4
chore: prettier formatting for prebuilt-deps doc and configuration.js
chrfalch Jul 6, 2026
5b90f71
fix(cocoapods): address review on dependency-only facades
chrfalch Jul 8, 2026
665f06a
fix(cocoapods): dedup prebuilt HEADER_SEARCH_PATHS; keep the FACADE_P…
chrfalch Jul 10, 2026
14e1502
feat(ios-prebuild): emit ReactNativeDependenciesHeaders.xcframework s…
chrfalch Jul 6, 2026
582f9bd
feat(ios-prebuild)!: make ReactNativeHeaders pure-RN
chrfalch Jul 6, 2026
8009b39
ci: cover rn-tester with prebuilt artifacts + dynamic frameworks
chrfalch Jul 6, 2026
e39bed8
feat(releases): publish ReactNativeHeaders + ReactNativeDependenciesH…
chrfalch Jul 6, 2026
68b0ac4
test: update verifyArtifactsAreOnMaven test for classifier HEAD-checks
chrfalch Jul 6, 2026
dfb6e45
fix(ios-prebuild): address review on the deps-headers sidecar
chrfalch Jul 8, 2026
318719f
fix(ios-prebuild): resolve Flow errors in headers-xcframework-test
chrfalch Jul 9, 2026
906124d
fix(ios-prebuild): platform-conditional cp flags in the deps headers …
chrfalch Jul 9, 2026
52f008c
fix(ios-prebuild): hash every compose-tooling sibling into the recomp…
chrfalch Jul 10, 2026
7d4ffe2
fix(ios-prebuild): carry the execFileSync refactor into headers-xcfra…
chrfalch Jul 10, 2026
9785803
fix(ios-prebuild): flow strict-local + prettier cleanup for the compo…
chrfalch Jul 10, 2026
6d13db7
feat(spm): SwiftPM package generation tooling
chrfalch Jun 20, 2026
a22d10b
feat(spm): rn-tester + helloworld SPM consumption & test library
chrfalch Jun 20, 2026
881e389
feat(spm): drop consumer-side headers compose; don't ship build-only …
chrfalch Jun 22, 2026
0b87465
feat(spm): redesign `react-native spm` to add/update/deinit; drop fro…
chrfalch Jun 25, 2026
debe5f9
fix(spm): Flow/ESLint/Prettier compliance for the SPM tooling
chrfalch Jun 25, 2026
57d09a7
chore(spm): drop in-repo SPM example xcodeprojs from rn-tester/hellow…
chrfalch Jun 25, 2026
418cfd9
feat(spm): wire ReactNativeDependenciesHeaders as the 5th binaryTarget
chrfalch Jul 6, 2026
536c1ed
fix(spm): migration fixes surfaced by rn-tester + helloworld SPM builds
chrfalch Jul 6, 2026
ba23950
fix(spm): harden shell usage + hashing flagged by CodeQL
chrfalch Jul 6, 2026
b2ce9b7
docs(spm): mark preview, fix fresh-clone/CI + stale VFS, SwiftPM naming
chrfalch Jul 7, 2026
ff889b8
fix(spm): detect install_modules_dependencies as an implicit React-co…
chrfalch Jul 8, 2026
a0040aa
feat(spm): framework autolinking plugins for `react-native spm` (Prev…
chrfalch Jul 8, 2026
04efa69
test(spm): regression-test the autolinking plugin-host exemption
chrfalch Jul 8, 2026
5fb940d
fix(spm): address review — Majors, minors, CodeQL + local-build ergon…
chrfalch Jul 8, 2026
4cab45d
fix(spm): SwiftPM Release support — NDEBUG propagation, hermesc, loca…
chrfalch Jul 8, 2026
89c8e9e
fix(spm): complete SwiftPM Release fixes surfaced by the build matrix
chrfalch Jul 8, 2026
e7b1f43
feat(spm): automatic Debug/Release flavor swap for SwiftPM
chrfalch Jul 8, 2026
50c94ca
feat(ios-prebuild): fold Hermes headers into the published ReactNativ…
chrfalch Jul 9, 2026
6e7defe
fix(spm): resolve Flow errors in download-spm-artifacts and swap-flavor
chrfalch Jul 9, 2026
35afc53
fix(spm): drop unnecessary \$ escapes in generated shell comments (es…
chrfalch Jul 9, 2026
b59f3f3
test(spm): mock plutil in swap-flavor-test for Linux CI
chrfalch Jul 9, 2026
f070241
fix(spm): dependency-free dispatch for the build-phase flavor swap an…
chrfalch Jul 9, 2026
33ea72e
fix(spm): remove the template's dangling JavaScriptCore.framework ref…
chrfalch Jul 9, 2026
db10901
fix(spm): deterministic Debug/Release flavor swap + plugin flavoredAr…
chrfalch Jul 9, 2026
c50e2ef
feat(spm): wire plugin generatedSources into the app target
chrfalch Jul 9, 2026
186b497
feat(spm): manifest+plugin watch paths, artifact version pinning, tem…
chrfalch Jul 9, 2026
efa4085
fix(spm): delete the embedded-flavor phase; hard-fail + converge on f…
chrfalch Jul 9, 2026
1992a18
fix(spm): invalidate Swift explicit-module + build-description caches…
chrfalch Jul 9, 2026
761a10a
fix(spm): preserve flavor pin in update; derive fresh-state flavor fr…
chrfalch Jul 9, 2026
58a2673
feat(spm): B1 flavor architecture — per-config linking + RN-owned emb…
chrfalch Jul 10, 2026
f3724c0
fix(spm): drop the plist npm dependency from flavored-frameworks
chrfalch Jul 10, 2026
b0a5081
fix(spm): lint/flow cleanup in the flavored-frameworks tests
chrfalch Jul 10, 2026
f18dc29
fix(ios): resolve hermesc for SwiftPM apps in react-native-xcode.sh
chrfalch Jul 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/actions/build-npm-package/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ runs:
pattern: ReactCore*
path: ./packages/react-native/ReactAndroid/external-artifacts/artifacts
merge-multiple: true
# ReactNativeDependenciesHeaders* is already covered by the
# ReactNativeDependencies* pattern above; ReactNativeHeaders* needs its own.
- name: Download ReactNativeHeaders artifacts
if: ${{ inputs.skip-apple-prebuilts != 'true' }}
uses: actions/download-artifact@v7
with:
pattern: ReactNativeHeaders*
path: ./packages/react-native/ReactAndroid/external-artifacts/artifacts
merge-multiple: true
- name: Print Artifacts Directory
if: ${{ inputs.skip-apple-prebuilts != 'true' }}
shell: bash
Expand Down
43 changes: 36 additions & 7 deletions .github/actions/test-ios-rntester/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,18 @@ inputs:
required: false
default: false
use-frameworks:
description: Whether we have to build with Dynamic Frameworks. If this is set to true, it builds from source
description: Whether we have to build with Dynamic Frameworks.
required: false
default: false
use-prebuilds:
description: >-
Whether to consume the prebuilt ReactCore/ReactNativeDependencies
artifacts. 'auto' (default) keeps the historical coupling: prebuilds for
static, source for dynamic frameworks. Pass 'true' with
use-frameworks:true for the prebuilt + dynamic-frameworks lane (the
config of the 2026-07-03 SocketRocket dual-copy regression).
required: false
default: auto

runs:
using: composite
Expand All @@ -41,33 +50,53 @@ runs:
- name: Prepare IOS Tests
if: ${{ inputs.run-unit-tests == 'true' }}
uses: ./.github/actions/prepare-ios-tests
- name: Resolve prebuilds mode
id: prebuilds
shell: bash
run: |
if [[ "${{ inputs.use-prebuilds }}" == "auto" ]]; then
# Historical coupling: prebuilds for static, source for dynamic frameworks.
if [[ "${{ inputs.use-frameworks }}" == "true" ]]; then
echo "enabled=false" >> "$GITHUB_OUTPUT"
else
echo "enabled=true" >> "$GITHUB_OUTPUT"
fi
elif [[ "${{ inputs.use-prebuilds }}" == "true" ]]; then
echo "enabled=true" >> "$GITHUB_OUTPUT"
elif [[ "${{ inputs.use-prebuilds }}" == "false" ]]; then
echo "enabled=false" >> "$GITHUB_OUTPUT"
else
# Don't silently treat a typo as 'disabled' — surface it.
echo "::warning::Unexpected use-prebuilds value '${{ inputs.use-prebuilds }}' (expected auto/true/false); treating as disabled."
echo "enabled=false" >> "$GITHUB_OUTPUT"
fi
- name: Download ReactNativeDependencies
if: ${{ inputs.use-frameworks == 'false' }}
if: ${{ steps.prebuilds.outputs.enabled == 'true' }}
uses: actions/download-artifact@v7
with:
name: ReactNativeDependencies${{ inputs.flavor }}.xcframework.tar.gz
path: /tmp/third-party/
- name: Print third-party folder
if: ${{ inputs.use-frameworks == 'false' }}
if: ${{ steps.prebuilds.outputs.enabled == 'true' }}
shell: bash
run: ls -lR /tmp/third-party
- name: Download React Native Prebuilds
if: ${{ inputs.use-frameworks == 'false' }}
if: ${{ steps.prebuilds.outputs.enabled == 'true' }}
uses: actions/download-artifact@v7
with:
name: ReactCore${{ inputs.flavor }}.xcframework.tar.gz
path: /tmp/ReactCore
- name: Print ReactCore folder
if: ${{ inputs.use-frameworks == 'false' }}
if: ${{ steps.prebuilds.outputs.enabled == 'true' }}
shell: bash
run: ls -lR /tmp/ReactCore
- name: Install CocoaPods dependencies
shell: bash
run: |
if [[ ${{ inputs.use-frameworks }} == "true" ]]; then
export USE_FRAMEWORKS=dynamic
else
# If use-frameworks is false, let's use prebuilds
fi
if [[ "${{ steps.prebuilds.outputs.enabled }}" == "true" ]]; then
export RCT_USE_LOCAL_RN_DEP="/tmp/third-party/ReactNativeDependencies${{ inputs.flavor }}.xcframework.tar.gz"
export RCT_TESTONLY_RNCORE_TARBALL_PATH="/tmp/ReactCore/ReactCore${{ inputs.flavor }}.xcframework.tar.gz"
fi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,47 @@ jest.mock('../utils.js', () => ({
process.exit = mockExit;
global.fetch = mockFetch;

const BASE_URL =
'https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts';

// The verifier HEAD-checks the POM plus every classifier tarball attached to
// the react-native-artifacts publication (external-artifacts/build.gradle.kts).
const expectedUrls = version => [
`${BASE_URL}/${version}/react-native-artifacts-${version}.pom`,
...[
'reactnative-core-debug',
'reactnative-core-release',
'reactnative-dependencies-debug',
'reactnative-dependencies-release',
'reactnative-headers-debug',
'reactnative-headers-release',
'reactnative-dependencies-headers-debug',
'reactnative-dependencies-headers-release',
].map(
classifier =>
`${BASE_URL}/${version}/react-native-artifacts-${version}-${classifier}.tar.gz`,
),
];

describe('#verifyArtifactsAreOnMaven', () => {
beforeEach(jest.clearAllMocks);

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

const version = '0.78.1';
await verifyArtifactsAreOnMaven(version);

expect(mockSleep).toHaveBeenCalledTimes(1);
expect(mockFetch).toHaveBeenCalledWith(
'https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.78.1/react-native-artifacts-0.78.1.pom',
);
for (const url of expectedUrls('0.78.1')) {
expect(mockFetch).toHaveBeenCalledWith(url, {method: 'HEAD'});
}
});

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

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

expect(mockSleep).toHaveBeenCalledTimes(1);
expect(mockFetch).toHaveBeenCalledWith(
'https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.78.1/react-native-artifacts-0.78.1.pom',
);
for (const url of expectedUrls('0.78.1')) {
expect(mockFetch).toHaveBeenCalledWith(url, {method: 'HEAD'});
}
});

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

const version = '0.78.1';
await verifyArtifactsAreOnMaven(version);

expect(mockSleep).toHaveBeenCalledTimes(0);
expect(mockFetch).toHaveBeenCalledWith(
'https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.78.1/react-native-artifacts-0.78.1.pom',
);
// All nine URLs (POM + 8 classifier tarballs) are verified in one pass.
expect(mockFetch).toHaveBeenCalledTimes(9);
for (const url of expectedUrls('0.78.1')) {
expect(mockFetch).toHaveBeenCalledWith(url, {method: 'HEAD'});
}
});

it('waits when a classifier artifact is missing even though the POM exists', async () => {
mockSleep.mockReturnValueOnce(Promise.resolve()).mockImplementation(() => {
throw new Error('Should not be called again!');
});
// First attempt: POM ok, first classifier missing. Second attempt: all ok.
mockFetch
.mockReturnValueOnce(Promise.resolve({status: 200}))
.mockReturnValueOnce(Promise.resolve({status: 404}))
.mockReturnValue(Promise.resolve({status: 200}));

const version = '0.78.1';
await verifyArtifactsAreOnMaven(version);

expect(mockSleep).toHaveBeenCalledTimes(1);
expect(mockExit).not.toHaveBeenCalled();
});

it('tries 90 times and then exits', async () => {
Expand All @@ -82,6 +124,7 @@ describe('#verifyArtifactsAreOnMaven', () => {
expect(mockExit).toHaveBeenCalledWith(1);
expect(mockFetch).toHaveBeenCalledWith(
'https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.78.1/react-native-artifacts-0.78.1.pom',
{method: 'HEAD'},
);
});
});
48 changes: 39 additions & 9 deletions .github/workflow-scripts/verifyArtifactsAreOnMaven.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* @format
*/

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

const SLEEP_S = 60; // 1 minute
Expand All @@ -15,23 +16,52 @@ const ARTIFACT_URL =
'https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/';
const ARTIFACT_NAME = 'react-native-artifacts-';

// The primary xcframework classifier tarballs attached to the
// react-native-artifacts publication (external-artifacts/build.gradle.kts).
// The 4 dSYM classifiers (core/deps dSYM debug+release) are intentionally
// excluded — they are debug-symbol sidecars, not consumed at install time.
// The POM check alone would pass even when a classifier artifact never made
// it to Maven.
const ARTIFACT_CLASSIFIERS = [
'reactnative-core-debug',
'reactnative-core-release',
'reactnative-dependencies-debug',
'reactnative-dependencies-release',
'reactnative-headers-debug',
'reactnative-headers-release',
'reactnative-dependencies-headers-debug',
'reactnative-dependencies-headers-release',
];

async function verifyArtifactsAreOnMaven(version, retries = MAX_RETRIES) {
if (version.startsWith('v')) {
version = version.substring(1);
}

const artifactUrl = `${ARTIFACT_URL}${version}/${ARTIFACT_NAME}${version}.pom`;
const urls = [
`${ARTIFACT_URL}${version}/${ARTIFACT_NAME}${version}.pom`,
...ARTIFACT_CLASSIFIERS.map(
classifier =>
`${ARTIFACT_URL}${version}/${ARTIFACT_NAME}${version}-${classifier}.tar.gz`,
),
];
for (let currentAttempt = 1; currentAttempt <= retries; currentAttempt++) {
const response = await fetch(artifactUrl);

if (response.status !== 200) {
log(
`${currentAttempt}) Artifact's for version ${version} are not on maven yet.\nURL: ${artifactUrl}\nLet's wait a minute and try again.\n`,
);
await sleep(SLEEP_S);
} else {
let missingUrl = null;
for (const url of urls) {
const response = await fetch(url, {method: 'HEAD'});
if (response.status !== 200) {
missingUrl = url;
break;
}
}

if (missingUrl == null) {
return;
}
log(
`${currentAttempt}) Artifact's for version ${version} are not on maven yet.\nURL: ${missingUrl}\nLet's wait a minute and try again.\n`,
);
await sleep(SLEEP_S);
}

log(
Expand Down
52 changes: 49 additions & 3 deletions .github/workflows/prebuild-ios-core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ jobs:
uses: actions/cache/restore@v5
with:
path: packages/react-native/.build/output/xcframeworks
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/**/*') }}
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/**/*') }}
- name: Setup node.js
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
uses: ./.github/actions/setup-node
Expand All @@ -157,6 +157,24 @@ jobs:
pattern: prebuild-ios-core-headers-${{ matrix.flavor }}-*
path: packages/react-native/.build/headers
merge-multiple: true
- name: Download ReactNativeDependencies
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
uses: actions/download-artifact@v7
with:
name: ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz
path: /tmp/third-party/
- name: Extract ReactNativeDependencies
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
shell: bash
run: |
# ReactNativeHeaders.xcframework is pure-RN (the deps namespaces ship
# in the ReactNativeDependenciesHeaders sidecar built by the deps
# prebuild), but the headers-verify compile gates still need the deps
# headers on their include path (folly/glog/... reached from RN's
# public headers), so the deps artifact is staged here too.
tar -xzf /tmp/third-party/ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz -C /tmp/third-party/
mkdir -p packages/react-native/third-party/
mv /tmp/third-party/packages/react-native/third-party/ReactNativeDependencies.xcframework packages/react-native/third-party/ReactNativeDependencies.xcframework
- name: Setup Keychain
if: ${{ steps.restore-ios-xcframework.outputs.cache-hit != 'true' && env.REACT_ORG_CODE_SIGNING_P12_CERT != '' }}
uses: apple-actions/import-codesign-certs@v3 # https://github.com/marketplace/actions/import-code-signing-certificates
Expand All @@ -173,16 +191,38 @@ jobs:
run: |
cd packages/react-native
node scripts/ios-prebuild -c -f "${{ matrix.flavor }}" -i "React Org"
- name: Verify composed headers
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
run: |
# Generator-time header gate: include-health ratchet, structural
# byte-compare of module maps/umbrellas against the spec render, and
# compile smokes (React module + every namespace module + the
# privileged-consumer/Expo fixtures). Catches consumer-facing header
# regressions here instead of in downstream builds.
cd packages/react-native
node scripts/ios-prebuild/headers-verify.js --flavor "${{ matrix.flavor }}"
- name: Compress and Rename XCFramework
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
run: |
cd packages/react-native/.build/output/xcframeworks/${{matrix.flavor}}
tar -cz -f ../ReactCore${{matrix.flavor}}.xcframework.tar.gz React.xcframework
# Ship BOTH xcframeworks: React-Core-prebuilt's prepare_command flattens
# ReactNativeHeaders.xcframework's Headers (incl. module.modulemap) into the
# pod. Omitting it leaves consumers without React-Core-prebuilt/Headers/module.modulemap.
tar -cz -f ../ReactCore${{matrix.flavor}}.xcframework.tar.gz React.xcframework ReactNativeHeaders.xcframework
- name: Compress and Rename dSYM
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
run: |
cd packages/react-native/.build/output/xcframeworks/${{matrix.flavor}}/Symbols
tar -cz -f ../../ReactCore${{ matrix.flavor }}.framework.dSYM.tar.gz .
- name: Rename ReactNativeHeaders XCFramework tarball
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
run: |
# The compose step already tars ReactNativeHeaders.xcframework standalone;
# published as its own Maven artifact (classifier reactnative-headers-*)
# so SwiftPM consumers can wire it as a separate binaryTarget. It also
# ships inside the ReactCore tarball for the CocoaPods pod.
cp packages/react-native/.build/output/xcframeworks/${{matrix.flavor}}/ReactNativeHeaders.xcframework.tar.gz \
packages/react-native/.build/output/xcframeworks/ReactNativeHeaders${{matrix.flavor}}.xcframework.tar.gz
- name: Upload XCFramework Artifact
uses: actions/upload-artifact@v6
with:
Expand All @@ -193,11 +233,17 @@ jobs:
with:
name: ReactCore${{ matrix.flavor }}.framework.dSYM.tar.gz
path: packages/react-native/.build/output/xcframeworks/ReactCore${{matrix.flavor}}.framework.dSYM.tar.gz
- name: Upload ReactNativeHeaders XCFramework Artifact
uses: actions/upload-artifact@v6
with:
name: ReactNativeHeaders${{ matrix.flavor }}.xcframework.tar.gz
path: packages/react-native/.build/output/xcframeworks/ReactNativeHeaders${{matrix.flavor}}.xcframework.tar.gz
- name: Save cache if present
if: ${{ github.ref == 'refs/heads/main' }} # To avoid that the cache explode
uses: actions/cache/save@v5
with:
path: |
packages/react-native/.build/output/xcframeworks/ReactCore${{matrix.flavor}}.xcframework.tar.gz
packages/react-native/.build/output/xcframeworks/ReactCore${{matrix.flavor}}.framework.dSYM.tar.gz
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/**/*') }}
packages/react-native/.build/output/xcframeworks/ReactNativeHeaders${{matrix.flavor}}.xcframework.tar.gz
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/**/*') }}
Loading
Loading