Skip to content

Conversation

@kraenhansen
Copy link
Collaborator

@kraenhansen kraenhansen commented Oct 27, 2025

Merging this PR will:

  • Use the caller-stack when patching hermes as a heuristics for determining the correct value to pass into --react-native-package - fixing Support vendoring Hermes for out-of-tree platforms #270
  • Remove a restriction in the Host package Podspec limiting this to iOS in a specific version - since we don't really depend on the iOS SDK, I believe we can remove the limitation entirely.
  • Add script to init a MacOS test app
  • Add a job in the check workflow to initialize and build the MacOS test app - fixing Initialize and run a MacOS test app on CI #296

Note how the CI job prints this while pod installing:

[Node-API] Using overridden Hermes in "/Users/runner/work/react-native-node-api/react-native-node-api/apps/macos-test-app/node_modules/react-native-macos/sdks/node-api-hermes"

@kraenhansen kraenhansen self-assigned this Oct 27, 2025
@kraenhansen kraenhansen added CI Continuous integration Apple 🍎 Anything related to the Apple platform (iOS, macOS, Cocoapods, Xcode, XCFrameworks, etc.) Host 🏡 Our `react-native-node-api-modules` package MacOS 💻 Anything related to the Apple MacOS platform or React Native MacOS support labels Oct 27, 2025
@kraenhansen kraenhansen requested a review from shirakaba October 27, 2025 22:19
@kraenhansen kraenhansen marked this pull request as ready for review October 27, 2025 23:36
@kraenhansen kraenhansen requested a review from Copilot October 28, 2025 00:08
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds support for macOS test apps by introducing initialization scripts, CI workflow integration, and fixes for React Native macOS compatibility. The changes enable automated testing on macOS and improve Hermes vendoring detection for react-native-macos.

Key Changes:

  • Added macOS test app initialization script with React Native macOS template setup
  • Implemented caller stack inspection in Ruby script to automatically detect react-native vs react-native-macos
  • Refactored XCFramework slice selection to use prioritized fallback lists instead of single hardcoded paths

Reviewed Changes

Copilot reviewed 7 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tsconfig.scripts.json New TypeScript configuration for scripts directory
scripts/init-macos-test-app.ts Script to initialize and configure a React Native macOS test application
packages/host/scripts/patch-hermes.rb Added automatic detection of React Native package type using caller stack
packages/ferric/src/cargo.ts Changed XCFramework slice mapping from single values to prioritized arrays with fallback logic
package.json Added init-macos-test-app script and read-pkg dependency
.github/workflows/check.yml Added macOS test job with label-based triggering
.changeset/silly-mice-warn.md Changeset documenting Hermes vendoring fix for macOS

- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/jod
Copy link

Copilot AI Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'jod' to 'iron'. The Node.js LTS codename should be 'iron'.

Copilot uses AI. Check for mistakes.
Comment on lines +34 to +36
// "--platform-name",
// "react-native-macos",
Copy link

Copilot AI Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented-out code should be removed. If these options were used during development but are no longer needed, they should be deleted rather than left as comments.

Suggested change
// "--platform-name",
// "react-native-macos",

Copilot uses AI. Check for mistakes.
@kraenhansen kraenhansen force-pushed the kh/macos-test-app branch 3 times, most recently from ecb0fee to ab26a44 Compare October 28, 2025 10:48
@kraenhansen kraenhansen marked this pull request as draft October 28, 2025 16:22
@kraenhansen
Copy link
Collaborator Author

Drafting again as I'll attempt to include running the tests in this PR as well. I believe I'm pretty far, while having difficulties initializing the host TurboModule 🤔

I'm experiencing issues (TurboModuleRegistry.getEnforcing throwing) while registering and initializing a TurboModule using the registerCxxModuleToGlobalModuleMap util from ReactCommon/react/nativemodule/core/ReactCommon/CxxTurboModuleUtils.cpp and I started wondering if this code in ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm is ran by React Native MacOS? I have Hermes and Fabric enabled in the app, if that makes a difference.

@kraenhansen
Copy link
Collaborator Author

@copilot can you add the missing x86_64 Darwin Rust target currently failing the build. I expect this will take just a single step with a single rustup command. Keep it brief, no comments in the workflow. Add only the missing target, nothing more and get some inspiration from how the other targets are added in other jobs of the workflow.

Copy link

Copilot AI commented Oct 28, 2025

@kraenhansen I've opened a new pull request, #298, to work on those changes. Once the pull request is ready, I'll request review from you.

@kraenhansen kraenhansen force-pushed the kh/macos-test-app branch 2 times, most recently from 063b11e to bd42182 Compare October 30, 2025 05:49
@kraenhansen kraenhansen marked this pull request as ready for review November 1, 2025 15:48
@kraenhansen kraenhansen requested a review from Copilot November 1, 2025 15:48
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 22 out of 25 changed files in this pull request and generated 2 comments.

premacos: "killall 'MacOSTestApp' || true",
macos: "react-native run-macos --no-packager",
test: "mocha-remote --exit-on-error -- concurrently --passthrough-arguments --kill-others-on-fail npm:metro 'npm:macos -- {@}' --",
"test:allTests": "MOCHA_REMOTE_CONTEXT=allTests node --run test:ios -- ",
Copy link

Copilot AI Nov 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The script reference 'test:ios' appears incorrect for a macOS test app. This should likely be 'test:macos' or just 'test' to match the other test scripts defined in this file.

Suggested change
"test:allTests": "MOCHA_REMOTE_CONTEXT=allTests node --run test:ios -- ",
"test:allTests": "MOCHA_REMOTE_CONTEXT=allTests node --run test -- ",

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pushed a fix for this 👍

Comment on lines 203 to 213
if (fs.existsSync(versionAPath) && !fs.existsSync(versionCurrentPath)) {
await fs.promises.symlink(
path.relative(path.dirname(versionCurrentPath), versionAPath),
versionCurrentPath,
);
}

const { CFBundleExecutable } = await readFrameworkInfo(
path.join(frameworkPath, "Versions", "Current", "Resources", "Info.plist"),
);

Copy link

Copilot AI Nov 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code creates the 'Current' symlink on line 204-207, then immediately uses it on line 211 to read the Info.plist. However, if the symlink didn't exist before and was just created, the Info.plist path should use 'A' instead of 'Current', or the readFrameworkInfo call should occur before attempting to restore any symlinks.

Suggested change
if (fs.existsSync(versionAPath) && !fs.existsSync(versionCurrentPath)) {
await fs.promises.symlink(
path.relative(path.dirname(versionCurrentPath), versionAPath),
versionCurrentPath,
);
}
const { CFBundleExecutable } = await readFrameworkInfo(
path.join(frameworkPath, "Versions", "Current", "Resources", "Info.plist"),
);
let symlinkJustCreated = false;
if (fs.existsSync(versionAPath) && !fs.existsSync(versionCurrentPath)) {
await fs.promises.symlink(
path.relative(path.dirname(versionCurrentPath), versionAPath),
versionCurrentPath,
);
symlinkJustCreated = true;
}
// If we just created the symlink, use the real path to Info.plist; otherwise, use the symlink path
const infoPlistPath = symlinkJustCreated
? path.join(frameworkPath, "Versions", "A", "Resources", "Info.plist")
: path.join(frameworkPath, "Versions", "Current", "Resources", "Info.plist");
const { CFBundleExecutable } = await readFrameworkInfo(infoPlistPath);

Copilot uses AI. Check for mistakes.
cursor[bot]

This comment was marked as outdated.

Enable Hermes and Fabric

Patch react_native_post_install to pass react native path

Don't pod install when initializing

Patch macos app with scripts and source files

Re-arm the init script

Move linked deps into install command to make --install-links effective

Using regular linking for monorepo deps

Include original dependencies

Enable new arch in Podfile

Fix comment from review
No need to Setup Android SDK

Debugging with Copilot

Pass --mode when building from CLI

Install CMake 3.22

Fix bootstrap issue

Trying a higher CMake version

Remove debug info from workflow

Build universal Darwin libraries

Add missing x86_64-apple-darwin Rust target to macOS CI job (#298)

* Initial plan

* Add missing x86_64-apple-darwin Rust target to macOS job

Co-authored-by: kraenhansen <[email protected]>

* Add only missing x86_64-apple-darwin target (aarch64 is host)

Co-authored-by: kraenhansen <[email protected]>

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: kraenhansen <[email protected]>

Run MacOS test app

Use package script to run all tests
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 9 out of 12 changed files in this pull request and generated 3 comments.

- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/jod
Copy link

Copilot AI Nov 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'jod' to 'jod' - this appears to be a typo for 'iron' (the current Node.js LTS codename).

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot you seem to be outdated on the name of the latest active LTS, please read https://nodejs.org/en/blog/release/v22.11.0 and update your instructions with a brief comment to ensure you won't make that mistake again.


if ENV['REACT_NATIVE_OVERRIDE_HERMES_DIR'].nil?
VENDORED_HERMES_DIR ||= `npx react-native-node-api vendor-hermes --silent '#{Pod::Config.instance.installation_root}'`.strip
VENDORED_HERMES_DIR ||= `npx react-native-node-api vendor-hermes --react-native-package '#{get_react_native_package()}' --silent '#{Pod::Config.instance.installation_root}'`.strip
Copy link

Copilot AI Nov 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method call uses unnecessary parentheses. In Ruby, get_react_native_package() should be written as get_react_native_package when calling methods without arguments.

Suggested change
VENDORED_HERMES_DIR ||= `npx react-native-node-api vendor-hermes --react-native-package '#{get_react_native_package()}' --silent '#{Pod::Config.instance.installation_root}'`.strip
VENDORED_HERMES_DIR ||= `npx react-native-node-api vendor-hermes --react-native-package '#{get_react_native_package}' --silent '#{Pod::Config.instance.installation_root}'`.strip

Copilot uses AI. Check for mistakes.
Comment on lines +167 to +172
console.log("Copying source files from test-app into macos-test-app:");
const FILE_NAMES = [
"App.tsx",
// Adds the babel plugin needed to transform require calls
"babel.config.js",
// Adds the ability to reference symlinked packages
Copy link

Copilot AI Nov 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The comment on line 170-172 mentions 'Adds the babel plugin' and 'Adds the ability', but these describe what the files do rather than why they're being copied. The console.log could be more specific about which test-app (iOS) the files are being copied from.

Suggested change
console.log("Copying source files from test-app into macos-test-app:");
const FILE_NAMES = [
"App.tsx",
// Adds the babel plugin needed to transform require calls
"babel.config.js",
// Adds the ability to reference symlinked packages
console.log(`Copying source files from ${OTHER_APP_PATH} into ${APP_PATH}:`);
const FILE_NAMES = [
// Ensure macos-test-app uses the same entry point as test-app
"App.tsx",
// Ensure macos-test-app uses the same Babel config as test-app (for require transformation)
"babel.config.js",
// Ensure macos-test-app uses the same Metro config as test-app (for symlinked packages)

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI commented Nov 2, 2025

@kraenhansen I've opened a new pull request, #306, to work on those changes. Once the pull request is ready, I'll request review from you.

@kraenhansen kraenhansen merged commit a2fd422 into main Nov 2, 2025
9 checks passed
@kraenhansen kraenhansen deleted the kh/macos-test-app branch November 2, 2025 19:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Apple 🍎 Anything related to the Apple platform (iOS, macOS, Cocoapods, Xcode, XCFrameworks, etc.) CI Continuous integration Host 🏡 Our `react-native-node-api-modules` package MacOS 💻 Anything related to the Apple MacOS platform or React Native MacOS support

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Initialize and run a MacOS test app on CI Support vendoring Hermes for out-of-tree platforms

2 participants