Compare commits

..
Author SHA1 Message Date
Distiller 097ce07602 Release 0.74.4
#publish-packages-to-npm&latest
2024-07-30 11:18:41 +00:00
Nicola Corti 13ea273850 [0.74] Stub com.facebook.react.settings on 0.74 (#45720) 2024-07-29 11:18:21 +02:00
CHEN Xian-an b9f7005c46 Not all the targets have a defined symbol_type (#45591)
Summary:
Errors occurred on running `pod install`:

```
[!] An error occurred while processing the post-install hook of the Podfile.

undefined method `symbol_type' for #<Xcodeproj::Project::Object::PBXAggregateTarget:0x000000010f6ea568>

[redact]/node_modules/react-native/scripts/cocoapods/privacy_manifest_utils.rb:53:in `block in get_application_targets'
```

## Changelog:

[iOS] [Fixed] - Fix error on handling privacy manifest

Pull Request resolved: https://github.com/facebook/react-native/pull/45591

Reviewed By: cipolleschi

Differential Revision: D60107607

Pulled By: dmytrorykun

fbshipit-source-id: 316220fe54174b18c9b61775f807d5d05d9f0240
2024-07-29 10:21:19 +02:00
Riccardo Cipolleschi 1835245e9e [RN][0.74]Fix XROS build (#45580) 2024-07-23 14:06:30 +02:00
Riccardo Cipolleschi c9ce04828f [LOCAL][RN][CI] Fix Typo for IOS_DEPLOYMENT_TARGET 2024-07-22 16:54:03 +01:00
Riccardo Cipolleschi 3597552c41 [LOCAL][RN][CI] Fix Build Slice Job for VisionOS 2024-07-22 16:40:22 +01:00
Riccardo Cipolleschi 713b6b930f [LOCAL][RN][CI] Fix Hermes for iOS in CI 2024-07-22 16:17:15 +01:00
Riccardo Cipolleschi c0dd23662e Factor out the CXX language standard in a separate const (#45374)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/45374

This change factors out the language standard in a separate constant so we can easily control it from a single place.

There are only 2 exception to this:
1. hermes-engine: the podspec is used in CI and it has no access to the rct_cxx_language_standard variable
2. Yoga: it can be used as a separate pod, outside of React Native, so it makes sense to leave it alone.

This change also fixes a problem where, in some setup, the language was set to C++14

[Internal] - Refactor Cxx language standard in a single constant

Reviewed By: dmytrorykun, blakef

Differential Revision: D59629061

fbshipit-source-id: 41eac64e47c14e239d8ee78bd88ea30af244d695
2024-07-22 15:49:46 +02:00
Oskar Kwaśniewski 8271278bba feat: build visionos hermes binary on the CI (#44691)
Summary:
As discussed with cipolleschi offline, this PR adds visionOS to the prebuilt Hermes binary for the CI.

[IOS] [ADDED] - Prebuilt version of Hermes for visionOS

Pull Request resolved: https://github.com/facebook/react-native/pull/44691

Test Plan: Check if CI builds xcframework for visionOS.

Reviewed By: cortinico

Differential Revision: D58189271

Pulled By: cipolleschi

fbshipit-source-id: dc76746b2c1e22670bef4c21411a598e43dad577
2024-07-22 15:46:54 +02:00
Douglas Lowder a8c6aa2344 fix: Remove setting of process.exitCode that breaks Jest tests (#45562)
Summary:
In Node 20, the script to run unit tests in CI (`scripts/run-ci-javascript-tests.js`) will fail, even when all the Jest tests pass. This happens because one of the JS modules being tested is setting `process.exitCode` (see https://github.com/jestjs/jest/issues/9324#issuecomment-1808090455).

Changes:

- Modified the affected module to throw an exception when failing, instead of setting the exit code
- Adjusted the unit test for that module

## Changelog:

[General] [Fixed] - Remove setting of process.exitCode that breaks Jest tests

Pull Request resolved: https://github.com/facebook/react-native/pull/45562

Test Plan:
Before this change, running `node scripts/run-ci-javascript-tests.js` would fail with Node 20.
After this change, it succeeds.

Reviewed By: blakef

Differential Revision: D60033582

Pulled By: cipolleschi

fbshipit-source-id: 71b7f4495d414e719a9bd2d892bd1bc3045ddd5d
2024-07-22 15:45:07 +02:00
nik910 c374415cec Adding space to $(inherited) string to avoid merging of inherited and… (#45520)
Summary:
Added space to $(inherited) string to avoid creation of wrong cpp flags in RCTAppDelegate podspec

<img width="1157" alt="Screenshot 2024-07-18 at 8 51 19 PM" src="https://github.com/user-attachments/assets/29d32d08-e81f-4c25-b8ee-5dccc0f620ea">

## Changelog:

[IOS] [FIXED] - Building of iOS project when RCTAppDelegate is used in the project

Pull Request resolved: https://github.com/facebook/react-native/pull/45520

Test Plan: To test this you can simply change in your node modules and run pod install, the build will now work successfully

Reviewed By: cipolleschi

Differential Revision: D59950906

Pulled By: arushikesarwani94

fbshipit-source-id: 0d58620aa0be7ac4fcbcd309f06df0eef7844016
2024-07-22 15:44:55 +02:00
Blake Friedman 141778db55 Fix: OSS builds can accidentally using coreutils cp (#44097)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44097

There are two places where we use a feature specific to the system version of 'cp', the:

  -X    Do not copy Extended Attributes (EAs) or resource forks.

This feature isn't available in GNU's cp, which is commonly installed on macOS using:

  brew install coreutils && brew link coreutils

We can avoid the problem alltogether by being specific about the path of the system cp.

Changelog: [General][Fixed] don't break script phase and codegen when coreutils installed on macOS

Reviewed By: cipolleschi

Differential Revision: D56143216

fbshipit-source-id: f1c1ef9ea2f01614d6d89c4e9eedf43113deb80c
2024-07-22 15:44:45 +02:00
Riccardo Cipolleschi f996422c81 Fix path to node in .xcode.env.local (#43333)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43333

This change fixes https://github.com/facebook/react-native/issues/43285.
Basically, when using a `yarn` alias to install pods, yarn creates a copy of the `node` and `yarn` executables and the `command -v node` command will return the path to that executable.

## Changelog
[iOS][Fixed] - Do not use temporary node when creating the .xcode.env.local

Reviewed By: dmytrorykun

Differential Revision: D54542774

fbshipit-source-id: 3ab0d0bb441988026feff9d5390dcfd10869a1b5
2024-07-22 15:44:34 +02:00
Riccardo Cipolleschi 1f806871c5 Make sure to pass the BridgeProxy to view managers in the interop layer (#45329)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/45329

Thanks to [#45232](https://github.com/facebook/react-native/issues/45232) we found a bug in the interop layer, where we were not passing the BridgeProxy in bridgeless mode to the view managers.

This Change should fix that issue.

## Changelog:
[iOS][Fixed] - Make sure to pass the RCTBridgeProxy to  ViewManagers

Reviewed By: dmytrorykun

Differential Revision: D59468292

fbshipit-source-id: 00666be21385a735878eb567c4b8a0986c609c5f
2024-07-22 15:44:23 +02:00
Irfanwani ab98c22085 fix: post install error in iOS after running pod install, undefined method 'path' for nil:NilClass (#45095)
Summary:
After upgrading my project to the latest version of react native i.e, 0.74.2, i was getting an error when running `pod install` an the error was coming from the post install hook. Going deeper into the file tree, i found that some of the things are Nil and react native is trying to use some methods on them, so fixed those issues by using chaining operators to conditionally apply the path method on them.

## Changelog:

[Internal] - fixes the post install issue when running pod install with react native version, 0.74.2

Pull Request resolved: https://github.com/facebook/react-native/pull/45095

Test Plan: Manually tested the fix. Works perfectly fine in both debug and production mode.

Reviewed By: cortinico

Differential Revision: D58863666

Pulled By: cipolleschi

fbshipit-source-id: 64459711dcf926b7544b99b542e9861c1c0f05ca
2024-07-22 15:43:45 +02:00
Håkon Knutzen b8006d40b0 Fix data races in RCTImageLoader and RCTNetworkTask with shared atomic counters (#45114)
Summary:
In order to fix the data races described in https://github.com/facebook/react-native/issues/44715, I propose a simple solution by leveraging shared counter functions wherein `std::atomic` is the backing for the integer values.

## Changelog:

[iOS] [Fixed] - Implement shared atomic counters and replace static integers in `RCTImageLoader` and `RCTNetworkTask` that were accessed concurrently, which in some cases lead to data races.

Pull Request resolved: https://github.com/facebook/react-native/pull/45114

Test Plan: Added unit tests for the counters in `RCTSharedCounterTests`.

Reviewed By: cipolleschi

Differential Revision: D59155076

Pulled By: javache

fbshipit-source-id: f73afce6a816ad3226ed8c123cb2ccf4183549a0
2024-07-22 15:43:31 +02:00
distiller 8e5a9360bb Release 0.74.3
#publish-packages-to-npm&latest
2024-07-01 17:33:11 +00:00
Thibault Malbranche 3d53992051 fix: typo when cherry picking from kotlin to java 2024-07-01 15:01:20 +02:00
Rubén Norte 3c4d7618f0 Back out "Revert D58459930: [react-native][PR] Add ReactMarkerConstants.CONTENT_APPEARED support on Android"
Summary:
Changelog: [ANDROID] [ADDED] - Add the ReactMarkerConstants.CONTENT_APPEARED support on Android in bridgeless mode.

This re-applies https://github.com/facebook/react-native/pull/43620 which was reverted because a CI job started failing because we forgot to update `packages/react-native/ReactAndroid/api/ReactAndroid.api`.

Reviewed By: cortinico

Differential Revision: D58535868

fbshipit-source-id: 9eec33c5e798850a7434a6c391abf2fc3fc9d0a6
2024-07-01 14:27:11 +02:00
Dmitry Rykun bdf6583c7e Fix output path for generated artifacts (#45165)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/45165

This is a fix for https://github.com/facebook/react-native/issues/45112
This diff changes the codegen so that the output path is computed relative to project root (or `path` if provided) instead of current working directory.

Changelog: [General][Fixed] - Codegen computes output path relative to project root instead of current working directory.

Reviewed By: fkgozali

Differential Revision: D59009821

fbshipit-source-id: 3a138a3508fc239c8600b8c9f242f1c665f8e3c0
2024-07-01 14:21:32 +02:00
Nicola Corti 278823ecc5 Back out "Add Float and Int type support for Android modules" (#45087)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/45087

Original commit changeset: 32b3bbdf5fd2

Fixes https://github.com/facebook/react-native/issues/44963
Closes https://github.com/facebook/react-native/pull/45024

Original Phabricator Diff: D52420921

Changelog:
[Internal] [Changed] - Back out "[RN][Codegen]Add Float and Int type support for Android  modules"

Reviewed By: dmytrorykun

Differential Revision: D58820544

fbshipit-source-id: 59cd0e7cc17a681785c57b5ce1a9d50d28a348af
2024-07-01 14:19:23 +02:00
Riccardo CipolleschiandRubén Norte 3a1ff94839 [Hermes] Bump Hermes (#45220)
* [Hermes] Bump Hermes

* Implement queueMicrotask and drainMicrotasks in JSC

Summary:
Changelog: [internal]

## Context

We want to enable the new React Native event loop by default for all users on the new RN architecture (on the bridgeless initialization path more concretely), which requires support for microtasks in all the JS engines that the support (Hermes already has it, JSC doesn't).

## Changes

This adds initial support for microtasks in JSC, so we can schedule and execute microtasks in this runtime.

One limitation about this approach is that, AFAIK, the public API for JSC doesn't allow us to customize its internal microtask queue or specify the method to be used by its built-in `Promise` or native `async function`, so we're forced to continue using a polyfill in that case (which uses `setImmediate` that will be mapped to `queueMicrotask`).

Reviewed By: NickGerleman

Differential Revision: D54302534

fbshipit-source-id: 47f71620344a81bc6624917f77452106ffbf55a3

---------

Co-authored-by: Rubén Norte <rubennorte@meta.com>
2024-07-01 11:38:09 +02:00
Riccardo Cipolleschi 28ccfdc3dd [CI] Disable unit tests as they are Flaky on M1 machines ## Summary Disable unit tests on iOS because they are flaky on M1 machines ## Changelog: [Internal] - Disable unit tests in CI ## Test Plan:
Circle CI is Green
2024-06-28 14:11:56 +02:00
Riccardo Cipolleschi 2b033756ef [CI] Move iOS Executors to M1 2024-06-28 12:51:27 +02:00
Szymon Rybczak d1e2a35061 feat: update CLI to 13.6.9 (#44793) 2024-06-19 14:15:13 +01:00
Rubén Norte 7dd6549e09 Continue running microtasks when parent task throws
Summary:
Changelog: [General][Fixed] Fixed LogBox not showing correctly on the New Architecture

We found an incorrect behavior in the event loop, where an error in a task would prevent its microtasks from running. This isn't spec compliant and should be fixed.

This caused LogBox to not work correctly, as error reporting is implemented via microtasks that would never execute.

Reviewed By: sammy-SC

Differential Revision: D58010521

fbshipit-source-id: 7901c5d6e83fb63af148e12ad6c32be490a3999d
2024-06-18 14:41:09 +02:00
Ramanpreet Nara 487c8489f1 Refactor: RuntimeScheduler: Delete ErrorUtils.h (#43953)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43953

RuntimeScheduler's ErrorUtils.h is redundant.

Let's just remove it.

Changelog: [Internal]

Reviewed By: cipolleschi

Differential Revision: D55547905

fbshipit-source-id: 5263c9fca8ae32bbfc672f0e16b79ee177cdd421
2024-06-18 14:41:09 +02:00
Rubén Norte 37b33c34ba Small refactor in RuntimeScheduler_Modern to favor references over shared_ptr for non-owning function args (#43852)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43852

Changelog: [internal]

Just a small refactor so we rely less on shared pointers within `RuntimeSCheduler_Modern`.

Reviewed By: javache

Differential Revision: D55646389

fbshipit-source-id: d01dcba7b1551d349d21717ba585828ed7fb3259
2024-06-18 14:41:09 +02:00
Nicola Corti 988bf162a0 Tentative fix for NPE JavaTimerManager$IdleCallbackRunnable.cancel (#44852)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44852

This attempts to fix #44842 by capturing the accessed field in a new variable.
We don't have a way to reproduce this & this is a best guess fix.

Changelog:
[Android] [Fixed] - Tentative fix for NPE `JavaTimerManager$IdleCallbackRunnable.cancel`

Reviewed By: javache

Differential Revision: D58356826

fbshipit-source-id: d016df9a52f81a8d645a0a100c6bc6111841e24e
2024-06-18 14:41:09 +02:00
huzhanbo.luc f4b0fcb922 fix: android native rejections should be instanceof Error (#44487)
Summary:
fix https://github.com/facebook/react-native/issues/44050

## Changelog:

[ANDROID] [FIXED] - fix: android native rejections should be instanceof Error

Pull Request resolved: https://github.com/facebook/react-native/pull/44487

Test Plan: reject returns Error.

Reviewed By: NickGerleman

Differential Revision: D57205131

Pulled By: javache

fbshipit-source-id: a5950481d0c4909be4dbea0b430e75222258ae68
2024-06-18 14:41:09 +02:00
Fabrizio Bertoglio e210c7c574 Fix Multiline TextInput with a fixed height scrolls to the bottom when prepending new lines to the text (#38679)
Summary:
### Please re-state the problem that we are trying to solve in this issue.

Multiline TextInput with a fixed height will scroll to the bottom of the screen when prepending new lines to the text.

### What is the root cause of that problem?

The issue is caused by iOS UITextView:
- The cursor moves to the end of the text when prepending new lines.
- Moving the cursor to the end of the text triggers the scroll to the bottom.

The behavior was reproduced on an iOS App (without react-native).
The example included below implements a Component RCTUITextView based on UITextView, which modifies the UITextView attributedText with the textViewDidChange callback (source code available in this [comment](https://github.com/Expensify/App/issues/19507#issuecomment-1595730348)).

Adding a new line on top of the UITextView on iOS results in:
Issue 1) The cursor moves to the end of TextInput text
Issue 2) The TextInput scrolls to the bottom

<details><summary>Reproducing the issue on an iOS App without react-native</summary>
<p>

<video src="https://user-images.githubusercontent.com/24992535/246601549-99f480f3-ce80-4678-9378-f71c8aa67e17.mp4" width="900" />

</p>
</details>

Issue 1) is already fixed in react-native, which restores the previous cursor position (on Fabric with  [_setAttributedString](https://github.com/fabriziobertoglio1987/react-native/blob/71e7bbbc2cf21abacf7009e300f5bba737e20d17/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm#L600-L610)) after changing the text.
Issue 2) needs to be fixed in react-native.

### What changes do you think we should make in order to solve the problem?

Setting the correct TextInput scroll position after re-setting the cursor.

## Changelog:

[IOS] [FIXED] - Fix Multiline TextInput with a fixed height scrolls to the bottom when changing AttributedText

Pull Request resolved: https://github.com/facebook/react-native/pull/38679

Test Plan:
Fabric (reproduces on controlled/not controlled TextInput example):

| Before    | After |
| ----------- | ----------- |
| <video src="https://github.com/facebook/react-native/assets/24992535/e06b31fe-407d-4897-b608-73e0cc0f224a" width="350" />      | <video src="https://github.com/facebook/react-native/assets/24992535/fa2eaa31-c616-43c5-9596-f84e7b70d80a" width="350" />       |

Paper (reproduces only on controlled TextInput example):

```javascript
function TextInputExample() {
  const [text, setText] = React.useState('');

  return (
    <View style={{marginTop: 200}}>
      <TextInput
        style={{height: 50, backgroundColor: 'white'}}
        multiline={true}
        value={text}
        onChangeText={text => {
          setText(text);
        }}
      />
    </View>
  );
}
```

| Before    | After |
| ----------- | ----------- |
| <video src="https://github.com/facebook/react-native/assets/24992535/6cb1f2de-717e-4dce-be0a-644f6a051c08" width="350" />      | <video src="https://github.com/facebook/react-native/assets/24992535/dee6edb6-76c6-48b0-b78f-99626235d30e" width="350" />       |

Reviewed By: sammy-SC, cipolleschi

Differential Revision: D48674090

Pulled By: NickGerleman

fbshipit-source-id: 349e7b0910e314ec94b45b68c38571fed41ef117
2024-06-18 14:41:09 +02:00
Kudo Chien d9e42785f3 Support customizeRootView from RCTRootViewFactory (#44775)
Summary:
The new `customizeRootView` does not have the feature parity as `createRootViewWithBridge` where reusing RCTRootViewFactory to create a root view, it does not call `customizeRootView`. This PR moves the `customizeRootView` support from RCTAppDelegate into RCTRootViewFactory and improves the customizeRootView support.

[IOS] [CHANGED] - Support `customizeRootView` from `RCTRootViewFactory`

Pull Request resolved: https://github.com/facebook/react-native/pull/44775

Test Plan:
Add customizeRootView to **packages/rn-tester/RNTester/AppDelegate.mm** and test whether RNTester has blue background color in both new arch and old arch mode.

```objc
- (void)customizeRootView:(RCTRootView *)rootView
{
  rootView.backgroundColor = [UIColor blueColor];
}
```

Reviewed By: dmytrorykun

Differential Revision: D58179693

Pulled By: cipolleschi

fbshipit-source-id: 0fac9a1bd5b2583a2700b3a3d2c80d0f608c4481
2024-06-18 14:41:09 +02:00
Jakub Piasecki a2b52af3bc Fix border drawn over children on iOS (#44777)
Summary:
Fixes https://github.com/facebook/react-native/issues/44690

In the code responsible for drawing border on iOS there's a comment saying:
> iOS draws borders in front of the content whereas CSS draws them behind the content. For this reason, only use iOS border drawing when clipping or when the border is hidden.

The condition that follows checks whether the content is clipped and the width and alpha channel of the border: https://github.com/facebook/react-native/blob/e0a2e86d0346bd7e40adf69311daa538ca8c9c5f/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm#L643-L644.

The problem is when the color is not set at all - `colorComponentsFromColor(borderMetrics.borderColors.left).alpha` will be equal to 0 since the relevant `SharedColor` is `null`: https://github.com/facebook/react-native/blob/e0a2e86d0346bd7e40adf69311daa538ca8c9c5f/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.mm#L76-L86

Then it uses the path with the default iOS behavior (drawing the border on top of the content) instead of the custom one (with the border below) and it seems like it defaults to drawing black when the passed color is `nil`.

This PR simply adds one more check to make sure the color is actually set before choosing the default platform behavior.

## Changelog:

[IOS] [FIXED] - Fixed border being drawn over children when no color was set

Pull Request resolved: https://github.com/facebook/react-native/pull/44777

Test Plan:
Tested on the code from the issue.

|Before|After|
|-|-|
|<img width="546" alt="Screenshot 2024-06-04 at 11 18 14" src="https://github.com/facebook/react-native/assets/21055725/f13250a9-2e99-41c5-a9bc-02d65c00a6c0">|<img width="546" alt="Screenshot 2024-06-04 at 11 17 38" src="https://github.com/facebook/react-native/assets/21055725/f4571a5f-dfc4-4191-854c-fd3faf698b29">|

Reviewed By: cortinico

Differential Revision: D58131337

Pulled By: cipolleschi

fbshipit-source-id: 7da247d81ecec586de6f0023e0cb399f9966213d
2024-06-18 14:41:09 +02:00
Soe Lynn 9a5faac12b overflow props is not honored in ScrollView in new architecture (#44699)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44699

Changelog: [Internal]

In Fabric, overflow props for ScrollView is not passed down. Hence, the overflow props is ignored and FlatList content is always clipped.

Reported from OSS https://github.com/facebook/react-native/issues/44683

Reviewed By: sammy-SC

Differential Revision: D57895399

fbshipit-source-id: 6ce65bea0803971060e8229b66563123dd6fc114
2024-06-18 14:41:09 +02:00
Alex Hunt 3888bf3238 Update Podfile.lock
Changelog: [Internal]
2024-06-04 18:00:01 +01:00
Distiller 17c0b1766f Release 0.74.2
#publish-packages-to-npm&latest
2024-06-04 15:08:03 +00:00
Kudo Chien 053f1d9822 Fix dangling surfaces in ReactHostImpl (#44393)
Summary:
Though the `ReactHost.destroy()` is not being used from OSS code, we use it at Expo for expo-dev-client to change loading apps from different dev servers. Without cleanup the `mAttachedSurfaces`, it will have dangling or duplicated attached surfaces that cause duplicated react trees.

<img src="https://github.com/facebook/react-native/assets/46429/f84d274e-aaad-4352-9e3c-6262571a5625">

This PR tries to cleanup the `mAttachedSurfaces` from destroying.

## Changelog:

[ANDROID] [FIXED] - Fixed dangling `mAttachedSurfaces` after `ReactHost.destroy()`

Pull Request resolved: https://github.com/facebook/react-native/pull/44393

Test Plan: have to manually call `ReactHost.destroy()` and recreate the MainActivity without killing the process. then reload the app will startSurface for the same attached surfaces.

Reviewed By: RSNara

Differential Revision: D56901863

Pulled By: javache

fbshipit-source-id: c7f822501d971810ac6aa7262b15da69ec41355e
2024-06-04 10:30:49 +01:00
legobt 0f44ca644b chore: Increase iOS script portability (#44417)
Summary:
`pod install` and CocoaPods are actually not macOS specific.
Still, the pod lifecycle scripts of `react-native` depend on macOS-only utilities and will fail on Linux.

This is an attempt to make the scripts portable and make the pod install cleanly on Linux as well as macOS.

## Changelog:

    [INTERNAL] [FIXED] - Skip XCode patching when not run on macOS
    [INTERNAL] [FIXED] - Fall back to `which gcc`/`which g++` to identify C/C++ compiler when `xcrun` not available
    [INTERNAL] [FEAT] - Recognize CC and CXX env vars supplied to the script and prefer them over autodetection

Pull Request resolved: https://github.com/facebook/react-native/pull/44417

Reviewed By: NickGerleman

Differential Revision: D57055928

Pulled By: cipolleschi

fbshipit-source-id: 1c49f70c52b4667abf0a215cbee52ee6aa6dd052
2024-06-04 10:30:03 +01:00
Alex HuntandLluís 1f50fb7816 [0.74] Update eslint-plugin-jest to 27.x, @typescript-eslint deps to 7.x (#44764)
Summary:
This PR updates `typescript-eslint/eslint-plugin` and `typescript-eslint/parser` to `v7` and `eslint-plugin-jest` to `v27`, removing any dependencies on `typescript-eslint` `v6`, allowing projects using `react-native/eslint-config` to safely update to  `typescript-eslint` `v7` without having to worry about duplicate major versions installed

## Changelog:

- [General] [Changed]: Updated `eslint-plugin-jest` to `v27`
- [General] [Changed]: Updated `typescript-eslint` monorepo to `v7`

Pull Request resolved: https://github.com/facebook/react-native/pull/43406

Test Plan: `yarn run lint` executed locally successfully

Reviewed By: robhogan

Differential Revision: D54749676

Pulled By: tdn120

fbshipit-source-id: f6fae92fc95333e28b36a3d2bd8470c8869d38bc

# Conflicts:
#	package.json
#	packages/eslint-config-react-native/package.json
#	yarn.lock

Co-authored-by: Lluís <lluis@skrit.es>
2024-06-04 10:27:56 +01:00
Riccardo Cipolleschi 2e21543017 [LOCAL] Fix prettier 2024-06-03 18:04:41 +01:00
Riccardo Cipolleschi 58f232c6c2 [LOCAL] Bump hermes version 2024-06-03 17:18:09 +01:00
Riccardo Cipolleschi 1e3d2161e8 Merge branch '0.74-stable' of https://github.com/facebook/react-native into 0.74-stable 2024-06-03 16:38:09 +01:00
Szymon Rybczak 335f6ed833 feat: upgrade CLI to 13.6.8 (#44757) 2024-06-03 15:49:09 +01:00
Renaud Chaput 752c173da5 Fix Privacy Manifest generator when it does not contain a NSPrivacyAccessedAPITypes key (#44628)
Summary:
XCode privacy files might not contain a `NSPrivacyAccessedAPITypes` key, which causes the following error:

```
[!] An error occurred while processing the post-install hook of the Podfile.

undefined method `each' for nil

node_modules/react-native/scripts/cocoapods/privacy_manifest_utils.rb:111:in `block (4 levels) in get_used_required_reason_apis'
node_modules/react-native/scripts/cocoapods/privacy_manifest_utils.rb:106:in `each'
node_modules/react-native/scripts/cocoapods/privacy_manifest_utils.rb:106:in `block (3 levels) in get_used_required_reason_apis'
```

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[IOS] [FIXED] - Privacy Manifest aggregation failing due to no `NSPrivacyAccessedAPITypes` key

Pull Request resolved: https://github.com/facebook/react-native/pull/44628

Test Plan: I tested this patch on our own app and it solved the issue.

Reviewed By: christophpurrer

Differential Revision: D57618425

Pulled By: cipolleschi

fbshipit-source-id: 1a36ab5a1bb45b8507d3663b782c95258d97c8a4
2024-06-03 15:48:28 +01:00
szymonrybczak 1860441d84 fix: warn only in init command when CLI uses cached npx version (#44644)
Summary:
In https://github.com/facebook/react-native/pull/37510, a check was introduced to check if user is using `latest` version of `npx`, but right now it checks for every command executed, but it should only ensure that `latest` is included when creating a new project.

In this Pull Request I've added a condition to only warn if `init` was fired.

[GENERAL] [FIXED] - Warn only in `init` command when CLI uses cached `npx` version

Pull Request resolved: https://github.com/facebook/react-native/pull/44644

Test Plan: Warning about using `latest` version CLI should only be presented when running `init` command.

Reviewed By: arushikesarwani94

Differential Revision: D57681864

Pulled By: blakef

fbshipit-source-id: 5c81b9a08141396efcd24539b2560cea16028dd9
2024-06-03 15:46:44 +01:00
zhongwuzw a88a3c5bbf iOS: Fixes textinput onscroll event payload (#43445)
Summary:
Fixes https://github.com/facebook/react-native/issues/43428 . cc cortinico .

## Changelog:

[IOS] [FIXED] - [Fabric] iOS: Fixes textinput onscroll event payload

Pull Request resolved: https://github.com/facebook/react-native/pull/43445

Test Plan:
```
    const onInputScroll = (e) => {
      if (Platform.OS !== "web") {
        const {
          nativeEvent: {
            contentOffset: { x, y },
          },
        } = e;
        console.log('onInputScroll ====', e?.nativeEvent)
      }
    };

<TextInput
          onScroll={onInputScroll}
          // ref={inputRef}
          multiline
  />
```

Reviewed By: cortinico

Differential Revision: D54813378

Pulled By: sammy-SC

fbshipit-source-id: 76671fbb390c2fbc67a9c29b6c2a834ba699fff4
2024-06-03 15:43:32 +01:00
Rui Ying 2375b077ed Handle the case where the file reference doesn't have a path (#44410)
Summary:
The new cocoapod post install script includes aggregation and generation of privacy manifests for iOS, which is great. However, the script doesn't consider the case where the file reference doesn't have a path.

Example, for a project setup like the screenshot:
<img width="249" alt="image" src="https://github.com/facebook/react-native/assets/22592111/45dd1cf4-c2f6-4abb-940f-136a4d502966">

The code
https://github.com/facebook/react-native/blob/05a4232dd591e2d43f192d69ca14a04f4a3fb6a1/packages/react-native/scripts/cocoapods/privacy_manifest_utils.rb#L80-L81

prints `file_refs`:
```
[
<PBXFileReference name=`LaunchScreen.storyboard` path=`learnX/LaunchScreen.storyboard` UUID=`81AB9BB72411601600AC10FF`>,
<PBXVariantGroup name=`InfoPlist.strings` UUID=`D40B9F832B248EF5004BC08C`>,
<PBXFileReference path=`AppCenter-Config.plist` UUID=`D40B9F802B248EC2004BC08C`>,
<PBXFileReference name=`PrivacyInfo.xcprivacy` path=`learnX/PrivacyInfo.xcprivacy` UUID=`D403DD362BCA2BCF00E5295C`>,
<PBXFileReference name=`Assets.xcassets` path=`learnX/Assets.xcassets` UUID=`D40B9F652B248AEB004BC08C`>
]
```

where a `PBXVariantGroup` exists and it doesn't have `path`. The error `undefined method 'end_with?' for nil` occurs as a result.

## Changelog:

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[IOS] [FIXED] - In privacy manifest post install script, handle the case where the file reference doesn't have a path

Pull Request resolved: https://github.com/facebook/react-native/pull/44410

Test Plan:
1. Add a new "Strings File (Legacy)" in Xcode to the project.
2. Run `pod install` for iOS.
3. See the error `undefined method 'end_with?' for nil`.
4. Apply the fix and rerun `pod install`.
5. The script runs successfully.

Reviewed By: javache

Differential Revision: D57056159

Pulled By: cipolleschi

fbshipit-source-id: 42caaf1a98efb9111f6ff1014a5c8b7703b042f2
2024-06-03 15:43:25 +01:00
Robin Shin 156e8cf52b fix: TextInput selectionColor props on iOS (#44420)
Summary:
This pull request fixes an issue where the `selectionColor` prop was not applied to the `TextInput` component on iOS, starting from React Native version 0.74.x.

This issue was introduced in PR [1e68e485](https://github.com/facebook/react-native/commit/1e68e48534aedf1533327bf65f26e5cf5b80127b#diff-b6634353ea5b10a91de24605dc51bdfb50e8ddb652ccd5b9dab194168a69d4b1) which relocated `selectionColor` along with `selectionHandleColor` and `cursorColor` out of `otherProps`. This modification inadvertently prevented `selectionColor` from being passed to the iOS native component.

This change ensures that the `selectionColor` prop is explicitly included in the `RCTTextInputView` component's properties, fixing the regression.

Note: `selectionHandleColor` and `cursorColor` are Android-specific and do not require explicit passing on iOS.

## Changelog:

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->
[IOS] [FIXED] - Fixed an issue where the `selectionColor` prop was not being applied on the `TextInput` component.

Pull Request resolved: https://github.com/facebook/react-native/pull/44420

Test Plan:
**Environment:** iOS Simulator, React Native 0.74.0.

**Steps to reproduce:**

- Implement a `TextInput` component with the `selectionColor` prop set.
- Run the application on an iOS device or simulator.
- Focus on the TextInput component, write some text and select it.

**Expected Result:** the selection color should match the color provided to the `selectionColor` prop.

**Actual result before fix:** the selection color did not reflect the specified `selectionColor` prop and fell back to the default iOS selection color (blue).

**Screenshots:**
- Before fix:
<img width="1710" alt="before_fix" src="https://github.com/facebook/react-native/assets/17989553/8660068c-55c9-4f55-a788-f96eb681fb70">

- After fix:
<img width="1710" alt="after_fix" src="https://github.com/facebook/react-native/assets/17989553/93c9eb26-7da0-4957-b54f-8444aff7e374">

Reviewed By: javache

Differential Revision: D57017836

Pulled By: NickGerleman

fbshipit-source-id: 263ce22168e09c15cdfdb4eb4300a2605d8af032
2024-06-03 15:43:15 +01:00
Alan Lee fc5e69e06b TextInput - selection prop is not set on component creation (#44398)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44398

**Problem:**
`selection` prop is not being set on component creation.
Not quite sure which RN version this issue was introduced but fixing it on latest code.

Use playground for testing (refer to following diff)

**Proposed Solution:**

Added notes in comments but `viewCommands.setTextAndSelection()` is called only on text or selection update which relies on comparing data with `lastNativeSelection`. Problem is that `lastNativeSelection` is initially set to the props value that is passed in so does not send the command on component creation.

So assign a default selection value of `{start: -1, end: -1}` so it can be set on component creation.

**Changelog:**
[General][Fixed] - `selection` prop in `TextInput` was not being applied at component creation

Reviewed By: cipolleschi

Differential Revision: D56911712

fbshipit-source-id: 7774b246383f85216536040688b0a8ea85b3478a
2024-06-03 15:43:08 +01:00
Arushi Kesarwani 71153f6c73 Add ReactSoftException in ReactHostImpl only when onActivityResult, onNewIntent and onWindowFocusChange do not have the context (#44155)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44155

Add ReactSoftException in ReactHostImpl only when `onActivityResult`, `onNewIntent`and `onWindowFocusChange` do not have the context

Changelog:
[Android][Fixed] ReactSoftExceptions in ReactHostImpl only when Context is null

Reviewed By: cortinico

Differential Revision: D56325407

fbshipit-source-id: a9f8fd5772fc05d39e72236fb8edfe5f8a9d6a43
2024-06-03 15:42:57 +01:00
Riccardo Cipolleschi 2636eb19d1 Update Podfile.lock
Changelog: [Internal]
2024-05-03 17:31:23 +01:00
Distiller 31f9d45074 Release 0.74.1
#publish-packages-to-npm&latest
2024-05-02 18:17:04 +00:00
Riccardo Cipolleschi 093a2adc07 [LOCAL] Fix privacy manifest aggregator 2024-05-02 19:07:45 +01:00
Nicola Corti a0ed073650 [LOCAL] Fix compilation error on ReactDelegate 2024-05-02 10:59:41 +01:00
Riccardo Cipolleschi ec512a70cb [LOCAL] Bump podfile.lock and update privacy manifest 2024-05-02 10:20:35 +01:00
aleqsio 4be1fafec8 Implement privacy manifest aggregation (#44214)
Summary:
As of now, Apple does not respect privacy manifests added as cocoapods resource bundles. This forces react-native developers to manually copy `.xcprivacy` files content for each native dependency that accesses restricted reason APIs to the root file.

This PR adds an aggregation step that crawls through pod dependencies to collect all reasons into the root privacy info file.

[IOS][ADDED] – Add privacy manifest aggregation.

Pull Request resolved: https://github.com/facebook/react-native/pull/44214

Test Plan:
When run on RNTester, it appends aggregated entries (while keeping existing ones) to existing .xcprivacy file without modifing .pbxproj:
![image](https://github.com/facebook/react-native/assets/5597580/1d07a07d-bbec-4266-a599-a8d629078971)

When run on RNTester with the xcprivacy file removed from xcode beforehand, it creates a new .xcprivacy file, and adds it to Compile Bundle Resources in the same way as in the new template:
![image](https://github.com/facebook/react-native/assets/5597580/f80a3b4e-e41a-4906-8e2f-06cca0bc225a)

When run on RNTester with an empty .xcprivacy file, it appends aggregated entries from pods AND reasons for react-native core.

When run with `privacy_file_aggregation_enabled: false` in `use_react_native`, it falls back to existing behavior:
![image](https://github.com/facebook/react-native/assets/5597580/4519bba1-c80e-4cd0-b19c-bbbebfa8493b)

Reviewed By: cipolleschi

Differential Revision: D56481045

Pulled By: philIip

fbshipit-source-id: 1841bad821511c734d0cc0fcff5065ed92af76d8
2024-05-02 10:18:43 +01:00
Kudo Chien 56631cd471 fix ReactActivity.getReactDelegate().reload() (#44223)
Summary:
fixing some problem for `ReactActivity.getReactDelegate().reload()` from https://github.com/facebook/react-native/issues/43521:
- the `reload()` does not work for bridge mode on release build

[ANDROID] [FIXED] - Fixed app reloading for `ReactActivity.getReactDelegate().reload()`.

Pull Request resolved: https://github.com/facebook/react-native/pull/44223

Test Plan:
tried to temporary change toast.show as reload and test from rn-tester
```diff
 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/toast/ToastModule.kt
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/toast/ToastModule.kt
@@ -10,6 +10,7 @@ package com.facebook.react.modules.toast
 import android.view.Gravity
 import android.widget.Toast
 import com.facebook.fbreact.specs.NativeToastAndroidSpec
+import com.facebook.react.ReactActivity
 import com.facebook.react.bridge.NativeModule
 import com.facebook.react.bridge.ReactApplicationContext
 import com.facebook.react.bridge.UiThreadUtil
@@ -30,9 +31,11 @@ public class ToastModule(reactContext: ReactApplicationContext) :
       )

   override public fun show(message: String?, durationDouble: Double) {
-    val duration = durationDouble.toInt()
-    UiThreadUtil.runOnUiThread(
-        Runnable { Toast.makeText(getReactApplicationContext(), message, duration).show() })
+//    val duration = durationDouble.toInt()
+//    UiThreadUtil.runOnUiThread(
+//        Runnable { Toast.makeText(getReactApplicationContext(), message, duration).show() })
+    val activity = reactApplicationContext.currentActivity as? ReactActivity
+    activity?.reactDelegate?.reload()
   }

   override public fun showWithGravity(
```

tried for different mode
- [x] bridge mode + debug build
- [x] bridgeless mode + debug build
- [x] bridge mode + release build
- [x] bridgeless mode + release build

Reviewed By: fkgozali

Differential Revision: D56795975

Pulled By: arushikesarwani94

fbshipit-source-id: 895eab1927ba6db748ebb32c0fd5313f19cf9d1b
2024-05-02 10:15:59 +01:00
Pieter De Baets cc1c69799e Support more stubbed methods in BridgelessCatalystInstance (#44091)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44091

These can be stubbed easily using existing ReactHostImpl/ReactInstance API's

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D56139806

fbshipit-source-id: cefabe3aa0fb6556f8e296243ff233df07ddffee
2024-05-02 10:14:21 +01:00
Szymon RybczakandRiccardo Cipolleschi 58b1f9b2d4 feat: upgrade @react-native-community/cli to 13.6.6 (#44253)
Co-authored-by: Riccardo Cipolleschi <cipolleschi@meta.com>
2024-05-01 18:31:39 +01:00
Riccardo Cipolleschi bb890a308f [LOCAL] Fix prettier and Flow 2024-05-01 18:25:08 +01:00
Riccardo Cipolleschi 8813061286 Honor requiresMainQueueSetup in bridgeless mode for ViewManagers
Summary:
We [received an issue](https://github.com/react-native-maps/react-native-maps/issues/5042) in OSS where a ViewManager was configured to be initialized on the main queue, but it wasn't.
This was creating a soft crash and showing a RedBox to the user.
The library was going through the Interop Layer.

This change makes sure that, if the ViewManager is configured to be setup in the main queue, we retrieve the constants from the Main Queue

## Changelog
[iOS][Fixed] - Extract the constants from ViewManagers in the UI Thread if needed.

Reviewed By: sammy-SC

Differential Revision: D56762253

fbshipit-source-id: ca807b34d6e61418da9fd6a639a05f3394879f7c
2024-05-01 18:15:33 +01:00
Alan Lee 13739510fb add missing struct member initialization in Props.h (#44294)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44294

**Problem:**

It was discovered while testing 3 party library, generated member variables in a C++ `struct` in `Props.h` is not initialized.
Also `WithDefault` would not work as well.
(For the problematic case it was a `boolean` but would also apply to other primitive types.)

If there is no default initialization and the component prop is optional and the user of the native component does not set the prop then the variable is never initialized and this is problematic for primitive types in C++ where no initialization results in an undefined behavior.

**Proposed solution:**

(Following C++Core Guideline of [always initialize](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-always).)
Reusing `generatePropsString()` used by `ClassTemplate` to generate props for `StructTemplate` as well.
updated relevant test snapshots.
This change is only concerning the `Props.h` file.

**Changelog:**
[General][Fixed] - fixed `Props.h` created from codegen missing default initializers in C++ `struct`

Reviewed By: cipolleschi

Differential Revision: D56659457

fbshipit-source-id: 0d21ad20c0491a7e8bb718cd3156da65def72f23
2024-05-01 18:15:27 +01:00
Riccardo Cipolleschi 59e7ed5038 Avoid calling abstract methods in RCTComposedViewRegistry
Summary:
`RCTComposedViewRegistry` extends `NSMutableDictionary` which is a clustered class in iOS.
NSMutableDictionary is techncially an abstract class, but when instantiated by `[NSMutableDictionary new];` the system will return one of concrete classes that inherit from `NSMutableDictionary`, opaquely from the perspective of the caller.

By calling `super`, we are actually calling the not implemented method for the abstract class. If this happen, this can crash the app.

Given that the `RCTComposedViewRegistry` is extending the dictionary only for its interface but is using other mechanisms as storage, is it fair to return `NULL`if the storages don't have the requested view.

## Changelog
[iOS][Fixed] -  Avoid calling abstract methods in RCTComposedViewRegistry

Reviewed By: cortinico

Differential Revision: D56755427

fbshipit-source-id: f5c56dc59ccc6b30c00199b4196c42eb9b021e2b
2024-05-01 18:15:21 +01:00
Samuel Susla 305249f964 maintain correct content offset when scroll view is suspended (#44256)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44256

[iOS] [Fixed] - Preserve content offset in ScrollView when the component is suspended

On iOS, components are recycled. For ScrollView, its content offset has to be reset back to original position. When we call `[UIScrollView setContentOffset:]`, it triggers all of its delegate methods and triggers `scrollViewDidScroll` where we set native state.

So when user scrolls to position 100 and scroll view suspends. it is removed from view hierarchy and recycled. Once the suspense boundary is resolved, scroll view will be inserted back into view hierarchy. But when it was recycled, we set back its original content offset (the default is 0, 0) but this was accidentally propagated through to shadow tree.

To avoid this, we simply need to invalidate `_state` before calling `[UIScrollView setContentOffset:]`.

Reviewed By: cipolleschi

Differential Revision: D56573370

fbshipit-source-id: c03d7d2d403af2e1649b4cf189072baeb4c286c8
2024-05-01 18:15:01 +01:00
Riccardo Cipolleschi 3467f2f3a3 Fix enable hermes debugger in Bridgeless mode
Summary:
Set the proper build flags for debugging in Bridgeless mode.

This fixes [#44240](https://github.com/facebook/react-native/issues/44240)

## Changelog:
[iOS][Fixed] - Add `HERMES_ENABLE_DEBUGGER=1` flag to React-RuntimeApple

Reviewed By: cortinico

Differential Revision: D56575647

fbshipit-source-id: a0613a5d46caeb1d3e636e54ecd43428fbaf46e8
2024-05-01 18:14:12 +01:00
Kudo Chien 10fc2af13e Defines module for React-jsinspector (#44252)
Summary:
Defines module for `React-jsinspector` that for swift modules to integrate with.

to fix https://github.com/expo/expo/issues/28209, any podspec depends on HermesExecutorFactory should use ` add_dependency(s, "React-jsinspector", :framework_name => 'jsinspector_modern')` to add dependency. otherwise it will encounter the header not found issue because use_frameworks will change "jsinspector-modern" to "jsinspector_modern".

to depend on React-jsinspector from expo-modules-core, we need it to define as a module.
otherwise, it will have the error
```
The Swift pod `ExpoModulesCore` depends upon `React-jsinspector`, which does not define modules. To opt into those targets generating module maps (which is necessary to import them from Swift when building as static libraries), you may set `use_modular_headers!` globally in your Podfile, or specify `:modular_headers => true` for particular dependencies.
```

## Changelog:

[IOS] [CHANGED] - Add `DEFINES_MODULE` for React-jsinspector.podspec

Pull Request resolved: https://github.com/facebook/react-native/pull/44252

Test Plan: ci passed

Reviewed By: cortinico

Differential Revision: D56575102

Pulled By: cipolleschi

fbshipit-source-id: 9b7b4568a3e499f0a741a79a846263118ff2d112
2024-05-01 18:14:07 +01:00
Riccardo Cipolleschi eaaf865449 Fallback to the first foregroundInactive window when there are no foregroundActive windows in RCTKeyWindow (#44167)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44167

We received an issue for OSS where, when the main window is inactive and the system tries to present a dialog, the dialog is not presented in the right position on the screen.

This change introduce a fallback to the first inactive window (which is still visible on screen) and it fixes the issues.

[iOS][Changed] - Fallback to the first `foregroundInactive` window when there are no `foregroundActive` windows in RCTKeyWindow

Reviewed By: dmytrorykun

Differential Revision: D56354741

fbshipit-source-id: fa23131ecd40f6d91c705879a72890506ee21486
2024-05-01 18:13:57 +01:00
Arushi Kesarwani 7a841dbcd1 Fixing exposing ReactDelegate through ReactActivity for reload() (#44227)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44227

In https://github.com/facebook/react-native/pull/44223/ kudo identified the incorrect return type.

Reviewed By: christophpurrer, philIip

Differential Revision: D56497700

fbshipit-source-id: 5d7fc7ef21c3d3033a2567eba51b613eb41f0a1a
2024-05-01 18:12:08 +01:00
Samuel Susla 165cabb21f reset animation state in TouchableOpacity and TouchableBounce (#44182)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44182

## Changelog:

[iOS] [Fixed] - Fixed stale state on TouchableOpacity and TouchableBounce

When TouchableOpacity and TouchableBounce are unmounted, we need to reset their state. This includes animation state. If we don't do that, view is unmounted on the mounting layer and animation will not be applied. This leaves view in undefined state. In TouchableOpacity, it is view with reduced opacity. TouchableBounce that is view with applied transform.

This was reported in https://github.com/facebook/react-native/issues/44044

Reviewed By: rubennorte, cipolleschi

Differential Revision: D56416571

fbshipit-source-id: 01214ec8a5e07c80a609e082b955a30305ad8396
2024-05-01 18:09:08 +01:00
Riccardo Cipolleschi 0a4d97362f Fix Symbol not found: (_JSGlobalContextSetInspectable) (#44185)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44185

This change will fix a symbol not found for JSC Runtime.

The `if` check was not a compile time check, therefore the symbol ended up in the binary even if it is not available.

Following this post on [Apple forum](https://forums.developer.apple.com/forums/thread/749534), this changes should do the trick.

## Changelog
[iOS][Fixed] - Fix Symbol not found: (_JSGlobalContextSetInspectable)

Reviewed By: hash3r

Differential Revision: D56425834

fbshipit-source-id: a37af51b078bd47a938e6b65d9d8e0f7506e746f
2024-05-01 18:09:02 +01:00
Samuel Susla 0a4cf4945c only trigger RCTContentDidAppearNotification when content appears (#43823)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43823

changelog: [internal]

Notification RCTContentDidAppearNotification was posted too early in RCTSurfaceHostingProxyRootView, which does not know when views are mounted.
It was also posted if no views were mounted, leading to inconsistent behaviour between Paper and Fabric.

The implementation is aligned with Paper: https://github.com/facebook/react-native/blob/main/packages/react-native/React/Base/RCTRootContentView.m#L45-L55

Reviewed By: cipolleschi

Differential Revision: D55640654

fbshipit-source-id: 2d7bc5afb6ba1c1e8db529ee11eac2bae2d936d6
2024-05-01 18:07:12 +01:00
Marc Rousavy a14df93b15 Allow ReactCommon/Folly to be used in Swift libraries (DEFINES_MODULE) (#43327)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43327

<!-- Thanks for submitting a pull request! We appreciate you spending the time to work on these changes. Please provide enough information so that others can review your pull request. The three fields below are mandatory. -->

## Summary

Swift Pods require the use of [modular headers](https://blog.cocoapods.org/CocoaPods-1.5.0/) to be statically linked. To interop with Objective-C modules, you need to make the Objective-C module "define a Module", that is modular header export.

This is already the case for a few podspecs so they can be consumed in Swift libraries, but `ReactCommon` and `RCT-Folly` don't do this yet and therefore this breaks in a few libraries of mine, for example see this issue: https://github.com/mrousavy/react-native-vision-camera/issues/195.

If I were to include `ReactCommon` or `RCT-Folly` in my Swift library's podspec, the following error arises:

```
[!] The following Swift pods cannot yet be integrated as static libraries:

The Swift pod `VisionCamera` depends upon `RCT-Folly`, which does not define modules.
To opt into those targets generating module maps (which is necessary to import them from Swift
when building as static libraries), you may set `use_modular_headers!` globally in your Podfile, or
specify `:modular_headers => true` for particular dependencies.
```

So this PR fixes this issue by allowing Swift libraries to consume the `ReactCommon` and `RCT-Folly` podspecs since they now export modular headers.

## Changelog

<!-- Help reviewers and the release process by writing your own changelog entry. For an example, see:
https://github.com/facebook/react-native/wiki/Changelog
-->

[General] [Fixed] - Expose Modular Headers for `ReactCommon` podspec
[General] [Fixed] - Expose Modular Headers for `RCT-Folly` podspec

Pull Request resolved: https://github.com/facebook/react-native/pull/31858

Test Plan: * Add s.dependency "ReactCommon" or RCT-Folly to a Swift pod and see what happens. (See https://github.com/mrousavy/react-native-vision-camera/pull/273)

Reviewed By: dmytrorykun

Differential Revision: D54539127

Pulled By: cipolleschi

fbshipit-source-id: 2291cc0c8d6675521b220b02ef0c3c6a3e73be38
2024-05-01 18:07:07 +01:00
Riccardo Cipolleschi df6bec5427 Optimize RCTUIManager to avoid too many calls to viewForReactTag
Summary:
This change fixes a couple of issues within the RCTUIManager:
* it calls the right method in the `super` branches (although they should neve be executed)
* it invert the call order between the `_registry` and the `uiManager` to avoid extra calls into the `viewForReactTag`.

## Changelog:
[Internal] - Use the right method in super and invert the order of where we search for views.

## Facebook:
See S397861 and T180527210 for more information.

Reviewed By: javache

Differential Revision: D54246220

fbshipit-source-id: 1c7503ad3e80cf50ecc016a984ca180a19b73cc0
2024-05-01 18:07:02 +01:00
Distiller 60962b4406 Release 0.74.1-rc.0
#publish-packages-to-npm&--no-tag
2024-05-01 12:34:20 +00:00
Riccardo Cipolleschi 649f4a0d3e [LOCAL] Update trigger-release to support patch prereleases 2024-05-01 13:26:27 +01:00
Riccardo Cipolleschi d7d42673a5 Add support for patch rc versions
Summary:
We might want to publish some new versions of React Native with experimental feature to allow some partners to test whether those versions fixes some reported issues, before creating a proper stable version for the whole ecosystem.

The infra is mostly [setup for this](https://www.internalfb.com/code/fbsource/[496a64d180faab501b8598aa0ec26d47454fb961]/xplat/js/react-native-github/scripts/releases/utils/version-utils.js?lines=149), already. The only detail we need to take care of is not to move the `next` tag.

[Internal]

Reviewed By: cortinico, huntie

Differential Revision: D56578456

fbshipit-source-id: 8dcc674aab5f85077c1b3e6580c5aeb99226eff8
2024-05-01 13:23:08 +01:00
Alex Hunt 3ef4cc9a2f [LOCAL] Add missing chrome-launcher typedef 2024-05-01 10:57:23 +01:00
Riccardo Cipolleschi 462915d89a [LOCAL] Remove duplicated feature flag and fix iOS build 2024-04-30 20:15:58 +01:00
Nicola Corti edd1b0a13b [LOCAL] Fix compilation error on DefaultNewArchitectureEntryPoint 2024-04-30 18:09:12 +01:00
Riccardo Cipolleschi ecd5e51a53 [Local] Remove duplicated feature flags 2024-04-30 17:58:40 +01:00
Riccardo Cipolleschi 1ba79ebb6f [react-native] enable event loop with useLayoutEffect fix 2024-04-30 15:44:06 +01:00
Riccardo Cipolleschi df54c24d8d [LOCAL] Fix merge conflicts not resolved properly 2024-04-30 15:39:15 +01:00
Pieter De Baets ff4b20e823 Split scheduler commit and flush delegate methods (#44188)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44188

The current approach used for `batchRenderingUpdatesInEventLoop` is not compatible with Android due to limitations in its props processing model. The raw props changeset is passed through to Android, and must be available for the Android mounting layer to correctly apply changes.

We have some logic to merge these payloads when multiple ShadowNode clones take place but were previously assuming that a ShadowTree commit was a safe state to synchronize.

In the current implementation this means that two commits driven from layout effects (triggering states A → B → C) may cause Android to observe only the B → C props change, and miss out on any props changed in A → B.

Changelog: [Android][Fixed] Cascading renders were not mounting correctly when `batchRenderingUpdatesInEventLoop` is enabled.

Reviewed By: rubennorte

Differential Revision: D56414689

fbshipit-source-id: 7c74d81620db0f8b7bd67e640168afc795c7a1d7
2024-04-30 15:27:00 +01:00
Rubén Norte b440672468 Enable event loop by default when bridgeless is enabled (#43396)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43396

Changelog: [General][Changed] Enabled new event loop behavior when bridgeless (new architecture) is enabled.

Reviewed By: rshest

Differential Revision: D54682678

fbshipit-source-id: ff8c45bc1caae0e9182aa94d915d7b6f9427caf9
2024-04-30 15:20:25 +01:00
Alex Hunt 261a58761c Update "Open Debugger" to print extended Flipper guidance
Summary:
Supports the removal of Flipper from the template in 0.74, paried with additional blog post messaging: https://reactnative.dev/blog/2024/04/22/release-0.74#removal-of-flipper-react-native-plugin.

Changelog:
[General][Changed] - Update "Open Debugger" action to print extended Flipper guidance

Reviewed By: cipolleschi

Differential Revision: D56705236

fbshipit-source-id: d7e869625262ebb02bc2454c924f832cccfbcd31
2024-04-30 14:07:05 +01:00
Alex Hunt 680d89b6c5 Update Hermes version
For pick request https://github.com/reactwg/react-native-releases/issues/241
2024-04-25 12:05:58 +01:00
Moti Zilberman 93956e267c Align debugger Chrome launch flags with Meta-internal version (#44180)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44180

Changelog: [General][Changed] Update Chrome launch flags for `--experimental-debugger` launch flow

Internally at Meta, we've been testing the experimental debugger launch flow with a different set of Chrome flags than are currently shipped in open source. This diff fixes those differences:

* Removes `--disable-backgrounding-occluded-windows`
* Adds `--guest`

Reviewed By: EdmondChuiHW

Differential Revision: D56418271

fbshipit-source-id: 884c5746e93cad89f17e4ef9e3ef193a2a454eb5
2024-04-25 11:45:48 +01:00
Alex Hunt a69dc5d2a6 Update Podfile.lock
Changelog: [Internal]
2024-04-25 11:45:38 +01:00
Distiller 972b42016e Release 0.74.0
#publish-packages-to-npm&latest
2024-04-22 11:41:17 +00:00
Alex Hunt 5d1272f9cd Update Podfile.lock
Changelog: [Internal]
2024-04-22 11:44:22 +01:00
Distiller d4a48ce692 Release 0.74.0-rc.9
#publish-packages-to-npm&next
2024-04-15 14:02:09 +00:00
Riccardo Cipolleschi 2b18fdf806 [LOCAL][iOS] Fix RNTester project and remove CCACHE from project when disabled 2024-04-15 12:15:37 +01:00
Phillip Pan 92c6d22f3c add privacy manifest to pod install
Summary:
Changelog: [iOS][Added]

this creates the RN privacy manifest in the ios build step if user has not created one yet. the reasons have been added for the following APIs:

NSPrivacyAccessedAPICategoryFileTimestamp
- C617.1: We use fstat and stat in a few places in the C++ layer. We use these to read information about the JavaScript files in RN.

NSPrivacyAccessedAPICategoryUserDefaults
- CA92.1: We access NSUserDefaults in a few places.
1) To store RTL preferences
2) As part of caching server URLs for developer mode
3) A generic native module that wraps NSUserDefaults

NSPrivacyAccessedAPICategorySystemBootTime
- 35F9.1: Best guess reason from RR API pulled in by boost

Reviewed By: cipolleschi

Differential Revision: D53687232

fbshipit-source-id: 6dffb1a6013f8f29438a49752e47ed75c13f4a5c

# Conflicts:
#	packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj
2024-04-15 11:30:01 +02:00
Riccardo Cipolleschi bb5451b425 Fix Open Debugger dev menu item missing from iOS Bridgeless
Summary:
After a [recent change](https://github.com/facebook/react-native/commit/90296be1d4fab09a52e02dd09f34f819136d0a07) we break part of the integration with the debug menu, which is was using the presence/absence of the bridge to decide whether we were in bridge or bridgeless.

For backward compatibility reasosn, the bridge ivar is now populated with the bridgeProxy, so just checking whether is nil or not is not enough to verify whether we are in bridge or in bridgeless mode anymore.

## Changelog:
[iOS][Fixed] - Make sure that the Open Debugger appears in bridgeless mode

Reviewed By: fkgozali

Differential Revision: D56067897

fbshipit-source-id: e2501ed730ff35bc755c24ef400130c551032e28
2024-04-15 11:22:11 +02:00
zhongwuzw 0b3ebdfb22 Change bridgeless check in dev menu (#43976)
Summary:
We would set the value of  _bridge ivar to bridgeProxy for turbo module in bridgeless mode in https://github.com/facebook/react-native/issues/43757 , so we need to change the way of bridgeless/bridge check.

## Changelog:

[IOS] [FIXED] - Change bridgeless check in dev menu

Pull Request resolved: https://github.com/facebook/react-native/pull/43976

Test Plan: Dev menu shows bridgeless/bridge mode correctly.

Reviewed By: christophpurrer

Differential Revision: D56056640

Pulled By: cipolleschi

fbshipit-source-id: 1358c3027c1d5f12c70dd4486cc1d5975c7a185a
2024-04-15 11:22:04 +02:00
Arushi Kesarwani 26854de04b Implement getJavaScriptContextHolder for BridgelessCatalystInstance (#44054)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44054

Implement `getJavaScriptContextHolder()` for BridgelessCatalystInstance

Changelog:
[Android][Breaking] Implement `getJavaScriptContextHolder()` for Bridgeless Catalyst Instance

Reviewed By: christophpurrer

Differential Revision: D56046452

fbshipit-source-id: b7fed1da3064608d8ef5fa84f4e53a4f7a84cba7
2024-04-15 11:21:13 +02:00
Arushi Kesarwani e7131fadca Implement getRuntimeExecutor for BridgelessCatalystInstance (#44053)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44053

Implement `getRuntimeExecutor()` for BridgelessCatalystInstance

Changelog:
[Android][Breaking] Implement `getRuntimeExecutor()` for Bridgeless Catalyst Instance

Reviewed By: christophpurrer

Differential Revision: D56046398

fbshipit-source-id: b9f947cf6f83ce7c1d334558a11b76fccab45dbd
2024-04-15 11:21:07 +02:00
Nicola Corti 012a95cf56 Update Podfile.lock
Changelog: [Internal]
2024-04-10 15:45:31 +01:00
Distiller 2a6e156054 Release 0.74.0-rc.8
#publish-packages-to-npm&next
2024-04-10 13:06:30 +00:00
Riccardo Cipolleschiandzhongwuzw cb2d93ea50 [RN][iOS] Cherry Pick #43757 and #43994 (#44007)
* Support launchOptions in bridgeless mode (#43757)

Summary:
Support launchOptions in bridgeless mode
bypass-github-export-checks

[IOS] [FIXED] - Support launchOptions in bridgeless mode

Pull Request resolved: https://github.com/facebook/react-native/pull/43757

Test Plan:
```
useEffect(() => {
    const processInitialURL = async () => {
      const url = await Linking.getInitialURL();
      if (url !== null) {
        console.log(`Initial url is: ${url}`);
      }
    };

    processInitialURL();
  }, []);
```

Reviewed By: javache

Differential Revision: D55790758

Pulled By: cipolleschi

fbshipit-source-id: 0f6aa6bdcebfc5bc42d632bea9193f122c1eb84f

* Fix Connect to Metro after Reload in Bridgeless mode (#43994)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43994

We received [this issue](https://github.com/facebook/react-native/issues/43764) from OSS where an app can't connect to Metro on reloads in the following scenario:

* Start the App when metro does not run.
* Observe the error screen
* Start Metro
* Press Reload
* Observe the error message again

While the desired behavior should be to connect to Metro now that this is running.

The root cause of the problem is that the RCTHost is initialized with a value of the `bundleURL` that is `nil`. Upon reload, the RCTHost is **not** recreated: the instance is restarted, but with the previous `bundleURL`, which is still `nil`.

The solution is to initialize the `RCTHost` with a closure that re-evaluate the `bundleURL` whenever it is invoked and to evaluate it only on `start`, to keep the initialization path light.
This way, when the app is started with Metro not running, the `bundleURL` is `nil`. But when it is reloaded with Metro starting, the `bundleURL` is properly initialized.

Note that the changes in this diff are not breaking as I reimplemented (and deprecated) the old initializer so that they should work in the same way.

[iOS][Fixed] - Let RCTHost be initialized with a function to provide the `bundleURL` so that it can connect to metro on Reload when the url changes.

Reviewed By: dmytrorykun

Differential Revision: D55916135

fbshipit-source-id: 6927b2154870245f28f42d26bd0209b28c9518f2

* Fix badly resolved merge  conflicts

---------

Co-authored-by: zhongwuzw <zhongwuzw@qq.com>
2024-04-10 11:01:24 +01:00
Phillip Pan 2d84d83534 add privacy manifest to hello world template
Summary:
Changelog: [iOS][Added]

this change will be included in the RN CLI. so all new apps running the RN CLI to get created will get this manifest. the reasons have been added for the following APIs:

NSPrivacyAccessedAPICategoryFileTimestamp
- C617.1: We use fstat and stat in a few places in the C++ layer. We use these to read information about the JavaScript files in RN.

NSPrivacyAccessedAPICategoryUserDefaults
- CA92.1: We access NSUserDefaults in a few places.
1) To store RTL preferences
2) As part of caching server URLs for developer mode
3) A generic native module that wraps NSUserDefaults

NSPrivacyAccessedAPICategorySystemBootTime
- 35F9.1: Best guess reason from RR API pulled in by boost

Reviewed By: cipolleschi

Differential Revision: D53682756

fbshipit-source-id: 0426fe0002a3bc8b45ef24053ac4228c9f61eb85
2024-04-10 08:34:48 +01:00
Nicola Corti 03d526f4d5 Fix bridge mode by constructing ReactDelegate correctly. (#43999)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43999

Currently NewArch-BridgeMode is partially broken when creating views via `ReactDelegate`.
That's because we're using the ctor that doesn't account for `Boolean: fabricEnabled`.

That means that the `RootView` that it will be created are all having setIsFabric(FALSE).
This is causing problems like whitescreens on several reload + multiple warnings such as:
```
                         E  com.facebook.react.bridge.ReactNoCrashSoftException: Cannot get UIManager because the context doesn't contain an active CatalystInstance.
```

Fixes #43692

See for more context on this issues: https://github.com/facebook/react-native/issues/43692

Changelog:
[Android] [Fixed] - Fix bridge mode by constructing ReactDelegate correctly

Reviewed By: cipolleschi

Differential Revision: D55921078

fbshipit-source-id: 2c21d089a49538402d546177bcdb26c8d7d5fbc1
2024-04-09 18:27:53 +01:00
Riccardo Cipolleschi 4eb0534513 Fix Orientation listener in bridgeless mode (#43971)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43971

It turns out that we forgot to add a listener for the orientation change event in Bridgeless.

We used to have `UIApplicationDidChangeStatusBarOrientationNotification` but this is slightly unreliable because there might be use cases where the status bar has been hidden and, therefore, the event is not triggered.

This should fix an issue reported by OSS.

## Changelog:
[iOS][Fixed] - Make sure that the New Architecture listens to orientation change events.

Reviewed By: cortinico

Differential Revision: D55871599

fbshipit-source-id: c9b0634ec2126aa7a6488c2c56c87a9610fa1adf
2024-04-09 18:26:52 +01:00
Riccardo Cipolleschi c2317bf9a5 Fix double metro banner in Bridgeless (#43967)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43967

Following up https://github.com/facebook/react-native/issues/43943, the metro loading banner is presented twice in Bridgeless mode.

This happens because both the RCTInstance and the RCTHost are listening to the Reload Command and issuing the instructions to refetch the JSBundle and to present the banner.

The RCTInstance should not concern itself with lifecycle events, owned by the RCTHost.

## Changelog:
[iOS][Fixed] - Avoid to show Metro Loading banner twice.

Reviewed By: cortinico

Differential Revision: D55870640

fbshipit-source-id: addb67d3226f7d7db20736309172a42fc15f3aa3
2024-04-09 18:26:41 +01:00
Evert Eti 85170c9442 Fix possible deadlock in dispatchViewUpdates (#43643)
Summary:
In https://github.com/th3rdwave/react-native-safe-area-context/issues/448 it was noticed that from 0.72 (https://github.com/facebook/react-native/commit/bc766ec7f8b18ddc0ff72a2fff5783eeeff24857 https://github.com/facebook/react-native/pull/35889) it was possible to get a deadlock in dispatchViewUpdates. ([More details](https://github.com/th3rdwave/react-native-safe-area-context/issues/448#issuecomment-1871155936))

This deadlock resulted in a laggy experience for all users using https://github.com/th3rdwave/react-native-safe-area-context/ on Android.

To avoid this problem, the author of the original fix [proposed](https://github.com/th3rdwave/react-native-safe-area-context/issues/448#issuecomment-1872121172) this solution which was tested by Discord and many other users.

It would be great to have this backported to 0.72 and 0.73 because of the large userbase using react-native-safe-area-context since it's recommended by expo and react-navigation.

## Changelog:

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID] [FIXED] - Fixed possible deadlock in dispatchViewUpdates

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[ANDROID] [FIXED] - Fixed possible deadlock in dispatchViewUpdates

Pull Request resolved: https://github.com/facebook/react-native/pull/43643

Test Plan:
The original memory leak remains fixed, and can be verified in https://github.com/feiyin0719/RNMemoryLeakAndroid.

To verify the deadlock is gone, every app using https://github.com/th3rdwave/react-native-safe-area-context will work smoothly and not log any excessive `Timed out waiting for layout`
(https://github.com/17Amir17/SafeAreaContext)

Reviewed By: arushikesarwani94

Differential Revision: D55339059

Pulled By: zeyap

fbshipit-source-id: c067997364fbec734510ce99b9994e89d044384a
2024-04-09 18:25:03 +01:00
Nicola Corti cbfa0a2055 Update Podfile.lock
Changelog: [Internal]
2024-04-08 14:56:24 +01:00
Distiller 40feba6a81 Release 0.74.0-rc.7
#publish-packages-to-npm&next
2024-04-08 12:21:14 +00:00
zhongwuzw 44159e35ce Remove invalidate observer instead of re-adding observer in DeviceInfo module (#43737)
Summary:
Previous fix brings in https://github.com/facebook/react-native/pull/42396. Seems it's a mistake to re-add observer?
So let's remove it and also not `invalidate` method not be called twice.

## Changelog:

[IOS] [FIXED] - Remove invalidate observer instead of re-adding observer in DeviceInfo module

Pull Request resolved: https://github.com/facebook/react-native/pull/43737

Test Plan: Fix for https://github.com/facebook/react-native/issues/42120 also works.

Reviewed By: javache

Differential Revision: D55692219

Pulled By: cipolleschi

fbshipit-source-id: dba1ddc39a9f2611fc2b84fadf8c23827891379a
2024-04-08 07:52:09 +01:00
Riccardo Cipolleschi 42eebafb81 Fix static linking for Bridgeless mode (#43846)
Summary:
Working with gabrieldonadel, we realized that static frameworks of the React-RendererRuntime are not following the proper folder structure.
When a user tries to import `ReactCommon/RCTHost` in the app delegate, for example, the user ends up with an error and they can't find the files.

These changes fixes this by establishing the right folder structure in the static frameworks

## Changelog:
[Internal] - Make sure that React-RuntimeCore and JSErrorHandler are created with the proper structure for static frameworks

Pull Request resolved: https://github.com/facebook/react-native/pull/43846

Test Plan:
Tested locally on an app with 0.74.
Before: it failed to build.
After: it build successfully.

Reviewed By: cortinico

Differential Revision: D55741581

Pulled By: cipolleschi

fbshipit-source-id: 11ac0882d3feea05ef8904d55856ba5704b7a3b8
2024-04-08 07:51:47 +01:00
Riccardo Cipolleschi 4e9196d433 Fix RCTRCTComposedViewRegistry for Old Arch by adding count and keyEnumerator (#43850)
Summary:
In the Old Architecture and for Swift Libraries, these two methods are used to initialize a new disctionary but their implementation was missing so some libraries like lottie were failig to build.

## Changelog:
[Internal] - Implement missing `count` and `keyEnumerator` methods for RCTComposedViewRegistry

Pull Request resolved: https://github.com/facebook/react-native/pull/43850

Test Plan: Tested locally with the repro provided by SWM

Reviewed By: javache

Differential Revision: D55743648

Pulled By: cipolleschi

fbshipit-source-id: 7bdb92625341cd704b8b09920ab3223a2ca61a54
2024-04-08 07:51:09 +01:00
Vojtech Novak 57ed1bde01 fix: add missing fields to native errors in new arch (#43649)
Summary:
With 0.74.rc-5 one bug which related to errors was fixed (https://github.com/facebook/react-native/issues/41950). However, the fix introduced another one: the shape of Error objects that come from native modules has changed. This PR attempts to fix that, though it's not (yet) doing it in a way that would be 100% compatible with the old arch.

The problem was observed on iOS, not sure what the situation is on Android but believe it's okay there.

edit: on Android, there are no issues but the `message` field is enumerable, so that part is different from ios (see logs below).

Consider this code, where `error` is produced from a promise rejection inside of a native module.

```ts
  console.log(
    'own properties: ',
    JSON.stringify(Object.getOwnPropertyNames(error), null, 2),
  );
  console.log(
    'own enumerable properties: ',
    JSON.stringify(Object.entries(error), null, 2),
  );
```

These are the results for

<details>
  <summary>Old architecture</summary>

```
 LOG  Running "google-one-tap-example" with {"rootTag":1,"initialProps":{}}
 LOG  own properties:  [
  "stack",
  "code",
  "message",
  "domain",
  "userInfo",
  "nativeStackIOS"
]
 LOG  own enumerable properties:  [
  [
    "code",
    "-5"
  ],
  [
    "message",
    "RNGoogleSignIn: The user canceled the sign in request., Error Domain=com.google.GIDSignIn Code=-5 \"The user canceled the sign-in flow.\" UserInfo={NSLocalizedDescription=The user canceled the sign-in flow.}"
  ],
  [
    "domain",
    "com.google.GIDSignIn"
  ],
  [
    "userInfo",
    {
      "NSLocalizedDescription": "The user canceled the sign-in flow."
    }
  ],
  [
    "nativeStackIOS",
    [
      "0   ReactTestApp                        0x0000000102f4a6d8 RCTJSErrorFromCodeMessageAndNSError + 112",
      "1   ReactTestApp                        0x0000000102eeedd0 __41-[RCTModuleMethod processMethodSignature]_block_invoke_2.73 + 152",
      "2   ReactTestApp                        0x0000000102e2ae24 +[RNGoogleSignin rejectWithSigninError:withRejector:] + 548",
      "3   ReactTestApp                        0x0000000102e2aa8c -[RNGoogleSignin handleCompletion:serverAuthCode:withError:withResolver:withRejector:fromCallsite:] + 184",
      "4   ReactTestApp                        0x0000000102e2a8e0 -[RNGoogleSignin handleCompletion:withError:withResolver:withRejector:fromCallsite:] + 236",
      "5   ReactTestApp                        0x0000000102e28628 __40-[RNGoogleSignin signIn:resolve:reject:]_block_invoke_2 + 100",
      "6   ReactTestApp                        0x0000000102dc9d80 __35-[GIDSignIn addCompletionCallback:]_block_invoke_2 + 132",
...
    ]
  ]
]
```
</details>

<details>
  <summary>RN 74 rc-5 (with bridgeless on)</summary>

```
  (NOBRIDGE) LOG  Bridgeless mode is enabled
 (NOBRIDGE) LOG  Running "google-one-tap-example" with {"rootTag":1,"initialProps":{"concurrentRoot":true},"fabric":true}
 (NOBRIDGE) LOG  own properties:  [
  "stack",
  "message",
  "cause"
]
 (NOBRIDGE) LOG  own enumerable properties:  [
  [
    "cause",
    {
      "code": "-5",
      "message": "RNGoogleSignIn: The user canceled the sign in request., Error Domain=com.google.GIDSignIn Code=-5 \"The user canceled the sign-in flow.\" UserInfo={NSLocalizedDescription=The user canceled the sign-in flow.}",
      "nativeStackIOS": [
        "0   ReactTestApp                        0x00000001023a7b38 RCTJSErrorFromCodeMessageAndNSError + 112",
        "1   ReactTestApp                        0x00000001026cf774 ___ZZN8facebook5react15ObjCTurboModule13createPromiseERNS_3jsi7RuntimeENSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEU13block_pointerFvU13block_pointerFvP11objc_objectEU13block_pointerFvP8NSStringSH_P7NSErrorEEENK3$_0clES4_RKNS2_5ValueEPSQ_m_block_invoke.57 + 332",
        "2   ReactTestApp                        0x0000000102270958 +[RNGoogleSignin rejectWithSigninError:withRejector:] + 548",
        "3   ReactTestApp                        0x00000001022705c0 -[RNGoogleSignin handleCompletion:serverAuthCode:withError:withResolver:withRejector:fromCallsite:] + 184",
        "4   ReactTestApp                        0x0000000102270414 -[RNGoogleSignin handleCompletion:withError:withResolver:withRejector:fromCallsite:] + 236",
        "5   ReactTestApp                        0x000000010226e15c __40-[RNGoogleSignin signIn:resolve:reject:]_block_invoke_2 + 100",
        "6   ReactTestApp                        0x000000010220f328 __35-[GIDSignIn addCompletionCallback:]_block_invoke_2 + 132",
...
      ],
      "domain": "com.google.GIDSignIn",
      "userInfo": {
        "NSLocalizedDescription": "The user canceled the sign-in flow."
      }
    }
  ]
]
```
</details>

<details>
  <summary>with the diff from this PR</summary>

```
 (NOBRIDGE) LOG  own properties:  [
  "stack",
  "message",
  "code",
  "nativeStackIOS",
  "domain",
  "userInfo"
]
 (NOBRIDGE) LOG  own enumerable properties:  [
  [
    "code",
    "-5"
  ],
  [
    "nativeStackIOS",
    [
      "0   ReactTestApp                        0x000000010083b8f8 RCTJSErrorFromCodeMessageAndNSError + 112",
      "1   ReactTestApp                        0x0000000100b63534 ___ZZN8facebook5react15ObjCTurboModule13createPromiseERNS_3jsi7RuntimeENSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEU13block_pointerFvU13block_pointerFvP11objc_objectEU13block_pointerFvP8NSStringSH_P7NSErrorEEENK3$_0clES4_RKNS2_5ValueEPSQ_m_block_invoke.57 + 332",
      "2   ReactTestApp                        0x0000000100704718 +[RNGoogleSignin rejectWithSigninError:withRejector:] + 548",
      "3   ReactTestApp                        0x0000000100704380 -[RNGoogleSignin handleCompletion:serverAuthCode:withError:withResolver:withRejector:fromCallsite:] + 184",
      "4   ReactTestApp                        0x00000001007041d4 -[RNGoogleSignin handleCompletion:withError:withResolver:withRejector:fromCallsite:] + 236",
      "5   ReactTestApp                        0x0000000100701f1c __40-[RNGoogleSignin signIn:resolve:reject:]_block_invoke_2 + 100",
      "6   ReactTestApp                        0x00000001006a30e8 __35-[GIDSignIn addCompletionCallback:]_block_invoke_2 + 132",
...
    ]
  ],
  [
    "domain",
    "com.google.GIDSignIn"
  ],
  [
    "userInfo",
    {
      "NSLocalizedDescription": "The user canceled the sign-in flow."
    }
  ]
]

```
</details>

You see there is a change compared to old arch because `message` is no longer own enumerable property. If that needs to change (I guess it should), it'd be nice if someone more familiar with JSI pointed me in the right direction. Even with this inconsistency, the PR is an improvement and would be nice to have this fix included in the next RC.

This is output from Chrome's console for completeness, just to have something to compare to:

```
let err = new Error('hello')
undefined
Object.getOwnPropertyNames(err)
> ['stack', 'message']
Object.entries(err)
> []
```

bypass-github-export-checks

## Changelog:

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[IOS] [FIXED] - add missing fields to native errors in new arch

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests

Pull Request resolved: https://github.com/facebook/react-native/pull/43649

Test Plan: Tested locally with an example app running RN 74-rc 5

Reviewed By: cortinico

Differential Revision: D55690184

Pulled By: cipolleschi

fbshipit-source-id: 60a857b9871af888dcd526782b5e6b73c07c051a
2024-04-08 07:50:19 +01:00
Jean-Baptiste LARRIVIERE 454e576b5b fix: build settings for custom build configuration (#43780)
Summary:
This allows build configuration named like `StagingDebug` to match with settings applied to `Debug` This fixes https://github.com/facebook/react-native/issues/43185

Custom build setting were only applied to `Debug` build configurations, preventing configurations named `StagingDebug` or similar to access the new experimental debugger, as reported in https://github.com/facebook/react-native/issues/43185

This now applies the setting to every configuration ending with `Debug`

## Changelog:

[IOS] [CHANGED] - fix: build settings for custom build configuration

Pull Request resolved: https://github.com/facebook/react-native/pull/43780

Reviewed By: dmytrorykun

Differential Revision: D55688996

Pulled By: cipolleschi

fbshipit-source-id: 1f34cd722f6acfaa08d3377e19a04d08af97ed7c
2024-04-08 07:49:43 +01:00
Dmitry Rykun d0dd48b4c9 Print Hermes build script shell commands only in CI (#43767)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43767

Print Hermes build script shell commands only in CI.

Changelog: [Internal]

Reviewed By: cipolleschi

Differential Revision: D55635527

fbshipit-source-id: f0a901e11c523987e97a28b5238dcc08586516dd
2024-04-08 07:49:43 +01:00
Riccardo Cipolleschi 0e5dc51bba [Yoga][0.74] Fix archive for MacOS Catalyst (#43900) 2024-04-08 07:49:36 +01:00
Alex Hunt 82643e1a35 Update Podfile.lock
Changelog: [Internal]
2024-04-02 13:48:19 +01:00
Distiller 6abca78895 Release 0.74.0-rc.6
#publish-packages-to-npm&next
2024-04-02 11:04:49 +00:00
Szymon Rybczak 4f50089da2 Upgrade @react-native-community/cli to 13.6.4 (#43681) 2024-04-02 10:38:55 +01:00
phillip 49bb2f37f1 [rn][ios][0.74][RC6] decouple RCTBridge+Private from jsinspector-modern (#43708) 2024-04-02 10:38:27 +01:00
Arushi Kesarwani dc851b6b3a React-Native-Restart in release (#43645)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43645

https://github.com/facebook/react-native/pull/43521 & https://github.com/facebook/react-native/pull/43588 aimed to fix `react-native-restart`, however in release `handleReloadJS()` is a no-op in [DisabledDevSupportManager](https://github.com/facebook/react-native/blob/ac714b1c3300d3a169bdcfec05d556e18a7b83ff/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DisabledDevSupportManager.java#L139) which is why this should not work. Fixing it by relying on `ReactHostImpl.reload()` instead for Bridgeless.

Adding implementation of `DisabledDevSupportManager.handleReloadJS()` won't work as it would mean introducing circular dependency `devsupport` -> `runtime`

Reviewed By: cortinico

Differential Revision: D55342296

fbshipit-source-id: ee6fba68586a2bdd1163522f75e6beb1b7736f6c
2024-04-02 10:37:19 +01:00
Ruslan Lesiutin 9a286d65d1 fix[android]: fix bridgeless configuration to include DebuggingOverlay in react packages (#43661)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43661

# Changelog: [Internal]

1. Remove `BridgelessDebugReactPackage.java`, this was added in D43407534. Technically, its the same as `DebugCorePackage.java`.
2. `ReactInstance` to add `DebugCorePackage`, so `DebuggingOverlay` view manager will be included in the bridgeless build.
3. Fix `RNTesterApplication.kt` to NOT create `MyLegacyViewManager` for every possible viewManagerName, apart from `"RNTMyNativeView"`, return null instead.

Reviewed By: cortinico

Differential Revision: D55375350

fbshipit-source-id: 1d3cb6b5ad3c0248df1def9f37c8c49b308f4473
2024-04-02 10:36:59 +01:00
Ruslan Lesiutin 1dc11cb2b3 fix: defer ReactDevToolsOverlay import (#43690)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43690

# Changelog: [Internal]

Fixes https://github.com/facebook/react-native/issues/43678.

The issue is that once `getInspectorDataForViewAtPoint` is imported, it should throw if RDT global hook was not injected. ReactDevTools overlay imports `getInspectorDataForViewAtPoint`, this is why it did throw in testing environment.

ReactDevToolsOverlay JSX-element is already gated with RDT global hook check, adding a deferred import, same as it was already implemented for Inspector.

Still unclear to me how this didn't throw all this time while using the Catalyst / RNTester.

Reviewed By: cortinico

Differential Revision: D55474774

fbshipit-source-id: 759e5e8227cc7534193e5b95616b6099c15f5cb5
2024-04-02 10:36:34 +01:00
Andrew Coates 5d63c85ced Add @types/react as optional peerDependency on packages that use it (#43509)
Summary:
Now that RN is providing TS type information, many of those .d.ts files depend on types from react.  In modern packagemanagers (Ex: pnpm) types/react will not be available to RN since it does not declare it as a dependency.

I also noticed that the types for react-native-popup-menu-android appear to be pointing to the wrong location.

Add types/react as a peerDependency on the packages that have .d.ts files that import from React.
Add types/react to peerDependencyMeta with optional:true to prevent users not using TS from requiring types/react.

[GENERAL] [ADDED] Added types/react as an optional peerDependency

Pull Request resolved: https://github.com/facebook/react-native/pull/43509

Reviewed By: cortinico

Differential Revision: D55225940

Pulled By: NickGerleman

fbshipit-source-id: 4cbab071928cb925baec45f55461559acc9a54e6
2024-04-02 10:35:24 +01:00
CatStudioApp 462fbaef0c Update package.json to fix ccache_enabled option, fixes #43633 (#43634)
Summary:
I found in 0.74.0-rc.x, `ccache_enabled` is introduced. However, it is not being delivered via npm.

fixes https://github.com/facebook/react-native/issues/43633

Changelog: [iOS] [Fixed] - Adding ccache_clang wrapper scripts to package.json for distribution

Pull Request resolved: https://github.com/facebook/react-native/pull/43634

Reviewed By: cortinico

Differential Revision: D55308743

Pulled By: blakef

fbshipit-source-id: e89a4bb3a1fbf8562d880b4c9d25dc9083717ba6
2024-04-02 10:34:18 +01:00
Dmitry Rykun d85f8b7e7a Set HERMES_RELEASE_VERSION correctly (#43699)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43699

This diff initializes `RELEASE_VERSION` with the value that is provided by the `get_react_native_version` job (it stores its output into `/tmp/react-native-version`).

Changelog: [Internal]

Reviewed By: fkgozali

Differential Revision: D55484988

fbshipit-source-id: f0b5bb473096f3691f50152beb3181a454916fdc
2024-04-02 10:33:29 +01:00
Dmitry Rykun a37ba6f3ff Move IOS_DEPLOYMENT_TARGET and MAC_DEPLOYMENT_TARGET to the command body
Summary:
This diff moves IOS_DEPLOYMENT_TARGET and MAC_DEPLOYMENT_TARGET definitions to the command body.

Changelog: [Internal]

Reviewed By: fkgozali

Differential Revision: D55478563

fbshipit-source-id: bae327edbaf88a9e8b39b304d938389e3fc56f4f
2024-04-02 10:33:26 +01:00
Dmitry Rykun f4b5bf1e14 Explicitly define IOS_DEPLOYMENT_TARGET and MAC_DEPLOYMENT_TARGET on CircleCI (#43683)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43683

This diff adds explicit definitions of IOS_DEPLOYMENT_TARGET and MAC_DEPLOYMENT_TARGET to `build_apple_slices_hermes` and `build_hermes_macos` jobs on CircleCI.
Eventually this will allow us to stop [interacting](https://github.com/facebook/react-native/blob/main/packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh#L28) with `hermes-engine.podspec` outside of the CocoaPods execution context, and make our CI jobs less error prone.

Changelog: [Internal]

Reviewed By: fkgozali, cortinico

Differential Revision: D55432703

fbshipit-source-id: dc1cc449ba60340d13db9e4d21970e4e3783f2da
2024-04-02 10:30:16 +01:00
Kevin Gozali 03237f449a Keep ES6Proxy enabled in bridgeless mode (#43538)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43538

The Hermes RuntimeConfig for bridgeless accidentally force-disabled ES6Proxy, resulting in https://github.com/facebook/react-native/issues/43523

Let's remove the incorrect override.

To test using RNTester, add the following change:

```
 diff --git a/packages/rn-tester/js/RNTesterAppShared.js b/packages/rn-tester/js/RNTesterAppShared.js
index 87cb6b69dfe..f2512d09c5a 100644
 --- a/packages/rn-tester/js/RNTesterAppShared.js
+++ b/packages/rn-tester/js/RNTesterAppShared.js
@@ -50,6 +50,8 @@ const RNTesterApp = ({
   );
   const colorScheme = useColorScheme();
+  new Proxy({}, {});
+
   const {
     activeModuleKey,
     activeModuleTitle,
```

Before this change, RNTester will get an error at start-up. After, the app loads correctly.

Changelog: [General][Fixed] Correctly keep ES6Proxy for bridgeless mode

Reviewed By: cortinico

Differential Revision: D55045780

fbshipit-source-id: 666b99712d35622f87d42f22a4611851df67d905
2024-04-02 10:29:43 +01:00
Alex Hunt d81065a621 [LOCAL] Update RNTester Podfile.lock 2024-04-02 10:29:27 +01:00
Distiller c0c3ac3f13 Release 0.74.0-rc.5
#publish-packages-to-npm&next
2024-03-25 13:57:17 +00:00
Nicola Corti cc6e734fa4 Revert "fix(iOS): add missing forward blocks to RCTRootViewFactory (#43638)"
This reverts commit eed035a3b6.
2024-03-25 12:18:44 +00:00
Arushi Kesarwani f6757a20c6 Expose ReactDelegate for react-native-restart (#43588)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43588

Supported `reload()` in Bridgeless through ReactDelegate in https://github.com/facebook/react-native/pull/43521 in order to unblock react-native-restart

https://github.com/avishayil/react-native-restart/blob/134cabd5b3f355ffe551e5dd1be1dd46d870fe13/android/src/main/java/com/reactnativerestart/RestartModule.java#L54

which can access React Delegate through :
```
if(currentActivity instanceof ReactActivity) {
    ReactActivity reactActivity = (ReactActivity) currentActivity;
    ReactDelegate reactDelegate = reactActivity.getReactDelegate();
    reactDelegate.reload()
}
```

Changelog:
[Android][Added] Expose ReactDelegate in ReactActivity

Reviewed By: cortinico

Differential Revision: D55166962

fbshipit-source-id: 5d8dfd7ad61edbcb5233014800eb66a538842ca5
2024-03-25 10:45:35 +00:00
Arushi Kesarwani 0e5ba6db2d Support reload in ReactDelegate (#43521)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43521

Changelog:
[Android] [Added] - Support reload() in ReactDelegate

Reviewed By: cortinico

Differential Revision: D54967602

fbshipit-source-id: adfa200cabcbecf9507775ac38f17c9d01b2671a
2024-03-25 10:45:00 +00:00
Arushi Kesarwani 36d64312c8 Refactor ReactDelegate to provide DevSupportManager (#43520)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43520

Refactor ReactDelegate to have a private `getDevSupportManager()` that can also be re-used  by `reload()`

This method conditionally provides the correct DevSupportManager in cases of Bridge & Bridgeless

Changelog:
[Internal] internal

Reviewed By: cortinico

Differential Revision: D54967130

fbshipit-source-id: 37d585de33a50b98d01803d3080c5693a8c494b9
2024-03-25 10:44:47 +00:00
Arushi Kesarwani 4fe26e3b2f Support onKeyLongPress in Bridgeless (#43472)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43472

Implement `onKeyLongPress` in Bridgeless

Changelog:
[Android][Breaking] Implement onKeyLongPress in Bridgeless

Reviewed By: cortinico

Differential Revision: D54876052

fbshipit-source-id: 88d572eab087d913205bdfa02dba96b169066393
2024-03-25 10:43:56 +00:00
Arushi Kesarwani 8bf509ec44 Support onKeyDown in Bridgeless (#43466)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43466

Implement `onKeyDown` in Bridgeless by adding it to ReactHostImpl

Changelog:
[Android][Breaking] Implement `onKeyDown` in Bridgeless

Reviewed By: cortinico

Differential Revision: D54870966

fbshipit-source-id: 0f8e48b29679f1bca92f6ac7b6ebf1592cdc5dac
2024-03-25 10:43:30 +00:00
Arushi Kesarwani 76463789fd Support onConfigurationChanged in Bridgeless (#43463)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43463

Implement `onConfigurationChanged` in Bridgeless by adding it to ReactHostImpl

Changelog:
[Android][Breaking] Implement onConfigurationChanged in Bridgeless

Reviewed By: cortinico, RSNara

Differential Revision: D54792399

fbshipit-source-id: 6851daca815f486f4d839e128a1d740d3fec1996
2024-03-25 10:42:52 +00:00
Arushi Kesarwani dbc83220e0 Support onNewIntent in Bridgeless (#43401)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43401

Implement `onNewIntent` in Bridgeless by adding it to ReactHostImpl

Changelog:
[Android][Breaking] Implement `onNewIntent` in Bridgeless

Reviewed By: fkgozali, RSNara

Differential Revision: D54703159

fbshipit-source-id: fd8589d8131f4fa57188d493331dc68fb38c4520
2024-03-25 10:40:54 +00:00
Arushi Kesarwani 5eea4cda1b Support onWindowFocusChange in Bridgeless (#43398)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43398

Implement onWindowFocusChange in Bridgeless by adding it to the ReactHostImpl

Changelog:
[Android][Breaking] Implement onWindowFocusChange in Bridgeless

Reviewed By: javache

Differential Revision: D54670119

fbshipit-source-id: 71f560e5a3bf0e853ac06955e67b8035f1ec0468
2024-03-25 10:40:25 +00:00
Nicola Corti 0f4234f450 Fix InteropUIBlockListener to support react-native-view-shot on Bridgeless (#43594)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43594

I've been migrating `react-native-view-shot` to Fabric by using the `InteropUiBlockListener`
and I've realized that the interop layer doesn't work well.

1. FabricUIManager needs to implement `UIBlockViewResolver` in order for the interop layer to work correctly.
2. We need to hook `addUIBlock` to the `didDispatchMountItems` callback otherwise the UIBlocks won't be executed at all.

Changelog:
[Android] [Fixed] - Fix InteropUIBlockListener to support react-native-view-shot on Bridgeless

Reviewed By: javache

Differential Revision: D55187939

fbshipit-source-id: d048b4b5eed77fa856fdfac17c0df5f23fd44844
2024-03-25 10:30:26 +00:00
Nick Gerleman 396d444e79 Fix Android HorizontalScrollView fling when content length less than ScrollView length (#43563)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43563

Fixes https://github.com/facebook/react-native/issues/42874

## Sumary

D9405703 added some custom logic for Flings, to support FlatList scenarios where content is being added on the fly, during Fling animation. This works by allowing start Fling to not have bounds, then correcting/cancelling Fling when overscroll happens over a bound that would normally be allowed.

This has some math to try to determine max content length, and will clamp to this when scrolling over it. This logic is incorrect when content length is less than scrollview length, and we end up snapping to a negative offset.

This change adds clamping, so that we don't snap to negative position in horizontal scroll view. This clamping was already indirectly present on vertical scroll view. https://www.internalfb.com/code/fbsource/[b43cdf9b2fec71f5341ec8ff2d47e28a066f052e]/xplat/js/react-native-github/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java?lines=609

## Test Plan

Above issue no longer reproes. Flinging while content is being added to horizontal FlatList still works correctly.

Changelog:
[Android][Fixed] - Fix Android HorizontalScrollView fling when content length less than ScrollView length

Reviewed By: javache

Differential Revision: D55108818

fbshipit-source-id: 7cf0065f9f92832cc2606d1c7534fc150407b9c9
2024-03-25 10:28:29 +00:00
Nick Gerleman 20bcf57ee3 Warn users during "pod install" if XCode is too old (#43583)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43583

Fail during `pod install` if user's version of XCode is too old to avoid cryptic errors (e.g. https://github.com/reactwg/react-native-releases/issues/163).

I reused existing mechanism for version detection, though it may not be reliable for future versions of XCode.

Changelog:
[iOS][Changed] - Warn users during "pod install" if XCode is too old

Reviewed By: dmytrorykun

Differential Revision: D55149636

fbshipit-source-id: 78387ff19a6eb10f3ca0d4aa78e6b934ae3b0711
2024-03-25 10:28:13 +00:00
Gabriel Donadel 33e3ec9426 Implement multiple view manager lookup for the interop layer on Android (#43595)
Summary:
When running with the new architurece and using the renderer interop layer on Android, view managers don't work if their names start with `RCT`. This happens because the `RCT` prefix is automatically removed from the component name, and inside the internal `mViewManagers` we store view managers with the `RCT` prefix.

Using the `RCT` pattern as a prefix works fine with the old architecture and is actually used on the [Android Native UI Components](https://reactnative.dev/docs/next/native-components-android) tutorial in the docs, making me believe that this same patterns is used across many community libraries.

This diff adds a secondary lookup logic for view managers:

1. We look for the XXXViewManager.
2. If not found, we look for RCTXXXViewManager.

Quite similar to the iOS implementation introduced in  https://github.com/facebook/react-native/pull/38093

 ---

With this change we can also remove most of the entries from FabricNameComponentMapping (I can address this in a follow up PR)

https://github.com/facebook/react-native/blob/4e6eba7a2dedaa855af0bff5df3bec73a95f0fc4/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/FabricNameComponentMapping.java#L22-L45

## Changelog:

[ANDROID] [ADDED] - Implement multiple view manager lookup for the interop layer

Pull Request resolved: https://github.com/facebook/react-native/pull/43595

Test Plan:
Tested installing a library such as [react-native-fbsdk-next](https://github.com/thebergamo/react-native-fbsdk-next) that names its view managers starting with `RCT`

<table>
<tr>
  <th>Before</th>
  <th>After</th>
</tr>
<tr>
<td>
<img width="519" alt="image" src="https://github.com/facebook/react-native/assets/11707729/123de1d6-f018-424b-b6ce-38221af9d83e">
</td>
<td><img width="519" alt="image" src="https://github.com/facebook/react-native/assets/11707729/0f35b369-e2e4-4bbf-b880-6471fbc05d38">
</td>
</tr>
</table>

Reviewed By: cortinico

Differential Revision: D55208396

Pulled By: arushikesarwani94

fbshipit-source-id: a1fb1f4cee8483cf91ebededd1d7c4ba7021f9d9
2024-03-25 10:27:49 +00:00
Jakub Piasecki 35f6000c66 Include boost headers needed by rrc_text and rrc_textinput (#43608)
Summary:
Updates `PreparePrefabHeadersTask` to copy more headers from `boost`, specifically those required by `rrc_text` and `rrc_textinput`.

## Changelog:

[ANDROID] [CHANGED] - Copy boost headers needed by `rrc_text` and `rrc_textinput`

Pull Request resolved: https://github.com/facebook/react-native/pull/43608

Reviewed By: rshest

Differential Revision: D55241345

Pulled By: cortinico

fbshipit-source-id: e92164676ba78ee15b3678a55c9098b0c6214b69
2024-03-25 10:27:25 +00:00
Jakub Piasecki 1d4b263d3d Fix prefab header paths for rrc_text and rrc_textinput (#43591)
Summary:
- `rrc_textinput` at the moment points to a wrong subdirectory and needlessly adds a prefix path
- `rrc_text` is missing headers for `attributedstring` which it depends on

## Changelog:

[ANDROID] [FIXED] - Fixed prefab header paths for `rrc_text` and `rrc_textinput`

Pull Request resolved: https://github.com/facebook/react-native/pull/43591

Reviewed By: fkgozali

Differential Revision: D55199580

Pulled By: cortinico

fbshipit-source-id: 85126c00943f82e908a52e05587661597761852e
2024-03-25 10:26:24 +00:00
Nicola CortiandTommy Nguyen 2c62dcabe5 [0.74] Fixes build from source on Android (#43616)
* fix(android): fix `ndkVersion` is unset when building from source (#43131)

Summary:
`ndkVersion` is unset when building from source using this guide: https://reactnative.dev/contributing/how-to-build-from-source

## Changelog:

[ANDROID] [FIXED] - Fix `ndkVersion` is unset when building from source

Pull Request resolved: https://github.com/facebook/react-native/pull/43131

Test Plan:
```
git clone https://github.com/microsoft/react-native-test-app.git
cd react-native-test-app
npm run set-react-version nightly
yarn

# Manually apply the patch in node_modules/react-native/ReactAndroid/build.gradle.kts
# Enable building from source
sed -i '' 's/#react.buildFromSource/react.buildFromSource/' example/android/gradle.properties

# Build
cd example/android
./gradlew assembleDebug
```

Reviewed By: christophpurrer

Differential Revision: D54006425

Pulled By: cortinico

fbshipit-source-id: 9ede64bc14af4cf609b7a4c12c5a1082bbc31f09

* Fix build from source for hermes-engine (#43609)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43609

When users are building from source for React Native they don't have an ndkVersion variable specified. So we want to fallback to the global NDK version we set for the whole build here.

Changelog:
[Android] [Fixed] - Fix build from source for hermes-engine

Reviewed By: dmytrorykun

Differential Revision: D55240603

fbshipit-source-id: 3c725a164b40e176548af8ada9fcb13d391ef017

---------

Co-authored-by: Tommy Nguyen <4123478+tido64@users.noreply.github.com>
2024-03-25 10:24:36 +00:00
eed035a3b6 fix(iOS): add missing forward blocks to RCTRootViewFactory (#43638)
* fix(iOS): add missing forward blocks to RCTRootViewFactory (#43526)

Summary:
This PR adds missing forwarding blocks to RCTRootViewFactory, currently when a user tries to override `sourceURLForBridge` in AppDelegate it isn't overridden.

## Changelog:

[IOS] [FIXED] - add missing forward blocks to RCTRootViewFactory

Pull Request resolved: https://github.com/facebook/react-native/pull/43526

Test Plan: Override: `extraModulesForBridge`, `extraLazyModuleClassesForBridge`, `bridge didNotFindModule`,  `sourceURLForBridge:` methods in AppDelegate and check if they are called on old architecture

Reviewed By: philIip

Differential Revision: D55186872

Pulled By: cortinico

fbshipit-source-id: 5988c7bab1439ccc4885b7337336c1e120ba9ea6
(cherry picked from commit 9d79f05e68)

* Follow-up with Review Feedback on RCTAppDelegate from #43526 (#43607)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43607

PR #43526 was accidentally merged with several changes excluded. I'm following up on those here.

Changelog:
[Internal] [Changed] - Follow-up with Review Feedback on RCTAppDelegate from #43526

Reviewed By: dmytrorykun

Differential Revision: D55240435

fbshipit-source-id: c296a1e14b7032b211551334ca7b5a6824e8d45c
(cherry picked from commit 84c1c6ea9b)

---------

Co-authored-by: Oskar Kwaśniewski <oskarkwasniewski@icloud.com>
Co-authored-by: Nicola Corti <ncor@meta.com>
2024-03-25 10:24:21 +00:00
Cedric van Putten f3b9226ca0 fix(dev-middleware): create custom message handler for synthetic page (#43559)
Summary:
This is a follow-up bugfix for expo/expo#27425, related to:
 - https://github.com/facebook/react-native/issues/43291
 - https://github.com/facebook/react-native/issues/43307
 - https://github.com/facebook/react-native/issues/43310
 - https://github.com/facebook/react-native/issues/43364

The middleware API works as intended and can run our extended CDP events. Unfortunately, this only applies to an actual `Page` from the device, not for the `React Native Experimental (Improved Chrome Reloads)` synthetic / virtual page.

That's because the middleware instantiation gets aborted when the page can't be found in `this.#pages.get(pageId)`, which always returns `null` for this synthetic page.

## Changelog:

[GENERAL] [FIXED] Create custom message handler for synthetic page

Pull Request resolved: https://github.com/facebook/react-native/pull/43559

Test Plan: See added test case.

Reviewed By: motiz88

Differential Revision: D55129412

Pulled By: huntie

fbshipit-source-id: 9679d8fe68f3cb4104f4a042f93612b995baddc9
2024-03-21 13:28:49 +00:00
Alex Hunt 0a7dbfd1a2 Adjust version parsing in release scripts, fix release dry runs in CI (#43568)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43568

Fixes to restore passing CI checks on main after D55027120.

- Widen validation checks in version utils to accept `0.x.x` (as opposed to `0.[not-'0'].x`).
- Use `tag: test` instead of `tag: latest` for dry run job params.

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D55123739

fbshipit-source-id: 9f76dced4e7aa3ce87d6680cd7687ae443305331
2024-03-20 17:42:06 +00:00
Alex Hunt d66bb7f853 Remove bump-all-updated-packages script (#43534)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43534

This is no longer used after switching to the new release workflow, which uses the newer and less error-prone `set-version` script.

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D55027122

fbshipit-source-id: faa8cfd2af9b54fab611b108df162793c5768695
2024-03-20 14:40:54 +00:00
Alex Hunt 8b5d650e60 Switch to new release workflow as default (#43533)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43533

Switch to the new unified release workflow by default, now that this has been validated on the `0.74-stable` branch.

- Remove `--use-new-workflow` flag and remove legacy logic.
- Remove legacy `prepare_package_for_release` CI job, and use `run_new_release_workflow` -> `run_release_workflow` as new workflow condition match.

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D55027120

fbshipit-source-id: 7c05cdff95ac369ce6cd1201ccfc5718798c4da6

# Conflicts:
#	scripts/releases-ci/prepare-package-for-release.js
2024-03-20 14:40:44 +00:00
Alex Hunt 32deb27219 Update RNTester Podfile.lock 2024-03-18 16:45:51 +00:00
Alex Hunt 24b1da16ea [LOCAL] Fix new release workflow script (4) 2024-03-18 16:02:31 +00:00
Distiller 907bd438ff Release 0.74.0-rc.4
#publish-packages-to-npm&next
2024-03-18 15:20:38 +00:00
Alex Hunt eadf9203bf [LOCAL] Fix new release workflow script (3) 2024-03-18 15:02:09 +00:00
Alex Hunt 8535f496d2 [LOCAL] Fix new release workflow script (2) 2024-03-18 14:31:58 +00:00
Alex Hunt d6ee80959e [LOCAL] Revert Podfile.lock error handling in CI script, remove same step from new workflow
It looks like this always failed (recent example from RC3: https://app.circleci.com/pipelines/github/facebook/react-native/42625/workflows/911813aa-8c1c-4c7f-8382-5d67d3551923/jobs/1396276), but since #43513 this now correctly raises as an error to CircleCI.

To unblock our release:
- Revert.
- Also remove "Updating RNTester Podfile.lock" entirely from `prepare_release_new` job — technically this isn't in the critical path for making a release, but is part of consistent branch state _post release_.

Changelog: [Internal]
2024-03-18 14:21:45 +00:00
Alex Hunt bdb1034e3e [LOCAL] Fix new release workflow script 2024-03-18 13:19:24 +00:00
Kudo Chien daf012a958 Add registerCallableModule types (#43366)
Summary:
`registerCallableModule()` was added from 7f549ec7be but no typescript types there. this pr tries to add the corresponding types.

## Changelog:

[GENERAL] [FIXED] - Add missing `registerCallableModule` TypeScript definitions

Pull Request resolved: https://github.com/facebook/react-native/pull/43366

Test Plan: patch locally and try to `import { registerCallableModule } from 'react-native';` in a 0.74.0-rc.2 project

Reviewed By: fabriziocucci

Differential Revision: D54676151

Pulled By: cortinico

fbshipit-source-id: cd01f2ebe2d2516b458fae5b2e83cba3d3794455
2024-03-18 11:09:04 +00:00
Alex Hunt 40a4df0637 Fix RNTester Podfile.lock update in release workflow (#43513)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43513

The previous `update_podfile_lock.sh` script would fail as executed from the repo root (could not locate RNTester dir). Delete this and replace with direct calls in `prepare-package-for-release.js`, which will fail script on error.

 {F1469216632}

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D54949214

fbshipit-source-id: 4f032069e803e84f835c279d01332d16787dfafc
2024-03-18 11:09:04 +00:00
Alex Hunt ff5d87db3e Fix E2E template install in CI jobs (#43323)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43323

This fixes a seemingly pre-existent misconfiguration within our `test_ios_template` E2E test setup in CircleCI.

**Background**

We call `npx react-native-community/cli init` with the `--skip-install` flag, as part of the bootstrapping logic in `scripts/e2e/init-template-e2e.js`. This is necessary because we later want to explicitly call `npm install` with a custom `--registry` for our locally mirrored packages (via Verdaccio).

For some reason, we were observing unexpected differences when this was run under CircleCI:

1. Runs `yarn init`
2. Runs a `yarn add` (unknown pkg)

 {F1464781818}

https://app.circleci.com/pipelines/github/facebook/react-native/42725/workflows/f648468b-e916-4501-887d-ad293aa6fccf/jobs/1398950

This is causing a Yarn-based install ahead of where we want — ignoring the `--skip-install` flag.

*I'm still unsure on the exact LOC cause in CLI* (but most likely, it's around the Yarn v3 move).

**Impact of this fix**

- The above meant that, when we were bootstrapping `test_ios_template` previously, packages weren't being read from Verdaccio, but **instead from npm** — using the `"0.74.0"` versions from the *previous branch cut* .
- After D54006327, this behaviour became breaking 💀 — since for the 0.74 -> 0.75 cut, we no longer physically published `"0.75.0-main"` (new format) packages to npm.

**This change**

I'm passing `--pm npm` to `npx react-native-community/cli init` to skip around any Yarn behaviour. This appears to have removed the erroneous `yarn` invocations .

Changelog: [Internal]

bypass-github-export-checks

Reviewed By: cortinico, cipolleschi

Differential Revision: D54536848

fbshipit-source-id: 473b11924955f5787c82a6c81d4527d77b810aa5
2024-03-18 11:09:04 +00:00
Alex Hunt 4e677f021a Update set-version script to version private packages and workspace deps
Summary:
Addresses a gap when using the `set-version` script to update all packages on `main` (i.e. post branch cut):
- Package versions were not being set consistently. It is safe to version all workspace packages, including `"private"`.
    - Our publishing workflow is independent from this, and only considers public packages for submission to npm.
- We also need to update the root `package.json`, which includes `devDependencies` referencing workspace dependencies.

Unblocks https://github.com/facebook/react-native/pull/43132.

Changelog: [Internal]

Reviewed By: lunaleaps

Differential Revision: D54419456

fbshipit-source-id: 93eee669c5cf7c2f16b68a2bf41e9a8ace5521bf
2024-03-18 11:09:04 +00:00
Alex Hunt 42e62bf963 Refactor remaining forEachPackage call sites (#43112)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43112

Changelog: [Internal]

Reviewed By: cipolleschi

Differential Revision: D53942028

fbshipit-source-id: 335bff3c3a31026bae7140fac1d1a6aae23a0f1e
2024-03-18 10:58:13 +00:00
Alex Hunt 3b170a0910 Add prepare_release_new workflow, configure via flag (#43518)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43518

This is a minimum approach to achieve a **single-command publish flow** for React Native, unifying the previous `yarn bump-all-updated-packages` and `yarn trigger-react-native-release` workflow entry points.

This diff aims to change as little as possible to achieve the above — introducing a new job that merges operations to create the versioning commit. The triggered publish jobs are unchanged. In future, we may follow this change with further simplifications down the workflow tree.

**Key changes**

- Adds a new CircleCI workflow, `prepare_release_new`, which versions **all packages** and writes a single release commit.
- This replaces `yarn bump-all-updated-packages`, now implemented with the newer `set-version` script.
- Wires this up as an experiment within `trigger-react-native-release.js`, conditionally running the new workflow when `--use-new-workflow` is passed.

**Not changed**

- The single release commit written will continue to trigger both of the existing CI workflows on push (`publish_release` and `publish_bumped_packages`), which are unchanged.
    - The commit summary now includes the `#publish-packages-to-npm` marker, in order to trigger `publish_bumped_packages`.
- Usage: Release Crew members will continue to use the existing local script entry point (as [documented in the releases repo](https://github.com/reactwg/react-native-releases/blob/main/docs/guide-release-process.md#step-7-publish-react-native)), with the opt in flag.
    ```
    yarn trigger-react-native-release --use-new-workflow [...args]
    ```

After we're happy with the E2E behaviour of this workflow in the next 0.74 RC, I will follow up by dropping the `--use-new-workflow` flag and removing the old scripts (T182533699).

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D54956345

fbshipit-source-id: 35fd7af8f3e60a39507b5d978ccd97472bf03ddb
2024-03-18 10:41:28 +00:00
Alex Hunt 680bfafcc2 Remove dangerous "9999" version string default (#43516)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43516

As titled. This seems dangerous — removing with the motivation that we'd prefer this script to fail during execution than to succeed in publishing `9999`.

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D54956661

fbshipit-source-id: 23f8d49abd300385dde74871b6d2492ef63f058e
2024-03-18 10:41:16 +00:00
Phillip Pan ffb93a81b5 support jsCallInvoker in RCTBridgeProxy (#43314)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43314

Changelog: [Internal]

making call invoker a breaking change to runtime executor in 0.74 seems to be causing a lot of discourse. let's simplify things and first add the callinvoker to the backwards compat layer

Reviewed By: cipolleschi

Differential Revision: D54404845

fbshipit-source-id: 983e86829030557033b95625dab9068492739417
2024-03-18 10:39:47 +00:00
Arushi Kesarwani 9048c0e0b3 Fix Bridgeless React Context test in OSS (#43424)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43424

https://github.com/facebook/react-native/pull/43400/ caused a `getCatalystInstanceTest` to fail in OSS due to `bridgelessReactContext` not being a Mock object.

Reviewed By: fkgozali

Differential Revision: D54781539

fbshipit-source-id: 1c784804c31d4b57fe438d49f3ee3eb7034dd7a6
2024-03-18 10:37:44 +00:00
Arushi Kesarwani bccedff09b Implement getJSCallInvokerHolder for BridgelessCatalystInstance (#43400)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43400

Implement `getJSCallInvokerHolder()` for BridgelessCatalystInstance

Changelog:
[Android][Breaking] Implement `getJSCallInvokerHolder()` for Bridgeless Catalyst Instance

Reviewed By: cortinico

Differential Revision: D54650305

fbshipit-source-id: effac3daaad5173c2fd78ab11bbe3f3156a9c07b
2024-03-18 10:37:27 +00:00
Arushi Kesarwani 3e5dd5e2f2 Fix CI by adding explicit visibility modifier to BridgelessCatalystInstance (#43296)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43296

Fix CI by adding explicit visibility modifier to the newly added `BridgelessCatalystInstance` class. In Kotlin, in explicit API mode, which is usually the default mode for Kotlin, we must explicitly specify one of the modifiers for every declaration to make it clear and explicit.

Changelog:
[Internal] internal

Reviewed By: makovkastar

Differential Revision: D54442485

fbshipit-source-id: 4409ff810a09cc4fadcd2ccf21f7fbac3015f413
2024-03-18 10:37:22 +00:00
Arushi Kesarwani 8a04e4418a Add BridgelessCatalystInstance as a placeholder for backwards comptability of legacy APIs of CatalystInstance
Summary:
In order to make the legacy APIs of Catalyst Instance backwards compatible, introducing a regular class that implements CatalystInstance so as to make these APIs available for folks in Bridgeless mode as well.

Changelog:
[Internal] internal

Reviewed By: RSNara

Differential Revision: D54093013

fbshipit-source-id: f494c05e79f570883f9b5374cd177862970304c0
2024-03-18 10:37:00 +00:00
Riccardo Cipolleschi ec48cb6560 Allow the app to control the Activity Indicator in Bridgeless mode (#43195)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43195

Right now, the activity indicator is automatically hidden when the view is ready to be shown in bridgeless mode.
There is no way to prevent that the activity indicator is automatically removed.

In OSS, we have libraries (e.g.: `react-native-bootsplash`) that will allow the app to control when and how dismiss the splashscreen, but due to the current automatic behavior on Bridgeless, they stopped working.

***Note:** In the previous implementation, they were working because instead of using the `loadingView` property, they were adding the splashscreen view on top of the existing one. However, with the lazy behavior of the bridgeless mode, this is not working anymore because the RCTMountingManager [expect not to have any subview](https://www.internalfb.com/code/fbsource/[6962fa457dbc74ab3a760cf6090d9643c6748781]/xplat/js/react-native-github/packages/react-native/React/Fabric/Mounting/RCTMountingManager.mm?lines=176) when the first surface is mounted.*

## Changelog
[iOS][Added] - Allow the activityIndicator to be controlled from JS in bridgeless mode

Reviewed By: philIip

Differential Revision: D54191856

fbshipit-source-id: 14738032f04adf7eaf7d200d889acd752aed0ed3
2024-03-18 10:31:50 +00:00
Cedric van Putten 768cf6e79c feature(dev-middleware): add custom message handlers to extend CDP capabilities (#43291)
Summary:
This is a proposal for the `react-native/dev-middleware` package, to allow implementers to extend the CDP capabilities of the `InspectorProxy`. It's unfortunately needed until we can move to the native Hermes CDP layer.

At Expo, we extend the CDP capabilities of this `InspectorProxy` by injecting functionality on the device level. This proposed API does the same, but without having to overwrite internal functions of both the `InspectorProxy` and `InspectorDevice`.

A good example of this is the network inspector's capabilities. This currently works through the inspection proxy, and roughly like:
- Handle any incoming `Expo(Network.receivedResponseBody)` from the _**device**_, store it, and stop event from propagating
- Handle the incoming `Network.getResponseBody` from the _**debugger**_, return the data, and stop event from propagating.

This API brings back that capability in a more structured way.

## API:

```ts
import { createDevMiddleware } from 'react-native/dev-middleware';

const { middleware, websocketEndpoints } = createDevMiddleware({
  unstable_customInspectorMessageHandler: ({ page, deviceInfo, debuggerInfo }) => {
    // Do not enable handler for page other than "SOMETHING", or for vscode debugging
    // Can also include `page.capabilities` to determine if handler is required
    if (page.title !== 'SOMETHING' || debuggerInfo.userAgent?.includes('vscode')) {
      return null;
    }

    return {
      handleDeviceMessage(message) {
        if (message.type === 'CDP_MESSAGE') {
          // Do something and stop message from propagating with return `true`
          return true;
        }
      },
      handleDebuggerMessage(message) {
        if (message.type === 'CDP_MESSAGE') {
          // Do something and stop message from propagating with return `true`
          return true;
        }
      },
    };
  },
});
```

## Changelog:

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[GENERAL] [ADDED] - Add inspector proxy device message middleware API

Pull Request resolved: https://github.com/facebook/react-native/pull/43291

Test Plan: See added tests and code above

Reviewed By: huntie

Differential Revision: D54804503

Pulled By: motiz88

fbshipit-source-id: ae918dcd5b7e76d3fb31db4c84717567ae60fa96
2024-03-18 10:30:57 +00:00
Cedric van Putten bf7f0d57cc feature(dev-middleware): use userAgent query parameter as fallback when header is unset (#43364)
Summary:
At Expo, we use [Expo Tools](https://github.com/expo/vscode-expo/blob/main/src/expoDebuggers.ts) to connect the [built-in vscode-js-debug](https://github.com/microsoft/vscode-js-debug) to Hermes.

Since there are a few differences in vscode vs chrome devtools, we need to enable a couple of modifications through the [`customMessageHandler` API](https://github.com/facebook/react-native/pull/43291). Unfortunately, vscode itself doesn't set the `user-agent` header when connecting to the inspector proxy. Becuase of that, we'd need a fallback to "manually" mark the debugger as being vscode ([we use this query parameter here](https://github.com/expo/vscode-expo/blob/main/src/expoDebuggers.ts#L208)).

This PR supports setting the `user-agent` through `?userAgent=` when the header is not set.

## Changelog:

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[GENERAL] [ADDED] - Fallback to query parameter based `user-agent` when header is unset

Pull Request resolved: https://github.com/facebook/react-native/pull/43364

Test Plan:
- Install [Expo Tools](https://marketplace.visualstudio.com/items?itemName=expo.vscode-expo-tools)
- Start Metro with this change.
- Connect a device.
- Run the vscode command `"Expo: Debug Expo app ..."`
- Debugger should connect, and have it's user-agent marked as:
    `vscode/1.87.0 vscode-expo-tools/1.3.0`

Reviewed By: huntie

Differential Revision: D54804556

Pulled By: motiz88

fbshipit-source-id: 1ff558ba5350811ad042d08a713438e046759feb
2024-03-18 10:30:42 +00:00
Cedric van Putten 0e0838448a fix(dev-middleware): allow inspector proxy to fetch sourcemaps on lan connections (#43307)
Summary:
The inspector proxy is inlining source maps on `Debugger.scriptParsed` CDP events. The inlining prevents Chrome DevTools from downloading this remotely, as that's not supported in newer versions anymore.

The current implementation locks this inlining mechanism to just `localhost` and/or `127.0.0.1` addresses, making it incompatible with LAN or tunnel device connections.

This PR removes that limitation to allow source map inlining on these LAN and tunnel connections.

## Changelog:

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[GENERAL][FIXED] Allow Inspector proxy to inline source maps on LAN connections

Pull Request resolved: https://github.com/facebook/react-native/pull/43307

Test Plan:
- See added test
- Start Metro and connect a device over LAN, open the chrome devtools

Reviewed By: huntie

Differential Revision: D54485247

Pulled By: robhogan

fbshipit-source-id: 6fcb0c6dd762d2f0a013497ba0a1126095b9130b
2024-03-18 10:30:25 +00:00
Nicola Corti 0f4aedfe82 Properly handle RR and CMD+M in Bridgeless Mode (#43460)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43460

Currently pressing the menu button (or CMD+M) is broken on Bridgeless mode.
Also pressing RR is not reloading the App.
That's because some Bridgeless API haven't been reimplemented correctly on Android. I'm fixing them here.

Fixes #43451

Changelog:
[Android] [Fixed] - Properly handle RR and CMD+M in Bridgeless Mode

Reviewed By: huntie

Differential Revision: D54852959

fbshipit-source-id: 8fbbdab6818da9177e6db40e45d35258c7f5e236
2024-03-18 10:28:40 +00:00
Dmitry Rykun 407be885fa Bring back the UNSET constant to TextAttributeProps (#43491)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43491

This diff brings back the `UNSET` constant to `TextAttributeProps`.
The removal of this constant was an unnecessary breaking change, that has broken several third-party libraries.

Changelog: [Android][Fixed] - Bring back the UNSET constant to TextAttributeProps.

Reviewed By: fabriziocucci

Differential Revision: D54899524

fbshipit-source-id: 368bde77d43f310fd458537d0191d09174fa5167
2024-03-18 10:28:17 +00:00
zhongwuzw aa0670b0ae iOS: Change image source url encode ascii to utf8 (#43502)
Summary:
We should use utf8 to cover more characters.

## Changelog:

[IOS] [FIXED] - [Fabric] iOS: Change image source url encode ascii to utf8

Pull Request resolved: https://github.com/facebook/react-native/pull/43502

Test Plan: Fixes https://github.com/facebook/react-native/issues/43462

Reviewed By: rshest

Differential Revision: D54944653

Pulled By: cortinico

fbshipit-source-id: 0bbd3d46c8e5c04ceffe7e0ebae46dc2ce9507df
2024-03-18 10:27:57 +00:00
Joe Vilches 8830ed6bba Fix bug where absolute nodes were not insetted correctly in certain cases (#43417)
Summary:
X-link: https://github.com/facebook/yoga/pull/1593

Pull Request resolved: https://github.com/facebook/react-native/pull/43417

There was a bug where we did not position absolute nodes correctly if the static node had a different main/cross axis from the containing node. This fixes that. The change is somewhat complicated unfortunately but I tried to add sufficient comments to explain what is happening

Reviewed By: NickGerleman

Differential Revision: D54703955

fbshipit-source-id: 096c643f61d4f9bb3ee6278d675ebd69b57350d7
2024-03-18 10:27:38 +00:00
szymonrybczak bc745cb6ff Update @react-native-community/cli to 13.6.2 2024-03-12 14:45:49 +00:00
Alex Hunt 24d3251d3f Update Podfile.lock 2024-03-12 10:09:39 +00:00
Distiller 57cc8e7f67 [0.74.0-rc.3] Bump version numbers 2024-03-11 14:59:31 +00:00
Alex Hunt 8a7c718ab3 Bump package versions
#publish-packages-to-npm&0.74-stable
2024-03-11 13:53:12 +00:00
Cedric van Putten 4efab59a1e feature(dev-middleware): add inspector proxy nativeNetworkInspection target capabilty flag (#43310)
Summary:
This adds the `nativeNetworkInspection` target capability flag, to enable/disable the proxy-side network inspection handling.

## Changelog:

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[GENERAL][ADDED] Add inspector proxy `nativeNetworkInspection` target capability flag

Pull Request resolved: https://github.com/facebook/react-native/pull/43310

Test Plan:
Once this lands, and is published through `react-native/dev-middleware`, we (Expo) can disable the proxy-side network inspection handling.

See https://github.com/expo/expo/pull/27425/commits/1a1b601a29fbc5766628238db7259121689f6cd6 on PR expo/expo#27425

Reviewed By: christophpurrer, motiz88

Differential Revision: D54486516

Pulled By: huntie

fbshipit-source-id: cc151349c816fb3866d3ec07af1a29a5f4ff9b00
2024-03-11 11:01:17 +00:00
Oskar Kwaśniewski e3da9b8c0a fix: add compiler conditional to hover style (#43331)
Summary:
Commit https://github.com/facebook/react-native/commit/73664f576aaa472d5c8fb2a02e0ddd017bbb2ea4 broke two jobs in CircleCI that we run using Xcode 14.3.1 because the commit introduced some types that are available only to iOS 17.
The code was wrapped around if(available()) statement, but this does not compile out the code. It is a runtime check and the code needs to build anyway.

This takes effect at compile time as well. However, unlike with #available, the method must type check and compile. The code will always be emitted into your binary: however, it will only be used when the binary is executed on platforms that meet the availability requirements.

source: [forums.swift.org/t/if-vs-available-vs-if-available/40266/2](https://forums.swift.org/t/if-vs-available-vs-if-available/40266/2)

This change should fix it, introducing some compile time pragmas that removes the code if we build with older versions of Xcode

## Changelog:

[IOS] [ADDED] - Compiler conditionals for hover style (cursor: pointer)

Pull Request resolved: https://github.com/facebook/react-native/pull/43331

Test Plan: CI Green

Reviewed By: dmytrorykun

Differential Revision: D54540520

Pulled By: cipolleschi

fbshipit-source-id: 943ac479062e11969efa7645ec0ead26c6866374
2024-03-11 10:59:17 +00:00
Saad Najmi 7395765cf8 feat(iOS): Implement cursor style prop (#43078)
Summary:
Implement the cursor style prop for iOS (and consequently, visionOS), as described in this RFC: https://github.com/react-native-community/discussions-and-proposals/pull/750

See related PR in React Native macOS, where we target macOS and visionOS (not running in iPad compatibility mode) with the same change: https://github.com/microsoft/react-native-macos/pull/2080

Docs update: https://github.com/facebook/react-native-website/pull/4033

## Changelog:

[IOS] [ADDED] - Implement cursor style prop

Pull Request resolved: https://github.com/facebook/react-native/pull/43078

Test Plan:
See the added example page, running on iOS with the new architecture enabled. This also runs the same on the old architecture.

https://github.com/facebook/react-native/assets/6722175/2af60a0c-1c1f-45c4-8d66-a20f6d5815df

See the example page running on all three apple platforms. The JS is slightly different because:
1. The "macOS Cursors" example is not part of this PR but the one in React Native macOS.
2. This PR (and exapmple) has went though a bunch of iterations and It got hard taking videos of every change 😅

https://github.com/facebook/react-native/assets/6722175/7775ba7c-8624-4873-a735-7665b94b7233

## Notes

- React Native macOS added the cursor prop to View with https://github.com/microsoft/react-native-macos/pull/760 and Text with https://github.com/microsoft/react-native-macos/pull/1469 . Much of the implementation comes from there.

- Due to an Apple bug, as of iOS 17.4 Beta 4, the shape of the iOS cursor hover effect doesn't render in the correct bounds (but it does on visionOS). I've worked around it with an ifdef. The result is that the hover effect will work on iOS and visionOS, but not iPad apps running in compatibility mode on visionOS.

Reviewed By: NickGerleman

Differential Revision: D54512945

Pulled By: vincentriemer

fbshipit-source-id: 699e3a01a901f55a466a2c1a19f667aede5aab80
2024-03-11 10:58:03 +00:00
Oskar Kwaśniewski 66b1cfee97 feat(RCTAppDelegate): Implement RCTRootViewFactory (#42263)
Summary:
This PR implements `RCTRootViewFactory` a utility class (suggested by cipolleschi) that returns proper RCTRootView based on the current environment state (new arch/old arch/bridgeless). This class aims to preserve background compatibility by implementing a configuration class forwarding necessary class to RCTAppDelegate.

This PR leverages the `RCTRootViewFactory` in `RCTAppDelegate` for the default initialization of React Native (greenfield).

Here is an example of creating a Brownfield integration (without RCTAppDelegate) using this class (can be later added to docs):

1. Store reference to `rootViewFactory` and to `UIWindow`

`AppDelegate.h`:
```objc
interface AppDelegate : UIResponder <UIApplicationDelegate>

property(nonatomic, strong) UIWindow* window;
property(nonatomic, strong) RCTRootViewFactory* rootViewFactory;

end
```

2. Create an initial configuration using `RCTRootViewFactoryConfiguration` and initialize `RCTRootViewFactory` using it. Then you can use the factory to create a new `RCTRootView` without worrying about old arch/new arch/bridgeless.

 `AppDelegate.mm`
```objc
implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary<UIApplicationLaunchOptionsKey,id> *)launchOptions {

  // Create configuration
 RCTRootViewFactoryConfiguration *configuration = [[RCTRootViewFactoryConfiguration alloc] initWithBundleURL:self.bundleURL
                                                                                                 newArchEnabled:self.fabricEnabled
                                                                                             turboModuleEnabled:self.turboModuleEnabled
                                                                                              bridgelessEnabled:self.bridgelessEnabled];

  // Initialize RCTRootViewFactory
  self.rootViewFactory = [[RCTRootViewFactory alloc] initWithConfiguration:configuration];

  // Create main root view
  UIView *rootView = [self.rootViewFactory viewWithModuleName:@"RNTesterApp" initialProperties:@{} launchOptions:launchOptions];

  // Set main window as you prefer for your Brownfield integration.
  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];

  // Later in the codebase you can initialize more rootView's using rootViewFactory.

  return YES;
}
end
```
bypass-github-export-checks

[INTERNAL] [ADDED] - Implement RCTRootViewFactory

Pull Request resolved: https://github.com/facebook/react-native/pull/42263

Test Plan: Check if root view is properly created on app initialization

Reviewed By: dmytrorykun

Differential Revision: D53179625

Pulled By: cipolleschi

fbshipit-source-id: 9bc850965ba30d84ad3e67d91dd888f0547c2136
2024-03-11 10:54:06 +00:00
Tomek Zawadzki 6440e35bc7 Expose react_render_textlayoutmanager via prefab (#43381)
Summary:
The `react_render_textlayoutmanager` was not exposed via prefab. I'm adding it to make possible for react-native-live-markdown to integrate on top of React Native via prefab. Based on https://github.com/facebook/react-native/issues/36166.

## Changelog:

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[ANDROID] [CHANGED] - Expose `react_render_textlayoutmanager` via prefab.

Pull Request resolved: https://github.com/facebook/react-native/pull/43381

Reviewed By: javache

Differential Revision: D54676207

Pulled By: cortinico

fbshipit-source-id: 90e3b90ff842250bf1e3abcc0c54f057b68a82fd
2024-03-11 10:49:09 +00:00
Arushi Kesarwani 10d65924ee Support onActivityResult in Bridgeless (#43351)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43351

Implement `onActivityResult` on Bridgeless

Changelog:
[Internal] internal

Reviewed By: cortinico

Differential Revision: D54574139

fbshipit-source-id: f2369077199186ac6ef0187b5dfe7ed95f3b87fc
2024-03-11 10:43:48 +00:00
Rick Hanlon 31b62ab7f0 Fix component stacks for tsx, ts, and jsx files (#43370)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43370

Component stacks with files ending in .ts, .tsx, or .jsx were skipped in LogBox reporting. This diff fixes the regex.

Changelog:
[General][Fixed] - Support .tsx, .ts, and .jsx in component stacks

Reviewed By: yungsters

Differential Revision: D54638526

fbshipit-source-id: a5271daaa7b687e8e075be3f94ab9b9c03f79b66
2024-03-11 10:41:29 +00:00
Pieter De Baets 1151ea1247 Fix DefaultReactNativeHost assuming lazyViewManagers are always available (#43334)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43334

cortinico flagged that bridge + fabric regressed in 0.74, likely due to D53406841.

Changelog: [Android][Fixed] Fix registration of ViewManagers in new renderer when not using lazyViewManagers.

Reviewed By: fkgozali

Differential Revision: D54551645

fbshipit-source-id: 0783030cd0d2900a3a254ae04c9ea4e51035272a
2024-03-11 10:39:14 +00:00
Oskar Kwaśniewski a9ec4203e1 fix(iOS) [0.74]: RCTRedBox not appearing in Bridgeless when metro is not running (#43147)
Summary:
When testing out `0.74.0-rc0` I found that when the metro is not running we are not displaying RedBox which bumps users to start the packager and reload the app. It also fixes the case where users try to reload by clicking the "Reload" button on RedBox.

## Before

https://github.com/facebook/react-native/assets/52801365/086c557f-ea1f-4a97-b4c7-df8a945cc7a0

## After

https://github.com/facebook/react-native/assets/52801365/9f8421b3-5e83-466f-8cdb-38f97981275d

## Changelog:

[IOS] [FIXED] - RCTRedBox not appearing in Bridgeless when metro is not running

Pull Request resolved: https://github.com/facebook/react-native/pull/43147

Test Plan: Build the app without metro running check if RedBox is shown

Reviewed By: javache

Differential Revision: D54632056

Pulled By: dmytrorykun

fbshipit-source-id: fb6742898d3bd82545bfffd9175208e1a5984cb6
2024-03-11 10:37:10 +00:00
Pieter De Baets bd39897abf Fix NullPointerException thrown on startup (#43293)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43293

Was debugging this, and found that this exception was being thrown due to `DefaultBindingsInstaller`, which was an invalid hybrid object. The ReactInstance initializer fully supports this being null, so let's use that as default.

Changelog: [Android][Fixed] NullPointerException is no longer ignored in MessageQueueThreadHandler

Reviewed By: sammy-SC

Differential Revision: D54434417

fbshipit-source-id: 52417b390061eface0f0578e32796d3a85303e03
2024-03-11 10:34:28 +00:00
Tomek Zawadzki 7c2fb7911a Expose rrc_text via prefab (#43275)
Summary:
The `rrc_text` was not exposed via prefab. I'm adding it to make possible for react-native-live-markdown to integrate on top of React Native via prefab. Based on https://github.com/facebook/react-native/issues/36166.

## Changelog:

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[ANDROID] [CHANGED] - Expose `rrc_text` via prefab.

Pull Request resolved: https://github.com/facebook/react-native/pull/43275

Reviewed By: cipolleschi

Differential Revision: D54536468

Pulled By: cortinico

fbshipit-source-id: 8c4ef983467bfc46930f10bf7bd95761c2d11788
2024-03-11 10:33:39 +00:00
Tomek Zawadzki 4dc9d54447 Expose rrc_textinput via prefab (#43274)
Summary:
The `rrc_textinput` was not exposed via prefab. I'm adding it to make possible for react-native-live-markdown to integrate on top of React Native via prefab. Based on https://github.com/facebook/react-native/issues/36166.

## Changelog:

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[ANDROID] [CHANGED] - Expose `rrc_textinput` via prefab.

Pull Request resolved: https://github.com/facebook/react-native/pull/43274

Reviewed By: cipolleschi

Differential Revision: D54482657

Pulled By: cortinico

fbshipit-source-id: ca7f4127f1808f841d88925238666e837de75bd0
2024-03-11 10:33:21 +00:00
Luna Wei 27b54bdcff local - podfile.lock update for rntester 2024-03-04 14:13:09 -08:00
Distiller c68669079a [0.74.0-rc.2] Bump version numbers 2024-03-04 19:42:11 +00:00
Luna Wei 1c1b03d6e8 bumped packages versions
#publish-packages-to-npm&0.74-stable
2024-03-04 11:29:35 -08:00
Luna Wei c7e704a0ef bumped packages versions
#publish-packages-to-npm&0.74-stable
2024-03-04 11:29:15 -08:00
Luna Wei 02d38e4eb5 bumped packages versions
#publish-packages-to-npm&0.74-stable
2024-03-04 11:28:55 -08:00
Luna Wei e063a1b0fb bumped packages versions
#publish-packages-to-npm&0.74-stable
2024-03-04 11:27:34 -08:00
Alex Hunt c09e4dacff Bump package versions
#publish-packages-to-npm&0.74-stable
2024-03-04 12:14:00 +00:00
Alex Hunt 011cb3a8d7 Update Podfile.lock 2024-03-04 12:11:28 +00:00
Riccardo Cipolleschi a5b5f6be78 Rename PopupMenuAndroidNativeComponent.js to PopupMenuAndroidNativeComponent.android.js to fix CI
Summary:
This change renames `PopupMenuAndroidNativeComponent.js` to `PopupMenuAndroidNativeComponent.android.js`.

The reason is that, without the suffix, Codegen was reading the NativeComponent spec also for iOS, generating some invalid specs and making RNTester fail.

## Changelog:
[Android][Changed] - Rename `PopupMenuAndroidNativeComponent.js` to `PopupMenuAndroidNativeComponent.android.js`

Reviewed By: cortinico, dmytrorykun

Differential Revision: D54199736

fbshipit-source-id: 7fd67c4d38a69fe3a84c800c8ee5dcbd8c4f9a6c
2024-03-04 11:02:58 +00:00
Ramanpreet Nara 29b34e70e3 Pull PopupMenuAndroid out of React Native core
Summary:
**History:** This component was originally introduced into React Native core in D52712758, to replace UIManagerModule.showPopupMenu().

**Problem:** But, React Native core should be lean. Adding this component to React Native bloats the core.

**Changes:** So, this diff pulls PopupMenuAndroid out into its own package in the react-native GitHub repository.

In the future, this will be migrated to a community package!

Changelog: [Android][Removed] Move PopupMenu out of React Native core

Reviewed By: NickGerleman

Differential Revision: D53328110

fbshipit-source-id: 469d8dc3e756c06040c72e08fa004aafa1bd6e18
2024-03-04 11:02:52 +00:00
Nicola Corti 6294453980 Undo moving of TurboModule to internal and expose utility function for TurboModule.class.isAssignableFrom (#43219)
Summary:
After discussing with mdvacca, we prefer to undo the change of `TurboModule` package to `.internal` as this is a quite aggressive breaking change for the ecosystem.

Moreover: users should not invoke `TurboModule.class.isAssignableFrom` because `TurboModule` is `.internal`. Therefore I'm exposing another API to check if a class is a TurboModule as a static field of `ReactModuleInfo`.

## Changelog:

[INTERNAL] - Do not use TurboModule.class.isAssignableFrom

Pull Request resolved: https://github.com/facebook/react-native/pull/43219

Test Plan: Tests are attached

Reviewed By: mdvacca, cipolleschi

Differential Revision: D54280882

Pulled By: cortinico

fbshipit-source-id: 9443c8aa23cf70dd5cfe574fe573d83313134358
2024-03-04 11:02:03 +00:00
Oskar Kwaśniewski 7822a7796f fix(iOS) [0.74]: properly warn about createRootViewWithBridge (#43146)
Summary:
This PR fixes an issue that `_logWarnIfCreateRootViewWithBridgeIsOverridden` was called in wrong place.

Assuming user overrides this method and call to `[super]`:

```objc
- (UIView *)createRootViewWithBridge:(RCTBridge *)bridge moduleName:(NSString *)moduleName initProps:(NSDictionary *)initProps {
  UIView *view = [super createRootViewWithBridge:bridge moduleName:moduleName initProps:initProps];
  view.backgroundColor = [UIColor redColor];
  return view;
}
```

This method still wasn't called in bridgeless (and not showing the error).

Checking if user overrides this method in `appDidFinishWithLaunching` works every time

![simulator_screenshot_0E22557C-CE37-4617-A25A-F39A6ED4D3D0](https://github.com/facebook/react-native/assets/52801365/d7865f37-32f0-40ad-a252-74ab7c5b7757)

## Changelog:

[IOS] [FIXED] - Properly warn about `createRootViewWithBridge` being deprecated

Pull Request resolved: https://github.com/facebook/react-native/pull/43146

Test Plan: Check if warning is shown when message is overridden

Reviewed By: huntie

Differential Revision: D54303506

Pulled By: cipolleschi

fbshipit-source-id: cf30555c791493f28b3015a189cf93b60cace8f8
2024-03-04 11:01:37 +00:00
Riccardo Cipolleschi 1ccc7a3e9e Deprecate getSurfacePresenter and getModuleRegistry in favor of their props
Summary:
This change align the `getSurfacePresenter` and `getModuleRegistry` to the iOS convention for which these should be computed properties with no `get` prefix in their name.

We want to land this change and to pick it in 0.74 so we can remove the `get` versions in 0.75.

## Changelog:
[iOS][Deprecated] - Deprecate `getSurfacePresenter` and `getModuleRegistry` for `surfacePresenter` and moduleRegistry` props.

Reviewed By: javache

Differential Revision: D54253805

fbshipit-source-id: e9ff7db744a73a3bd0f8ae1d87875e54ddd9a1a4
2024-03-04 11:01:15 +00:00
Dmitry Rykun 987c1f2880 Fix findLibrariesFromReactNativeConfig
Summary:
This diff removes extra argument from the `extractLibrariesFromJSON` call inside `findLibrariesFromReactNativeConfig`.
This should fix the iOS failurte discribed in https://github.com/facebook/react-native/issues/43204
Changelog: [iOS][Fixed] - Codegen correctly handles react-native.config.js.

Reviewed By: cipolleschi

Differential Revision: D54248400

fbshipit-source-id: 2ae5d0d29f49725877559a5b0edd7d59f8bdefaa
2024-03-04 10:56:27 +00:00
Moti Zilberman f6f3b5cb98 Restore Content-Length header in inspector-proxy JSON responses
Summary:
Changelog: [General][Fixed] Re-enable listing Hermes debugger targets in chrome://inspect, broken in 0.74 RC

Fixes https://github.com/facebook/react-native/issues/43259.

Reverts D52958725 and fixes the original `Content-Length` Unicode bug using a different approach.

Reviewed By: fabriziocucci

Differential Revision: D54409847

fbshipit-source-id: ed5bb464ab67f37535947646b124814d8bbf797c
2024-03-01 10:45:51 +00:00
Riccardo Cipolleschi f7644be6d4 [RN][iOS]Rename BUILD_FROM_SOURCE to RCT_BUILD_HERMES_FROM_SOURCE 2024-02-29 10:48:01 +00:00
Distiller ad3f6b5274 [0.74.0-rc.1] Bump version numbers 2024-02-27 01:08:06 +00:00
Nicola Corti ba3cf235f5 bumped packages versions
#publish-packages-to-npm&0.74-stable
2024-02-26 16:54:52 -08:00
Cedric van Putten d032e35f86 feat(cli): warn underlying command when using npx react-native init (#43127)
Summary:
This adds a new warning for React Native 0.74, implementing the [RFC 0759](https://github.com/react-native-community/discussions-and-proposals/blob/nc/rnf/proposals/0759-react-native-frameworks.md#the-init-command) init command changes.

- It's added inside `react-native/cli.js` to avoid warning users when actually executing `npx react-native-community/cli` commands.
- The check is fairly simple: `process.argv[2] === 'init'`. The first two args are the Node bin and the actual script bin paths.
- The message is sent over `console.warn` to avoid potentially mixing JSON with non-JSON output.

## Changelog:

[GENERAL] [ADDED] - Warn with future command when using `npx react-native init`

Pull Request resolved: https://github.com/facebook/react-native/pull/43127

Test Plan:
Any command other than `init` must not warn.

- `$ node ./path/to/react-native/cli.js init`
- `$ node ./path/to/react-native/cli.js init --help`
  - Should warn with `Running: npx react-native-community/cli init`
    ![image](https://github.com/facebook/react-native/assets/1203991/a3f5e3d2-7b59-41fe-9a53-bc9ce5a21fd1)
- `$ node ./path/to/react-native/cli.js --help`
  - Must not warn
    ![image](https://github.com/facebook/react-native/assets/1203991/97679429-db35-47f8-bdeb-33187bb167cf)

Reviewed By: cipolleschi

Differential Revision: D54063131

Pulled By: cortinico

fbshipit-source-id: c60b8b6034087b584e98b51f5bedf68a46caf44c
2024-02-26 11:47:20 -08:00
Nicola Corti b33b80f51c Bump CLI to 13.6.1 (#43153)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43153

This contains an hotfix for the CLI needed for 0.74

Changelog:
[Internal] [Changed] - Bump CLI to 13.6.1

Reviewed By: huntie

Differential Revision: D54073715

fbshipit-source-id: a5fdf02f47c5e144efc58e6b7fd355669a21e07b
2024-02-26 11:15:57 -08:00
Nicola Corti b3300d77ea Remove accidental files included inside the template.
Summary:
Those files should not stay in the root `/app` folder but inside the `/app/gradle/wrapper` folder.
I've noticed this in the Upgrade Helper UI hence I'm removing them.

Changelog:
[Internal] [Changed] - Remove accidental files included inside the template

Reviewed By: mdvacca

Differential Revision: D54122995

fbshipit-source-id: 8873a91ffbea20f609c7aabd428a815c77a38db5
2024-02-26 11:10:30 -08:00
Nicola Corti fde94ce307 Do not crash on onJSBundleLoadedFromServer when fast-refreshing on bridgeless mode
Summary:
RN-Tester is currently instacrashing on fast-refresh (pressing r on Metro) as it ends up on `onJSBundleLoadedFromServer`
which throws an exception on Bridgeless mode. I'm fixing it by following the same logic as `onReloadWithJSDebugger`.

Changelog:
[Android] [Fixed] - Do not crash on onJSBundleLoadedFromServer when fast-refreshing on bridgeless mode

Reviewed By: huntie

Differential Revision: D54121838

fbshipit-source-id: 82d98ec0c5b2295f5751525368c956574dd7f3a0
2024-02-26 11:10:23 -08:00
Diego Segura 1f7ed063c9 fix flatlist props being undefined in ios (#43141)
Summary:
When using Flatlist on iOS and Android its failing because props are undefined

The problem is described on https://github.com/facebook/react-native/issues/34783

![Captura de pantalla 2024-02-22 a las 4 13 11](https://github.com/facebook/react-native/assets/1161455/325738d9-2e49-44a0-bb6a-077b2e02e9cd)

![Captura de pantalla 2024-02-22 a las 4 14 58](https://github.com/facebook/react-native/assets/1161455/118f76e1-a818-428e-938e-123b55536b49)

Fixed by setting constructor before any statement and removing unnecessary props declaration at the top of the class.

## Changelog:

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->
[GENERAL] [FIXED] - Fix undefined props crash in FlatList

Pull Request resolved: https://github.com/facebook/react-native/pull/43141

Reviewed By: javache

Differential Revision: D54069559

Pulled By: robhogan

fbshipit-source-id: b39cd9a273eb0279ed353f9efcb66a3c4ccf93b4
2024-02-26 11:09:34 -08:00
Nicola Corti 4def40ee33 Hook the default-app-setup OnLoad.cpp file with the cxxModuleProvider from RNCLI (#43049)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43049

This connects the OnLoad.cpp file used by OSS apps with the `rncli_cxxModuleProvider`.
This method is created by the CLI and takes care of querying all the TM CXX Modules discovered and returning them.

This PR is currently waiting on https://github.com/react-native-community/cli/pull/2296

Changelog:
[Internal] [Changed] - Hook the default-app-setup OnLoad.cpp file with the cxxModuleProvider from RNCLI

Reviewed By: cipolleschi

Differential Revision: D53812109

fbshipit-source-id: 47bc0ea699516993070cfa0127de97853acf8890
2024-02-22 11:01:50 +00:00
Riccardo Cipolleschi 341fbe5486 [RN][Release] Fix release testing script 2024-02-21 17:55:37 +00:00
Distiller 898e207bcf [0.74.0-rc.0] Bump version numbers 2024-02-21 16:33:24 +00:00
Alex Hunt 619b8eb4d0 Bump package versions
#publish-packages-to-npm&0.74-stable
2024-02-21 15:20:42 +00:00
Alex Hunt ebca982365 Update Hermes version 2024-02-20 15:24:28 +00:00
7019 changed files with 299021 additions and 556906 deletions
+172
View File
@@ -0,0 +1,172 @@
# Circle CI
This directory is home to the Circle CI configuration files. Circle is our continuous integration service provider. You can see the overall status of React Native's builds at https://circleci.com/gh/facebook/react-native
You may also see an individual PR's build status by scrolling down to the Checks section in the PR.
## Purposes
We use CircleCI for mainly 3 purposes:
1. Testing changes
2. Release Nightlies
3. Release Stable Versions of React Native
When testing changes, we run all the tests on commits that lands on `main`. For commits in PR, we try to understand which kind of changes the PR is about and we try to selectively run only the relevant tests. so, for example, if a PR only touches iOS files, we are going to run only iOS tests.
A Nighly job runs every day at around 9:00 PM, GMT. They run from `main` and they publish a version of React Native using the current state of the codebase, creating a version number that follows the format: `0.<current-version+1>.0-nightly-<YYYYMMDD>-<short-commit-hash>`.
The nightly job also publish all the monorepo packages, taking care of updating the transitive dependencies of those packages.
Stable versions are released manually by the Release Crew and they run from a stable branch. Stable branches have the shape of `0.<version>-stable`.
## How It Works?
CircleCI execution is now split in two steps:
- Setup
- Testing
The setup step takes care of analyzing the changes in the PR and of deciding which jobs needs to run.
The testing flow is a set of workflows that executes the required tests.
### Setup
The code of the setup workflow lives in the root [`config.yml`](https://github.com/facebook/react-native/blob/main/.circleci/config.yml) file.
It uses the `Continuation orb` from CircleCI to start a CI flow that depends on the changes present in the PR.
If the changes are not coming from a PR (either a simple commit or if the CI is running on main) **we always run all the tests** as a cautionary measure.
The setup job has also to expose all the pipeline parameters that we would need to pass to the actual workflow. Those parameters are **automatically forwarded** to the workflows that are started as a result of the setup.
The setup job uses a JS script to carry on its logic. The [`pipeline_selection.js`](https://github.com/facebook/react-native/blob/main/scripts/circleci/pipeline_selection.js) script can be invoked with two commands:
- `filter-jobs`
- `create-configs`
The **`filter-jobs`** command takes care of creating a JSON representation of the tests we need to run based on the changes in the PR.
The **`create-configs`** command consumes the JSON representation to create a CircleCI configuration that can then executes all the required tests.
#### Creating a Configuration
To create a configuration, the `pipeline-selection` scripts collates together various pieces of `YML` files that lives in the [`Configurations` folder](https://github.com/facebook/react-native/tree/main/.circleci/configurations).
The order in which these files are appended is **important** and it always contains the following.:
1. `top_level.yml`: this file contains some high level directives for CircleCI, like the version, the list of orbs, the cache-keys, and the pipeline parameters that can be used by the workflows.
2. `executors.yml`: this file contains the list of the executors used in our jobs and their configurations.
3. `commands.yml`: this file contains all the commands that can be used by jobs to executes. Commands are reusable functions that are shared by multiple jobs.
4. `jobs.yml`: this file contains the jobs that are used by workflows to carry on some specific tasks. They are composed of sequential commands.
5. `workflows.yml`: this file contains the shared workflows that needs to (or can) be always executed, no matter which kind of changes are pushed to CI. An example of these workflows is `analysis` (which is always executed) or `nightly` (which can be executed if a specific pipeline parameter is passed to the CI).
Then, the `pipeline_selection create-configs` attach some specific test workflows, depending on the changes that are present in the PR. These change-dependent workflows live in the [`test_workflows`](https://github.com/facebook/react-native/tree/main/.circleci/configurations/test_workflows) folder.
These workflows are:
* `testAll.yml` => runs all the possible tests. This workflow is executed on main and on PRs which change set touches both iOS and Android
* `testAndroid.yml` => runs all the build steps and Android tests. This is used on changes that happens on the Android codebase and infra (`ReactAndroid` folder)
* `testIOS.yml` => runs all the build steps and iOS tests. This is used on changes that happens on the iOS codebase and infra (`React` folder)
* `testE2E.yml` => runs the E2E tests. As of today, E2E tests can be triggered if the commit message contains the `#run-e2e-tests` tag.
* `testJS.yml` => For all the changes that do not touch native/platform code, we only run JS tests.
Notice that if there are changes on files that do not represents code (for example `.md` files like this one or the `Changelog`) we don't run any CI.
## Test workflows
The test workflows for native code are composed of 2 parts:
- building React Native
- testing
Building React Native requires us to build several parts of it:
1. We need to build the Hermes JS engine
2. We need to build Android to create prebuilds
3. We need to package everything in an npm package that will mimic a React native release
4. We need to create a local maven repository
### Building Hermes Engine
#### Android
The `build_android` workflows takes care of building the Android version of Hermes and to put it properly in a local maven repository.
See the [Build Android](#build_android) section below.
#### iOS
Hermes is a very complicated item to build for iOS.
It is composed of the Hermes compiler (HermesC) and of the actual engine.
Hermes is shipped as a universal XCFramework. This means that we need to build all the architecture slices and then put them together in the XCFramework archive.
We also need to build 2 configurations: Debug and Release.
In order to be efficient and to save costs, we parallelize the process as much as possible:
1. We prepare the environment for building Hermes.
2. We build HermesC which is required by all the slices.
3. We start 8 jobs to build all the required slices in parallel:
1. `iphone` slice, Debug mode
1. `iphonesimulator` slice, Debug mode
1. `macos` slice, Debug mode
1. `catalyst` slice, Debug mode
1. `iphone` slice, Release mode
1. `iphonesimulator` slice, Release mode
1. `macos` slice, Release mode
1. `catalyst` slice, Release mode
4. We then have 2 jobs to create the Debug and Release tarballs in parallel.
1. The Debug job receives the 4 Debug slices
1. The Release job receives the 4 Release slices
The `Debug` and `Release` tarball are then uploaded as artifacts. Notice that these we use these artifacts to **test the release** of React Native.
While building Hermes, we take also care of building the dSYMs. A dSYM (Debug Symbols) is an archive that contains the Debug Symbols that users can load to de-symbolicate the Hermes Stack traces. These symbols are published when we create a React Native release.
A lot of these build steps are automated by some shell scripts that lives in the [`react-native/packages/react-native/sdks/hermes-engine/utils` folder](https://github.com/facebook/react-native/tree/main/packages/react-native/sdks/hermes-engine/utils).
### Build Android
The android build is all managed by Gradle, so building android should be as easy as calling a [`gradle` command](https://github.com/facebook/react-native/blob/main/.circleci/configurations/jobs.yml#L268-L274).
The relevant part here is that the build android generates a `maven-local` repository that is passed to the [`build_npm_package`](https://github.com/facebook/react-native/blob/main/.circleci/configurations/jobs.yml#L1182) and that we use to test the releases.
### Build NPM package
This job is the responsible to create an NPM package that is suitable to be released or tested in CI.
If we are in a release flow (for example the Nightly workflow), it also proceed with the publication.
The job can be invoked with different parameters:
- `dry-run` => it does not publish anything, but prepare the artifacts to be used for testing
- `nightly` => it creates the artifacts and publish a nightly version of React Native.
- `release` => it creates the artifacts and publish a stable version of React Native.
The build NPM package takes all the artifacts produced in the previous steps (iOS' Hermes, iOS' Hermes dSYMs, Android's `maven-local`) and creates an npm package packing all the code.
If in a release mode, it also proceed publishing the NPM package to NPM, and the artifacts to Maven central, which we use to distribute all the artifacts.
This job also uploads the `maven-local` repository and a zipped version of the npm package to CircleCI's artifacts. We use these artifacts to **test the release** of React Native.
## Testing React Native
React Native tests runs in two different scenarios:
- RNTester
- A New App
### RNTester
RNTester is our internal testing app. It is a fully working React Native app that lives in the [`react-native/packages/rn-tester` folder](https://github.com/facebook/react-native/tree/main/packages/rn-tester) of the repository.
RNTester is an app which contains code that exercise most part of the React Native frameworks.
It also has the feature of building React Native **from source**. For that reason, it does not have to wait for the NPM package to be ready, but RNTester's tests can start as soon as the `build_android` step and the step that builds Hermes for iOS are done.
Notice the Tests on RNTester for iOS consumes the Hermes engine that is built in the previous steps.
For Android, these tests creates an APK that is uploaded as an artifact in CircleCI. We use these artifacts to **test the releases** of React Native..
### A New App
The React Native repo contains a template app in the [`react-native/packages/react-native/template` folder]() that is used to spin up a new application that is preconfigured with React Native.
We have several tests that we run starting from the template, testing various configurations:
- Debug/Release
- JSC/Hermes (two different JS engine we support)
- New/Old Architecture (two different Architectures for React Native)
We want to test all the React Native changes against the template, but we can't publish a React native version on each change that is merged. Therefore, to run tests on the template we use a NPM registry proxy called [Verdaccio](https://verdaccio.org/).
When running a Template test our CI follows roughly these steps:
1. Prepare the executor
2. Start a Verdaccio server
3. Publish on Verdaccio all the monorepo [packages](https://github.com/facebook/react-native/tree/main/packages) on which React Native depends on.
4. Publish on Verdaccio the react-native NPM package that has been created in the NPM step
5. Spin up a new React native apps from the template, downloading react-native from Verdaccio.
In this way, we are sure that we can test all the changes that happen in React Native on a new React Native app.
+114
View File
@@ -0,0 +1,114 @@
version: 2.1
# this allows you to use CircleCI's dynamic configuration feature
setup: true
orbs:
continuation: circleci/continuation@1.0.0
parameters:
# Real pipelines parameters
run_release_workflow:
default: false
type: boolean
run_nightly_workflow:
default: false
type: boolean
release_version:
default: ""
type: string
release_monorepo_packages_version:
default: ""
type: string
release_tag:
default: ""
type: string
release_dry_run:
default: false
type: boolean
jobs:
choose_ci_jobs:
docker:
- image: debian:bullseye
resource_class: small
steps:
- run:
name: Install Yarn
command: |
apt update
apt install -y wget git curl jq
apt-get update
apt-get install -y ca-certificates curl gnupg
mkdir -p /etc/apt/keyrings
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
NODE_MAJOR=18
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list
apt-get update
apt install -y nodejs
npm install --global yarn
- checkout
- run:
name: Yarn Install
command: yarn install
- when:
condition:
or:
- equal: [ main, << pipeline.git.branch >> ]
- matches:
pattern: /0\.[0-9]+[\.[0-9]+]?-stable/
value: << pipeline.git.branch >>
steps:
- run:
name: "[Main or Stable] Create input for config to test everything"
command: |
mkdir -p /tmp/circleci/
echo '{ "run_all": true }' > /tmp/circleci/pipeline_config.json
- when:
condition:
not:
or:
- equal: [ main, << pipeline.git.branch >> ]
- matches:
pattern: /0\.[0-9]+[\.[0-9]+]?-stable/
value: << pipeline.git.branch >>
steps:
- run:
name: "[PR Branch] Filter jobs"
command: |
if [[ -z "$CIRCLE_PULL_REQUEST" ]]; then
echo "Not in a PR. Can't filter properly outside a PR. Please open a PR so that we can run the proper CI tests."
echo "For safety, we run all the tests!"
mkdir -p /tmp/circleci/
echo '{ "run_all": true }' > /tmp/circleci/pipeline_config.json
else
PR_NUMBER="${CIRCLE_PULL_REQUEST##*/}"
node ./scripts/circleci/pipeline_selection.js filter-jobs
fi
- run:
name: Create config
description: Generates a configuration on the fly, depending on the files that have been modified
command: |
node ./scripts/circleci/pipeline_selection.js create-configs
- store_artifacts:
path: .circleci/generated_config.yml
destination: generated_config.yml
- continuation/continue:
configuration_path: .circleci/generated_config.yml
# our single workflow, that triggers the setup job defined above
workflows:
always-run:
jobs:
- choose_ci_jobs:
filters:
tags:
only: /.*/
+578
View File
@@ -0,0 +1,578 @@
# -------------------------
# COMMANDS
# -------------------------
commands:
# Checkout with cache, on machines that are using Docker the cache is ignored
checkout_code_with_cache:
parameters:
checkout_base_cache_key:
default: *checkout_cache_key
type: string
steps:
- restore_cache:
key: << parameters.checkout_base_cache_key >>-{{ arch }}-{{ .Branch }}-{{ .Revision }}
- checkout
- save_cache:
key: << parameters.checkout_base_cache_key >>-{{ arch }}-{{ .Branch }}-{{ .Revision }}
paths:
- ".git"
setup_ruby:
parameters:
ruby_version:
default: "2.6.10"
type: string
steps:
- restore_cache:
key: *gems_cache_key
- run:
name: Set Required Ruby
command: echo << parameters.ruby_version >> > /tmp/required_ruby
- restore_cache:
key: *rbenv_cache_key
- run:
name: Install the proper Ruby and run Bundle install
command: |
# Check if rbenv is installed. CircleCI is migrating to rbenv so we may not need to always install it.
if [[ -z "$(command -v rbenv)" ]]; then
brew install rbenv ruby-build
# Load and init rbenv
(rbenv init 2> /dev/null) || true
echo '' >> ~/.bash_profile
echo 'eval "$(rbenv init - bash)"' >> ~/.bash_profile
source ~/.bash_profile
else
echo "rbenv found; Skipping installation"
fi
# Install the right version of ruby
if [[ -z "$(rbenv versions | grep << parameters.ruby_version >>)" ]]; then
# ensure that `ruby-build` can see all the available versions of Ruby
# some PRs received machines in a weird state, this should make the pipelines
# more robust.
brew update && brew upgrade ruby-build
rbenv install << parameters.ruby_version >>
fi
# Set ruby dependencies
rbenv global << parameters.ruby_version >>
if [[ << parameters.ruby_version >> == "2.6.10" ]]; then
rbenv rehash
gem install bundler -v 2.4.22
else
rbenv rehash
gem install bundler
fi
bundle check || bundle install --path vendor/bundle --clean
- save_cache:
key: *rbenv_cache_key
paths:
- ~/.rbenv
- save_cache:
key: *gems_cache_key
paths:
- vendor/bundle
run_yarn:
parameters:
yarn_base_cache_key:
default: *yarn_cache_key
type: string
steps:
- restore_cache:
keys:
- << parameters.yarn_base_cache_key >>-{{ arch }}-{{ checksum "yarn.lock" }}
- << parameters.yarn_base_cache_key >>-{{ arch }}
- << parameters.yarn_base_cache_key >>
- run:
name: "Yarn: Install Dependencies"
command: |
# Skip yarn install on metro bump commits as the package is not yet
# available on npm
if [[ $(echo "$GIT_COMMIT_DESC" | grep -c "Bump metro@") -eq 0 ]]; then
yarn install --non-interactive --cache-folder ~/.cache/yarn
fi
- save_cache:
paths:
- ~/.cache/yarn
key: << parameters.yarn_base_cache_key >>-{{ arch }}-{{ checksum "yarn.lock" }}
build_packages:
steps:
- run:
name: Build packages
command: yarn build
brew_install:
parameters:
package:
description: Homebrew package to install
type: string
steps:
- run:
name: "Brew: Install << parameters.package >>"
command: brew install << parameters.package >>
with_rntester_pods_cache_span:
parameters:
steps:
type: steps
steps:
- run:
name: Setup CocoaPods cache
# Copy packages/rn-tester/Podfile.lock since it can be changed by pod install
command: cp packages/rn-tester/Podfile.lock packages/rn-tester/Podfile.lock.bak
- restore_cache:
keys:
# The committed lockfile is generated using static libraries and USE_HERMES=1 so it could load an outdated cache if a change
# only affects the frameworks or hermes config. To help prevent this also cache based on the content of Podfile.
- *pods_cache_key
- steps: << parameters.steps >>
- save_cache:
paths:
- packages/rn-tester/Pods
key: *pods_cache_key
with_gradle_cache:
parameters:
steps:
type: steps
steps:
- restore_cache:
keys:
- *gradle_cache_key
- v3-gradle-{{ .Environment.CIRCLE_JOB }}-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}-
- v3-gradle-{{ .Environment.CIRCLE_JOB }}-
- v3-gradle-
- steps: << parameters.steps >>
- save_cache:
paths:
- ~/.gradle/caches
- ~/.gradle/wrapper
- packages/react-native/ReactAndroid/build/downloads
- packages/react-native/ReactAndroid/build/third-party-ndk
key: *gradle_cache_key
run_e2e:
parameters:
platform:
description: Target platform
type: enum
enum: ["android", "ios", "js"]
default: "js"
retries:
description: How many times the job should try to run these tests
type: integer
default: 3
steps:
- run:
name: "Run Tests: << parameters.platform >> End-to-End Tests"
command: node ./scripts/e2e/run-ci-e2e-tests.js --<< parameters.platform >> --retries << parameters.retries >>
report_bundle_size:
parameters:
platform:
description: Target platform
type: enum
enum: ["android", "ios"]
steps:
- run:
name: Report size of RNTester.app (analysis-bot)
command: GITHUB_TOKEN="$PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A""$PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B" scripts/circleci/report-bundle-size.sh << parameters.platform >> || true
setup_hermes_version:
steps:
- run:
name: Set up Hermes workspace and caching
command: |
mkdir -p "/tmp/hermes" "/tmp/hermes/download" "/tmp/hermes/hermes"
if [ -f "$HERMES_VERSION_FILE" ]; then
echo "Hermes Version file found! Using this version for the build:"
cat $HERMES_VERSION_FILE > /tmp/hermes/hermesversion
else
echo "Hermes Version file not found!!!"
echo "Using the last commit from main for the build:"
HERMES_TAG_SHA=$(git ls-remote https://github.com/facebook/hermes main | cut -f 1 | tr -d '[:space:]')
echo $HERMES_TAG_SHA > /tmp/hermes/hermesversion
fi
cat /tmp/hermes/hermesversion
get_react_native_version:
steps:
- run:
name: Get React Native version
command: |
VERSION=$(cat packages/react-native/package.json | jq -r '.version')
# Save the react native version we are building in a file so we can use that file as part of the cache key.
echo "$VERSION" > /tmp/react-native-version
echo "React Native Version is $(cat /tmp/react-native-version)"
HERMES_VERSION="$(cat /tmp/hermes/hermesversion)"
echo "Hermes commit is $HERMES_VERSION"
get_react_native_version_windows:
steps:
- run:
name: Get React Native version on Windows
command: |
$VERSION=cat packages/react-native/package.json | jq -r '.version'
# Save the react native version we are building in a file so we can use that file as part of the cache key.
echo "$VERSION" > /tmp/react-native-version
echo "React Native Version is $(cat /tmp/react-native-version)"
$HERMES_VERSION=cat C:\Users\circleci\project\tmp\hermes\hermesversion
echo "Hermes commit is $HERMES_VERSION"
with_hermes_tarball_cache_span:
parameters:
steps:
type: steps
set_tarball_path:
type: boolean
default: False
flavor:
default: "Debug"
description: The Hermes build type. Must be one of "Debug", "Release".
type: enum
enum: ["Debug", "Release"]
hermes_tarball_artifacts_dir:
type: string
default: *hermes_tarball_artifacts_dir
steps:
- get_react_native_version
- when:
condition:
equal: [ << parameters.flavor >>, "Debug"]
steps:
- restore_cache:
keys:
- *hermes_tarball_debug_cache_key
- when:
condition:
equal: [ << parameters.flavor >>, "Release"]
steps:
- restore_cache:
keys:
- *hermes_tarball_release_cache_key
- when:
condition: << parameters.set_tarball_path >>
steps:
- run:
name: Set HERMES_ENGINE_TARBALL_PATH envvar if Hermes tarball is present
command: |
HERMES_TARBALL_ARTIFACTS_DIR=<< parameters.hermes_tarball_artifacts_dir >>
if [ ! -d $HERMES_TARBALL_ARTIFACTS_DIR ]; then
echo "Hermes tarball artifacts dir not present ($HERMES_TARBALL_ARTIFACTS_DIR). Build Hermes from source."
exit 0
fi
if [ ! -d ~/react-native ]; then
echo "No React Native checkout found. Run `checkout` first."
exit 0
fi
TARBALL_FILENAME=$(node ~/react-native/packages/react-native/scripts/hermes/get-tarball-name.js --buildType "<< parameters.flavor >>")
TARBALL_PATH=$HERMES_TARBALL_ARTIFACTS_DIR/$TARBALL_FILENAME
echo "Looking for $TARBALL_FILENAME in $HERMES_TARBALL_ARTIFACTS_DIR"
echo "$TARBALL_PATH"
if [ ! -f $TARBALL_PATH ]; then
echo "Hermes tarball not present ($TARBALL_PATH). Build Hermes from source."
exit 0
fi
echo "Found Hermes tarball at $TARBALL_PATH"
echo "export HERMES_ENGINE_TARBALL_PATH=$TARBALL_PATH" >> $BASH_ENV
- run:
name: Print Hermes version
command: |
HERMES_TARBALL_ARTIFACTS_DIR=<< parameters.hermes_tarball_artifacts_dir >>
TARBALL_FILENAME=$(node ~/react-native/packages/react-native/scripts/hermes/get-tarball-name.js --buildType "<< parameters.flavor >>")
TARBALL_PATH=$HERMES_TARBALL_ARTIFACTS_DIR/$TARBALL_FILENAME
if [[ -e $TARBALL_PATH ]]; then
tar -xf $TARBALL_PATH
echo 'print(HermesInternal?.getRuntimeProperties?.()["OSS Release Version"])' > test.js
./destroot/bin/hermes test.js
rm test.js
rm -rf destroot
else
echo 'No Hermes tarball found.'
fi
- steps: << parameters.steps >>
- when:
condition:
equal: [ << parameters.flavor >>, "Debug"]
steps:
- save_cache:
key: *hermes_tarball_debug_cache_key
paths: *hermes_tarball_cache_paths
- when:
condition:
equal: [ << parameters.flavor >>, "Release"]
steps:
- save_cache:
key: *hermes_tarball_release_cache_key
paths: *hermes_tarball_cache_paths
store_hermes_apple_artifacts:
description: Stores the tarball and the osx binaries
parameters:
flavor:
default: "Debug"
description: The Hermes build type. Must be one of "Debug", "Release".
type: enum
enum: ["Debug", "Release"]
steps:
- when:
condition:
equal: [ << parameters.flavor >>, "Debug"]
steps:
- store_artifacts:
path: /tmp/hermes/hermes-runtime-darwin/hermes-ios-debug.tar.gz
- when:
condition:
equal: [ << parameters.flavor >>, "Release"]
steps:
- store_artifacts:
path: /tmp/hermes/hermes-runtime-darwin/hermes-ios-release.tar.gz
- store_artifacts:
path: /tmp/hermes/osx-bin/<< parameters.flavor >>/hermesc
- store_artifacts:
path: /tmp/hermes/dSYM/<< parameters.flavor >>/hermes.framework.dSYM
stop_job_if_apple_artifacts_are_there:
description: Stops the current job if there are already the required artifacts
parameters:
flavor:
default: "All"
description: The flavor of artifacts to check. Must be one of "Debug", "Release" or "All"
type: enum
enum: ["Debug", "Release", "All"]
steps:
- when:
condition:
equal: [ << parameters.flavor >>, "All"]
steps:
- run:
name: "Export files to be checked"
command: |
echo "/tmp/hermes/Release_tarball_present" > /tmp/hermes_files
echo "/tmp/hermes/Debug_tarball_present" >> /tmp/hermes_files
echo "/tmp/hermes/Release_osx_bin" >> /tmp/hermes_files
echo "/tmp/hermes/Debug_osx_bin" >> /tmp/hermes_files
echo "/tmp/hermes/Release_dSYM" >> /tmp/hermes_files
echo "/tmp/hermes/Debug_dSYM" >> /tmp/hermes_files
- when:
condition:
not:
equal: [ << parameters.flavor >>, "All"]
steps:
- run:
name: "Export files to be checked"
command: |
echo "/tmp/hermes/<< parameters.flavor >>_tarball_present" > /tmp/hermes_files
echo "/tmp/hermes/<< parameters.flavor >>_osx_bin" >> /tmp/hermes_files
echo "/tmp/hermes/<< parameters.flavor >>_dSYM" >> /tmp/hermes_files
- run:
name: Stop if files are present
command: |
files=($(cat /tmp/hermes_files))
# Initialize a flag indicating all files exist
all_files_exist=true
for file in "${files[@]}"; do
if [[ ! -f "$file" ]]; then
all_files_exist=false
echo "$file does not exist."
else
echo "$file exist."
fi
done
if [[ "$all_files_exist" == true ]]; then
echo "Tarball, osx-bin and dSYM are present. Halting this job"
circleci-agent step halt
fi
check_if_tarball_is_present:
description: "Checks if the tarball of a specific Flavor is present and adds a marker file"
parameters:
flavor:
default: "Debug"
description: The flavor of artifacts to check. Must be one of "Debug" or "Release"
type: enum
enum: ["Debug", "Release"]
steps:
- run:
name: Check if << parameters.flavor >> tarball is there
command: |
FLAVOR=debug
if [[ << parameters.flavor >> == "Release" ]]; then
FLAVOR=release
fi
if [[ -f "/tmp/hermes/hermes-runtime-darwin/hermes-ios-$FLAVOR.tar.gz" ]]; then
echo "[HERMES TARBALL] Found the << parameters.flavor >> tarball"
touch /tmp/hermes/<< parameters.flavor >>_tarball_present
fi
check_if_osx_bin_is_present:
description: "Checks if the osx bin of a specific Flavor is present and adds a marker file"
parameters:
flavor:
default: "Debug"
description: The flavor of artifacts to check. Must be one of "Debug" or "Release"
type: enum
enum: ["Debug", "Release"]
steps:
- run:
name: Check if macosx binary is there
command: |
if [[ -d /tmp/hermes/osx-bin/<< parameters.flavor >> ]]; then
echo "[HERMES MACOSX BIN] Found the osx bin << parameters.flavor >>"
touch /tmp/hermes/<< parameters.flavor >>_osx_bin
fi
check_if_dsym_are_present:
description: "Checks if the dSYM a specific Flavor are present and adds a marker file"
parameters:
flavor:
default: "Debug"
description: The flavor of artifacts to check. Must be one of "Debug" or "Release"
type: enum
enum: ["Debug", "Release"]
steps:
- run:
name: Check if dSYM are there
command: |
if [[ -d /tmp/hermes/dSYM/<< parameters.flavor >> ]]; then
echo "[HERMES dSYM] Found the dSYM << parameters.flavor >>"
touch /tmp/hermes/<< parameters.flavor >>_dSYM
fi
setup_hermes_workspace:
description: "Setup Hermes Workspace"
steps:
- run:
name: Set up workspace
command: |
mkdir -p $HERMES_OSXBIN_ARTIFACTS_DIR ./packages/react-native/sdks/hermes
cp -r $HERMES_WS_DIR/hermes/* ./packages/react-native/sdks/hermes/.
cp -r ./packages/react-native/sdks/hermes-engine/utils ./packages/react-native/sdks/hermes/.
with_xcodebuild_cache:
description: "Add caching to iOS jobs to speed up builds"
parameters:
steps:
type: steps
podfile_lock_path:
type: string
default: packages/rn-tester/Podfile.lock
pods_build_folder:
type: string
default: packages/rn-tester/Pods
podfile_lock_cache_key:
type: string
default: *rntester_podfile_lock_cache_key
cocoapods_cache_key:
type: string
default: *cocoapods_cache_key
steps:
- run:
name: Prepare Xcodebuild cache
command: |
WEEK=$(date +"%U")
YEAR=$(date +"%Y")
echo "$WEEK-$YEAR" > /tmp/week_year
- restore_cache:
key: << parameters.podfile_lock_cache_key >>
- restore_cache:
key: << parameters.cocoapods_cache_key >>
- steps: << parameters.steps >>
- save_cache:
key: << parameters.podfile_lock_cache_key >>
paths:
- << parameters.podfile_lock_path >>
- save_cache:
key: << parameters.cocoapods_cache_key >>
paths:
- << parameters.pods_build_folder >>
store_artifacts_if_needed:
description: "This step stores the artifacts only if we are on main or on a stable branch"
parameters:
path:
type: string
destination:
type: string
default: << parameters.path >>
when:
type: enum
enum: ['always', 'on_fail', 'on_success']
default: 'always'
steps:
- when:
condition:
or:
- equal: [ main, << pipeline.git.branch >> ]
- matches:
pattern: /0\.[0-9]+[\.[0-9]+]?-stable/
value: << pipeline.git.branch >>
steps:
- store_artifacts:
when: << parameters.when >>
path: << parameters.path >>
destination: << parameters.destination >>
prepare_ios_tests:
description: This command runs a set of commands to prepare iOS for running unit tests
steps:
- brew_install:
package: xcbeautify
- run:
name: Run Ruby Tests
command: |
cd packages/react-native/scripts
sh run_ruby_tests.sh
- run:
name: Boot iPhone Simulator
command: source scripts/.tests.env && xcrun simctl boot "$IOS_DEVICE" || true
- run:
name: Configure Environment Variables
command: |
echo 'export PATH=/usr/local/opt/node@18/bin:$PATH' >> $BASH_ENV
source $BASH_ENV
- run:
name: "Brew: Tap wix/brew"
command: brew tap wix/brew
- brew_install:
package: applesimutils watchman
- run:
name: Configure Watchman
command: echo "{}" > .watchmanconfig
run_ios_tests:
description: This command run iOS tests and collects results
steps:
- run:
name: "Run Tests: iOS Unit and Integration Tests"
command: node ./scripts/circleci/run_with_retry.js 3 yarn test-ios
- run:
name: Zip Derived data folder
when: always
command: |
echo "zipping tests results"
cd /Users/distiller/Library/Developer/Xcode
XCRESULT_PATH=$(find . -name '*.xcresult')
tar -zcvf xcresults.tar.gz $XCRESULT_PATH
- store_artifacts_if_needed:
path: /Users/distiller/Library/Developer/Xcode/xcresults.tar.gz
- report_bundle_size:
platform: ios
- store_test_results:
path: ./reports/junit
+45
View File
@@ -0,0 +1,45 @@
# -------------------------
# EXECUTORS
# -------------------------
executors:
nodelts:
<<: *defaults
docker:
- image: *nodelts_image
resource_class: "large"
nodeprevlts:
<<: *defaults
docker:
- image: *nodeprevlts_image
resource_class: "large"
# Executor with Node & Java used to inspect and lint
node-browsers-small:
<<: *defaults
docker:
- image: *nodelts_browser_image
resource_class: "small"
node-browsers-medium:
<<: *defaults
docker:
- image: *nodelts_browser_image
resource_class: "medium"
reactnativeandroid-xlarge:
<<: *android-defaults
resource_class: "xlarge"
reactnativeandroid-large:
<<: *android-defaults
resource_class: "large"
reactnativeios:
<<: *defaults
macos:
xcode: *xcode_version
resource_class: macos.m1.medium.gen1
environment:
- RCT_BUILD_HERMES_FROM_SOURCE: true
reactnativeios-lts:
<<: *defaults
macos:
xcode: '15.1'
resource_class: macos.m1.medium.gen1
environment:
- RCT_BUILD_HERMES_FROM_SOURCE: true
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,111 @@
tests:
when:
and:
- equal: [ false, << pipeline.parameters.run_release_workflow >> ]
- equal: [ false, << pipeline.parameters.run_nightly_workflow >> ]
jobs:
- prepare_release:
name: "prepare_release (dry run test)"
version: "0.0.0"
monorepo_packages_version: "0.0.0"
tag: test
dry_run: true
- prepare_hermes_workspace
- build_android:
release_type: "dry-run"
- build_hermesc_linux:
requires:
- prepare_hermes_workspace
- build_hermesc_apple:
requires:
- prepare_hermes_workspace
- build_apple_slices_hermes:
requires:
- build_hermesc_apple
matrix:
parameters:
flavor: ["Debug", "Release"]
slice: ["macosx", "iphoneos", "iphonesimulator", "catalyst", "xros", "xrsimulator"]
- build_hermes_macos:
requires:
- build_apple_slices_hermes
matrix:
parameters:
flavor: ["Debug", "Release"]
- build_hermesc_windows:
requires:
- prepare_hermes_workspace
- build_npm_package:
# Build a release package on every untagged commit, but do not publish to npm.
release_type: "dry-run"
requires:
- build_android
- build_hermesc_linux
- build_hermes_macos
- build_hermesc_windows
- test_android:
requires:
- build_android
- test_android_template:
requires:
- build_npm_package
matrix:
parameters:
architecture: ["NewArch", "OldArch"]
jsengine: ["Hermes", "JSC"]
flavor: ["Debug", "Release"]
- test_ios_template:
requires:
- build_npm_package
name: "Test Template with Ruby 3.2.2"
ruby_version: "3.2.2"
architecture: "NewArch"
flavor: "Debug"
executor: reactnativeios-lts
- test_ios_template:
architecture: "OldArch"
requires:
- build_npm_package
matrix:
parameters:
flavor: ["Debug", "Release"]
jsengine: ["Hermes", "JSC"]
use_frameworks: ["StaticLibraries", "DynamicFrameworks"]
exclude:
# This config is tested with Ruby 3.2.2. Let's not double test it.
- flavor: "Debug"
jsengine: "Hermes"
use_frameworks: "StaticLibraries"
- test_ios_rntester:
requires:
- build_hermes_macos
name: "Test RNTester with Ruby 3.2.2"
ruby_version: "3.2.2"
executor: reactnativeios-lts
- test_ios_rntester:
requires:
- build_hermes_macos
matrix:
parameters:
jsengine: ["Hermes", "JSC"]
use_frameworks: ["StaticLibraries", "DynamicFrameworks"]
exclude:
# Tested by test_ios-Hermes
- jsengine: "Hermes"
use_frameworks: "StaticLibraries"
# Tested by test_ios-JSC
- jsengine: "JSC"
use_frameworks: "StaticLibraries"
# Tested with Ruby 3.2.2, do not test this twice.
- jsengine: "Hermes"
use_frameworks: "StaticLibraries"
- test_ios_rntester:
run_unit_tests: false
use_frameworks: "StaticLibraries"
ruby_version: "2.6.10"
requires:
- build_hermes_macos
matrix:
parameters:
jsengine: ["Hermes", "JSC"]
architecture: ["NewArch", "OldArch"]
@@ -0,0 +1,57 @@
tests_android:
when:
and:
- equal: [ false, << pipeline.parameters.run_release_workflow >> ]
- equal: [ false, << pipeline.parameters.run_nightly_workflow >> ]
jobs:
- prepare_release:
name: "prepare_release (dry run test)"
version: "0.0.0"
monorepo_packages_version: "0.0.0"
tag: test
dry_run: true
- prepare_hermes_workspace
- build_android:
release_type: "dry-run"
- build_hermesc_linux:
requires:
- prepare_hermes_workspace
- build_hermesc_apple:
requires:
- prepare_hermes_workspace
- build_apple_slices_hermes:
requires:
- build_hermesc_apple
matrix:
parameters:
flavor: ["Debug", "Release"]
slice: ["macosx", "iphoneos", "iphonesimulator", "catalyst", "xros", "xrsimulator"]
- build_hermes_macos:
requires:
- build_apple_slices_hermes
matrix:
parameters:
flavor: ["Debug", "Release"]
- build_hermesc_windows:
requires:
- prepare_hermes_workspace
- build_npm_package:
# Build a release package on every untagged commit, but do not publish to npm.
release_type: "dry-run"
requires:
- build_android
- build_hermesc_linux
- build_hermes_macos
- build_hermesc_windows
- test_android:
requires:
- build_android
# - test_e2e_android
- test_android_template:
requires:
- build_npm_package
matrix:
parameters:
architecture: ["NewArch", "OldArch"]
jsengine: ["Hermes", "JSC"]
flavor: ["Debug", "Release"]
@@ -0,0 +1,9 @@
tests_e2e:
when:
and:
- equal: [ false, << pipeline.parameters.run_release_workflow >> ]
- equal: [ false, << pipeline.parameters.run_nightly_workflow >> ]
jobs:
- test_e2e_ios:
ruby_version: "2.7.8"
- test_e2e_android
@@ -0,0 +1,94 @@
test_ios:
when:
and:
- equal: [ false, << pipeline.parameters.run_release_workflow >> ]
- equal: [ false, << pipeline.parameters.run_nightly_workflow >> ]
jobs:
- prepare_release:
name: "prepare_release (dry run test)"
version: "0.0.0"
monorepo_packages_version: "0.0.0"
tag: test
dry_run: true
- prepare_hermes_workspace
- build_android:
release_type: "dry-run"
- build_hermesc_linux:
requires:
- prepare_hermes_workspace
- build_hermesc_apple:
requires:
- prepare_hermes_workspace
- build_apple_slices_hermes:
requires:
- build_hermesc_apple
matrix:
parameters:
flavor: ["Debug", "Release"]
slice: ["macosx", "iphoneos", "iphonesimulator", "catalyst", "xros", "xrsimulator"]
- build_hermes_macos:
requires:
- build_apple_slices_hermes
matrix:
parameters:
flavor: ["Debug", "Release"]
- build_hermesc_windows:
requires:
- prepare_hermes_workspace
- build_npm_package:
# Build a release package on every untagged commit, but do not publish to npm.
release_type: "dry-run"
requires:
- build_android
- build_hermesc_linux
- build_hermes_macos
- build_hermesc_windows
# - test_e2e_ios:
# ruby_version: "2.7.7"
- test_ios_template:
requires:
- build_npm_package
name: "Test Template with Ruby 3.2.2"
ruby_version: "3.2.2"
architecture: "NewArch"
flavor: "Debug"
executor: reactnativeios-lts
- test_ios_template:
architecture: "OldArch"
requires:
- build_npm_package
matrix:
parameters:
flavor: ["Debug", "Release"]
jsengine: ["Hermes", "JSC"]
use_frameworks: ["StaticLibraries", "DynamicFrameworks"]
exclude:
# Tested with Ruby 3.2.2, let's not double test this
- flavor: "Debug"
jsengine: "Hermes"
use_frameworks: "StaticLibraries"
- test_ios_rntester:
requires:
- build_hermes_macos
name: "RNTester on Ruby 3.2.2"
ruby_version: "3.2.2"
executor: reactnativeios-lts
- test_ios_rntester:
name: "RNTester with Dynamic Frameworks"
use_frameworks: "DynamicFrameworks"
requires:
- build_hermes_macos
matrix:
parameters:
jsengine: ["Hermes", "JSC"]
- test_ios_rntester:
name: "RNTester Integration Tests"
run_unit_tests: false
use_frameworks: "StaticLibraries"
ruby_version: "2.6.10"
requires:
- build_hermes_macos
matrix:
parameters:
jsengine: ["Hermes", "JSC"]
architecture: ["NewArch", "OldArch"]
@@ -0,0 +1,11 @@
tests_js:
when:
and:
- equal: [ false, << pipeline.parameters.run_release_workflow >> ]
- equal: [ false, << pipeline.parameters.run_nightly_workflow >> ]
jobs:
- test_js:
run_disabled_tests: false
- test_js:
name: test_js_prev_lts
executor: nodeprevlts
+150
View File
@@ -0,0 +1,150 @@
version: 2.1
# -------------------------
# ORBS
# -------------------------
orbs:
win: circleci/windows@2.4.0
android: circleci/android@2.3.0
# -------------------------
# REFERENCES
# -------------------------
references:
defaults: &defaults
working_directory: ~/react-native
environment:
- GIT_COMMIT_DESC: git log --format=oneline -n 1 $CIRCLE_SHA1
# The public github tokens are publicly visible by design
- PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A: &github_analysisbot_token_a "312d354b5c36f082cfe9"
- PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B: &github_analysisbot_token_b "07973d757026bdd9f196"
# Homebrew currently breaks while updating:
# https://discuss.circleci.com/t/brew-install-fails-while-updating/32992
- HOMEBREW_NO_AUTO_UPDATE: 1
android-defaults: &android-defaults
working_directory: ~/react-native
docker:
- image: reactnativecommunity/react-native-android:v13.0
environment:
- TERM: "dumb"
- GRADLE_OPTS: '-Dorg.gradle.daemon=false'
# By default we only build ARM64 to save time/resources. For release/nightlies/prealpha, we override this value to build all archs.
- ORG_GRADLE_PROJECT_reactNativeArchitectures: "arm64-v8a"
# Repeated here, as the environment key in this executor will overwrite the one in defaults
- PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A: *github_analysisbot_token_a
- PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B: *github_analysisbot_token_b
hermes_workspace_root: &hermes_workspace_root
/tmp/hermes
hermes_tarball_artifacts_dir: &hermes_tarball_artifacts_dir
/tmp/hermes/hermes-runtime-darwin
hermes_osxbin_artifacts_dir: &hermes_osxbin_artifacts_dir
/tmp/hermes/osx-bin
attach_hermes_workspace: &attach_hermes_workspace
attach_workspace:
at: *hermes_workspace_root
xcodebuild_derived_data_path: &xcodebuild_derived_data_path
~/Library/Developer/Xcode/DerivedData/
main_or_stable_only: &main_or_stable_only
filters:
branches:
only:
- main
- /0\.[0-9]+[\.[0-9]+]?-stable/
# -------------------------
# Dependency Anchors
# -------------------------
dependency_versions:
xcode_version: &xcode_version "15.2"
nodelts_image: &nodelts_image "cimg/node:20.2.0"
nodeprevlts_image: &nodeprevlts_image "cimg/node:18.12.1"
nodelts_browser_image: &nodelts_browser_image "cimg/node:20.2.0-browsers"
# -------------------------
# Cache Key Anchors
# -------------------------
# Anchors for the cache keys
cache_keys:
checkout_cache_key: &checkout_cache_key v1-checkout
gems_cache_key: &gems_cache_key v1-gems-{{ arch }}-{{ checksum "Gemfile.lock" }}
gradle_cache_key: &gradle_cache_key v3-gradle-{{ .Environment.CIRCLE_JOB }}-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}-{{ checksum "packages/react-native/ReactAndroid/gradle.properties" }}
yarn_cache_key: &yarn_cache_key v6-yarn-cache-{{ .Environment.CIRCLE_JOB }}
rbenv_cache_key: &rbenv_cache_key v1-rbenv-{{ arch }}-{{ checksum "/tmp/required_ruby" }}
hermes_workspace_cache_key: &hermes_workspace_cache_key v5-hermes-{{ .Environment.CIRCLE_JOB }}-{{ checksum "/tmp/hermes/hermesversion" }}
hermes_workspace_debug_cache_key: &hermes_workspace_debug_cache_key v2-hermes-{{ .Environment.CIRCLE_JOB }}-debug-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}-{{ checksum "packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh" }}
hermes_workspace_release_cache_key: &hermes_workspace_release_cache_key v2-hermes-{{ .Environment.CIRCLE_JOB }}-release-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}-{{ checksum "packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh" }}
hermes_linux_cache_key: &hermes_linux_cache_key v1-hermes-{{ .Environment.CIRCLE_JOB }}-linux-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
hermes_windows_cache_key: &hermes_windows_cache_key v2-hermes-{{ .Environment.CIRCLE_JOB }}-windows-{{ checksum "/Users/circleci/project/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
# Hermes iOS
hermesc_apple_cache_key: &hermesc_apple_cache_key v4-hermesc-apple-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
hermes_apple_slices_cache_key: &hermes_apple_slices_cache_key v8-hermes-apple-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}-{{ checksum "packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh" }}
hermes_tarball_debug_cache_key: &hermes_tarball_debug_cache_key v6-hermes-tarball-debug-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}-{{ checksum "packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh" }}
hermes_tarball_release_cache_key: &hermes_tarball_release_cache_key v5-hermes-tarball-release-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}-{{ checksum "packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh" }}
hermes_macosx_bin_release_cache_key: &hermes_macosx_bin_release_cache_key v5-hermes-release-macosx-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
hermes_macosx_bin_debug_cache_key: &hermes_macosx_bin_debug_cache_key v3-hermes-debug-macosx-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
hermes_dsym_debug_cache_key: &hermes_dsym_debug_cache_key v3-hermes-debug-dsym-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
hermes_dsym_release_cache_key: &hermes_dsym_release_cache_key v3-hermes-release-dsym-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
# Cocoapods - RNTester
pods_cache_key: &pods_cache_key v12-pods-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile.lock.bak" }}-{{ checksum "packages/rn-tester/Podfile" }}
cocoapods_cache_key: &cocoapods_cache_key v12-cocoapods-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile.lock" }}-{{ checksum "packages/rn-tester/Podfile" }}-{{ checksum "/tmp/hermes/hermesversion" }}
rntester_podfile_lock_cache_key: &rntester_podfile_lock_cache_key v10-podfilelock-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile" }}-{{ checksum "/tmp/week_year" }}-{{ checksum "/tmp/hermes/hermesversion" }}
# Cocoapods - Template
template_cocoapods_cache_key: &template_cocoapods_cache_key v6-cocoapods-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ checksum "/tmp/iOSTemplateProject/ios/Podfile.lock" }}-{{ checksum "/tmp/iOSTemplateProject/ios/Podfile" }}-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "packages/rn-tester/Podfile.lock" }}
template_podfile_lock_cache_key: &template_podfile_lock_cache_key v6-podfilelock-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ checksum "/tmp/iOSTemplateProject/ios/Podfile" }}-{{ checksum "/tmp/week_year" }}-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "packages/rn-tester/Podfile.lock" }}
cache_paths:
hermes_workspace_macos_cache_paths: &hermes_workspace_macos_cache_paths
- ~/react-native/packages/react-native/sdks/hermes/build_macosx
- ~/react-native/packages/react-native/sdks/hermes/destroot
hermes_tarball_cache_paths: &hermes_tarball_cache_paths
- *hermes_tarball_artifacts_dir
# -------------------------
# Filters
# -------------------------
# CircleCI filters are OR-ed, with all branches triggering by default and tags excluded by default
# CircleCI env-vars are only set with the branch OR tag that triggered the job, not both.
# In this case, CIRCLE_BRANCH is unset, but CIRCLE_TAG is set.
only_release_tags: &only_release_tags
# Both of the following conditions must be included!
# Ignore any commit on any branch by default.
branches:
ignore: /.*/
# Only act on version tags.
tags:
only: /v[0-9]+(\.[0-9]+)*(\-rc(\.[0-9]+)?)?/
# -------------------------
# PIPELINE PARAMETERS
# -------------------------
parameters:
run_release_workflow:
default: false
type: boolean
run_nightly_workflow:
default: false
type: boolean
release_version:
default: ""
type: string
release_monorepo_packages_version:
default: ""
type: string
release_tag:
default: ""
type: string
release_dry_run:
default: false
type: boolean
+134
View File
@@ -0,0 +1,134 @@
# -------------------------
# WORKFLOWS
#
# When creating a new workflow, make sure to include condition:
#
# when:
# and:
# - equal: [ false, << pipeline.parameters.run_release_workflow >> ]
# - equal: [ false, << pipeline.parameters.run_nightly_workflow >> ]
#
# It's setup this way so we can trigger a release via a POST
# See limitations: https://support.circleci.com/hc/en-us/articles/360050351292-How-to-trigger-a-workflow-via-CircleCI-API-v2
# -------------------------
workflows:
version: 2
# Release workflow, triggered by `yarn trigger-react-native-release`
create_release:
when: << pipeline.parameters.run_release_workflow >>
jobs:
- prepare_release:
name: prepare_release
version: << pipeline.parameters.release_version >>
monorepo_packages_version: << pipeline.parameters.release_monorepo_packages_version >>
tag: << pipeline.parameters.release_tag >>
dry_run: << pipeline.parameters.release_dry_run >>
# This job will run only when a tag is published due to all the jobs being filtered.
publish_release:
jobs:
- prepare_hermes_workspace:
filters: *only_release_tags
- build_android:
filters: *only_release_tags
name: build_android_for_release
release_type: "release"
- build_hermesc_linux:
filters: *only_release_tags
requires:
- prepare_hermes_workspace
- build_hermesc_apple:
filters: *only_release_tags
requires:
- prepare_hermes_workspace
- build_apple_slices_hermes:
filters: *only_release_tags
requires:
- build_hermesc_apple
matrix:
parameters:
flavor: ["Debug", "Release"]
slice: ["macosx", "iphoneos", "iphonesimulator", "catalyst"]
- build_hermesc_windows:
filters: *only_release_tags
requires:
- prepare_hermes_workspace
- build_hermes_macos:
filters: *only_release_tags
requires:
- build_apple_slices_hermes
matrix:
parameters:
flavor: ["Debug", "Release"]
# This job will trigger when a version tag is pushed (by package_release)
- build_npm_package:
name: build_and_publish_npm_package
release_type: "release"
filters: *only_release_tags
requires:
- build_android_for_release
- build_hermesc_linux
- build_hermes_macos
- build_hermesc_windows
- poll_maven:
requires:
- build_and_publish_npm_package
analysis:
when:
and:
- equal: [ false, << pipeline.parameters.run_release_workflow >> ]
- equal: [ false, << pipeline.parameters.run_nightly_workflow >> ]
jobs:
# Run lints on every commit
- analyze_code
# Run code checks on PRs
- analyze_pr
nightly:
when: << pipeline.parameters.run_nightly_workflow >>
jobs:
- prepare_hermes_workspace
- build_android:
release_type: "nightly"
- build_hermesc_linux:
requires:
- prepare_hermes_workspace
- build_hermesc_apple:
requires:
- prepare_hermes_workspace
- build_apple_slices_hermes:
requires:
- build_hermesc_apple
matrix:
parameters:
flavor: ["Debug", "Release"]
slice: ["macosx", "iphoneos", "iphonesimulator", "catalyst"]
- build_hermesc_windows:
requires:
- prepare_hermes_workspace
- build_hermes_macos:
requires:
- build_apple_slices_hermes
matrix:
parameters:
flavor: ["Debug", "Release"]
- build_npm_package:
release_type: "nightly"
requires:
- build_android
- build_hermesc_linux
- build_hermes_macos
- build_hermesc_windows
publish_bumped_packages:
when:
and:
- equal: [ false, << pipeline.parameters.run_release_workflow >> ]
- equal: [ false, << pipeline.parameters.run_nightly_workflow >> ]
jobs:
- find_and_publish_bumped_packages:
<<: *main_or_stable_only
-1
View File
@@ -84,7 +84,6 @@ SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 8
UseTab: Never
QualifierAlignment: Left
---
Language: ObjC
ColumnLimit: 120
+9
View File
@@ -9,3 +9,12 @@ end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 2
[*.gradle]
indent_size = 4
[*.kts]
indent_size = 4
[BUCK]
indent_size = 4
+1 -4
View File
@@ -2,17 +2,14 @@
**/staticBundle.js
docs/generatedComponentApiDocs.js
packages/react-native/flow/
packages/react-native/sdks/
packages/react-native/ReactAndroid/build
packages/react-native/ReactAndroid/hermes-engine/build/
packages/react-native/Libraries/Renderer/*
packages/react-native/Libraries/vendor/**/*
node_modules/
packages/*/node_modules
packages/*/dist
packages/*/types_generated
packages/debugger-frontend/dist/**/*
packages/react-native-codegen/lib
tools/eslint/rules/sort-imports.js
**/Pods/*
**/*.macos.js
**/*.windows.js
+23 -48
View File
@@ -4,54 +4,41 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @noflow
* @format
*/
'use strict';
const path = require('node:path');
require('eslint-plugin-lint').load(path.join(__dirname, 'tools/eslint/rules'));
module.exports = {
root: true,
extends: ['@react-native'],
plugins: ['@react-native/monorepo', '@react-native/specs'],
plugins: ['@react-native/eslint-plugin-specs', 'lint'],
overrides: [
// overriding the JS config from @react-native/eslint-config to ensure
// that we use hermes-eslint for all js files
{
files: ['*.js', '*.js.flow', '*.jsx'],
files: ['*.js', '*.js.flow'],
parser: 'hermes-eslint',
rules: {
'@react-native/monorepo/sort-imports': 'warn',
'eslint-comments/no-unlimited-disable': 'off',
'ft-flow/require-valid-file-annotation': ['error', 'always'],
'no-extra-boolean-cast': 'off',
'no-void': 'off',
// These rules are not required with hermes-eslint
'ft-flow/define-flow-type': 'off',
'ft-flow/use-flow-type': 'off',
// Flow handles these checks for us, so they aren't required
'no-undef': 'off',
'no-unreachable': 'off',
'ft-flow/define-flow-type': 0,
'ft-flow/use-flow-type': 0,
// flow handles this check for us, so it's not required
'no-undef': 0,
},
},
{
files: ['*.js', '*.jsx', '*.ts', '*.tsx'],
files: ['*.js', '*.js.flow'],
excludedFiles: ['packages/react-native/template/**/*'],
rules: {
'@react-native/no-deep-imports': 'off',
},
},
{
files: [
'./packages/react-native/Libraries/**/*.{js,flow}',
'./packages/react-native/src/**/*.{js,flow}',
'./packages/assets/registry.js',
],
parser: 'hermes-eslint',
rules: {
'@react-native/monorepo/no-commonjs-exports': 'warn',
'lint/sort-imports': 1,
},
},
{
@@ -61,17 +48,15 @@ module.exports = {
{
files: ['package.json'],
rules: {
'@react-native/monorepo/react-native-manifest': 'error',
'lint/react-native-manifest': 2,
},
},
{
files: ['flow-typed/**/*.js', 'packages/react-native/flow/**/*'],
files: ['flow-typed/**/*.js'],
rules: {
'@react-native/monorepo/valid-flow-typed-signature': 'error',
'ft-flow/require-valid-file-annotation': 'off',
'no-shadow': 'off',
'no-unused-vars': 'off',
quotes: 'off',
'lint/valid-flow-typed-signature': 2,
'no-unused-vars': 0,
quotes: 0,
},
},
{
@@ -80,14 +65,11 @@ module.exports = {
'packages/react-native/src/**/*.js',
],
rules: {
'@react-native/monorepo/no-haste-imports': 'error',
'@react-native/monorepo/no-react-default-imports': 'error',
'@react-native/monorepo/no-react-named-type-imports': 'error',
'@react-native/monorepo/no-react-native-imports': 'error',
'@react-native/monorepo/no-react-node-imports': 'error',
'@react-native/monorepo/require-extends-error': 'error',
'@react-native/platform-colors': 'error',
'@react-native/specs/react-native-modules': 'error',
'@react-native/platform-colors': 2,
'@react-native/specs/react-native-modules': 2,
'lint/no-haste-imports': 2,
'lint/no-react-native-imports': 2,
'lint/require-extends-error': 2,
},
},
{
@@ -131,18 +113,11 @@ module.exports = {
files: ['**/*.d.ts'],
plugins: ['redundant-undefined'],
rules: {
'no-dupe-class-members': 'off',
'redundant-undefined/redundant-undefined': [
'error',
{followExactOptionalPropertyTypes: true},
],
},
},
{
files: ['**/__tests__/**'],
rules: {
'@react-native/monorepo/no-react-native-imports': 'off',
},
},
],
};
+6 -25
View File
@@ -1,15 +1,9 @@
[ignore]
; Ignore build cache folder
<PROJECT_ROOT>/packages/react-native/sdks/.*
; Ignore fb_internal modules
<PROJECT_ROOT>/packages/react-native/src/fb_internal/.*
; Ignore the codegen e2e tests
<PROJECT_ROOT>/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeEnumTurboModule.js
; Ignore templates for 'react-native init'
<PROJECT_ROOT>/packages/react-native/template/.*
; Ignore the Dangerfile
<PROJECT_ROOT>/private/react-native-bots/dangerfile.js
<PROJECT_ROOT>/packages/react-native-bots/dangerfile.js
; Ignore "BUCK" generated dirs
<PROJECT_ROOT>/\.buckd/
@@ -26,12 +20,6 @@
; Generated build output
<PROJECT_ROOT>/packages/.*/dist
; helloworld
<PROJECT_ROOT>/private/helloworld/ios/Pods/
; Ignore rn-tester Pods
<PROJECT_ROOT>/packages/rn-tester/Pods/
[untyped]
.*/node_modules/@react-native-community/cli/.*/.*
@@ -46,10 +34,9 @@ packages/react-native/interface.js
packages/react-native/flow/
[options]
experimental.global_find_ref=true
enums=true
experimental.pattern_matching=true
casting_syntax=both
component_syntax=true
emoji=true
@@ -69,11 +56,7 @@ munge_underscores=true
module.name_mapper='^react-native$' -> '<PROJECT_ROOT>/packages/react-native/index.js'
module.name_mapper='^react-native/\(.*\)$' -> '<PROJECT_ROOT>/packages/react-native/\1'
module.name_mapper='^@react-native/dev-middleware$' -> '<PROJECT_ROOT>/packages/dev-middleware'
module.name_mapper='^@?[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\|xml\)$' -> '<PROJECT_ROOT>/packages/react-native/Libraries/Image/RelativeImageStub'
module.system.haste.module_ref_prefix=m#
react.runtime=automatic
module.name_mapper='^@?[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '<PROJECT_ROOT>/packages/react-native/Libraries/Image/RelativeImageStub'
suppress_type=$FlowIssue
suppress_type=$FlowFixMe
@@ -81,8 +64,6 @@ suppress_type=$FlowFixMeProps
suppress_type=$FlowFixMeState
suppress_type=$FlowFixMeEmpty
ban_spread_key_props=true
[lints]
sketchy-null-number=warn
sketchy-null-mixed=warn
@@ -104,4 +85,4 @@ untyped-import
untyped-type-import
[version]
^0.275.0
^0.228.0
-1
View File
@@ -1 +0,0 @@
*.js.flow linguist-language=JavaScript
+9 -9
View File
@@ -1,4 +1,4 @@
name: 🐛 React Native - Bug Report
name: 🐛 Bug Report
description: Report a reproducible bug or regression in React Native.
labels: ["Needs: Triage :mag:"]
body:
@@ -19,10 +19,10 @@ body:
* Please [search for similar issues](https://github.com/facebook/react-native/issues) in our issue tracker.
Make sure that your issue:
* Have a **valid reproducer** (See [How to report a bug](https://reactnative.dev/contributing/how-to-report-a-bug)).
* Have a **valid reproducer** (either a [Expo Snack](https://snack.expo.dev/) or a [empty project from template](https://github.com/react-native-community/reproducer-react-native).
* Is tested against the [**latest stable**](https://github.com/facebook/react-native/releases/) of React Native.
🚨 IMPORTANT: Due to the extreme number of bugs we receive, issues **without a reproducer** or for an [**unsupported versions**](https://github.com/reactwg/react-native-releases#which-versions-are-currently-supported) of React Native **will be closed**.
Due to the extreme number of bugs we receive, we will be looking **ONLY** into issues with a reproducer, and on [supported versions](https://github.com/reactwg/react-native-releases#which-versions-are-currently-supported) of React Native.
- type: textarea
id: description
attributes:
@@ -69,10 +69,10 @@ body:
- type: textarea
id: react-native-info
attributes:
label: Output of `npx @react-native-community/cli info`
description: Run `npx @react-native-community/cli info` in your terminal, copy and paste the results here.
label: Output of `npx react-native info`
description: Run `npx react-native info` in your terminal, copy and paste the results here.
placeholder: |
Paste the output of `npx @react-native-community/cli info` here. The output looks like:
Paste the output of `npx react-native info` here. The output looks like:
...
System:
OS: macOS 14.1.1
@@ -83,7 +83,7 @@ body:
path: /bin/zsh
Binaries:
Node: ...
version: 22.14.0
version: 18.14.0
...
render: text
validations:
@@ -109,8 +109,8 @@ body:
- type: input
id: reproducer
attributes:
label: MANDATORY Reproducer
description: A link to either a failing RNTesterPlayground.js file, an Expo Snack or a public repository from [this template](https://github.com/react-native-community/reproducer-react-native) that reproduces this bug. Reproducers are **mandatory**, issues without a reproducer will be closed.
label: Reproducer
description: A link to a Expo Snack or a public repository that reproduces this bug, using [this template](https://github.com/react-native-community/reproducer-react-native). Reproducers are **mandatory**.
placeholder: "https://github.com/<myuser>/<myreproducer>"
validations:
required: true
-4
View File
@@ -1,9 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: ⬆️ Upgrade - Build Regression
url: https://github.com/reactwg/react-native-releases/issues/new/choose
about: |
If you are upgrading to a new React Native version (stable or pre-release) and encounter a build regression.
- name: 🚀 Expo Issue
url: https://github.com/expo/expo/issues/new
about: |
@@ -1,76 +0,0 @@
name: 🔍 Debugger - Bug Report
description: Report a bug with React Native DevTools and the New Debugger
labels: ["Needs: Triage :mag:", "Debugger"]
body:
- type: markdown
attributes:
value: "## Reporting a bug for React Native DevTools"
- type: markdown
attributes:
value: |
Thank you for taking the time to report an issue for React Native DevTools, our new Debugger for React Native.
Before you continue:
* If you're using **Expo** and you're noticing a bug, [report it here](https://github.com/expo/expo/issues).
* If you've found a problem with our **documentation**, [report it here](https://github.com/facebook/react-native-website/issues/).
* If you're having an issue with **Metro** (the bundler), [report it here](https://github.com/facebook/metro/issues/).
* If you're using an external library, report the issue to the **library first**.
* Please [search for similar issues](https://github.com/facebook/react-native/issues) in our issue tracker.
Make sure that your issue is tested against the [**latest stable**](https://github.com/facebook/react-native/releases/) of React Native.
- type: textarea
id: description
attributes:
label: Description
description: A clear and concise description of what the bug is.
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: Steps to reproduce
description: The list of steps that reproduces the issue.
placeholder: |
1. Install the application with `yarn android`
2. Press `j` to open the debugger
3. Do something...
validations:
required: true
- type: input
id: version
attributes:
label: React Native Version
description: The version of react-native that this issue reproduces on. Bear in mind that only issues on [supported versions](https://github.com/reactwg/react-native-releases#which-versions-are-currently-supported) will be looked into.
placeholder: "0.76.0"
validations:
required: true
- type: textarea
id: react-native-info
attributes:
label: Output of `npx @react-native-community/cli info`
description: Run `npx @react-native-community/cli info` in your terminal, copy and paste the results here.
placeholder: |
Paste the output of `npx @react-native-community/cli info` here. The output looks like:
...
System:
OS: macOS 14.1.1
CPU: (10) arm64 Apple M1 Max
Memory: 417.81 MB / 64.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node: ...
version: 22.14.0
...
render: text
validations:
required: true
- type: textarea
id: extra
attributes:
label: Screenshots and Videos
description: |
Please provide screenshot or a video of your bug if relevant.
Issues with videos and screenshots are more likely to **get prioritized**.
@@ -16,10 +16,10 @@ body:
Do not attempt to open a bug in this category if you're not using the New Architecture as your bug will be closed.
Make sure that your issue:
* Have a **valid reproducer** (See [How to report a bug](https://reactnative.dev/contributing/how-to-report-a-bug)).
* Have a **valid reproducer** (either a [Expo Snack](https://snack.expo.dev/) or a [empty project from template](https://github.com/react-native-community/reproducer-react-native).
* Is tested against the [**latest stable**](https://github.com/facebook/react-native/releases/) of React Native.
🚨 IMPORTANT: Due to the extreme number of bugs we receive, issues **without a reproducer** or for an [**unsupported versions**](https://github.com/reactwg/react-native-releases#which-versions-are-currently-supported) of React Native **will be closed**.
Due to the extreme number of bugs we receive, we will be looking **ONLY** into issues with a reproducer, and on [supported versions](https://github.com/reactwg/react-native-releases#which-versions-are-currently-supported) of React Native.
- type: textarea
id: description
attributes:
@@ -81,10 +81,10 @@ body:
- type: textarea
id: react-native-info
attributes:
label: Output of `npx @react-native-community/cli info`
description: Run `npx @react-native-community/cli info` in your terminal, copy and paste the results here.
label: Output of `npx react-native info`
description: Run `npx react-native info` in your terminal, copy and paste the results here.
placeholder: |
Paste the output of `npx @react-native-community/cli info` here. The output looks like:
Paste the output of `npx react-native info` here. The output looks like:
...
System:
OS: macOS 14.1.1
@@ -95,7 +95,7 @@ body:
path: /bin/zsh
Binaries:
Node: ...
version: 22.14.0
version: 18.14.0
...
render: text
validations:
@@ -121,8 +121,8 @@ body:
- type: input
id: reproducer
attributes:
label: MANDATORY Reproducer
description: A link to either a failing RNTesterPlayground.js file, an Expo Snack or a public repository from [this template](https://github.com/react-native-community/reproducer-react-native) that reproduces this bug. Reproducers are **mandatory**, issues without a reproducer will be closed.
label: Reproducer
description: A link to a Expo Snack or a public repository that reproduces this bug, using [this template](https://github.com/react-native-community/reproducer-react-native). Reproducers are **mandatory**.
placeholder: "https://github.com/<myuser>/<myreproducer>"
validations:
required: true
@@ -0,0 +1,133 @@
name: ⬆️ Upgrade - Build Regression
description: If you are upgrading to a new React Native version (stable or pre-release) and encounter a build regression.
labels: ["Needs: Triage :mag:", "Type: Upgrade Issue"]
body:
- type: markdown
attributes:
value: "## Upgrade Issues"
- type: markdown
attributes:
value: |
Please use this form to file an issue if you have upgraded or are upgrading to [latest stable release](https://github.com/facebook/react-native/releases/latest) and have experienced a regression (something that used to work in previous version).
If you're **NOT** upgrading the React Native version, please use this [other bug type](https://github.com/facebook/react-native/issues/new?template=bug_report.yml).
Before you continue:
* If you're using **Expo** and having problems updating it, [report it here](https://github.com/expo/expo/issues).
* If you're found a problem with our **documentation**, [report it here](https://github.com/facebook/react-native-website/issues/).
* If you're having an issue with **Metro** (the bundler), [report it here](https://github.com/facebook/metro/issues/).
* If you're using an external library, report the issue to the **library first**.
* Please [search for similar issues](https://github.com/facebook/react-native/issues) in our issue tracker.
Make sure that your issue:
* Have a **valid reproducer** with an [empty project from template](https://github.com/react-native-community/reproducer-react-native).
* Is upgrading to the [**latest stable**](https://github.com/facebook/react-native/releases/) of React Native.
Due to the extreme number of bugs we receive, we will be looking **ONLY** into issues with a reproducer, and on [supported versions](https://github.com/reactwg/react-native-releases#which-versions-are-currently-supported) of React Native.
- type: input
id: old-version
attributes:
label: Old Version
description: The version of react-native that you're upgrading from.
placeholder: "0.72.0"
validations:
required: true
- type: input
id: new-version
attributes:
label: New Version
description: The version of react-native that you're upgrading to. Bear in mind that only issues that are upgrading to the [latest stable](https://github.com/facebook/react-native/releases/) will be looked into.
placeholder: "0.73.0"
validations:
required: true
- type: textarea
id: description
attributes:
label: Description
description: A clear and concise description of what the bug is.
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: Steps to reproduce
description: The list of steps and commands to reproduce the issue.
placeholder: |
1. Install the application with `yarn android`
2. Click on the button on the Home
3. Notice the crash
validations:
required: true
- type: dropdown
id: platforms
attributes:
label: Affected Platforms
description: Please select which platform you're developing to, and which OS you're using for building.
multiple: true
options:
- Runtime - Android
- Runtime - iOS
- Runtime - Web
- Runtime - Desktop
- Build - MacOS
- Build - Windows
- Build - Linux
- Other (please specify)
validations:
required: true
- type: textarea
id: react-native-info
attributes:
label: Output of `npx react-native info`
description: Run `npx react-native info` in your terminal, copy and paste the results here.
placeholder: |
Paste the output of `npx react-native info` here. The output looks like:
...
System:
OS: macOS 14.1.1
CPU: (10) arm64 Apple M1 Max
Memory: 417.81 MB / 64.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node: ...
version: 18.14.0
...
render: text
validations:
required: true
- type: textarea
id: stacktrace
attributes:
label: Stacktrace or Logs
description: Please provide a stacktrace or a log of your crash or failure
render: text
placeholder: |
Paste your stacktraces and logs here. They might look like:
java.lang.UnsatisfiedLinkError: couldn't find DSO to load: libfabricjni.so caused by: com.facebook.react.fabric.StateWrapperImpl result: 0
at com.facebook.soloader.SoLoader.g(Unknown Source:341)
at com.facebook.soloader.SoLoader.t(Unknown Source:124)
at com.facebook.soloader.SoLoader.s(Unknown Source:2)
at com.facebook.soloader.SoLoader.q(Unknown Source:42)
at com.facebook.soloader.SoLoader.p(Unknown Source:1)
...
validations:
required: true
- type: input
id: reproducer
attributes:
label: Reproducer
description: A link to a Expo Snack or a public repository that reproduces this bug, using [this template](https://github.com/react-native-community/reproducer-react-native). Reproducers are **mandatory**.
placeholder: "https://github.com/<myuser>/<myreproducer>"
validations:
required: true
- type: textarea
id: extra
attributes:
label: Screenshots and Videos
description: |
Please provide screenshot or a video of your bug if relevant.
Issues with videos and screenshots are more likely to **get prioritized**.
-98
View File
@@ -1,98 +0,0 @@
name: build-android
description: This action builds android
inputs:
release-type:
required: true
description: The type of release we are building. It could be nightly, release or dry-run
run-e2e-tests:
default: 'false'
description: If we need to build to run E2E tests. If yes, we need to build also x86.
gradle-cache-encryption-key:
description: "The encryption key needed to store the Gradle Configuration cache"
runs:
using: composite
steps:
- name: Setup git safe folders
shell: bash
run: git config --global --add safe.directory '*'
- name: Setup node.js
uses: ./.github/actions/setup-node
- name: Install node dependencies
uses: ./.github/actions/yarn-install
- name: Set React Native Version
shell: bash
run: node ./scripts/releases/set-rn-artifacts-version.js --build-type ${{ inputs.release-type }}
- name: Setup gradle
uses: ./.github/actions/setup-gradle
with:
cache-read-only: "false"
cache-encryption-key: ${{ inputs.gradle-cache-encryption-key }}
- name: Restore Android ccache
uses: actions/cache/restore@v4
with:
path: /github/home/.cache/ccache
key: v1-ccache-android-${{ github.job }}-${{ github.ref }}
restore-keys: |
v1-ccache-android-${{ github.job }}-
v1-ccache-android-
- name: Show ccache stats
shell: bash
run: ccache -s -v
- name: Build and publish all the Android Artifacts to /tmp/maven-local
shell: bash
run: |
if [[ "${{ inputs.release-type }}" == "dry-run" ]]; then
# dry-run: we only build ARM64 to save time/resources. For release/nightlies the default is to build all archs.
if [[ "${{ inputs.run-e2e-tests }}" == 'true' ]]; then
export ORG_GRADLE_PROJECT_reactNativeArchitectures="arm64-v8a,x86" # x86 is required for E2E testing
else
export ORG_GRADLE_PROJECT_reactNativeArchitectures="arm64-v8a"
fi
TASKS="publishAllToMavenTempLocal build"
elif [[ "${{ inputs.release-type }}" == "nightly" ]]; then
# nightly: we set isSnapshot to true so artifacts are sent to the right repository on Maven Central.
export ORG_GRADLE_PROJECT_isSnapshot="true"
TASKS="publishAllToMavenTempLocal publishAndroidToSonatype build"
else
# release: we want to build all archs (default)
TASKS="publishAllToMavenTempLocal publishAndroidToSonatype build"
fi
./gradlew $TASKS -PenableWarningsAsErrors=true
- name: Save Android ccache
if: ${{ github.ref == 'refs/heads/main' || contains(github.ref, '-stable') }}
uses: actions/cache/save@v4
with:
path: /github/home/.cache/ccache
key: v1-ccache-android-${{ github.job }}-${{ github.ref }}
- name: Show ccache stats
shell: bash
run: ccache -s -v
- name: Upload Maven Artifacts
uses: actions/upload-artifact@v4.3.4
with:
name: maven-local
path: /tmp/maven-local
- name: Upload test results
if: ${{ always() }}
uses: actions/upload-artifact@v4.3.4
with:
name: build-android-results
compression-level: 1
path: |
packages/react-native-gradle-plugin/react-native-gradle-plugin/build/reports
packages/react-native-gradle-plugin/settings-plugin/build/reports
packages/react-native/ReactAndroid/build/reports
- name: Upload RNTester APK - hermes-debug
if: ${{ always() }}
uses: actions/upload-artifact@v4.3.4
with:
name: rntester-debug
path: packages/rn-tester/android/app/build/outputs/apk/debug/
compression-level: 0
- name: Upload RNTester APK - hermes-release
if: ${{ always() }}
uses: actions/upload-artifact@v4.3.4
with:
name: rntester-release
path: packages/rn-tester/android/app/build/outputs/apk/release/
compression-level: 0
@@ -1,103 +0,0 @@
name: build-apple-slices-hermes
description: This action builds hermesc for Apple platforms
inputs:
hermes-version:
required: true
description: The version of Hermes
react-native-version:
required: true
description: The version of Hermes
slice:
required: true
description: The slice of hermes you want to build. It could be iphone, iphonesimulator, macos, catalyst, appletvos, appletvsimulator, xros, or xrossimulator
flavor:
required: true
description: The flavor we want to build. It can be Debug or Release
runs:
using: composite
steps:
- name: Setup xcode
uses: ./.github/actions/setup-xcode
- name: Restore Hermes workspace
uses: ./.github/actions/restore-hermes-workspace
- name: Restore HermesC Artifact
uses: actions/download-artifact@v4
with:
name: hermesc-apple
path: ./packages/react-native/sdks/hermes/build_host_hermesc
- name: Restore Slice From Cache
id: restore-slice-cache
uses: actions/cache/restore@v4
with:
path: ./packages/react-native/sdks/hermes/build_${{ inputs.slice }}_${{ inputs.flavor }}
key: v6-hermes-apple-${{ inputs.hermes-version }}-${{ inputs.react-native-version }}-${{ hashfiles('packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}-${{ inputs.slice }}-${{ inputs.flavor }}
- name: Build the Hermes ${{ inputs.slice }} frameworks
shell: bash
run: |
cd ./packages/react-native/sdks/hermes || exit 1
SLICE=${{ inputs.slice }}
FLAVOR=${{ inputs.flavor }}
FINAL_PATH=build_"$SLICE"_"$FLAVOR"
echo "Final path for this slice is: $FINAL_PATH"
if [[ -d "$FINAL_PATH" ]]; then
echo "[HERMES] Skipping! Found the requested slice at $FINAL_PATH".
exit 0
fi
if [[ "$ARTIFACTS_EXIST" ]]; then
echo "[HERMES] Skipping! Artifacts exists already."
exit 0
fi
export RELEASE_VERSION=${{ inputs.react-native-version }}
# HermesC is used to build hermes, so it has to be executable
chmod +x ./build_host_hermesc/bin/hermesc
if [[ "$SLICE" == "macosx" ]]; then
echo "[HERMES] Building Hermes for MacOS"
chmod +x ./utils/build-mac-framework.sh
BUILD_TYPE="${{ inputs.flavor }}" ./utils/build-mac-framework.sh
else
echo "[HERMES] Building Hermes for iOS: $SLICE"
chmod +x ./utils/build-ios-framework.sh
BUILD_TYPE="${{ inputs.flavor }}" ./utils/build-ios-framework.sh "$SLICE"
fi
echo "Moving from build_$SLICE to $FINAL_PATH"
mv build_"$SLICE" "$FINAL_PATH"
# check whether everything is there
if [[ -d "$FINAL_PATH/API/hermes/hermes.framework" ]]; then
echo "Successfully built hermes.framework for $SLICE in $FLAVOR"
else
echo "Failed to built hermes.framework for $SLICE in $FLAVOR"
exit 1
fi
if [[ -d "$FINAL_PATH/API/hermes/hermes.framework.dSYM" ]]; then
echo "Successfully built hermes.framework.dSYM for $SLICE in $FLAVOR"
else
echo "Failed to built hermes.framework.dSYM for $SLICE in $FLAVOR"
echo "Please try again"
exit 1
fi
- name: Compress slices to preserve Symlinks
shell: bash
run: |
cd ./packages/react-native/sdks/hermes
tar -czv -f build_${{ matrix.slice }}_${{ matrix.flavor }}.tar.gz build_${{ matrix.slice }}_${{ matrix.flavor }}
- name: Upload Artifact for Slice (${{ inputs.slice }}, ${{ inputs.flavor }}}
uses: actions/upload-artifact@v4.3.4
with:
name: slice-${{ inputs.slice }}-${{ inputs.flavor }}
path: ./packages/react-native/sdks/hermes/build_${{ inputs.slice }}_${{ inputs.flavor }}.tar.gz
- name: Save slice cache
if: ${{ github.ref == 'refs/heads/main' || contains(github.ref, '-stable') }} # To avoid that the cache explode.
uses: actions/cache/save@v4
with:
path: ./packages/react-native/sdks/hermes/build_${{ inputs.slice }}_${{ inputs.flavor }}
key: v6-hermes-apple-${{ inputs.hermes-version }}-${{ inputs.react-native-version }}-${{ hashfiles('packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}-${{ inputs.SLICE }}-${{ inputs.FLAVOR }}
@@ -1,227 +0,0 @@
name: build-hermes-macos
description: This action builds hermesc for Apple platforms
inputs:
hermes-version:
required: true
description: The version of Hermes
react-native-version:
required: true
description: The version of React Native
flavor:
required: true
description: The flavor we want to build. It can be Debug or Release
runs:
using: composite
steps:
- name: Setup xcode
uses: ./.github/actions/setup-xcode
- name: Setup node.js
uses: ./.github/actions/setup-node
- name: Restore Hermes workspace
uses: ./.github/actions/restore-hermes-workspace
- name: Restore Cached Artifacts
uses: actions/cache/restore@v4
with:
key: v4-hermes-artifacts-${{ inputs.flavor }}-${{ inputs.hermes-version }}-${{ inputs.react-native-version }}-${{ hashFiles('./packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}
path: |
/tmp/hermes/osx-bin/${{ inputs.flavor }}
/tmp/hermes/dSYM/${{ inputs.flavor }}
/tmp/hermes/hermes-runtime-darwin/hermes-ios-${{ inputs.flavor }}.tar.gz
- name: Check if the required artifacts already exist
id: check_if_apple_artifacts_are_there
shell: bash
run: |
FLAVOR="${{ inputs.flavor }}"
echo "Flavor is $FLAVOR"
OSX_BIN="/tmp/hermes/osx-bin/$FLAVOR"
DSYM="/tmp/hermes/dSYM/$FLAVOR"
HERMES="/tmp/hermes/hermes-runtime-darwin/hermes-ios-$FLAVOR.tar.gz"
if [[ -d "$OSX_BIN" ]] && \
[[ -d "$DSYM" ]] && \
[[ -f "$HERMES" ]]; then
echo "Artifacts are there!"
echo "ARTIFACTS_EXIST=true" >> $GITHUB_ENV
echo "ARTIFACTS_EXIST=true" >> $GITHUB_OUTPUT
fi
- name: Yarn- Install Dependencies
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
uses: ./.github/actions/yarn-install
- name: Slice cache macosx
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
uses: actions/download-artifact@v4
with:
path: ./packages/react-native/sdks/hermes/
name: slice-macosx-${{ inputs.flavor }}
- name: Slice cache iphoneos
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
uses: actions/download-artifact@v4
with:
path: ./packages/react-native/sdks/hermes/
name: slice-iphoneos-${{ inputs.flavor }}
- name: Slice cache iphonesimulator
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
uses: actions/download-artifact@v4
with:
path: ./packages/react-native/sdks/hermes/
name: slice-iphonesimulator-${{ inputs.flavor }}
- name: Slice cache appletvos
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
uses: actions/download-artifact@v4
with:
path: ./packages/react-native/sdks/hermes/
name: slice-appletvos-${{ inputs.flavor }}
- name: Slice cache appletvsimulator
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
uses: actions/download-artifact@v4
with:
path: ./packages/react-native/sdks/hermes/
name: slice-appletvsimulator-${{ inputs.flavor }}
- name: Slice cache catalyst
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
uses: actions/download-artifact@v4
with:
path: ./packages/react-native/sdks/hermes/
name: slice-catalyst-${{ inputs.flavor }}
- name: Slice cache xros
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
uses: actions/download-artifact@v4
with:
path: ./packages/react-native/sdks/hermes/
name: slice-xros-${{ inputs.flavor }}
- name: Slice cache xrsimulator
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
uses: actions/download-artifact@v4
with:
path: ./packages/react-native/sdks/hermes/
name: slice-xrsimulator-${{ inputs.flavor }}
- name: Unzip slices
shell: bash
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
run: |
cd ./packages/react-native/sdks/hermes
ls -l .
tar -xzv -f build_catalyst_${{ matrix.flavor }}.tar.gz
tar -xzv -f build_iphoneos_${{ matrix.flavor }}.tar.gz
tar -xzv -f build_iphonesimulator_${{ matrix.flavor }}.tar.gz
tar -xzv -f build_appletvos_${{ matrix.flavor }}.tar.gz
tar -xzv -f build_appletvsimulator_${{ matrix.flavor }}.tar.gz
tar -xzv -f build_macosx_${{ matrix.flavor }}.tar.gz
tar -xzv -f build_xros_${{ matrix.flavor }}.tar.gz
tar -xzv -f build_xrsimulator_${{ matrix.flavor }}.tar.gz
- name: Move back build folders
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
shell: bash
run: |
ls -l ./packages/react-native/sdks/hermes
cd ./packages/react-native/sdks/hermes || exit 1
mv build_macosx_${{ inputs.flavor }} build_macosx
mv build_iphoneos_${{ inputs.flavor }} build_iphoneos
mv build_iphonesimulator_${{ inputs.flavor }} build_iphonesimulator
mv build_appletvos_${{ inputs.flavor }} build_appletvos
mv build_appletvsimulator_${{ inputs.flavor }} build_appletvsimulator
mv build_catalyst_${{ inputs.flavor }} build_catalyst
mv build_xros_${{ inputs.flavor }} build_xros
mv build_xrsimulator_${{ inputs.flavor }} build_xrsimulator
- name: Prepare destroot folder
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
shell: bash
run: |
cd ./packages/react-native/sdks/hermes || exit 1
chmod +x ./utils/build-apple-framework.sh
. ./utils/build-apple-framework.sh
prepare_dest_root_for_ci
- name: Create fat framework for iOS
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
shell: bash
run: |
cd ./packages/react-native/sdks/hermes || exit 1
echo "[HERMES] Creating the universal framework"
chmod +x ./utils/build-ios-framework.sh
./utils/build-ios-framework.sh build_framework
chmod +x ./destroot/bin/hermesc
- name: Package the Hermes Apple frameworks
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
shell: bash
run: |
BUILD_TYPE="${{ inputs.flavor }}"
echo "Packaging Hermes Apple frameworks for $BUILD_TYPE build type"
TARBALL_OUTPUT_DIR=$(mktemp -d /tmp/hermes-tarball-output-XXXXXXXX)
TARBALL_FILENAME=$(node ./packages/react-native/scripts/hermes/get-tarball-name.js --buildType "$BUILD_TYPE")
echo "Packaging Hermes Apple frameworks for $BUILD_TYPE build type"
TARBALL_OUTPUT_PATH=$(node ./packages/react-native/scripts/hermes/create-tarball.js \
--inputDir ./packages/react-native/sdks/hermes \
--buildType "$BUILD_TYPE" \
--outputDir $TARBALL_OUTPUT_DIR)
echo "Hermes tarball saved to $TARBALL_OUTPUT_PATH"
mkdir -p $HERMES_TARBALL_ARTIFACTS_DIR
cp $TARBALL_OUTPUT_PATH $HERMES_TARBALL_ARTIFACTS_DIR/.
mkdir -p /tmp/hermes/osx-bin/${{ inputs.flavor }}
cp ./packages/react-native/sdks/hermes/build_macosx/bin/* /tmp/hermes/osx-bin/${{ inputs.flavor }}
ls -lR /tmp/hermes/osx-bin/
- name: Create dSYM archive
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
shell: bash
run: |
FLAVOR=${{ inputs.flavor }}
WORKING_DIR="/tmp/hermes_tmp/dSYM/$FLAVOR"
mkdir -p "$WORKING_DIR/macosx"
mkdir -p "$WORKING_DIR/catalyst"
mkdir -p "$WORKING_DIR/iphoneos"
mkdir -p "$WORKING_DIR/iphonesimulator"
mkdir -p "$WORKING_DIR/appletvos"
mkdir -p "$WORKING_DIR/appletvsimulator"
mkdir -p "$WORKING_DIR/xros"
mkdir -p "$WORKING_DIR/xrsimulator"
cd ./packages/react-native/sdks/hermes || exit 1
DSYM_FILE_PATH=API/hermes/hermes.framework.dSYM
cp -r build_macosx/$DSYM_FILE_PATH "$WORKING_DIR/macosx/"
cp -r build_catalyst/$DSYM_FILE_PATH "$WORKING_DIR/catalyst/"
cp -r build_iphoneos/$DSYM_FILE_PATH "$WORKING_DIR/iphoneos/"
cp -r build_iphonesimulator/$DSYM_FILE_PATH "$WORKING_DIR/iphonesimulator/"
cp -r build_appletvos/$DSYM_FILE_PATH "$WORKING_DIR/appletvos/"
cp -r build_appletvsimulator/$DSYM_FILE_PATH "$WORKING_DIR/appletvsimulator/"
cp -r build_xros/$DSYM_FILE_PATH "$WORKING_DIR/xros/"
cp -r build_xrsimulator/$DSYM_FILE_PATH "$WORKING_DIR/xrsimulator/"
DEST_DIR="/tmp/hermes/dSYM/$FLAVOR"
tar -C "$WORKING_DIR" -czvf "hermes.framework.dSYM" .
mkdir -p "$DEST_DIR"
mv "hermes.framework.dSYM" "$DEST_DIR"
- name: Upload hermes dSYM artifacts
uses: actions/upload-artifact@v4.3.4
with:
name: hermes-dSYM-${{ inputs.flavor }}
path: /tmp/hermes/dSYM/${{ inputs.flavor }}
- name: Upload hermes Runtime artifacts
uses: actions/upload-artifact@v4.3.4
with:
name: hermes-darwin-bin-${{ inputs.flavor }}
path: /tmp/hermes/hermes-runtime-darwin/hermes-ios-${{ inputs.flavor }}.tar.gz
- name: Upload hermes osx artifacts
uses: actions/upload-artifact@v4.3.4
with:
name: hermes-osx-bin-${{ inputs.flavor }}
path: /tmp/hermes/osx-bin/${{ inputs.flavor }}
- name: Upload Hermes Artifacts
uses: actions/cache/save@v4
if: ${{ github.ref == 'refs/heads/main' || contains(github.ref, '-stable') }} # To avoid that the cache explode.
with:
key: v4-hermes-artifacts-${{ inputs.flavor }}-${{ inputs.hermes-version }}-${{ inputs.react-native-version }}-${{ hashFiles('./packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}
path: |
/tmp/hermes/osx-bin/${{ inputs.flavor }}
/tmp/hermes/dSYM/${{ inputs.flavor }}
/tmp/hermes/hermes-runtime-darwin/hermes-ios-${{ inputs.flavor }}.tar.gz
@@ -1,39 +0,0 @@
name: build-hermesc-apple
description: This action builds hermesc for Apple platforms
inputs:
hermes-version:
required: true
description: The version of Hermes
react-native-version:
required: true
description: The version of React Native
runs:
using: composite
steps:
- name: Setup xcode
uses: ./.github/actions/setup-xcode
- name: Restore Hermes workspace
uses: ./.github/actions/restore-hermes-workspace
- name: Hermes apple cache
uses: actions/cache/restore@v4
with:
path: ./packages/react-native/sdks/hermes/build_host_hermesc
key: v2-hermesc-apple-${{ inputs.hermes-version }}-${{ inputs.react-native-version }}
- name: Build HermesC Apple
shell: bash
run: |
cd ./packages/react-native/sdks/hermes || exit 1
. ./utils/build-apple-framework.sh
build_host_hermesc_if_needed
- name: Upload HermesC Artifact
uses: actions/upload-artifact@v4.3.4
with:
name: hermesc-apple
path: ./packages/react-native/sdks/hermes/build_host_hermesc
- name: Cache hermesc apple
uses: actions/cache/save@v4
if: ${{ github.ref == 'refs/heads/main' || contains(github.ref, '-stable') }} # To avoid that the cache explode.
with:
path: ./packages/react-native/sdks/hermes/build_host_hermesc
key: v2-hermesc-apple-${{ inputs.hermes-version }}-${{ inputs.react-native-version }}
enableCrossOsArchive: true
@@ -1,53 +0,0 @@
name: build-hermesc-linux
description: This action builds hermesc for linux platforms
inputs:
hermes-version:
required: True
description: The version of Hermes
react-native-version:
required: True
description: The version of React Native
runs:
using: composite
steps:
- name: Install dependencies
shell: bash
run: |
sudo apt update
sudo apt install -y git openssh-client build-essential \
libreadline-dev libicu-dev jq zip python3
# Install cmake 3.28.3-1build7
sudo apt-get install cmake=3.28.3-1build7
sudo ln -sf /usr/bin/cmake /usr/local/bin/cmake
- name: Restore Hermes workspace
uses: ./.github/actions/restore-hermes-workspace
- name: Linux cache
uses: actions/cache@v4
with:
key: v1-hermes-${{ github.job }}-linux-${{ inputs.hermes-version }}-${{ inputs.react-native-version }}
path: |
/tmp/hermes/linux64-bin/
/tmp/hermes/hermes/destroot/
- name: Set up workspace
shell: bash
run: |
mkdir -p /tmp/hermes/linux64-bin
- name: Build HermesC for Linux
shell: bash
run: |
if [ -f /tmp/hermes/linux64-bin/hermesc ]; then
echo 'Skipping; Clean "/tmp/hermes/linux64-bin" to rebuild.'
else
cd /tmp/hermes
cmake -S hermes -B build -DHERMES_STATIC_LINK=ON -DCMAKE_BUILD_TYPE=Release -DHERMES_ENABLE_TEST_SUITE=OFF \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=True -DCMAKE_CXX_FLAGS=-s -DCMAKE_C_FLAGS=-s \
-DCMAKE_EXE_LINKER_FLAGS="-Wl,--whole-archive -lpthread -Wl,--no-whole-archive"
cmake --build build --target hermesc -j 4
cp /tmp/hermes/build/bin/hermesc /tmp/hermes/linux64-bin/.
fi
- name: Upload linux artifacts
uses: actions/upload-artifact@v4.3.4
with:
name: hermes-linux-bin
path: /tmp/hermes/linux64-bin
@@ -1,86 +0,0 @@
name: build-hermesc-windows
description: This action builds hermesc for Windows platforms
inputs:
hermes-version:
required: True
description: The version of Hermes
react-native-version:
required: True
description: The version of React Native
runs:
using: composite
steps:
- name: Download Previous Artifacts
uses: actions/download-artifact@v4
with:
name: hermes-workspace
path: 'C:\tmp\hermes'
- name: Set up workspace
shell: powershell
run: |
mkdir -p C:\tmp\hermes\osx-bin
mkdir -p .\packages\react-native\sdks\hermes
cp -r -Force C:\tmp\hermes\hermes\* .\packages\react-native\sdks\hermes\.
cp -r -Force .\packages\react-native\sdks\hermes-engine\utils\* .\packages\react-native\sdks\hermes\.
- name: Windows cache
uses: actions/cache@v4
with:
key: v3-hermes-${{ github.job }}-windows-${{ inputs.hermes-version }}-${{ inputs.react-native-version }}
path: |
C:\tmp\hermes\win64-bin\
C:\tmp\hermes\hermes\icu\
C:\tmp\hermes\hermes\deps\
C:\tmp\hermes\hermes\build_release\
- name: setup-msbuild
uses: microsoft/setup-msbuild@v1.3.2
- name: Set up workspace
shell: powershell
run: |
New-Item -ItemType Directory -ErrorAction SilentlyContinue $Env:HERMES_WS_DIR\icu
New-Item -ItemType Directory -ErrorAction SilentlyContinue $Env:HERMES_WS_DIR\deps
New-Item -ItemType Directory -ErrorAction SilentlyContinue $Env:HERMES_WS_DIR\win64-bin
- name: Downgrade CMake
shell: powershell
run: choco install cmake --version 3.31.6 --force
- name: Build HermesC for Windows
shell: powershell
run: |
if (-not(Test-Path -Path $Env:HERMES_WS_DIR\win64-bin\hermesc.exe)) {
cd $Env:HERMES_WS_DIR\icu
# If Invoke-WebRequest shows a progress bar, it will fail with
# Win32 internal error "Access is denied" 0x5 occurred [...]
$progressPreference = 'silentlyContinue'
Invoke-WebRequest -Uri "$Env:ICU_URL" -OutFile "icu.zip"
Expand-Archive -Path "icu.zip" -DestinationPath "."
cd $Env:HERMES_WS_DIR
Copy-Item -Path "icu\bin64\icu*.dll" -Destination "deps"
# Include MSVC++ 2015 redistributables
Copy-Item -Path "c:\windows\system32\msvcp140.dll" -Destination "deps"
Copy-Item -Path "c:\windows\system32\vcruntime140.dll" -Destination "deps"
Copy-Item -Path "c:\windows\system32\vcruntime140_1.dll" -Destination "deps"
$Env:PATH += ";$Env:CMAKE_DIR;$Env:MSBUILD_DIR"
$Env:ICU_ROOT = "$Env:HERMES_WS_DIR\icu"
cmake -S hermes -B build_release -G 'Visual Studio 17 2022' -Ax64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=True -DHERMES_ENABLE_WIN10_ICU_FALLBACK=OFF
if (-not $?) { throw "Failed to configure Hermes" }
echo "Running windows build..."
cd build_release
cmake --build . --target hermesc --config Release
if (-not $?) { throw "Failed to build Hermes" }
echo "Copying hermesc.exe to win64-bin"
cd $Env:HERMES_WS_DIR
Copy-Item -Path "build_release\bin\Release\hermesc.exe" -Destination "win64-bin"
# Include Windows runtime dependencies
Copy-Item -Path "deps\*" -Destination "win64-bin"
}
else {
Write-Host "Skipping; Clean c:\tmp\hermes\win64-bin to rebuild."
}
- name: Upload windows artifacts
uses: actions/upload-artifact@v4.3.4
with:
name: hermes-win64-bin
path: C:\tmp\hermes\win64-bin\
@@ -1,171 +0,0 @@
name: build-npm-package
description: This action builds the NPM package and uploads it to Maven
inputs:
release-type:
required: true
description: The type of release we are building. It could be nightly, release or dry-run
hermes-ws-dir:
required: 'true'
description: The workspace for hermes
gha-npm-token:
required: false
description: The GHA npm token, required only to publish to npm
default: ''
gradle-cache-encryption-key:
description: The encryption key needed to store the Gradle Configuration cache
runs:
using: composite
steps:
- name: Setup git safe folders
shell: bash
run: git config --global --add safe.directory '*'
- name: Create /tmp/hermes/osx-bin directory
shell: bash
run: mkdir -p /tmp/hermes/osx-bin
- name: Download osx-bin release artifacts
uses: actions/download-artifact@v4
with:
name: hermes-osx-bin-Release
path: /tmp/hermes/osx-bin/Release
- name: Download osx-bin debug artifacts
uses: actions/download-artifact@v4
with:
name: hermes-osx-bin-Debug
path: /tmp/hermes/osx-bin/Debug
- name: Download darwin-bin release artifacts
uses: actions/download-artifact@v4
with:
name: hermes-darwin-bin-Release
path: /tmp/hermes/hermes-runtime-darwin
- name: Download darwin-bin debug artifacts
uses: actions/download-artifact@v4
with:
name: hermes-darwin-bin-Debug
path: /tmp/hermes/hermes-runtime-darwin
- name: Download hermes dSYM debug artifacts
uses: actions/download-artifact@v4
with:
name: hermes-dSYM-Debug
path: /tmp/hermes/dSYM/Debug
- name: Download hermes dSYM release vartifacts
uses: actions/download-artifact@v4
with:
name: hermes-dSYM-Release
path: /tmp/hermes/dSYM/Release
- name: Download windows-bin artifacts
uses: actions/download-artifact@v4
with:
name: hermes-win64-bin
path: /tmp/hermes/win64-bin
- name: Download linux-bin artifacts
uses: actions/download-artifact@v4
with:
name: hermes-linux-bin
path: /tmp/hermes/linux64-bin
- name: Show /tmp/hermes directory
shell: bash
run: ls -lR /tmp/hermes
- name: Copy Hermes binaries
shell: bash
run: |
mkdir -p ./packages/react-native/sdks/hermesc ./packages/react-native/sdks/hermesc/osx-bin ./packages/react-native/sdks/hermesc/win64-bin ./packages/react-native/sdks/hermesc/linux64-bin
# When build_hermes_macos runs as a matrix, it outputs
if [[ -d ${{ inputs.hermes-ws-dir }}/osx-bin/Release ]]; then
cp -r ${{ inputs.hermes-ws-dir }}/osx-bin/Release/* ./packages/react-native/sdks/hermesc/osx-bin/.
elif [[ -d ${{ inputs.hermes-ws-dir }}/osx-bin/Debug ]]; then
cp -r ${{ inputs.hermes-ws-dir }}/osx-bin/Debug/* ./packages/react-native/sdks/hermesc/osx-bin/.
else
ls ${{ inputs.hermes-ws-dir }}/osx-bin || echo "hermesc macOS artifacts directory missing."
echo "Could not locate macOS hermesc binary."; exit 1;
fi
# Sometimes, GHA creates artifacts with lowercase Debug/Release. Make sure that if it happen, we uppercase them.
if [[ -f "${{ inputs.hermes-ws-dir }}/hermes-runtime-darwin/hermes-ios-debug.tar.gz" ]]; then
mv "${{ inputs.hermes-ws-dir }}/hermes-runtime-darwin/hermes-ios-debug.tar.gz" "${{ inputs.hermes-ws-dir }}/hermes-runtime-darwin/hermes-ios-Debug.tar.gz"
fi
if [[ -f "${{ inputs.hermes-ws-dir }}/hermes-runtime-darwin/hermes-ios-release.tar.gz" ]]; then
mv "${{ inputs.hermes-ws-dir }}/hermes-runtime-darwin/hermes-ios-release.tar.gz" "${{ inputs.hermes-ws-dir }}/hermes-runtime-darwin/hermes-ios-Release.tar.gz"
fi
cp -r ${{ inputs.hermes-ws-dir }}/win64-bin/* ./packages/react-native/sdks/hermesc/win64-bin/.
cp -r ${{ inputs.hermes-ws-dir }}/linux64-bin/* ./packages/react-native/sdks/hermesc/linux64-bin/.
# Make sure the hermesc files are actually executable.
chmod -R +x packages/react-native/sdks/hermesc/*
mkdir -p ./packages/react-native/ReactAndroid/external-artifacts/artifacts/
cp ${{ inputs.hermes-ws-dir }}/hermes-runtime-darwin/hermes-ios-Debug.tar.gz ./packages/react-native/ReactAndroid/external-artifacts/artifacts/hermes-ios-debug.tar.gz
cp ${{ inputs.hermes-ws-dir }}/hermes-runtime-darwin/hermes-ios-Release.tar.gz ./packages/react-native/ReactAndroid/external-artifacts/artifacts/hermes-ios-release.tar.gz
cp ${{ inputs.hermes-ws-dir }}/dSYM/Debug/hermes.framework.dSYM ./packages/react-native/ReactAndroid/external-artifacts/artifacts/hermes-framework-dSYM-debug.tar.gz
cp ${{ inputs.hermes-ws-dir }}/dSYM/Release/hermes.framework.dSYM ./packages/react-native/ReactAndroid/external-artifacts/artifacts/hermes-framework-dSYM-release.tar.gz
- name: Download ReactNativeDependencies
uses: actions/download-artifact@v4
with:
pattern: ReactNativeDependencies*
path: ./packages/react-native/ReactAndroid/external-artifacts/artifacts
merge-multiple: true
- name: Download ReactCore artifacts
uses: actions/download-artifact@v4
with:
pattern: ReactCore*
path: ./packages/react-native/ReactAndroid/external-artifacts/artifacts
merge-multiple: true
- name: Print Artifacts Directory
shell: bash
run: ls -lR ./packages/react-native/ReactAndroid/external-artifacts/artifacts/
- name: Setup node.js
uses: ./.github/actions/setup-node
- name: Setup gradle
uses: ./.github/actions/setup-gradle
with:
cache-encryption-key: ${{ inputs.gradle-cache-encryption-key }}
- name: Install dependencies
uses: ./.github/actions/yarn-install
- name: Build packages
shell: bash
run: yarn build
- name: Build types
shell: bash
run: yarn build-types --skip-snapshot
# Continue with publish steps
- name: Set npm credentials
if: ${{ inputs.release-type == 'release' ||
inputs.release-type == 'nightly' }}
shell: bash
run: echo "//registry.npmjs.org/:_authToken=${{ inputs.gha-npm-token }}" > ~/.npmrc
- name: Publish NPM
shell: bash
run: |
echo "GRADLE_OPTS = $GRADLE_OPTS"
# We can't have a separate step because each command is executed in a separate shell
# so variables exported in a command are not visible in another.
if [[ "${{ inputs.release-type }}" == "dry-run" ]]; then
export ORG_GRADLE_PROJECT_reactNativeArchitectures="arm64-v8a"
else
export ORG_GRADLE_PROJECT_reactNativeArchitectures="armeabi-v7a,arm64-v8a,x86,x86_64"
fi
node ./scripts/releases-ci/publish-npm.js -t ${{ inputs.release-type }}
- name: Upload npm logs
uses: actions/upload-artifact@v4.3.4
with:
name: npm-logs
path: ~/.npm/_logs
- name: Build release package as a job artifact
if: ${{ inputs.release-type == 'dry-run' }}
shell: bash
run: |
mkdir -p build
FILENAME=$(cd packages/react-native; npm pack | tail -1)
mv "packages/react-native/$FILENAME" build/
echo "$FILENAME" > build/react-native-package-version
- name: Upload release package
uses: actions/upload-artifact@v4.3.4
if: ${{ inputs.release-type == 'dry-run' }}
with:
name: react-native-package
path: build
-44
View File
@@ -1,44 +0,0 @@
name: create_release
description: Creates a new React Native release
inputs:
version:
description: "The version of React Native we want to release. For example 0.75.0-rc.0"
required: true
is-latest-on-npm:
description: "Whether we want to tag this release as latest on NPM"
required: true
default: "false"
dry-run:
description: "Whether the job should be executed in dry-run mode or not"
default: "true"
runs:
using: composite
steps:
- name: Yarn install
uses: ./.github/actions/yarn-install
- name: Configure Git
shell: bash
run: |
git config --local user.email "bot@reactnative.dev"
git config --local user.name "React Native Bot"
- name: Creating release commit
shell: bash
run: |
node scripts/releases/create-release-commit.js \
--reactNativeVersion "${{ inputs.version }}" \
--tagAsLatestRelease "${{ inputs.is-latest-on-npm }}" \
--dryRun "${{ inputs.dry-run }}"
GIT_PAGER=cat git show HEAD
- name: Update "latest" tag if needed
shell: bash
if: ${{ inputs.is-latest-on-npm == 'true' }}
run: |
git tag -d "latest"
git push origin :latest
git tag -a "latest" -m "latest"
- name: Pushing release commit
shell: bash
if: ${{ inputs.dry-run == 'false' }}
run: |
CURR_BRANCH="$(git branch --show-current)"
git push origin "$CURR_BRANCH" --follow-tags
@@ -1,23 +0,0 @@
name: diff-js-api-breaking-changes
description: Check for breaking changes in the public React Native JS API
runs:
using: composite
steps:
- name: Fetch snapshot from PR head
shell: bash
env:
SCRATCH_DIR: ${{ runner.temp }}/diff-js-api-breaking-changes
run: |
mkdir $SCRATCH_DIR
git fetch --depth=1 origin ${{ github.event.pull_request.head.sha }}
git show ${{ github.event.pull_request.head.sha }}:packages/react-native/ReactNativeApi.d.ts > $SCRATCH_DIR/ReactNativeApi-after.d.ts \
|| echo "" > $SCRATCH_DIR/ReactNativeApi.d.ts
- name: Run breaking change detection
shell: bash
env:
SCRATCH_DIR: ${{ runner.temp }}/diff-js-api-breaking-changes
run: |
node ./scripts/js-api/diff-api-snapshot \
${{ github.workspace }}/packages/react-native/ReactNativeApi.d.ts \
$SCRATCH_DIR/ReactNativeApi-after.d.ts \
> $SCRATCH_DIR/output.json
-55
View File
@@ -1,55 +0,0 @@
name: lint
description: Runs all the linters in the codebase
inputs:
node-version:
description: "The node.js version to use"
required: false
default: "22"
github-token:
description: "The GitHub token used by pull-bot"
required: true
runs:
using: composite
steps:
- name: Setup node.js
uses: ./.github/actions/setup-node
with:
node-version: ${{ inputs.node-version }}
- name: Run yarn install
uses: ./.github/actions/yarn-install
- name: Run linters against modified files (analysis-bot)
shell: bash
run: yarn lint-ci
env:
GITHUB_TOKEN: ${{ inputs.github-token }}
GITHUB_PR_NUMBER: ${{ github.event.number }}
- name: Lint code
shell: bash
run: ./.github/workflow-scripts/exec_swallow_error.sh yarn lint --format junit -o ./reports/junit/eslint/results.xml
- name: Lint file structure
shell: bash
run: ./.github/workflow-scripts/lint_files.sh
- name: Verify not committing repo after running build
shell: bash
run: yarn run build --validate
- name: Run flowcheck
shell: bash
run: yarn flow-check
- name: Run typescript check
shell: bash
run: yarn test-typescript
- name: Check license
shell: bash
run: ./.github/workflow-scripts/check_license.sh
- name: Check formatting
shell: bash
run: yarn run format-check
- name: Lint markdown
shell: bash
run: yarn run lint-markdown
- name: Build types
shell: bash
run: yarn build-types --skip-snapshot
- name: Run typescript check of generated types
shell: bash
run: yarn test-generated-typescript
@@ -1,84 +0,0 @@
name: Maestro E2E Android
description: Runs E2E Tests on Android using Maestro
inputs:
app-path:
required: true
description: The path to the .apk file
app-id:
required: true
description: The id of the app to test
maestro-flow:
required: true
description: the folder that contains the maestro tests
install-java:
required: false
default: 'true'
description: whether this action has to install java 17 or not
flavor:
required: true
description: the flavor we want to run - either debug or release
default: release
working-directory:
required: false
default: "."
description: The directory from which metro should be started
runs:
using: composite
steps:
- name: Installing Maestro
shell: bash
run: export MAESTRO_VERSION=1.40.0; curl -Ls "https://get.maestro.mobile.dev" | bash
- name: Set up JDK 17
if: ${{ inputs.install-java == 'true' }}
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'zulu'
- name: Enable KVM group perms
shell: bash
run: |
# ubuntu machines have hardware acceleration available and when we try to create an emulator, the script pauses asking for user input
# These lines set the rules to reply automatically to that question and unblock the creation of the emulator.
# source: https://github.com/ReactiveCircus/android-emulator-runner?tab=readme-ov-file#running-hardware-accelerated-emulators-on-linux-runners
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: Build Codegen
shell: bash
if: ${{ inputs.flavor == 'debug' }}
run: ./packages/react-native-codegen/scripts/oss/build.sh
- name: Run e2e tests
id: run-tests
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 24
arch: x86
ram-size: '8192M'
heap-size: '4096M'
disk-size: '10G'
cores: '4'
disable-animations: false
avd-name: e2e_emulator
script: node .github/workflow-scripts/maestro-android.js ${{ inputs.app-path }} ${{ inputs.app-id }} ${{ inputs.maestro-flow }} ${{ inputs.flavor }} ${{ inputs.working-directory }}
- name: Normalize APP_ID
id: normalize-app-id
shell: bash
if: always()
run: |
NORM_APP_ID=$(echo "${{ inputs.app-id }}" | tr '.' '-')
echo "app-id=$NORM_APP_ID" >> $GITHUB_OUTPUT
- name: Store tests result
uses: actions/upload-artifact@v4.3.4
if: always()
with:
name: e2e_android_${{ steps.normalize-app-id.outputs.app-id }}_report_${{ inputs.flavor }}_NewArch
path: |
report.xml
screen.mp4
- name: Store Logs
if: steps.run-tests.outcome == 'failure'
uses: actions/upload-artifact@v4.3.4
with:
name: maestro-logs-android-${{ steps.normalize-app-id.outputs.app-id }}-${{ inputs.flavor }}-NewArch
path: /tmp/MaestroLogs
-82
View File
@@ -1,82 +0,0 @@
name: Maestro E2E iOS
description: Runs E2E Tests on iOS using Maestro
inputs:
app-path:
required: true
description: The path to the .app file
app-id:
required: true
description: The id of the app to test
maestro-flow:
required: true
description: the folder that contains the maestro tests
flavor:
required: true
description: Whether we are building for Debug or Release
default: Release
working-directory:
required: false
default: "."
description: The directory from which metro should be started
runs:
using: composite
steps:
- name: Installing Maestro
shell: bash
run: export MAESTRO_VERSION=1.40.0; curl -Ls "https://get.maestro.mobile.dev" | bash
- name: Installing Maestro dependencies
shell: bash
run: |
brew tap facebook/fb
brew install facebook/fb/idb-companion
- name: Set up JDK 11
uses: actions/setup-java@v2
with:
java-version: '17'
distribution: 'zulu'
- name: Run yarn install
uses: ./.github/actions/yarn-install
- name: Start Metro in Debug
shell: bash
if: ${{ inputs.flavor == 'Debug' }}
run: |
# build codegen or we will see a redbox
./packages/react-native-codegen/scripts/oss/build.sh
cd ${{ inputs.working-directory }}
yarn start &
sleep 5 # to give metro time to load
- name: Run tests
id: run-tests
shell: bash
run: |
# Avoid exit from the job if one of the command returns an error.
# Maestro can fail in case of flakyness, we have some retry logic.
set +e
node .github/workflow-scripts/maestro-ios.js \
"${{ inputs.app-path }}" \
"${{ inputs.app-id }}" \
"${{ inputs.maestro-flow }}" \
"Hermes" \
"${{ inputs.flavor }}" \
"${{ inputs.working-directory }}"
- name: Store video record
if: always()
uses: actions/upload-artifact@v4.3.4
with:
name: e2e_ios_${{ inputs.app-id }}_report_${{ inputs.flavor }}_NewArch
path: |
video_record_1.mov
video_record_2.mov
video_record_3.mov
video_record_4.mov
video_record_5.mov
report.xml
- name: Store Logs
if: failure() && steps.run-tests.outcome == 'failure'
uses: actions/upload-artifact@v4.3.4
with:
name: maestro-logs-${{ inputs.app-id }}-${{ inputs.flavor }}-NewArch
path: /tmp/MaestroLogs
@@ -1,100 +0,0 @@
name: prepare-hermes-workspace
description: This action prepares the hermes workspace with the right hermes and react-native versions.
inputs:
hermes-ws-dir:
required: true
description: The hermes dir we need to use to setup the workspace
hermes-version-file:
required: true
description: the path to the file that will contain the hermes version
outputs:
hermes-version:
description: the version of Hermes tied to this run
value: ${{ steps.hermes-version.outputs.VERSION }}
react-native-version:
description: the version of React Native tied to this run
value: ${{ steps.react-native-version.outputs.VERSION }}
runs:
using: composite
steps:
- name: Setup node.js
uses: ./.github/actions/setup-node
- name: Setup hermes version
shell: bash
id: hermes-version
run: |
mkdir -p "/tmp/hermes" "/tmp/hermes/download" "/tmp/hermes/hermes"
if [ -f "${{ inputs.hermes-version-file }}" ]; then
echo "Hermes Version file found! Using this version for the build:"
echo "VERSION=$(cat ${{ inputs.hermes-version-file }})" >> "$GITHUB_OUTPUT"
else
echo "Hermes Version file not found!!!"
echo "Using the last commit from main for the build:"
HERMES_TAG_SHA=$(git ls-remote https://github.com/facebook/hermes main | cut -f 1 | tr -d '[:space:]')
echo "VERSION=$HERMES_TAG_SHA" >> "$GITHUB_OUTPUT"
fi
echo "Hermes commit is $HERMES_TAG_SHA"
- name: Get react-native version
shell: bash
id: react-native-version
run: |
VERSION=$(cat packages/react-native/package.json | jq -r '.version')
# Save the react native version we are building in an output variable so we can use that file as part of the cache key.
echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT"
echo "React Native Version is $VERSION"
- name: Cache hermes workspace
id: restore-hermes
uses: actions/cache/restore@v4
with:
path: |
/tmp/hermes/download/
/tmp/hermes/hermes/
key: v1-hermes-${{ steps.hermes-version.outputs.version }}
enableCrossOsArchive: true
# It happened while testing that a cache was created from the right folders
# but those folders where empty. Thus, the next check ensures that we can work with those caches.
- name: Check if cache was meaningful
id: meaningful-cache
shell: bash
run: |
if [[ -d /tmp/hermes/hermes ]] && [[ -n "$(ls -A /tmp/hermes/hermes)" ]]; then
echo "Found a good hermes cache"
echo "HERMES_CACHED=true" >> "$GITHUB_OUTPUT"
fi
- name: Yarn- Install Dependencies
if: ${{ steps.meaningful-cache.outputs.HERMES_CACHED != 'true' }}
uses: ./.github/actions/yarn-install
- name: Download Hermes tarball
if: ${{ steps.meaningful-cache.outputs.HERMES_CACHED != 'true' }}
shell: bash
run: |
node packages/react-native/scripts/hermes/prepare-hermes-for-build ${{ github.event.pull_request.html_url }}
cp packages/react-native/sdks/download/* ${{ inputs.hermes-ws-dir }}/download/.
cp -r packages/react-native/sdks/hermes/* ${{ inputs.hermes-ws-dir }}/hermes/.
echo ${{ steps.hermes-version.outputs.version }}
- name: Upload Hermes artifact
uses: actions/upload-artifact@v4.3.4
with:
name: hermes-workspace
path: |
/tmp/hermes/download/
/tmp/hermes/hermes/
- name: Cache hermes workspace
uses: actions/cache/save@v4
if: ${{ github.ref == 'refs/heads/main' }} # To avoid that the cache explode.
with:
path: |
/tmp/hermes/download/
/tmp/hermes/hermes/
key: v1-hermes-${{ steps.hermes-version.outputs.version }}
enableCrossOsArchive: true
@@ -1,22 +0,0 @@
name: prepare-ios-tests
description: Prepare iOS Tests
runs:
using: composite
steps:
- name: Run Ruby Tests
shell: bash
run: |
cd packages/react-native/scripts
sh run_ruby_tests.sh
- name: Boot iPhone Simulator
shell: bash
run: source scripts/.tests.env && xcrun simctl boot "$IOS_DEVICE" || true
- name: "Brew: Tap wix/brew"
shell: bash
run: brew tap wix/brew
- name: brew install applesimutils watchman
shell: bash
run: brew install applesimutils watchman
- name: Configure Watchman
shell: bash
run: echo "{}" > .watchmanconfig
@@ -1,16 +0,0 @@
name: restore-hermes-workspace
description: "Restore hermes workspace that has been created in Prepare Hermes Workspace"
runs:
using: composite
steps:
- name: Download Previous Artifacts
uses: actions/download-artifact@v4
with:
name: hermes-workspace
path: /tmp/hermes
- name: Set up workspace
shell: bash
run: |
mkdir -p $HERMES_OSXBIN_ARTIFACTS_DIR ./packages/react-native/sdks/hermes
cp -r $HERMES_WS_DIR/hermes/* ./packages/react-native/sdks/hermes/.
cp -r ./packages/react-native/sdks/hermes-engine/utils ./packages/react-native/sdks/hermes/.
-23
View File
@@ -1,23 +0,0 @@
name: Setup gradle
description: "Set up your GitHub Actions workflow with a specific version of gradle"
inputs:
cache-read-only:
description: "Whether the Gradle Cache should be in read-only mode so this job won't be allowed to write to it"
default: "true"
cache-encryption-key:
description: "The encryption key needed to store the Gradle Configuration cache"
runs:
using: "composite"
steps:
- name: Setup gradle
uses: gradle/actions/setup-gradle@v4
with:
gradle-version: wrapper
# We want the Gradle cache to be written only on main/-stable branches run, and only for jobs with `cache-read-only` == false (i.e. `build_android`).
cache-read-only: ${{ (github.ref != 'refs/heads/main' && !contains(github.ref, '-stable')) || inputs.cache-read-only == 'true' }}
# Similarly, for those jobs we want to start with a clean cache so it doesn't grow without limits (this is the negation of the previous condition).
cache-write-only: ${{ (github.ref == 'refs/heads/main' || contains(github.ref, '-stable')) && inputs.cache-read-only != 'true' }}
add-job-summary-as-pr-comment: on-failure
# Encryption key for the Gradle Configuration Cache.
# See https://docs.gradle.org/8.6/userguide/configuration_cache.html#config_cache:secrets:configuring_encryption_key
cache-encryption-key: ${{ inputs.cache-encryption-key }}
-15
View File
@@ -1,15 +0,0 @@
name: Setup node.js
description: 'Set up your GitHub Actions workflow with a specific version of node.js'
inputs:
node-version:
description: 'The node.js version to use'
required: false
default: '22.14.0'
runs:
using: "composite"
steps:
- name: Setup node.js
uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
cache: yarn
@@ -1,32 +0,0 @@
name: setup-xcode-build-cache
description: Add caching to iOS jobs to speed up builds
inputs:
hermes-version:
description: The version of hermes
required: true
flavor:
description: The flavor that is going to be built
default: Debug
use-frameworks:
description: Whether we are bulding with DynamicFrameworks or StaticLibraries
default: StaticLibraries
ruby-version:
description: The ruby version we are going to use
default: 2.6.10
runs:
using: composite
steps:
- name: See commands.yml with_xcodebuild_cache
shell: bash
run: echo "See commands.yml with_xcodebuild_cache"
- name: Cache podfile lock
uses: actions/cache@v4
with:
path: packages/rn-tester/Podfile.lock
key: v13-podfilelock-${{ github.job }}-NewArch-${{ inputs.flavor }}-${{ inputs.use-frameworks }}-${{ inputs.ruby-version }}-${{ hashfiles('packages/rn-tester/Podfile') }}-${{ inputs.hermes-version }}
- name: Cache cocoapods
uses: actions/cache@v4
with:
path: packages/rn-tester/Pods
key: v15-cocoapods-${{ github.job }}-NewArch-${{ inputs.flavor }}-${{ inputs.use-frameworks }}-${{ inputs.ruby-version }}-${{ hashfiles('packages/rn-tester/Podfile.lock') }}-${{ hashfiles('packages/rn-tester/Podfile') }}-${{ inputs.hermes-version}}
-14
View File
@@ -1,14 +0,0 @@
name: Setup xcode
description: 'Set up your GitHub Actions workflow with a specific version of xcode'
inputs:
xcode-version:
description: 'The xcode version to use'
required: false
default: '16.2.0'
runs:
using: "composite"
steps:
- name: Setup xcode
uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd
with:
xcode-version: ${{ inputs.xcode-version }}
@@ -1,104 +0,0 @@
name: test-ios-helloworld
description: Test iOS Hello World
inputs:
use-frameworks:
description: The dependency building and linking strategy to use. Must be one of "StaticLibraries", "DynamicFrameworks"
default: StaticLibraries
ruby-version:
description: The version of ruby that must be used
default: 2.6.10
flavor:
description: The flavor of the build. Must be one of "Debug", "Release".
default: Debug
hermes-version:
description: The version of hermes
required: true
react-native-version:
description: The version of react-native
required: true
runs:
using: composite
steps:
- name: Setup xcode
uses: ./.github/actions/setup-xcode
- name: Setup node.js
uses: ./.github/actions/setup-node
- name: Create Hermes folder
shell: bash
run: mkdir -p "$HERMES_WS_DIR"
- name: Download Hermes
uses: actions/download-artifact@v4
with:
name: hermes-darwin-bin-${{ inputs.flavor }}
path: /tmp/hermes/hermes-runtime-darwin/
- name: Print Downloaded hermes
shell: bash
run: ls -lR "$HERMES_WS_DIR"
- name: Run yarn
uses: ./.github/actions/yarn-install
- name: Setup ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ inputs.ruby-version }}
- name: Download ReactNativeDependencies
uses: actions/download-artifact@v4
with:
name: ReactNativeDependencies${{ inputs.flavor }}.xcframework.tar.gz
path: /tmp/third-party
- name: Print third-party folder
shell: bash
run: ls -lR /tmp/third-party
- name: Download React Native Prebuilds
uses: actions/download-artifact@v4
with:
name: ReactCore${{ inputs.flavor }}.xcframework.tar.gz
path: /tmp/ReactCore
- name: Print ReactCore folder
shell: bash
run: ls -lR /tmp/ReactCore
- name: Install iOS dependencies - Configuration ${{ inputs.flavor }};
shell: bash
run: |
cd private/helloworld
args=()
if [[ ${{ inputs.use-frameworks }} == "DynamicFrameworks" ]]; then
args+=(--frameworks dynamic)
fi
# Tarball is restored with capital flavors suffix, but somehow the tarball name from JS at line 96 returns as lowercased.
# Let's ensure that the tarballs have the right names
if [[ -f "$HERMES_WS_DIR/hermes-runtime-darwin/hermes-ios-Debug.tar.gz" ]]; then
mv "$HERMES_WS_DIR/hermes-runtime-darwin/hermes-ios-Debug.tar.gz" "$HERMES_WS_DIR/hermes-runtime-darwin/hermes-ios-debug.tar.gz"
fi
if [[ -f "$HERMES_WS_DIR/hermes-runtime-darwin/hermes-ios-Release.tar.gz" ]]; then
mv "$HERMES_WS_DIR/hermes-runtime-darwin/hermes-ios-Release.tar.gz" "$HERMES_WS_DIR/hermes-runtime-darwin/hermes-ios-release.tar.gz"
fi
BUILD_TYPE="${{ inputs.flavor }}"
TARBALL_FILENAME=$(node ../../packages/react-native/scripts/hermes/get-tarball-name.js --buildType "$BUILD_TYPE")
export HERMES_ENGINE_TARBALL_PATH="$HERMES_WS_DIR/hermes-runtime-darwin/$TARBALL_FILENAME"
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"
yarn bootstrap ios "${args[@]}" | cat
- name: Run Helloworld tests
shell: bash
run: |
cd private/helloworld
yarn test
- name: Build HelloWorld project
shell: bash
run: |
cd private/helloworld
args=()
if [[ ${{ inputs.flavor }} == "Release" ]]; then
args+=(--prod)
fi
yarn build ios "${args[@]}" | cat
yarn bundle ios "${args[@]}" | cat
@@ -1,173 +0,0 @@
name: test-ios-rntester
description: Test iOS RNTester
inputs:
use-frameworks:
description: The dependency building and linking strategy to use. Must be one of "StaticLibraries", "DynamicFrameworks"
default: StaticLibraries
ruby-version:
description: The version of ruby that must be used
default: 2.6.10
run-unit-tests:
description: whether unit tests should run or not.
default: "false"
hermes-tarball-artifacts-dir:
description: The directory where the hermes tarball artifacts are stored
default: /tmp/hermes/hermes-runtime-darwin
flavor:
description: The flavor of the build. Must be one of "Debug", "Release".
default: Debug
hermes-version:
description: The version of hermes
required: true
react-native-version:
description: The version of react-native
required: true
run-e2e-tests:
description: Whether we want to run E2E tests or not
required: false
default: false
runs:
using: composite
steps:
- name: Setup xcode
uses: ./.github/actions/setup-xcode
- name: Setup node.js
uses: ./.github/actions/setup-node
- name: Run yarn
uses: ./.github/actions/yarn-install
- name: Download Hermes
uses: actions/download-artifact@v4
with:
name: hermes-darwin-bin-${{ inputs.flavor }}
path: ${{ inputs.hermes-tarball-artifacts-dir }}
- name: Setup ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ inputs.ruby-version }}
- name: Prepare IOS Tests
if: ${{ inputs.run-unit-tests == 'true' }}
uses: ./.github/actions/prepare-ios-tests
- name: Set HERMES_ENGINE_TARBALL_PATH envvar if Hermes tarball is present
shell: bash
run: |
HERMES_TARBALL_ARTIFACTS_DIR=${{ inputs.hermes-tarball-artifacts-dir }}
if [ ! -d $HERMES_TARBALL_ARTIFACTS_DIR ]; then
echo "Hermes tarball artifacts dir not present ($HERMES_TARBALL_ARTIFACTS_DIR). Build Hermes from source."
exit 0
fi
TARBALL_FILENAME=$(node ./packages/react-native/scripts/hermes/get-tarball-name.js --buildType "${{ inputs.flavor }}")
TARBALL_PATH=$HERMES_TARBALL_ARTIFACTS_DIR/$TARBALL_FILENAME
echo "Looking for $TARBALL_FILENAME in $HERMES_TARBALL_ARTIFACTS_DIR"
echo "$TARBALL_PATH"
if [ ! -f $TARBALL_PATH ]; then
echo "Hermes tarball not present ($TARBALL_PATH). Build Hermes from source."
exit 0
fi
echo "Found Hermes tarball at $TARBALL_PATH"
echo "HERMES_ENGINE_TARBALL_PATH=$TARBALL_PATH" >> $GITHUB_ENV
- name: Print Hermes version
shell: bash
run: |
HERMES_TARBALL_ARTIFACTS_DIR=${{ inputs.hermes-tarball-artifacts-dir }}
TARBALL_FILENAME=$(node ./packages/react-native/scripts/hermes/get-tarball-name.js --buildType "${{ inputs.flavor }}")
TARBALL_PATH=$HERMES_TARBALL_ARTIFACTS_DIR/$TARBALL_FILENAME
if [[ -e $TARBALL_PATH ]]; then
tar -xf $TARBALL_PATH
echo 'print(HermesInternal?.getRuntimeProperties?.()["OSS Release Version"])' > test.js
chmod +x ./destroot/bin/hermes
./destroot/bin/hermes test.js
rm test.js
rm -rf destroot
else
echo 'No Hermes tarball found.'
fi
- name: Download ReactNativeDependencies
uses: actions/download-artifact@v4
with:
name: ReactNativeDependencies${{ inputs.flavor }}.xcframework.tar.gz
path: /tmp/third-party/
- name: Print third-party folder
shell: bash
run: ls -lR /tmp/third-party
- name: Download React Native Prebuilds
uses: actions/download-artifact@v4
with:
name: ReactCore${{ inputs.flavor }}.xcframework.tar.gz
path: /tmp/ReactCore
- name: Print ReactCore folder
shell: bash
run: ls -lR /tmp/ReactCore
- name: Setup xcode build cache
uses: ./.github/actions/setup-xcode-build-cache
with:
hermes-version: ${{ inputs.hermes-version }}
use-frameworks: ${{ inputs.use-frameworks }}
flavor: ${{ inputs.flavor }}
ruby-version: ${{ inputs.ruby-version }}
- name: Install CocoaPods dependencies
shell: bash
run: |
export HERMES_ENGINE_TARBALL_PATH=$HERMES_ENGINE_TARBALL_PATH
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"
if [[ ${{ inputs.use-frameworks }} == "DynamicFrameworks" ]]; then
export USE_FRAMEWORKS=dynamic
fi
cd packages/rn-tester
bundle install
bundle exec pod install
- name: Build RNTester
shell: bash
run: |
xcodebuild \
-scheme "RNTester" \
-workspace packages/rn-tester/RNTesterPods.xcworkspace \
-configuration "${{ inputs.flavor }}" \
-sdk "iphonesimulator" \
-destination "generic/platform=iOS Simulator" \
-derivedDataPath "/tmp/RNTesterBuild"
echo "Print path to *.app file"
APP_PATH=$(find "/tmp/RNTesterBuild" -type d -name "*.app")
echo "App found at $APP_PATH"
echo "app-path=$APP_PATH" >> $GITHUB_ENV
- name: "Run Tests: iOS Unit and Integration Tests"
if: ${{ inputs.run-unit-tests == 'true' }}
shell: bash
run: yarn test-ios
- name: Zip Derived data folder
if: ${{ inputs.run-unit-tests == 'true' }}
shell: bash
run: |
echo "zipping tests results"
cd /Users/distiller/Library/Developer/Xcode
XCRESULT_PATH=$(find . -name '*.xcresult')
tar -zcvf xcresults.tar.gz $XCRESULT_PATH
- name: Upload artifact
uses: actions/upload-artifact@v4.3.4
if: ${{ inputs.run-unit-tests == 'true' }}
with:
name: xcresults
path: /Users/distiller/Library/Developer/Xcode/xcresults.tar.gz
- name: Upload RNTester App
if: ${{ inputs.use-frameworks == 'StaticLibraries' && inputs.ruby-version == '2.6.10' }} # This is needed to avoid conflicts with the artifacts
uses: actions/upload-artifact@v4.3.4
with:
name: RNTesterApp-NewArch-${{ inputs.flavor }}
path: ${{ env.app-path }}
- name: Store test results
if: ${{ inputs.run-unit-tests == 'true' }}
uses: actions/upload-artifact@v4.3.4
with:
name: test-results
path: ./reports/junit
-26
View File
@@ -1,26 +0,0 @@
name: test-js
description: Runs all the JS tests in the codebase
inputs:
node-version:
description: "The node.js version to use"
required: false
default: "22"
runs:
using: composite
steps:
- name: Setup node.js
uses: ./.github/actions/setup-node
with:
node-version: ${{ inputs.node-version }}
- name: Yarn install
uses: ./.github/actions/yarn-install
- name: Run Tests - JavaScript Tests
shell: bash
run: node ./scripts/run-ci-javascript-tests.js --maxWorkers 2
- name: Upload test results
if: ${{ always() }}
uses: actions/upload-artifact@v4.3.4
with:
name: test-js-results
compression-level: 1
path: ./reports/junit
@@ -1,52 +0,0 @@
name: test-library-on-nightly
description: Tests a library on a nightly
inputs:
library-npm-package:
description: The library npm package to add
required: true
platform:
description: whether we want to build for iOS or Android
required: true
runs:
using: composite
steps:
- name: Create new app
shell: bash
run: |
cd /tmp
npx @react-native-community/cli init RNApp --skip-install --version nightly
- name: Add library
shell: bash
run: |
cd /tmp/RNApp
yarn add ${{ inputs.library-npm-package }}
# iOS
- name: Setup xcode
if: ${{ inputs.platform == 'ios' }}
uses: ./.github/actions/setup-xcode
- name: Build iOS
shell: bash
if: ${{ inputs.platform == 'ios' }}
run: |
cd /tmp/RNApp/ios
bundle install
bundle exec pod install
xcodebuild build \
-workspace RNApp.xcworkspace \
-scheme RNApp \
-sdk iphonesimulator
# Android
- name: Setup Java for Android
if: ${{ inputs.platform == 'android' }}
uses: actions/setup-java@v2
with:
java-version: '17'
distribution: 'zulu'
- name: Build Android
shell: bash
if: ${{ inputs.platform == 'android' }}
run: |
cd /tmp/RNApp/android
./gradlew assembleDebug
-22
View File
@@ -1,22 +0,0 @@
name: yarn-install
runs:
using: composite
steps:
- name: Setup node.js
uses: ./.github/actions/setup-node
- name: Install dependencies
shell: bash
run: |
MAX_ATTEMPTS=2
ATTEMPT=0
WAIT_TIME=20
while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do
yarn install --non-interactive --frozen-lockfile && break
echo "yarn install failed. Retrying in $WAIT_TIME seconds..."
sleep $WAIT_TIME
ATTEMPT=$((ATTEMPT + 1))
done
if [ $ATTEMPT -eq $MAX_ATTEMPTS ]; then
echo "All attempts to invoke yarn install failed - Aborting the workflow"
exit 1
fi
@@ -1,305 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
const {
_verifyTagExists,
_extractChangelog,
_computeBody,
_createDraftReleaseOnGitHub,
} = require('../createDraftRelease');
const fs = require('fs');
const silence = () => {};
const mockFetch = jest.fn();
jest.mock('../utils.js', () => ({
log: silence,
}));
global.fetch = mockFetch;
describe('Create Draft Release', () => {
beforeEach(jest.clearAllMocks);
describe('#_verifyTagExists', () => {
it('throws if the tag does not exists', async () => {
const token = 'token';
mockFetch.mockReturnValueOnce(Promise.resolve({status: 404}));
await expect(_verifyTagExists('0.77.1')).rejects.toThrowError(
`Tag v0.77.1 does not exist`,
);
expect(mockFetch).toHaveBeenCalledTimes(1);
expect(mockFetch).toHaveBeenCalledWith(
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
);
});
});
describe('#_extractChangelog', () => {
it(`extracts changelog from CHANGELOG.md`, async () => {
const mockedReturnValue = `# Changelog
## v0.77.2
- [PR #1234](https://github.com/facebook/react-native/pull/1234) - Some change
- [PR #5678](https://github.com/facebook/react-native/pull/5678) - Some other change
## v0.77.1
### Breaking Changes
- [PR #9012](https://github.com/facebook/react-native/pull/9012) - Some other change
#### Android
- [PR #3456](https://github.com/facebook/react-native/pull/3456) - Some other change
- [PR #3457](https://github.com/facebook/react-native/pull/3457) - Some other change
#### iOS
- [PR #3436](https://github.com/facebook/react-native/pull/3436) - Some other change
- [PR #3437](https://github.com/facebook/react-native/pull/3437) - Some other change
### Fixed
- [PR #9012](https://github.com/facebook/react-native/pull/9012) - Some other change
#### Android
- [PR #3456](https://github.com/facebook/react-native/pull/3456) - Some other change
#### iOS
- [PR #3437](https://github.com/facebook/react-native/pull/3437) - Some other change
## v0.77.0
- [PR #3456](https://github.com/facebook/react-native/pull/3456) - Some other change
## v0.76.0
- [PR #7890](https://github.com/facebook/react-native/pull/7890) - Some other change`;
jest.spyOn(fs, 'readFileSync').mockImplementationOnce(func => {
return mockedReturnValue;
});
const changelog = _extractChangelog('0.77.1');
expect(changelog).toEqual(`## v0.77.1
### Breaking Changes
- [PR #9012](https://github.com/facebook/react-native/pull/9012) - Some other change
#### Android
- [PR #3456](https://github.com/facebook/react-native/pull/3456) - Some other change
- [PR #3457](https://github.com/facebook/react-native/pull/3457) - Some other change
#### iOS
- [PR #3436](https://github.com/facebook/react-native/pull/3436) - Some other change
- [PR #3437](https://github.com/facebook/react-native/pull/3437) - Some other change
### Fixed
- [PR #9012](https://github.com/facebook/react-native/pull/9012) - Some other change
#### Android
- [PR #3456](https://github.com/facebook/react-native/pull/3456) - Some other change
#### iOS
- [PR #3437](https://github.com/facebook/react-native/pull/3437) - Some other change`);
});
it('does not extract changelog for rc.0', async () => {
const changelog = _extractChangelog('0.77.0-rc.0');
expect(changelog).toEqual('');
});
it('does not extract changelog for 0.X.0', async () => {
const changelog = _extractChangelog('0.77.0');
expect(changelog).toEqual('');
});
});
describe('#_computeBody', () => {
it('computes body for release', async () => {
const version = '0.77.1';
const changelog = `## v${version}
### Breaking Changes
- [PR #9012](https://github.com/facebook/react-native/pull/9012) - Some other change
#### Android
- [PR #3456](https://github.com/facebook/react-native/pull/3456) - Some other change
- [PR #3457](https://github.com/facebook/react-native/pull/3457) - Some other change
#### iOS
- [PR #3436](https://github.com/facebook/react-native/pull/3436) - Some other change
- [PR #3437](https://github.com/facebook/react-native/pull/3437) - Some other change`;
const body = _computeBody(version, changelog);
expect(body).toEqual(`${changelog}
---
Hermes dSYMS:
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-hermes-framework-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-hermes-framework-dSYM-release.tar.gz)
ReactNativeDependencies dSYMs:
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-dependencies-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-dependencies-dSYM-release.tar.gz)
---
You can file issues or pick requests against this release [here](https://github.com/reactwg/react-native-releases/issues/new/choose).
---
To help you upgrade to this version, you can use the [Upgrade Helper](https://react-native-community.github.io/upgrade-helper/) ⚛️.
---
View the whole changelog in the [CHANGELOG.md file](https://github.com/facebook/react-native/blob/main/CHANGELOG.md).`);
});
});
describe('#_createDraftReleaseOnGitHub', () => {
it('creates a draft release on GitHub', async () => {
const version = '0.77.1';
const url = 'https://api.github.com/repos/facebook/react-native/releases';
const token = 'token';
const headers = {
Accept: 'Accept: application/vnd.github+json',
'X-GitHub-Api-Version': '2022-11-28',
Authorization: `Bearer ${token}`,
};
const body = `Draft release body`;
const latest = true;
const fetchBody = JSON.stringify({
tag_name: `v${version}`,
name: `${version}`,
body: body,
draft: true,
prerelease: false,
make_latest: `${latest}`,
});
mockFetch.mockReturnValueOnce(
Promise.resolve({
status: 201,
json: () =>
Promise.resolve({
html_url:
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
}),
}),
);
const response = await _createDraftReleaseOnGitHub(
version,
body,
latest,
token,
);
expect(mockFetch).toHaveBeenCalledTimes(1);
expect(mockFetch).toHaveBeenCalledWith(
`https://api.github.com/repos/facebook/react-native/releases`,
{
method: 'POST',
headers: headers,
body: fetchBody,
},
);
expect(response).toEqual(
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
);
});
it('creates a draft release for prerelease on GitHub', async () => {
const version = '0.77.0-rc.2';
const url = 'https://api.github.com/repos/facebook/react-native/releases';
const token = 'token';
const headers = {
Accept: 'Accept: application/vnd.github+json',
'X-GitHub-Api-Version': '2022-11-28',
Authorization: `Bearer ${token}`,
};
const body = `Draft release body`;
const latest = true;
const fetchBody = JSON.stringify({
tag_name: `v${version}`,
name: `${version}`,
body: body,
draft: true,
prerelease: true,
make_latest: `${latest}`,
});
mockFetch.mockReturnValueOnce(
Promise.resolve({
status: 201,
json: () =>
Promise.resolve({
html_url:
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
}),
}),
);
const response = await _createDraftReleaseOnGitHub(
version,
body,
latest,
token,
);
expect(mockFetch).toHaveBeenCalledTimes(1);
expect(mockFetch).toHaveBeenCalledWith(
`https://api.github.com/repos/facebook/react-native/releases`,
{
method: 'POST',
headers: headers,
body: fetchBody,
},
);
expect(response).toEqual(
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
);
});
it('throws if the post failes', async () => {
const version = '0.77.0-rc.2';
const url = 'https://api.github.com/repos/facebook/react-native/releases';
const token = 'token';
const headers = {
Accept: 'Accept: application/vnd.github+json',
'X-GitHub-Api-Version': '2022-11-28',
Authorization: `Bearer ${token}`,
};
const body = `Draft release body`;
const latest = true;
const fetchBody = JSON.stringify({
tag_name: `v${version}`,
name: `${version}`,
body: body,
draft: true,
prerelease: true,
make_latest: `${latest}`,
});
mockFetch.mockReturnValueOnce(
Promise.resolve({
status: 401,
}),
);
await expect(
_createDraftReleaseOnGitHub(version, body, latest, token),
).rejects.toThrowError();
expect(mockFetch).toHaveBeenCalledTimes(1);
expect(mockFetch).toHaveBeenCalledWith(
`https://api.github.com/repos/facebook/react-native/releases`,
{
method: 'POST',
headers: headers,
body: fetchBody,
},
);
});
});
});
@@ -1,83 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
const {extractIssueOncalls} = require('../extractIssueOncalls');
const userMap = {
'@g': '1785',
'@c': '1781',
'@s': '1272',
'@d': '1332',
'@m': '9555',
'@p': '6097',
'@f': '7565',
};
const schedule = {
'2025-04-01': ['@m', '@f'],
'2025-04-08': ['@g', '@d'],
};
describe('extractIssueOncalls', () => {
beforeEach(() => {
jest.clearAllMocks();
jest.useFakeTimers('modern');
});
afterEach(() => {
jest.useRealTimers();
});
it('extracts m and f on 6 of April', () => {
jest.setSystemTime(new Date(2025, 3, 6));
const oncalls = extractIssueOncalls(schedule, userMap);
expect(oncalls).toEqual([userMap['@m'], userMap['@f']]);
});
it('extracts m and f on 7 of April', () => {
jest.setSystemTime(new Date(2025, 3, 7));
const oncalls = extractIssueOncalls(schedule, userMap);
expect(oncalls).toEqual([userMap['@m'], userMap['@f']]);
});
it('extracts g and d on 8 of April', () => {
jest.setSystemTime(new Date(2025, 3, 8));
const oncalls = extractIssueOncalls(schedule, userMap);
expect(oncalls).toEqual([userMap['@g'], userMap['@d']]);
});
it('extracts g and d on 9 of April', () => {
jest.setSystemTime(new Date(2025, 3, 9));
const oncalls = extractIssueOncalls(schedule, userMap);
expect(oncalls).toEqual([userMap['@g'], userMap['@d']]);
});
it('extracts g and d on 10 of April', () => {
jest.setSystemTime(new Date(2025, 3, 10));
const oncalls = extractIssueOncalls(schedule, userMap);
expect(oncalls).toEqual([userMap['@g'], userMap['@d']]);
});
it('extracts g and d on 11 of April', () => {
jest.setSystemTime(new Date(2025, 3, 11));
const oncalls = extractIssueOncalls(schedule, userMap);
expect(oncalls).toEqual([userMap['@g'], userMap['@d']]);
});
it('extracts g and d on 12 of April', () => {
jest.setSystemTime(new Date(2025, 3, 12));
const oncalls = extractIssueOncalls(schedule, userMap);
expect(oncalls).toEqual([userMap['@g'], userMap['@d']]);
});
it('extracts g and d on 13 of April', () => {
jest.setSystemTime(new Date(2025, 3, 13));
const oncalls = extractIssueOncalls(schedule, userMap);
expect(oncalls).toEqual([userMap['@g'], userMap['@d']]);
});
});
@@ -1,251 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
const {
generateChangelog,
_computePreviousVersionFrom,
_generateChangelog,
_pushCommit,
_createPR,
} = require('../generateChangelog');
const silence = () => {};
const mockGetNpmPackageInfo = jest.fn();
const mockExecSync = jest.fn();
const mockRun = jest.fn();
const mockFetch = jest.fn();
const mockExit = jest.fn();
jest.mock('../utils.js', () => ({
log: silence,
run: mockRun,
getNpmPackageInfo: mockGetNpmPackageInfo,
}));
process.exit = mockExit;
global.fetch = mockFetch;
describe('Generate Changelog', () => {
beforeEach(jest.clearAllMocks);
describe('_computePreviousVersionFrom', () => {
it('returns rc.0 when rc is 1', async () => {
const currentVersion = '0.78.0-rc.1';
const expectedVersion = '0.78.0-rc.0';
const receivedVersion = await _computePreviousVersionFrom(currentVersion);
expect(receivedVersion).toEqual(expectedVersion);
});
it('returns previous rc version when rc is > 1', async () => {
const currentVersion = '0.78.0-rc.5';
const expectedVersion = '0.78.0-rc.4';
const receivedVersion = await _computePreviousVersionFrom(currentVersion);
expect(receivedVersion).toEqual(expectedVersion);
});
it('returns previous patch version when rc is 0', async () => {
const currentVersion = '0.78.0-rc.0';
const expectedVersion = '0.77.1';
mockGetNpmPackageInfo.mockReturnValueOnce(
Promise.resolve({version: '0.77.1'}),
);
const receivedVersion = await _computePreviousVersionFrom(currentVersion);
expect(receivedVersion).toEqual(expectedVersion);
});
it('returns patch 0 when patch is 1', async () => {
const currentVersion = '0.78.1';
const expectedVersion = '0.78.0';
const receivedVersion = await _computePreviousVersionFrom(currentVersion);
expect(receivedVersion).toEqual(expectedVersion);
});
it('returns previous patch when patch is > 1', async () => {
const currentVersion = '0.78.5';
const expectedVersion = '0.78.4';
const receivedVersion = await _computePreviousVersionFrom(currentVersion);
expect(receivedVersion).toEqual(expectedVersion);
});
it('returns null when patch is 0', async () => {
const currentVersion = '0.78.0';
const receivedVersion = await _computePreviousVersionFrom(currentVersion);
expect(receivedVersion).toBeNull();
});
it("throws an error when the version can't be parsed", async () => {
const currentVersion = '0.78.0-rc0';
await expect(
_computePreviousVersionFrom(currentVersion),
).rejects.toThrow();
});
});
describe('_generateChangelog', () => {
it('calls git in the right order', async () => {
const currentVersion = '0.79.0-rc5';
const previousVersion = '0.79.0-rc4';
const token = 'token';
expectedCommandArgs = [
'@rnx-kit/rn-changelog-generator',
'--base',
`v${previousVersion}`,
'--compare',
`v${currentVersion}`,
'--repo',
'.',
'--changelog',
'./CHANGELOG.md',
'--token',
`${token}`,
];
_generateChangelog(previousVersion, currentVersion, token);
expect(mockRun).toHaveBeenCalledTimes(4);
expect(mockRun).toHaveBeenNthCalledWith(1, 'git checkout main');
expect(mockRun).toHaveBeenNthCalledWith(2, 'git fetch');
expect(mockRun).toHaveBeenNthCalledWith(3, 'git pull origin main');
expect(mockRun).toHaveBeenNthCalledWith(
4,
`npx ${expectedCommandArgs.join(' ')}`,
);
});
});
describe('_pushCommit', () => {
it('calls git in the right order', async () => {
const currentVersion = '0.79.0-rc5';
_pushCommit(currentVersion);
expect(mockRun).toHaveBeenCalledTimes(4);
expect(mockRun).toHaveBeenNthCalledWith(
1,
`git checkout -b changelog/v${currentVersion}`,
);
expect(mockRun).toHaveBeenNthCalledWith(2, 'git add CHANGELOG.md');
expect(mockRun).toHaveBeenNthCalledWith(
3,
`git commit -m "[RN][Changelog] Add changelog for v${currentVersion}"`,
);
expect(mockRun).toHaveBeenNthCalledWith(
4,
`git push origin changelog/v${currentVersion}`,
);
});
});
describe('_createPR', () => {
it('throws error when status is not 201', async () => {
const currentVersion = '0.79.0-rc5';
const token = 'token';
mockFetch.mockReturnValueOnce(Promise.resolve({status: 401}));
const headers = {
Accept: 'Accept: application/vnd.github+json',
'X-GitHub-Api-Version': '2022-11-28',
Authorization: `Bearer ${token}`,
};
const content = `
## Summary
Add Changelog for ${currentVersion}
## Changelog:
[Internal] - Add Changelog for ${currentVersion}
## Test Plan:
N/A`;
const body = {
title: `[RN][Changelog] Add changelog for v${currentVersion}`,
head: `changelog/v${currentVersion}`,
base: 'main',
body: content,
};
await expect(_createPR(currentVersion, token)).rejects.toThrow();
expect(mockFetch).toHaveBeenCalledTimes(1);
expect(mockFetch).toHaveBeenCalledWith(
'https://api.github.com/repos/facebook/react-native/pulls',
{
method: 'POST',
headers: headers,
body: JSON.stringify(body),
},
);
});
it('Returns the pr url', async () => {
const currentVersion = '0.79.0-rc5';
const token = 'token';
const expectedPrURL =
'https://github.com/facebook/react-native/pulls/1234';
const returnedObject = {
status: 201,
json: () => Promise.resolve({html_url: expectedPrURL}),
};
mockFetch.mockReturnValueOnce(Promise.resolve(returnedObject));
const headers = {
Accept: 'Accept: application/vnd.github+json',
'X-GitHub-Api-Version': '2022-11-28',
Authorization: `Bearer ${token}`,
};
const content = `
## Summary
Add Changelog for ${currentVersion}
## Changelog:
[Internal] - Add Changelog for ${currentVersion}
## Test Plan:
N/A`;
const body = {
title: `[RN][Changelog] Add changelog for v${currentVersion}`,
head: `changelog/v${currentVersion}`,
base: 'main',
body: content,
};
const receivedPrURL = await _createPR(currentVersion, token);
expect(mockFetch).toHaveBeenCalledTimes(1);
expect(mockFetch).toHaveBeenCalledWith(
'https://api.github.com/repos/facebook/react-native/pulls',
{
method: 'POST',
headers: headers,
body: JSON.stringify(body),
},
);
expect(receivedPrURL).toEqual(expectedPrURL);
});
});
});
@@ -1,189 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
'use strict';
const {
prepareFailurePayload,
sendMessageToDiscord,
} = require('../notifyDiscord');
describe('prepareFailurePayload', () => {
it('should handle undefined failures', () => {
const message = prepareFailurePayload(undefined);
expect(message).toEqual({
content:
'⚠️ **React Native Nightly Integration Failures** ⚠️\n\nNo failures to report.',
});
});
it('should handle empty failures array', () => {
const message = prepareFailurePayload([]);
expect(message).toEqual({
content:
'⚠️ **React Native Nightly Integration Failures** ⚠️\n\nNo failures to report.',
});
});
it('should format a single failure correctly', () => {
const failures = [
{
library: 'react-native-reanimated',
platform: 'iOS',
},
];
const message = prepareFailurePayload(failures);
expect(message).toEqual({
content:
'⚠️ **React Native Nightly Integration Failures** ⚠️\n\nThe integration of libraries with React Native nightly failed for the following libraries:\n\n❌ [iOS] react-native-reanimated',
});
});
it('should sort multiple failures by platform and library name', () => {
const failures = [
{
library: 'react-native-reanimated',
platform: 'iOS',
},
{
library: 'react-native-gesture-handler',
platform: 'Android',
},
{
library: 'react-native-screens',
platform: 'iOS',
},
{
library: 'react-native-svg',
platform: 'Android',
},
];
const message = prepareFailurePayload(failures);
// The failures should be sorted: first Android (alphabetically), then iOS
// Within each platform, libraries should be sorted alphabetically
expect(message).toEqual({
content:
'⚠️ **React Native Nightly Integration Failures** ⚠️\n\nThe integration of libraries with React Native nightly failed for the following libraries:\n\n❌ [Android] react-native-gesture-handler\n❌ [Android] react-native-svg\n❌ [iOS] react-native-reanimated\n❌ [iOS] react-native-screens',
});
});
it('should handle failures with missing properties', () => {
const failures = [
{
// Missing library
platform: 'iOS',
},
{
library: 'react-native-gesture-handler',
// Missing platform
},
{
// Both missing
},
];
const message = prepareFailurePayload(failures);
expect(message).toEqual({
content:
'⚠️ **React Native Nightly Integration Failures** ⚠️\n\nThe integration of libraries with React Native nightly failed for the following libraries:\n\n❌ [iOS] Unknown\n❌ [Unknown] react-native-gesture-handler\n❌ [Unknown] Unknown',
});
});
});
describe('sendMessageToDiscord', () => {
// Store the original fetch function
const originalFetch = global.fetch;
// Setup and teardown for each test
beforeEach(() => {
// Mock the global fetch function
global.fetch = jest.fn();
// Silence console logs during tests
jest.spyOn(console, 'log').mockImplementation(() => {});
jest.spyOn(console, 'error').mockImplementation(() => {});
});
afterEach(() => {
// Restore the original fetch function
global.fetch = originalFetch;
// Restore console functions
jest.restoreAllMocks();
});
it('should throw an error if webhook URL is missing', async () => {
await expect(sendMessageToDiscord(null, {})).rejects.toThrow(
'Discord webhook URL is missing',
);
});
it('should send a message successfully', async () => {
// Mock a successful response
global.fetch.mockResolvedValueOnce({
ok: true,
status: 200,
});
const webhook = 'https://discord.com/api/webhooks/123/abc';
const message = {content: 'Test message'};
await expect(sendMessageToDiscord(webhook, message)).resolves.not.toThrow();
// Verify fetch was called with the right arguments
expect(global.fetch).toHaveBeenCalledWith(webhook, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(message),
});
// Verify console.log was called
expect(console.log).toHaveBeenCalledWith(
'Successfully sent message to Discord',
);
});
it('should throw an error if the response is not ok', async () => {
// Mock a failed response
global.fetch.mockResolvedValueOnce({
ok: false,
status: 400,
text: jest.fn().mockResolvedValueOnce('Bad Request'),
});
const webhook = 'https://discord.com/api/webhooks/123/abc';
const message = {content: 'Test message'};
await expect(sendMessageToDiscord(webhook, message)).rejects.toThrow(
'HTTP status code: 400',
);
// Verify console.error was called
expect(console.error).toHaveBeenCalledWith(
'Failed to send message to Discord: 400 Bad Request',
);
});
it('should throw an error if fetch fails', async () => {
// Mock a network error
const networkError = new Error('Network error');
global.fetch.mockRejectedValueOnce(networkError);
const webhook = 'https://discord.com/api/webhooks/123/abc';
const message = {content: 'Test message'};
await expect(sendMessageToDiscord(webhook, message)).rejects.toThrow(
'Network error',
);
});
});
@@ -1,129 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
const {
publishTemplate,
verifyPublishedTemplate,
} = require('../publishTemplate');
const mockRun = jest.fn();
const mockSleep = jest.fn();
const mockGetNpmPackageInfo = jest.fn();
const mockVerifyPublishedPackage = jest.fn();
const silence = () => {};
jest.mock('../utils.js', () => ({
log: silence,
run: mockRun,
sleep: mockSleep,
getNpmPackageInfo: mockGetNpmPackageInfo,
}));
jest.mock('../verifyPublishedPackage.js', () => ({
verifyPublishedPackage: mockVerifyPublishedPackage,
}));
const getMockGithub = () => ({
rest: {
actions: {
createWorkflowDispatch: jest.fn(),
},
},
});
describe('#publishTemplate', () => {
beforeEach(jest.clearAllMocks);
it('checks commits for magic #publish-package-to-npm&latest string and sets latest', async () => {
mockRun.mockReturnValueOnce(`
The commit message
#publish-packages-to-npm&latest`);
const github = getMockGithub();
await publishTemplate(github, '0.76.0', true);
expect(github.rest.actions.createWorkflowDispatch).toHaveBeenCalledWith({
owner: 'react-native-community',
repo: 'template',
workflow_id: 'release.yaml',
ref: '0.76-stable',
inputs: {
dry_run: true,
is_latest_on_npm: true,
version: '0.76.0',
},
});
});
it('pubished as is_latest_on_npm = false if missing magic string', async () => {
mockRun.mockReturnValueOnce(`
The commit message without magic
`);
const github = getMockGithub();
await publishTemplate(github, '0.76.0', false);
expect(github.rest.actions.createWorkflowDispatch).toHaveBeenCalledWith({
owner: 'react-native-community',
repo: 'template',
workflow_id: 'release.yaml',
ref: '0.76-stable',
inputs: {
dry_run: false,
is_latest_on_npm: false,
version: '0.76.0',
},
});
});
});
describe('#verifyPublishedTemplate', () => {
beforeEach(jest.clearAllMocks);
it("waits on npm updating for version and not 'latest'", async () => {
const NOT_LATEST = false;
const version = '0.77.0';
await verifyPublishedTemplate(version, NOT_LATEST);
expect(mockVerifyPublishedPackage).toHaveBeenCalledWith(
'@react-native-community/template',
version,
null,
18,
);
});
it('waits on npm updating version and latest tag', async () => {
const IS_LATEST = true;
const version = '0.77.0';
await verifyPublishedTemplate(version, IS_LATEST);
expect(mockVerifyPublishedPackage).toHaveBeenCalledWith(
'@react-native-community/template',
version,
'latest',
18,
);
});
describe('retries', () => {
it('will timeout if npm does not update package version after a set number of retries', async () => {
const RETRIES = 2;
await verifyPublishedTemplate('0.77.0', true, RETRIES),
expect(mockVerifyPublishedPackage).toHaveBeenCalledWith(
'@react-native-community/template',
'0.77.0',
'latest',
2,
);
});
});
});
@@ -1,87 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
const {verifyArtifactsAreOnMaven} = require('../verifyArtifactsAreOnMaven');
const mockSleep = jest.fn();
const silence = () => {};
const mockFetch = jest.fn();
const mockExit = jest.fn();
jest.mock('../utils.js', () => ({
log: silence,
sleep: mockSleep,
}));
process.exit = mockExit;
global.fetch = mockFetch;
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!');
});
mockFetch
.mockReturnValueOnce(Promise.resolve({status: 404}))
.mockReturnValueOnce(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',
);
});
it('waits for the packages to be published on maven, when version starts with v', async () => {
mockSleep.mockReturnValueOnce(Promise.resolve()).mockImplementation(() => {
throw new Error('Should not be called again!');
});
mockFetch
.mockReturnValueOnce(Promise.resolve({status: 404}))
.mockReturnValueOnce(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',
);
});
it('passes immediately if packages are already on Maven', async () => {
mockFetch.mockReturnValueOnce(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',
);
});
it('tries 90 times and then exits', async () => {
mockSleep.mockReturnValue(Promise.resolve());
mockFetch.mockReturnValue(Promise.resolve({status: 404}));
const version = '0.78.1';
await verifyArtifactsAreOnMaven(version);
expect(mockSleep).toHaveBeenCalledTimes(90);
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',
);
});
});
@@ -1,135 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
const {verifyPublishedPackage} = require('../verifyPublishedPackage');
const mockRun = jest.fn();
const mockSleep = jest.fn();
const mockGetNpmPackageInfo = jest.fn();
const silence = () => {};
const REACT_NATIVE_PACKAGE = 'react-native';
jest.mock('../utils.js', () => ({
log: silence,
run: mockRun,
sleep: mockSleep,
getNpmPackageInfo: mockGetNpmPackageInfo,
}));
describe('#verifyPublishedPackage', () => {
beforeEach(jest.clearAllMocks);
it("waits on npm updating for version and not 'latest'", async () => {
mockGetNpmPackageInfo
// template@<version>
.mockReturnValueOnce(Promise.reject('mock http/404'))
.mockReturnValueOnce(Promise.resolve());
mockSleep.mockReturnValueOnce(Promise.resolve()).mockImplementation(() => {
throw new Error('Should not be called again!');
});
const version = '0.78.0';
await verifyPublishedPackage(REACT_NATIVE_PACKAGE, version, null);
expect(mockGetNpmPackageInfo).toHaveBeenLastCalledWith(
REACT_NATIVE_PACKAGE,
version,
);
});
it('waits on npm updating version and latest tag', async () => {
const version = '0.78.0';
mockGetNpmPackageInfo
// template@latest → unknown tag
.mockReturnValueOnce(Promise.reject('mock http/404'))
// template@latest != version → old tag
.mockReturnValueOnce(Promise.resolve({version: '0.76.5'}))
// template@latest == version → correct tag
.mockReturnValueOnce(Promise.resolve({version}));
mockSleep
.mockReturnValueOnce(Promise.resolve())
.mockReturnValueOnce(Promise.resolve())
.mockImplementation(() => {
throw new Error('Should not be called again!');
});
await verifyPublishedPackage(REACT_NATIVE_PACKAGE, version, 'latest');
expect(mockGetNpmPackageInfo).toHaveBeenCalledWith(
REACT_NATIVE_PACKAGE,
'latest',
);
});
it('waits on npm updating version and next tag', async () => {
const version = '0.78.0-rc.0';
mockGetNpmPackageInfo
// template@latest → unknown tag
.mockReturnValueOnce(Promise.reject('mock http/404'))
// template@latest != version → old tag
.mockReturnValueOnce(Promise.resolve({version: '0.76.5'}))
// template@latest == version → correct tag
.mockReturnValueOnce(Promise.resolve({version}));
mockSleep
.mockReturnValueOnce(Promise.resolve())
.mockReturnValueOnce(Promise.resolve())
.mockImplementation(() => {
throw new Error('Should not be called again!');
});
await verifyPublishedPackage(REACT_NATIVE_PACKAGE, version, 'next');
expect(mockGetNpmPackageInfo).toHaveBeenCalledWith(
REACT_NATIVE_PACKAGE,
'next',
);
});
describe('timeouts', () => {
let mockProcess;
beforeEach(() => {
mockProcess = jest.spyOn(process, 'exit').mockImplementation(code => {
throw new Error(`process.exit(${code}) called!`);
});
});
afterEach(() => mockProcess.mockRestore());
it('will timeout if npm does not update package version after a set number of retries', async () => {
const RETRIES = 2;
mockGetNpmPackageInfo.mockReturnValue(Promise.reject('mock http/404'));
mockSleep.mockReturnValue(Promise.resolve());
await expect(() =>
verifyPublishedPackage(
REACT_NATIVE_PACKAGE,
'0.77.0',
'latest',
RETRIES,
),
).rejects.toThrowError('process.exit(1) called!');
expect(mockGetNpmPackageInfo).toHaveBeenCalledTimes(RETRIES);
});
it('will timeout if npm does not update latest tag after a set number of retries', async () => {
const RETRIES = 7;
const IS_LATEST = true;
mockGetNpmPackageInfo.mockReturnValue(
Promise.resolve({version: '0.76.5'}),
);
mockSleep.mockReturnValue(Promise.resolve());
await expect(async () => {
await verifyPublishedPackage(
REACT_NATIVE_PACKAGE,
'0.77.0',
'latest',
RETRIES,
);
}).rejects.toThrowError('process.exit(1) called!');
expect(mockGetNpmPackageInfo).toHaveBeenCalledTimes(RETRIES);
});
});
});
@@ -1,109 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
const {verifyReleaseOnNpm} = require('../verifyReleaseOnNpm');
const mockVerifyPublishedPackage = jest.fn();
const silence = () => {};
jest.mock('../utils.js', () => ({
log: silence,
sleep: silence,
}));
jest.mock('../verifyPublishedPackage.js', () => ({
verifyPublishedPackage: mockVerifyPublishedPackage,
}));
describe('#verifyReleaseOnNPM', () => {
beforeEach(jest.clearAllMocks);
it("waits on npm updating for version and not 'latest'", async () => {
const NOT_LATEST = false;
const version = '0.78.0';
await verifyReleaseOnNpm(version, NOT_LATEST);
expect(mockVerifyPublishedPackage).toHaveBeenLastCalledWith(
'react-native',
version,
null,
18,
);
});
it('waits on npm updating version and latest tag', async () => {
const IS_LATEST = true;
const version = '0.78.0';
await verifyReleaseOnNpm(version, IS_LATEST);
expect(mockVerifyPublishedPackage).toHaveBeenCalledWith(
'react-native',
version,
'latest',
18,
);
});
it('waits on npm updating version, not latest and next tag', async () => {
const IS_LATEST = false;
const version = '0.78.0-rc.0';
await verifyReleaseOnNpm(version, IS_LATEST);
expect(mockVerifyPublishedPackage).toHaveBeenCalledWith(
'react-native',
version,
'next',
18,
);
});
it('waits on npm updating version, latest and next tag', async () => {
const IS_LATEST = true;
const version = '0.78.0-rc.0';
await verifyReleaseOnNpm(version, IS_LATEST);
expect(mockVerifyPublishedPackage).toHaveBeenCalledWith(
'react-native',
version,
'next',
18,
);
});
describe('timeouts', () => {
it('will timeout if npm does not update package version after a set number of retries', async () => {
const RETRIES = 2;
await verifyReleaseOnNpm('0.77.0', true, RETRIES),
expect(mockVerifyPublishedPackage).toHaveBeenCalledWith(
'react-native',
'0.77.0',
'latest',
2,
);
});
it('will timeout if npm does not update latest tag after a set number of retries', async () => {
const RETRIES = 7;
const IS_LATEST = true;
await verifyReleaseOnNpm('0.77.0', IS_LATEST, RETRIES);
expect(mockVerifyPublishedPackage).toHaveBeenCalledWith(
'react-native',
'0.77.0',
'latest',
7,
);
});
});
});
+45 -27
View File
@@ -48,78 +48,96 @@ module.exports = async (github, context, labelWithContext) => {
switch (labelWithContext.label) {
case 'Type: Invalid':
await addComment(
`> [!CAUTION]\n` +
`> **Invalid issue**: This issue is not valid, either is not a bug in React Native, it doesn't match any of the issue template, or we can't help further with this.`,
`| :warning: | Issue is Invalid |\n` +
`| --- | --- |\n` +
`| :information_source: | This issue doesn't match any of the expected types for this repository - closing. |`,
);
await closeIssue();
return;
case 'Type: Question':
await addComment(
`> [!NOTE]\n` +
`> **Not a bug report**: This issue looks like a question. We are using GitHub issues exclusively to track bugs in React Native. GitHub may not be the ideal place to ask a question, but you can try asking over on [Stack Overflow](http://stackoverflow.com/questions/tagged/react-native), or on [Reactiflux](https://www.reactiflux.com/).`,
);
await closeIssue();
return;
case 'Resolution: For Stack Overflow':
await addComment(
`> [!NOTE]\n` +
`> **Not a bug report**: This issue looks like a question. We are using GitHub issues exclusively to track bugs in React Native. GitHub may not be the ideal place to ask a question, but you can try asking over on [Stack Overflow](http://stackoverflow.com/questions/tagged/react-native), or on [Reactiflux](https://www.reactiflux.com/).`,
`| :warning: | Issue is a Question |\n` +
`| --- | --- |\n` +
`| :information_source: | We are using GitHub issues exclusively to track bugs in React Native. GitHub may not be the ideal place to ask a question, but you can try asking over on [Stack Overflow](http://stackoverflow.com/questions/tagged/react-native), or on [Reactiflux](https://www.reactiflux.com/). |`,
);
await closeIssue();
return;
case 'Type: Docs':
await addComment(
`> [!NOTE]\n` +
`> **Docs issue**: This issue looks like an issue related to our docs. Please report documentation issues in the [react-native-website](https://github.com/facebook/react-native-website/issues) repository.`,
`| :warning: | Documentation Issue |\n` +
`| --- | --- |\n` +
`| :information_source: | Please report documentation issues in the [react-native-website](https://github.com/facebook/react-native-website/issues) repository. |`,
);
await closeIssue();
return;
case 'Resolution: For Stack Overflow':
await addComment(
`| :warning: | Issue is a Question |\n` +
`| --- | --- |\n` +
`| :information_source: | We are using GitHub issues exclusively to track bugs in the core React Native library. Please try asking over on [Stack Overflow](http://stackoverflow.com/questions/tagged/react-native) as it is better suited for this type of question. |`,
);
await closeIssue();
return;
case 'Type: Expo':
await addComment(
`> [!NOTE]\n` +
`> **Expo related**: It looks like your issue is related to Expo and not React Native core. Please open your issue in [Expo's repository](https://github.com/expo/expo/issues/new). If you are able to create a repro that showcases that this issue is also happening in React Native vanilla, we will be happy to re-open.`,
`| :warning: | Issue is Related to Expo |\n` +
`| --- | --- |\n` +
`| :information_source: | It looks like your issue is related to Expo and not React Native core. Please open your issue in [Expo's repository](https://github.com/expo/expo/issues/new). If you are able to create a repro that showcases that this issue is also happening in React Native vanilla, we will be happy to re-open. |`,
);
await closeIssue();
return;
case 'Needs: Issue Template':
await addComment(
`> [!WARNING]\n` +
`> **Missing issue template**: It looks like your issue may be missing some necessary information. GitHub provides an example template whenever a [new issue is created](https://github.com/facebook/react-native/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A&projects=&template=bug_report.yml). Could you go back and make sure to fill out the template? You may edit this issue, or close it and open a new one.`,
`| :warning: | Missing Required Fields |\n` +
`| --- | --- |\n` +
`| :information_source: | It looks like your issue may be missing some necessary information. GitHub provides an example template whenever a [new issue is created](https://github.com/facebook/react-native/issues/new?template=bug_report.md). Could you go back and make sure to fill out the template? You may edit this issue, or close it and open a new one. |`,
);
await requestAuthorFeedback();
return;
case 'Needs: Environment Info':
await addComment(
`> [!WARNING]\n` +
`> **Missing info**: It looks like your issue may be missing information about your development environment. You can obtain the missing information by running <code>react-native info</code> in a console.`,
`| :warning: | Missing Environment Information |\n` +
`| --- | --- |\n` +
`| :information_source: | Your issue may be missing information about your development environment. You can obtain the missing information by running <code>react-native info</code> in a console. |`,
);
await requestAuthorFeedback();
return;
case 'Newer Patch Available':
await addComment(
`| :warning: | Newer Version of React Native is Available! |\n` +
`| --- | --- |\n` +
`| :information_source: | You are on a supported minor version, but it looks like there's a newer patch available - ${labelWithContext.newestPatch}. Please [upgrade](https://reactnative.dev/docs/upgrading) to the highest patch for your minor or latest and verify if the issue persists (alternatively, create a new project and repro the issue in it). If it does not repro, please let us know so we can close out this issue. This helps us ensure we are looking at issues that still exist in the most recent releases. |`,
);
return;
case 'Needs: Version Info':
await addComment(
`> [!WARNING]\n` +
`> **Could not parse version**: We could not find or parse the version number of React Native in your issue report. Please use the template, and report your version including major, minor, and patch numbers - e.g. 0.76.2.`,
`| :warning: | Add or Reformat Version Info |\n` +
`| --- | --- |\n` +
`| :information_source: | We could not find or parse the version number of React Native in your issue report. Please use the template, and report your version including major, minor, and patch numbers - e.g. 0.70.2 |`,
);
await requestAuthorFeedback();
return;
case 'Needs: Repro':
await addComment(
`> [!WARNING]\n` +
`> **Missing reproducer**: We could not detect a reproducible example in your issue report. Reproducers are **mandatory** and we can accept only one of those as a valid reproducer: <br/><ul><li>For majority of bugs: send us a Pull Request with the [RNTesterPlayground.js](https://github.com/facebook/react-native/blob/main/packages/rn-tester/js/examples/Playground/RNTesterPlayground.js) edited to reproduce your bug.</li><li>If your bug is UI related: a [Snack](https://snack.expo.dev)</li><li> If your bug is build/upgrade related: a project using our [Reproducer Template](https://github.com/react-native-community/reproducer-react-native/generate)</li></ul><br/>You can read more about about it on our website: [How to report a bug](https://reactnative.dev/contributing/how-to-report-a-bug).`,
`| :warning: | Missing Reproducible Example |\n` +
`| --- | --- |\n` +
`| :information_source: | We could not detect a reproducible example in your issue report. Please provide either: <br /><ul><li>If your bug is UI related: a [Snack](https://snack.expo.dev)</li><li> If your bug is build/update related: use our [Reproducer Template](https://github.com/react-native-community/reproducer-react-native/generate)</li></ul> |`,
);
await requestAuthorFeedback();
return;
case 'Type: Unsupported Version':
await addComment(
`> [!WARNING]\n` +
`> **Unsupported version**: It looks like your issue or the example you provided uses an [unsupported version of React Native](https://github.com/reactwg/react-native-releases/blob/main/docs/support.md).<br/><br/>Due to the number of issues we receive, we're currently only accepting new issues against one of the supported versions. Please [upgrade](https://reactnative.dev/docs/upgrading) to latest and verify if the issue persists (alternatively, create a new project and repro the issue in it). If you cannot upgrade, please open your issue on [StackOverflow](https://stackoverflow.com/questions/tagged/react-native) to get further community support.`,
`| :warning: | Unsupported Version of React Native |\n` +
`| --- | --- |\n` +
`| :information_source: | It looks like your issue or the example you provided uses an [unsupported version of React Native](https://github.com/reactwg/react-native-releases/blob/main/README.md#releases-support-policy).<br/><br/>Due to the number of issues we receive, we're currently only accepting new issues against one of the supported versions. Please [upgrade](https://reactnative.dev/docs/upgrading) to latest and verify if the issue persists (alternatively, create a new project and repro the issue in it). If you cannot upgrade, please open your issue on [StackOverflow](https://stackoverflow.com/questions/tagged/react-native) to get further community support. |`,
);
await requestAuthorFeedback();
return;
case 'Type: Too Old Version':
await addComment(
`> [!CAUTION]\n` +
`> **Too old version**: It looks like your issue or the example you provided uses a [**Too Old Version of React Native**](https://github.com/reactwg/react-native-releases/blob/main/docs/support.md).<br/><br/>Due to the number of issues we receive, we're currently only accepting new issues against one of the supported versions. Please [upgrade](https://reactnative.dev/docs/upgrading) to latest and verify if the issue persists (alternatively, create a new project and repro the issue in it). If you cannot upgrade, please open your issue on [StackOverflow](https://stackoverflow.com/questions/tagged/react-native) to get further community support.`,
`| :warning: | Too Old Version of React Native |\n` +
`| --- | --- |\n` +
`| :information_source: | It looks like your issue or the example you provided uses a [**Too Old Version of React Native**](https://github.com/reactwg/react-native-releases/blob/main/README.md#releases-support-policy).<br/><br/>Due to the number of issues we receive, we're currently only accepting new issues against one of the supported versions. Please [upgrade](https://reactnative.dev/docs/upgrading) to latest and verify if the issue persists (alternatively, create a new project and repro the issue in it). If you cannot upgrade, please open your issue on [StackOverflow](https://stackoverflow.com/questions/tagged/react-native) to get further community support. |`,
);
await closeIssue();
return;
@@ -149,5 +149,6 @@ const topics = {
'react-native-cli': labelCli,
'react-native upgrade': labelCli,
'react-native link': labelCli,
'local-cli': labelCli,
regression: labelRegression,
};
-24
View File
@@ -1,24 +0,0 @@
#!/bin/bash
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
export GITHUB_OWNER=-facebook
export GITHUB_REPO=-react-native
{
echo eslint
npm run lint --silent -- --format=json
echo flow
npm run flow-check --silent --json
} | node private/react-native-bots/code-analysis-bot.js
STATUS=$?
if [ $STATUS == 0 ]; then
echo "Code analyzed successfully."
else
echo "Code analysis failed, error status $STATUS."
fi
exit $STATUS
@@ -1,25 +0,0 @@
#!/bin/bash
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
GITHUB_OWNER=-facebook
GITHUB_REPO=-react-native
export GITHUB_OWNER
export GITHUB_REPO
if [ -x "$(command -v shellcheck)" ]; then
IFS=$'\n'
find . \
-type f \
-not -path "*node_modules*" \
-not -path "*third-party*" \
-name '*.sh' \
-exec sh -c 'shellcheck "$1"' -- {} \;
else
echo 'shellcheck is not installed. See https://github.com/facebook/react-native/wiki/Development-Dependencies#shellcheck for instructions.'
exit 1
fi
+26 -7
View File
@@ -9,6 +9,11 @@
const NEEDS_REPRO_LABEL = 'Needs: Repro';
const NEEDS_AUTHOR_FEEDBACK_LABEL = 'Needs: Author Feedback';
const NEEDS_REPRO_HEADER = 'Missing Reproducible Example';
const NEEDS_REPRO_MESSAGE =
`| :warning: | Missing Reproducible Example |\n` +
`| --- | --- |\n` +
`| :information_source: | We could not detect a reproducible example in your issue report. Please provide either: <br /><ul><li>If your bug is UI related: a [Snack](https://snack.expo.dev)</li><li> If your bug is build/update related: use our [Reproducer Template](https://github.com/react-native-community/reproducer-react-native/generate). A reproducer needs to be in a GitHub repository under your username.</li></ul> |`;
const SKIP_ISSUES_OLDER_THAN = '2023-07-01T00:00:00Z';
module.exports = async (github, context) => {
@@ -20,6 +25,7 @@ module.exports = async (github, context) => {
const issue = await github.rest.issues.get(issueData);
const comments = await github.rest.issues.listComments(issueData);
const author = issue.data.user.login;
const issueDate = issue.data.created_at;
@@ -37,15 +43,14 @@ module.exports = async (github, context) => {
return;
}
const botComment = comments.data.find(comment =>
comment.body.includes(NEEDS_REPRO_HEADER),
);
const entities = [issue.data, ...comments.data];
// Look for Snack or a GH repo associated with the user that added an issue or comment
const hasValidReproducer = entities.some(entity => {
const hasPullRequestRepoLink = containsPattern(
entity.body,
`https?:\/\/github\.com\/facebook\/react-native\/pull\/\d+\/?`,
);
const hasExpoSnackLink = containsPattern(
entity.body,
`https?:\\/\\/snack\\.expo\\.dev\\/[^\\s)\\]]+`,
@@ -55,7 +60,7 @@ module.exports = async (github, context) => {
entity.body,
`https?:\\/\\/github\\.com\\/(${entity.user.login})\\/[^/]+\\/?\\s?`,
);
return hasPullRequestRepoLink || hasExpoSnackLink || hasGithubRepoLink;
return hasExpoSnackLink || hasGithubRepoLink;
});
if (hasValidReproducer) {
@@ -69,11 +74,25 @@ module.exports = async (github, context) => {
throw error;
}
}
if (!botComment) return;
await github.rest.issues.deleteComment({
...issueData,
comment_id: botComment.id,
});
} else {
await github.rest.issues.addLabels({
...issueData,
labels: [NEEDS_REPRO_LABEL, NEEDS_AUTHOR_FEEDBACK_LABEL],
});
if (botComment) return;
await github.rest.issues.createComment({
...issueData,
body: NEEDS_REPRO_MESSAGE,
});
}
};
@@ -82,7 +101,7 @@ function containsPattern(body, pattern) {
return body.search(regexp) !== -1;
}
// Prevents the bot from responding when maintainer has changed the 'Needs: Repro' label
// Prevents the bot from responding when maintainer has changed Needs: Repro the label
async function hasMaintainerChangedLabel(github, issueData, author) {
const timeline = await github.rest.issues.listEventsForTimeline(issueData);
@@ -1,121 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
const fs = require('fs');
const path = require('path');
const {
prepareFailurePayload,
sendMessageToDiscord,
} = require('./notifyDiscord');
function readOutcomes() {
const baseDir = '/tmp';
let outcomes = [];
fs.readdirSync(baseDir).forEach(file => {
const fullPath = path.join(baseDir, file);
if (fullPath.endsWith('outcome') && fs.statSync(fullPath).isDirectory) {
fs.readdirSync(fullPath).forEach(subFile => {
const subFullPath = path.join(fullPath, subFile);
if (subFullPath.endsWith('outcome')) {
const [library, status] = String(fs.readFileSync(subFullPath, 'utf8'))
.trim()
.split(':');
const platform = subFile.includes('android') ? 'Android' : 'iOS';
console.log(
`[${platform}] ${library} completed with status ${status}`,
);
outcomes.push({
library: library.trim(),
platform,
status: status.trim(),
});
}
});
} else if (fullPath.endsWith('outcome')) {
const [library, status] = String(fs.readFileSync(fullPath, 'utf8'))
.trim()
.split(':');
const platform = file.includes('android') ? 'Android' : 'iOS';
console.log(`[${platform}] ${library} completed with status ${status}`);
outcomes.push({
library: library.trim(),
platform,
status: status.trim(),
});
}
});
return outcomes;
}
function printFailures(outcomes) {
console.log('Printing failures...');
let failedLibraries = [];
outcomes.forEach(entry => {
if (entry.status !== 'success') {
console.log(
`❌ [${entry.platform}] ${entry.library} failed with status ${entry.status}`,
);
failedLibraries.push({
library: entry.library,
platform: entry.platform,
});
}
});
return failedLibraries;
}
/**
* Sends a message to Discord with the list of failures.
* @param {string} webHook - The Discord webhook URL
* @param {Array<Object>} failures - List of failures to report
* @returns {Promise<void>} - A promise that resolves when the message is sent
*/
async function notifyDiscord(webHook, failures) {
if (!webHook) {
console.error('Discord webhook URL is missing');
return;
}
if (!failures || failures.length === 0) {
console.log('No failures to report to Discord');
return;
}
try {
// Use the prepareFailurePayload function to format the message
const message = prepareFailurePayload(failures);
// Use the sendMessageToDiscord function to send the message
await sendMessageToDiscord(webHook, message);
} catch (error) {
console.error('Error in notifyDiscord function:', error);
throw error;
}
}
async function collectResults(discordWebHook) {
const outcomes = readOutcomes();
const failures = printFailures(outcomes);
if (failures.length > 0) {
if (discordWebHook) {
console.log('Sending to discord');
await notifyDiscord(discordWebHook, failures);
} else {
console.log('Web hook not set');
}
process.exit(1);
}
console.log('✅ All tests passed!');
}
module.exports = {
collectResults,
notifyDiscord,
};
@@ -1,137 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
const {log, run} = require('./utils');
const fs = require('fs');
function _headers(token) {
return {
Accept: 'Accept: application/vnd.github+json',
'X-GitHub-Api-Version': '2022-11-28',
Authorization: `Bearer ${token}`,
};
}
function _extractChangelog(version) {
if (version.endsWith('.0')) {
// for RC.0 and for the release of a new stable minor, the changelog is too long
// to be added in a release. The release body is usually something shorter.
// See for example the release for 0.76.0 or 0.77.0:
// 0.76: https://github.com/facebook/react-native/releases/tag/v0.76.0
// 0.77: https://github.com/facebook/react-native/releases/tag/v0.77.0
return '';
}
const changelog = String(fs.readFileSync('CHANGELOG.md', 'utf8')).split('\n');
const changelogStarts = changelog.indexOf(`## v${version}`);
let changelogEnds = changelogStarts;
// Scan the changelog to find the next version
for (var line = changelogStarts + 1; line < changelog.length; line++) {
if (changelog[line].startsWith('## ')) {
changelogEnds = line;
break;
}
}
return changelog.slice(changelogStarts, changelogEnds).join('\n').trim();
}
function _computeBody(version, changelog) {
return `${changelog}
---
Hermes dSYMS:
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-hermes-framework-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-hermes-framework-dSYM-release.tar.gz)
ReactNativeDependencies dSYMs:
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-dependencies-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-dependencies-dSYM-release.tar.gz)
---
You can file issues or pick requests against this release [here](https://github.com/reactwg/react-native-releases/issues/new/choose).
---
To help you upgrade to this version, you can use the [Upgrade Helper](https://react-native-community.github.io/upgrade-helper/) ⚛️.
---
View the whole changelog in the [CHANGELOG.md file](https://github.com/facebook/react-native/blob/main/CHANGELOG.md).`;
}
async function _verifyTagExists(version) {
const url = `https://github.com/facebook/react-native/releases/tag/v${version}`;
const response = await fetch(url);
if (response.status === 404) {
throw new Error(`Tag v${version} does not exist`);
}
}
async function _createDraftReleaseOnGitHub(version, body, latest, token) {
const url = 'https://api.github.com/repos/facebook/react-native/releases';
const method = 'POST';
const headers = _headers(token);
const fetchBody = JSON.stringify({
tag_name: `v${version}`,
name: `${version}`,
body: body,
draft: true, // NEVER CHANGE this value to false. If false, it will publish the release, and send a GH notification to all the subscribers.
prerelease: version.includes('-rc.') ? true : false,
make_latest: `${latest}`,
});
const response = await fetch(url, {
method,
headers,
body: fetchBody,
});
if (response.status !== 201) {
throw new Error(
`Failed to create the release: ${response.status} ${response.statusText}`,
);
}
const data = await response.json();
return data.html_url;
}
function moveToChangelogBranch(version) {
log(`Moving to changelog branch: changelog/v${version}`);
run(`git checkout -b changelog/v${version}`);
}
async function createDraftRelease(version, latest, token) {
if (version.startsWith('v')) {
version = version.substring(1);
}
_verifyTagExists(version);
moveToChangelogBranch(version);
const changelog = _extractChangelog(version);
const body = _computeBody(version, changelog);
const release = await _createDraftReleaseOnGitHub(
version,
body,
latest,
token,
);
log(`Created draft release: ${release}`);
}
module.exports = {
createDraftRelease,
// Exported for testing purposes
_verifyTagExists,
_extractChangelog,
_computeBody,
_createDraftReleaseOnGitHub,
};
@@ -1,61 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
const fs = require('fs');
const MSEC_IN_DAY = 1000 * 60 * 60 * 24;
function formatUsers(users) {
console.log(`${users[0]} ${users[1]}`.trim());
}
function extractUsersFromScheduleAndDate(schedule, userMap, date) {
const year = date.getFullYear();
const month = date.getMonth() + 1; // 0 is January, 1 is February
const day = date.getDate();
const dateStr = `${year}-${month < 10 ? `0${month}` : month}-${day < 10 ? `0${day}` : day}`;
const user1 = userMap[schedule[dateStr][0]];
const user2 = userMap[schedule[dateStr][1]];
return [user1, user2];
}
function main() {
const configuration = process.argv[2];
const {userMap, schedule} = JSON.parse(configuration);
extractIssueOncalls(schedule, userMap);
}
function extractIssueOncalls(schedule, userMap) {
const now = new Date();
const dayOfTheWeek = now.getDay(); // 0 is Sunday, 1 is Monday, etc.
let users;
if (dayOfTheWeek === 2) {
// exact match in the schedule
users = extractUsersFromScheduleAndDate(schedule, userMap, now);
} else if (dayOfTheWeek < 2) {
// sunday
// go to the tuesday of the last week
const lastWeekTuesday = new Date(now - (5 + dayOfTheWeek) * MSEC_IN_DAY);
users = extractUsersFromScheduleAndDate(schedule, userMap, lastWeekTuesday);
} else if (dayOfTheWeek > 1) {
// go to the previous tuesday
const thisWeekTuesday = new Date(now - (dayOfTheWeek - 2) * MSEC_IN_DAY);
users = extractUsersFromScheduleAndDate(schedule, userMap, thisWeekTuesday);
}
formatUsers(users);
return users;
}
if (require.main === module) {
void main();
}
module.exports = {
extractIssueOncalls,
};
@@ -1,120 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
const {log, getNpmPackageInfo, run} = require('./utils');
async function _computePreviousVersionFrom(version) {
log(`Computing previous version from: ${version}`);
const regex = /^0\.(\d+)\.(\d+)(-rc\.(\d+))?$/;
const match = version.match(regex);
if (!match) {
throw new Error(`Invalid version format: ${version}`);
}
const minor = match[1];
const patch = match[2];
const rc = match[4];
if (rc) {
if (Number(rc) > 0) {
return `0.${minor}.${patch}-rc.${Number(rc) - 1}`;
}
//fetch latest version on NPM
const latestPkg = await getNpmPackageInfo('react-native', 'latest');
return latestPkg.version;
} else {
if (Number(patch) === 0) {
// No need to generate the changelog for 0.X.0 as we already generated it from RCs
log(
`Skipping changelog generation for ${version} as we already have it from the RCs`,
);
return null;
}
return `0.${minor}.${Number(patch) - 1}`;
}
}
function _generateChangelog(previousVersion, version, token) {
log(`Generating changelog for ${version} from ${previousVersion}`);
run('git checkout main');
run('git fetch');
run('git pull origin main');
const generateChangelogComand = `npx @rnx-kit/rn-changelog-generator --base v${previousVersion} --compare v${version} --repo . --changelog ./CHANGELOG.md --token ${token}`;
run(generateChangelogComand);
}
function _pushCommit(version) {
log(`Pushing commit to changelog/v${version}`);
run(`git checkout -b changelog/v${version}`);
run('git add CHANGELOG.md');
run(`git commit -m "[RN][Changelog] Add changelog for v${version}"`);
run(`git push origin changelog/v${version}`);
}
async function _createPR(version, token) {
log('Creating changelog pr');
const url = 'https://api.github.com/repos/facebook/react-native/pulls';
const body = `
## Summary
Add Changelog for ${version}
## Changelog:
[Internal] - Add Changelog for ${version}
## Test Plan:
N/A`;
const response = await fetch(url, {
method: 'POST',
headers: {
Accept: 'Accept: application/vnd.github+json',
'X-GitHub-Api-Version': '2022-11-28',
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({
title: `[RN][Changelog] Add changelog for v${version}`,
head: `changelog/v${version}`,
base: 'main',
body: body,
}),
});
if (response.status !== 201) {
throw new Error(
`Failed to create PR: ${response.status} ${response.statusText}`,
);
}
const data = await response.json();
return data.html_url;
}
async function generateChangelog(version, token) {
if (version.startsWith('v')) {
version = version.substring(1);
}
const previousVersion = await _computePreviousVersionFrom(version);
if (previousVersion) {
log(`Previous version is ${previousVersion}`);
_generateChangelog(previousVersion, version, token);
_pushCommit(version);
const prURL = await _createPR(version, token);
log(`Created PR: ${prURL}`);
}
}
module.exports = {
generateChangelog,
// Exported only for testing purposes:
_computePreviousVersionFrom,
_generateChangelog,
_pushCommit,
_createPR,
};
-12
View File
@@ -1,12 +0,0 @@
#!/bin/bash
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
set -e
if git ls-files | grep -E '\.npmignore$'; then
echo "Error: Found unexpected .npmignore file(s). Please use package.json#files instead."
exit 1
fi
-152
View File
@@ -1,152 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
const childProcess = require('child_process');
const fs = require('fs');
const usage = `
=== Usage ===
node maestro-android.js <path to app> <app_id> <maestro_flow> <flavor> <working_directory>
@param {string} appPath - Path to the app APK
@param {string} appId - App ID that needs to be launched
@param {string} maestroFlow - Path to the maestro flow to be executed
@param {string} flavor - Flavor of the app to be launched. Can be 'release' or 'debug'
@param {string} workingDirectory - Working directory from where to run Metro
==============
`;
const args = process.argv.slice(2);
if (args.length !== 5) {
throw new Error(`Invalid number of arguments.\n${usage}`);
}
const APP_PATH = args[0];
const APP_ID = args[1];
const MAESTRO_FLOW = args[2];
const IS_DEBUG = args[3] === 'debug';
const WORKING_DIRECTORY = args[4];
const MAX_ATTEMPTS = 3;
async function executeFlowWithRetries(flow, currentAttempt) {
try {
console.info(`Executing flow: ${flow}`);
const timeout = 1000 * 60 * 10; // 10 minutes
childProcess.execSync(
`MAESTRO_DRIVER_STARTUP_TIMEOUT=120000 $HOME/.maestro/bin/maestro test ${flow} --format junit -e APP_ID=${APP_ID} --debug-output /tmp/MaestroLogs`,
{stdio: 'inherit', timeout},
);
} catch (err) {
if (currentAttempt < MAX_ATTEMPTS) {
console.info(`Retrying...`);
await executeFlowWithRetries(flow, currentAttempt + 1);
} else {
throw err;
}
}
}
async function executeFlowInFolder(flowFolder) {
const files = fs.readdirSync(flowFolder);
for (const file of files) {
const filePath = `${flowFolder}/${file}`;
if (fs.lstatSync(filePath).isDirectory()) {
await executeFlowInFolder(filePath);
} else {
await executeFlowWithRetries(filePath, 0);
}
}
}
async function main() {
console.info('\n==============================');
console.info('Running tests for Android with the following parameters:');
console.info(`APP_PATH: ${APP_PATH}`);
console.info(`APP_ID: ${APP_ID}`);
console.info(`MAESTRO_FLOW: ${MAESTRO_FLOW}`);
console.info(`IS_DEBUG: ${IS_DEBUG}`);
console.info(`WORKING_DIRECTORY: ${WORKING_DIRECTORY}`);
console.info('==============================\n');
console.info('Install app');
childProcess.execSync(`adb install ${APP_PATH}`, {stdio: 'ignore'});
let metroProcess = null;
if (IS_DEBUG) {
console.info('Start Metro');
childProcess.execSync(`cd ${WORKING_DIRECTORY}`, {stdio: 'ignore'});
metroProcess = childProcess.spawn('yarn', ['start', '&'], {
cwd: WORKING_DIRECTORY,
stdio: 'ignore',
detached: true,
});
metroProcess.unref();
console.info(`- Metro PID: ${metroProcess.pid}`);
console.info('Wait For Metro to Start');
await sleep(5000);
}
console.info('Start the app');
childProcess.execSync(`adb shell monkey -p ${APP_ID} 1`, {stdio: 'ignore'});
if (IS_DEBUG) {
console.info('Wait For App to warm from Metro');
await sleep(10000);
}
console.info('Start recording to /sdcard/screen.mp4');
childProcess
.exec('adb shell screenrecord /sdcard/screen.mp4', {
stdio: 'ignore',
detached: true,
})
.unref();
console.info(`Start testing ${MAESTRO_FLOW}`);
let error = null;
try {
//check if MAESTRO_FLOW is a folder
if (
fs.existsSync(MAESTRO_FLOW) &&
fs.lstatSync(MAESTRO_FLOW).isDirectory()
) {
await executeFlowInFolder(MAESTRO_FLOW);
} else {
await executeFlowWithRetries(MAESTRO_FLOW, 0);
}
} catch (err) {
error = err;
} finally {
console.info('Stop recording');
childProcess.execSync('adb pull /sdcard/screen.mp4', {stdio: 'ignore'});
if (IS_DEBUG && metroProcess != null) {
const pid = metroProcess.pid;
console.info(`Kill Metro. PID: ${pid}`);
process.kill(pid);
console.info(`Metro Killed`);
}
}
if (error) {
throw error;
}
process.exit();
}
function sleep(ms) {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
}
main();
-176
View File
@@ -1,176 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
const childProcess = require('child_process');
const fs = require('fs');
const usage = `
=== Usage ===
node maestro-android.js <path to app> <app_id> <maestro_flow> <flavor> <working_directory>
@param {string} appPath - Path to the app APK
@param {string} appId - App ID that needs to be launched
@param {string} maestroFlow - Path to the maestro flow to be executed
@param {string} jsengine - The JSEngine to use for the test
@param {string} flavor - Flavor of the app to be launched. Can be 'Release' or 'Debug'
@param {string} workingDirectory - Working directory from where to run Metro
==============
`;
const args = process.argv.slice(2);
if (args.length !== 6) {
throw new Error(`Invalid number of arguments.\n${usage}`);
}
const APP_PATH = args[0];
const APP_ID = args[1];
const MAESTRO_FLOW = args[2];
const JS_ENGINE = args[3];
const IS_DEBUG = args[4] === 'Debug';
const WORKING_DIRECTORY = args[5];
const MAX_ATTEMPTS = 5;
function launchSimulator(simulatorName) {
console.log(`Launching simulator ${simulatorName}`);
try {
childProcess.execSync(`xcrun simctl boot "${simulatorName}"`);
} catch (error) {
if (
!error.message.includes('Unable to boot device in current state: Booted')
) {
throw error;
}
}
}
function installAppOnSimulator(appPath) {
console.log(`Installing app at path ${appPath}`);
childProcess.execSync(`xcrun simctl install booted "${appPath}"`);
}
function extractSimulatorUDID() {
console.log('Retrieving device UDID');
const command = `xcrun simctl list devices booted -j | jq -r '[.devices[]] | add | first | .udid'`;
const udid = String(childProcess.execSync(command)).trim();
console.log(`UDID is ${udid}`);
return udid;
}
function bringSimulatorInForeground() {
console.log('Bringing simulator in foreground');
childProcess.execSync('open -a simulator');
}
function sleep(ms) {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
}
async function launchAppOnSimulator(appId, udid, isDebug) {
console.log('Launch the app');
childProcess.execSync(`xcrun simctl launch "${udid}" "${appId}"`);
if (isDebug) {
console.log('Wait for metro to warm');
await sleep(20 * 1000);
}
}
function startVideoRecording(jsengine, currentAttempt) {
console.log(
`Start video record using pid: video_record_${jsengine}_${currentAttempt}.pid`,
);
const recordingArgs =
`simctl io booted recordVideo video_record_${jsengine}_${currentAttempt}.mov`.split(
' ',
);
const recordingProcess = childProcess.spawn('xcrun', recordingArgs, {
detached: true,
stdio: 'ignore',
});
return recordingProcess;
}
function stopVideoRecording(recordingProcess) {
if (!recordingProcess) {
console.log("Passed a null recording process. Can't kill it");
return;
}
console.log(`Stop video record using pid: ${recordingProcess.pid}`);
recordingProcess.kill('SIGINT');
}
function executeTestsWithRetries(
appId,
udid,
maestroFlow,
jsengine,
currentAttempt,
) {
const recProcess = startVideoRecording(jsengine, currentAttempt);
try {
const timeout = 1000 * 60 * 10; // 10 minutes
const command = `$HOME/.maestro/bin/maestro --udid="${udid}" test "${maestroFlow}" --format junit -e APP_ID="${appId}"`;
console.log(command);
childProcess.execSync(`MAESTRO_DRIVER_STARTUP_TIMEOUT=1500000 ${command}`, {
stdio: 'inherit',
timeout,
});
stopVideoRecording(recProcess);
} catch (error) {
// Can't put this in the finally block because it will be executed after the
// recursive call of executeTestsWithRetries
stopVideoRecording(recProcess);
if (currentAttempt < MAX_ATTEMPTS) {
executeTestsWithRetries(
appId,
udid,
maestroFlow,
jsengine,
currentAttempt + 1,
);
} else {
console.error(`Failed to execute flow after ${MAX_ATTEMPTS} attempts.`);
throw error;
}
}
}
async function main() {
console.info('\n==============================');
console.info('Running tests for iOS with the following parameters:');
console.info(`APP_PATH: ${APP_PATH}`);
console.info(`APP_ID: ${APP_ID}`);
console.info(`MAESTRO_FLOW: ${MAESTRO_FLOW}`);
console.info(`JS_ENGINE: ${JS_ENGINE}`);
console.info(`IS_DEBUG: ${IS_DEBUG}`);
console.info(`WORKING_DIRECTORY: ${WORKING_DIRECTORY}`);
console.info('==============================\n');
const simulatorName = 'iPhone 15 Pro';
launchSimulator(simulatorName);
installAppOnSimulator(APP_PATH);
const udid = extractSimulatorUDID();
bringSimulatorInForeground();
await launchAppOnSimulator(APP_ID, udid, IS_DEBUG);
executeTestsWithRetries(APP_ID, udid, MAESTRO_FLOW, JS_ENGINE, 1);
console.log('Test finished');
process.exit(0);
}
main();
-90
View File
@@ -1,90 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
/**
* Sends a message to Discord using the webhook URL.
* @param {string} webHook - The Discord webhook URL
* @param {Object} message - The message to send
* @returns {Promise<void>} - A promise that resolves when the message is sent
*/
async function sendMessageToDiscord(webHook, message) {
if (!webHook) {
throw new Error('Discord webhook URL is missing');
}
// Send the request using fetch
const response = await fetch(webHook, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(message),
});
// Handle the response
if (response.ok) {
console.log('Successfully sent message to Discord');
return;
} else {
const errorText = await response.text();
console.error(
`Failed to send message to Discord: ${response.status} ${errorText}`,
);
throw new Error(`HTTP status code: ${response.status}`);
}
}
/**
* Prepares a formatted Discord message payload from a list of failures.
* @param {Array<Object>} failures - List of failures to format
* @returns {Object} - The formatted Discord message payload
*/
function prepareFailurePayload(failures) {
if (!failures || failures.length === 0) {
return {
content:
'⚠️ **React Native Nightly Integration Failures** ⚠️\n\nNo failures to report.',
};
}
// Sort failures by platform and then by library name
const sortedFailures = [...failures].sort((a, b) => {
// First sort by platform
const platformA = a.platform || 'Unknown';
const platformB = b.platform || 'Unknown';
if (platformA !== platformB) {
return platformA.localeCompare(platformB);
}
// Then sort by library name
const libraryA = a.library || 'Unknown';
const libraryB = b.library || 'Unknown';
return libraryA.localeCompare(libraryB);
});
// Format the failures into a message
const formattedFailures = sortedFailures
.map(failure => {
const library = failure.library || 'Unknown';
const platform = failure.platform || 'Unknown';
return `❌ [${platform}] ${library}`;
})
.join('\n');
return {
content: `⚠️ **React Native Nightly Integration Failures** ⚠️\n\nThe integration of libraries with React Native nightly failed for the following libraries:\n\n${formattedFailures}`,
};
}
// Export the functions using CommonJS syntax
module.exports = {
prepareFailurePayload,
sendMessageToDiscord,
};
@@ -1,85 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
const {run, sleep, log} = require('./utils.js');
const {verifyPublishedPackage} = require('./verifyPublishedPackage.js');
const TAG_AS_LATEST_REGEX = /#publish-packages-to-npm&latest/;
/**
* Should this commit be `latest` on npm?
*/
function isLatest() {
const commitMessage = run('git log -n1 --pretty=%B');
return TAG_AS_LATEST_REGEX.test(commitMessage);
}
module.exports.isLatest = isLatest;
/**
* Create a Github Action to publish the community template matching the released version
* of React Native.
*/
module.exports.publishTemplate = async (github, version, dryRun = true) => {
log(`📤 Get the ${TEMPLATE_NPM_PKG} repo to publish ${version}`);
const is_latest_on_npm = isLatest();
const majorMinor = /^v?(\d+\.\d+)/.exec(version);
if (!majorMinor) {
log(`🔥 can't capture MAJOR.MINOR from '${version}', giving up.`);
process.exit(1);
}
// MAJOR.MINOR-stable
const ref = `${majorMinor[1]}-stable`;
await github.rest.actions.createWorkflowDispatch({
owner: 'react-native-community',
repo: 'template',
workflow_id: 'release.yaml',
ref,
inputs: {
dry_run: dryRun,
is_latest_on_npm,
// 0.75.0-rc.0, note no 'v' prefix
version: version.replace(/^v/, ''),
},
});
};
const MAX_RETRIES = 3 * 6; // 18 attempts. Waiting between attempt: 10 s. Total time: 3 mins.
const TEMPLATE_NPM_PKG = '@react-native-community/template';
/**
* Will verify that @latest and the @<version> have been published.
*
* NOTE: This will infinitely query each step until successful, make sure the
* calling job has a timeout.
*/
module.exports.verifyPublishedTemplate = async (
version,
latest = false,
retries = MAX_RETRIES,
) => {
try {
if (version.startsWith('v')) {
version = version.slice(1);
}
await verifyPublishedPackage(
TEMPLATE_NPM_PKG,
version,
latest ? 'latest' : null,
retries,
);
} catch (e) {
console.error(e.message);
process.exit(1);
}
};
-33
View File
@@ -1,33 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
const {execSync} = require('child_process');
const log = (...args) => console.log(...args);
async function getNpmPackageInfo(pkg, versionOrTag) {
return fetch(`https://registry.npmjs.org/${pkg}/${versionOrTag}`).then(resp =>
resp.json(),
);
}
async function sleep(seconds) {
return new Promise(resolve => setTimeout(resolve, seconds * 1000));
}
function run(cmd) {
return execSync(cmd, 'utf8').toString().trim();
}
module.exports = {
log,
getNpmPackageInfo,
sleep,
run,
};
@@ -1,43 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
const {log, sleep} = require('./utils');
const SLEEP_S = 60; // 1 minute
const MAX_RETRIES = 90; // 90 attempts. Waiting between attempt: 1 min. Total time: 90 min.
const ARTIFACT_URL =
'https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/';
const ARTIFACT_NAME = 'react-native-artifacts-';
async function verifyArtifactsAreOnMaven(version, retries = MAX_RETRIES) {
if (version.startsWith('v')) {
version = version.substring(1);
}
const artifactUrl = `${ARTIFACT_URL}${version}/${ARTIFACT_NAME}${version}.pom`;
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 {
return;
}
}
log(
`We waited 90 minutes for the artifacts to be on Maven. Check https://status.maven.org/ if there are issues wth the service.`,
);
process.exit(1);
}
module.exports = {verifyArtifactsAreOnMaven};
@@ -1,63 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
const {log, getNpmPackageInfo, sleep} = require('./utils');
const SLEEP_S = 10;
const MAX_RETRIES = 3 * 6; // 18 attempts. Waiting between attempt: 10 s. Total time: 3 mins.
async function verifyPublishedPackage(
packageName,
version,
tag = null,
retries = MAX_RETRIES,
) {
log(`🔍 Is ${packageName}@${version} on npm?`);
let count = retries;
while (count-- > 0) {
try {
const json = await getNpmPackageInfo(packageName, tag ? tag : version);
log(`🎉 Found ${packageName}@${version} on npm`);
if (!tag) {
return;
}
// check for next tag
if (tag === 'next' && json.version === version) {
log(`🎉 ${packageName}@next → ${version} on npm`);
return;
}
// Check for latest tag
if (tag === 'latest' && json.version === version) {
log(`🎉 ${packageName}@latest → ${version} on npm`);
return;
}
log(
`🐌 ${packageName}@${tag}${json.version} on npm and not ${version} as expected, retrying...`,
);
} catch (e) {
log(`Nope, fetch failed: ${e.message}`);
}
await sleep(SLEEP_S);
}
let msg = `🚨 Timed out when trying to verify ${packageName}@${version} on npm`;
if (tag) {
msg += ` and ${tag} tag points to this version.`;
}
log(msg);
process.exit(1);
}
module.exports = {
verifyPublishedPackage,
};
@@ -1,30 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
const {run, sleep, log} = require('./utils.js');
const {verifyPublishedPackage} = require('./verifyPublishedPackage.js');
const REACT_NATIVE_NPM_PKG = 'react-native';
const MAX_RETRIES = 3 * 6; // 18 attempts. Waiting between attempt: 10 s. Total time: 3 mins.
/**
* Will verify that @latest, @next and the @<version> have been published.
*
* NOTE: This will infinitely query each step until successful, make sure the
* calling job has a timeout.
*/
module.exports.verifyReleaseOnNpm = async (
version,
latest = false,
retries = MAX_RETRIES,
) => {
const tag = version.includes('-rc.') ? 'next' : latest ? 'latest' : null;
if (version.startsWith('v')) {
version = version.slice(1);
}
await verifyPublishedPackage(REACT_NATIVE_NPM_PKG, version, tag, retries);
};
+33
View File
@@ -10,6 +10,11 @@
module.exports = async (github, context) => {
const issue = context.payload.issue;
// Ignore issues using upgrade template (they use a special label)
if (issue.labels.find(label => label.name === 'Type: Upgrade Issue')) {
return;
}
const issueVersionUnparsed =
getReactNativeVersionFromIssueBodyIfExists(issue);
const issueVersion = parseVersionFromString(issueVersionUnparsed);
@@ -45,6 +50,18 @@ module.exports = async (github, context) => {
if (!isVersionSupported(issueVersion, latestVersion)) {
return {label: 'Type: Unsupported Version'};
}
// We want to encourage users to repro the issue on the highest available patch for the given minor.
const latestPatchForVersion = getLatestPatchForVersion(
issueVersion,
recentReleases,
);
if (latestPatchForVersion > issueVersion.patch) {
return {
label: 'Newer Patch Available',
newestPatch: `${issueVersion.major}.${issueVersion.minor}.${latestPatchForVersion}`,
};
}
};
/**
@@ -75,6 +92,22 @@ function isVersionTooOld(actualVersion, latestVersion) {
);
}
// Assumes that releases are sorted in the order of recency (i.e. most recent releases are earlier in the list)
// This enables us to stop looking as soon as we find the first release with a matching major/minor version, since
// we know it's the most recent release, therefore the highest patch available.
function getLatestPatchForVersion(version, releases) {
for (releaseName of releases) {
const release = parseVersionFromString(releaseName);
if (
release &&
release.major == version.major &&
release.minor == version.minor
) {
return release.patch;
}
}
}
function getReactNativeVersionFromIssueBodyIfExists(issue) {
if (!issue || !issue.body) return;
const rnVersionRegex = /React Native Version[\r\n]+(?<version>.+)[\r\n]*/;
@@ -0,0 +1,22 @@
name: Apply version label to issue
on:
issues:
types: [opened, edited]
permissions:
contents: read
jobs:
add-version-label-issue:
permissions:
issues: write # for react-native-community/actions-apply-version-label to label issues
runs-on: ubuntu-latest
continue-on-error: true
if: github.repository == 'facebook/react-native'
steps:
- uses: react-native-community/actions-apply-version-label@v0.0.3
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
required-label: "Type: Upgrade Issue"
+1 -1
View File
@@ -24,4 +24,4 @@ jobs:
- name: Automatic Rebase
uses: cirrus-actions/rebase@1.8
env:
GITHUB_TOKEN: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-45
View File
@@ -1,45 +0,0 @@
name: Bump Podfile.lock
on:
workflow_call: # this directive allow us to call this workflow from other workflows
jobs:
bump-podfile-lock:
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Install dependencies
uses: ./.github/actions/yarn-install
- name: Configure git
run: |
git config --local user.email "bot@reactnative.dev"
git config --local user.name "React Native Bot"
- name: Setup xcode
uses: ./.github/actions/setup-xcode
with:
xcode-version: '16.2.0'
- name: Extract branch name
run: |
TAG="${{ github.ref_name }}";
BRANCH_NAME=$(echo "$TAG" | sed -E 's/v([0-9]+\.[0-9]+)\.[0-9]+(-rc\.[0-9]+)?/\1-stable/')
echo "Branch Name is $BRANCH_NAME"
echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV
- name: Checkout release branch
run: |
git checkout "$BRANCH_NAME"
git fetch
git pull origin "$BRANCH_NAME"
- name: Bump podfile.lock
run: |
cd packages/rn-tester
bundle install
bundle exec pod update hermes-engine --no-repo-update
- name: Commit changes
run: |
git add packages/rn-tester/Podfile.lock
git commit -m "[LOCAL] Bump Podfile.lock"
git push origin "$BRANCH_NAME"
-20
View File
@@ -1,20 +0,0 @@
name: Keep Github Actions Cache < 10GB
on:
workflow_dispatch:
schedule:
# Run every 2hrs during weekdays
- cron: "0 0/2 * * 1-5"
jobs:
cache-cleaner:
if: github.repository == 'facebook/react-native'
runs-on: ubuntu-latest
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
- name: Trim the cache
run: node scripts/clean-gha-cache.js
+1 -1
View File
@@ -13,7 +13,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/github-script@v6
with:
github-token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const checkForReproducer = require('./.github/workflow-scripts/checkForReproducer.js')
await checkForReproducer(github, context)
-34
View File
@@ -1,34 +0,0 @@
# This jobs runs every day 2 hours after the nightly job and its purpose is to report
# a failure in case the nightly failed to be published. We are going to hook this to an internal automation.
name: Check Nightlies
on:
workflow_dispatch:
# nightly build @ 4:15 AM UTC
schedule:
- cron: '15 4 * * *'
jobs:
check-nightly:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Check nightly
run: |
TODAY=$(date "+%Y%m%d")
echo "Checking nightly for $TODAY"
NIGHTLY="$(npm view react-native | grep $TODAY)"
if [[ -z $NIGHTLY ]]; then
echo 'Nightly job failed.'
exit 1
else
echo 'Nightly Worked, All Good!'
fi
test-libraries:
uses: ./.github/workflows/test-libraries-on-nightlies.yml
needs: check-nightly
secrets:
discord_webhook_url: ${{ secrets.NIGHTLY_DISCORD_WEBHOOK }}
-63
View File
@@ -1,63 +0,0 @@
name: Label closed PR as merged and leave a comment
on:
push
permissions:
contents: read
pull-requests: write
jobs:
comment-and-label:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
steps:
- uses: actions/github-script@v6
with:
github-token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
script: |
if(!context.payload.commits || !context.payload.commits.length) return;
const sha = context.payload.commits[0].id;
const {commit, author} = (await github.rest.repos.getCommit({
ref: sha,
owner: context.repo.owner,
repo: context.repo.repo,
})).data;
// Looking at the commit message, checks which PR number, if any, was closed by this commit
const getClosedPrIfExists = (commit) => {
if(!commit || !commit.message) return;
const prClosingRegex = /Closes https:\/\/github.com\/facebook\/react-native\/pull\/([0-9]+)|Pull Request resolved: https:\/\/github.com\/facebook\/react-native\/pull\/([0-9]+)/;
const prClosingMatch = commit.message.match(prClosingRegex);
if(!prClosingMatch || (!prClosingMatch[1] && ! prClosingMatch[2])) return;
return prClosingMatch[1] ?? prClosingMatch[2];
};
const closedPrNumber = getClosedPrIfExists(commit);
if(!closedPrNumber) return;
const pr = (await github.rest.pulls.get({
pull_number: closedPrNumber,
owner: context.repo.owner,
repo: context.repo.repo,
})).data;
const authorName = author?.login ? `@${author.login}` : commit.author.name;
github.rest.issues.createComment({
issue_number: closedPrNumber,
owner: context.repo.owner,
repo: context.repo.repo,
body: `This pull request was successfully merged by ${authorName} in **${sha}**\n\n<sup>[When will my fix make it into a release?](https://github.com/reactwg/react-native-releases/blob/main/docs/faq.md#when-will-my-fix-make-it-into-a-release) | [How to file a pick request?](https://github.com/reactwg/react-native-releases/blob/main/docs/faq.md#how-to-open-a-pick-request)</sup>`
});
// If the PR has already been processed (labeled as Merged), skip it
const mergedLabel = "Merged";
if(pr.labels && pr.labels.some(label => label.name === mergedLabel)) return;
github.rest.issues.addLabels({
issue_number: closedPrNumber,
owner: context.repo.owner,
repo: context.repo.repo,
labels: [mergedLabel]
});
+63
View File
@@ -0,0 +1,63 @@
name: Label closed PR as merged and leave a comment
on:
push
permissions:
contents: read
pull-requests: write
jobs:
comment-and-label:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
steps:
- uses: actions/github-script@v6
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
if(!context.payload.commits || !context.payload.commits.length) return;
const sha = context.payload.commits[0].id;
const {commit, author} = (await github.rest.repos.getCommit({
ref: sha,
owner: context.repo.owner,
repo: context.repo.repo,
})).data;
// Looking at the commit message, checks which PR number, if any, was closed by this commit
const getClosedPrIfExists = (commit) => {
if(!commit || !commit.message) return;
const prClosingRegex = /Closes https:\/\/github.com\/facebook\/react-native\/pull\/([0-9]+)|Pull Request resolved: https:\/\/github.com\/facebook\/react-native\/pull\/([0-9]+)/;
const prClosingMatch = commit.message.match(prClosingRegex);
if(!prClosingMatch || (!prClosingMatch[1] && ! prClosingMatch[2])) return;
return prClosingMatch[1] ?? prClosingMatch[2];
};
const closedPrNumber = getClosedPrIfExists(commit);
if(!closedPrNumber) return;
const pr = (await github.rest.pulls.get({
pull_number: closedPrNumber,
owner: context.repo.owner,
repo: context.repo.repo,
})).data;
// If the PR has already been processed (labeled as Merged), skip it
const mergedLabel = "Merged";
if(pr.labels && pr.labels.some(label => label.name === mergedLabel)) return;
const authorName = author?.login ? `@${author.login}` : commit.author.name;
github.rest.issues.createComment({
issue_number: closedPrNumber,
owner: context.repo.owner,
repo: context.repo.repo,
body: `This pull request was successfully merged by ${authorName} in **${sha}**.\n\n<sup>[When will my fix make it into a release?](https://github.com/facebook/react-native/wiki/Release-FAQ#when-will-my-fix-make-it-into-a-release) | [Upcoming Releases](https://github.com/reactwg/react-native-releases/discussions/categories/releases)</sup>`
});
github.rest.issues.addLabels({
issue_number: closedPrNumber,
owner: context.repo.owner,
repo: context.repo.repo,
labels: [mergedLabel]
});
@@ -1,29 +0,0 @@
name: Create Draft Release
on:
workflow_call:
jobs:
create-draft-release:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Install dependencies
uses: ./.github/actions/yarn-install
- name: Configure Git
shell: bash
run: |
git config --local user.email "bot@reactnative.dev"
git config --local user.name "React Native Bot"
- name: Create draft release
uses: actions/github-script@v6
with:
script: |
const {createDraftRelease} = require('./.github/workflow-scripts/createDraftRelease.js');
const version = '${{ github.ref_name }}';
const {isLatest} = require('./.github/workflow-scripts/publishTemplate.js');
await createDraftRelease(version, isLatest(), '${{secrets.REACT_NATIVE_BOT_GITHUB_TOKEN}}');
-56
View File
@@ -1,56 +0,0 @@
name: Create release
on:
workflow_dispatch:
inputs:
version:
description: "The version of React Native we want to release. For example 0.75.0-rc.0"
required: true
type: string
is-latest-on-npm:
description: "Whether we want to tag this release as latest on NPM"
required: true
type: boolean
default: false
dry-run:
description: "Whether the job should be executed in dry-run mode or not"
type: boolean
default: true
jobs:
create_release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
fetch-depth: 0
fetch-tags: 'true'
- name: Check if on stable branch
id: check_stable_branch
run: |
BRANCH="$(git branch --show-current)"
PATTERN='^0\.[0-9]+-stable$'
if [[ $BRANCH =~ $PATTERN ]]; then
echo "On a stable branch"
echo "ON_STABLE_BRANCH=true" >> $GITHUB_OUTPUT
fi
- name: Print output
run: echo "ON_STABLE_BRANCH ${{steps.check_stable_branch.outputs.ON_STABLE_BRANCH}}"
- name: Check if tag already exists
id: check_if_tag_exists
run: |
TAG="v${{ inputs.version }}"
TAG_EXISTS=$(git tag -l "$TAG")
if [[ -n "$TAG_EXISTS" ]]; then
echo "Version tag already exists!"
echo "TAG_EXISTS=true" >> $GITHUB_OUTPUT
fi
- name: Execute Prepare Release
if: ${{ steps.check_stable_branch.outputs.ON_STABLE_BRANCH && !steps.check_if_tag_exists.outputs.TAG_EXISTS }}
uses: ./.github/actions/create-release
with:
version: ${{ inputs.version }}
is-latest-on-npm: ${{ inputs.is-latest-on-npm }}
dry-run: ${{ inputs.dry-run }}
-31
View File
@@ -1,31 +0,0 @@
name: Run Danger on PR
on:
pull_request_target:
types: [opened, edited, reopened, synchronize]
permissions:
actions: write
checks: write
contents: write
issues: write
pull-requests: write
statuses: write
jobs:
danger:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
- name: Run yarn install
uses: ./.github/actions/yarn-install
- name: Run diff-js-api-breaking-changes
uses: ./.github/actions/diff-js-api-breaking-changes
- name: Danger
run: yarn danger ci --use-github-checks --failOnErrors
working-directory: private/react-native-bots
env:
DANGER_GITHUB_API_TOKEN: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
+28
View File
@@ -0,0 +1,28 @@
name: Run Danger on PR
on:
pull_request_target:
types: [opened, edited, reopened, synchronize]
permissions:
actions: write
checks: write
contents: write
issues: write
pull-requests: write
statuses: write
jobs:
danger:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
steps:
- uses: actions/checkout@v4
- name: Run Yarn Install on Root
run: yarn install
working-directory: .
- name: Danger
run: yarn danger ci --use-github-checks --failOnErrors
working-directory: packages/react-native-bots
env:
DANGER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-28
View File
@@ -1,28 +0,0 @@
name: Generate Changelog
on:
workflow_call:
jobs:
generate-changelog:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Install dependencies
uses: ./.github/actions/yarn-install
- name: Configure Git
shell: bash
run: |
git config --local user.email "bot@reactnative.dev"
git config --local user.name "React Native Bot"
- name: Generate Changelog
uses: actions/github-script@v6
with:
script: |
const {generateChangelog} = require('./.github/workflow-scripts/generateChangelog');
const version = '${{ github.ref_name }}';
await generateChangelog(version, '${{secrets.REACT_NATIVE_BOT_GITHUB_TOKEN}}');
+48
View File
@@ -0,0 +1,48 @@
name: ios-tests
on:
push:
branches:
- main
pull_request:
branches:
- "*"
jobs:
test_ios_rntester-Hermes:
runs-on: macos-latest-large
steps:
- name: Checkout Repo
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'yarn'
- name: Yarn Install
run: yarn install
- name: Get latest commit from Hermes
run: |
mkdir -p tmp/hermes
HERMES_TAG_SHA=$(git ls-remote https://github.com/facebook/hermes main | cut -f 1 | tr -d '[:space:]')
echo $HERMES_TAG_SHA > tmp/hermes/hermesversion
echo "Latest Commit is:"
cat tmp/hermes/hermesversion
- uses: ruby/setup-ruby@v1
with:
bundler-cache: true
ruby-version: '3.2'
- name: Cache cocoapods
uses: actions/cache@v3
with:
path: packages/rn-tester/Pods
key: v1-${{ runner.os }}-RNTesterPods-${{ hashFiles('packages/rn-tester/Podfile.lock') }}-${{ hashFiles('packages/rn-tester/Podfile') }}-${{ hashFiles('tmp/hermes/hermesversion') }}
- name: Pod Install
run: |
cd packages/rn-tester
bundle install
bundle exec pod install
- name: Install XCBeautify
run: brew install xcbeautify
- name: Build iOS
run: ./scripts/objc-test.sh
-45
View File
@@ -1,45 +0,0 @@
name: Monitor React Native New Issues
on:
schedule:
- cron: "0 0,6,12,18 * * *"
workflow_dispatch:
# Reminder for when we have to update the schedule (before Jan 2026):
# the secrets.ONCALL_SCHEDULE secret must be on a single line and must have all the `"` escaped as `\"`.
# Only a meta engineer can update it through the OSS internal portal.
jobs:
monitor-issues:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Node.js
uses: ./.github/actions/setup-node
- name: Install dependencies
uses: ./.github/actions/yarn-install
- name: Extract next oncall
run: |
ONCALLS=$(node ./.github/workflow-scripts/extractIssueOncalls.js "${{ secrets.ONCALL_SCHEDULE }}")
ONCALL1=$(echo $ONCALLS | cut -d ' ' -f 1)
ONCALL2=$(echo $ONCALLS | cut -d ' ' -f 2)
echo "oncall1=$ONCALL1" >> $GITHUB_ENV
echo "oncall2=$ONCALL2" >> $GITHUB_ENV
- name: Print oncalls
run: |
echo "oncall1: ${{ env.oncall1 }}"
echo "oncall2: ${{ env.oncall2 }}"
- name: Monitor New Issues
uses: react-native-community/repo-monitor@v1.0.1
with:
task: "monitor-issues"
git_secret: ${{ secrets.GITHUB_TOKEN }}
notifier: "discord"
fetch_data_interval: 6
repo_owner: "facebook"
repo_name: "react-native"
discord_webhook_url: "${{ secrets.DISCORD_WEBHOOK_URL }}"
discord_id_type: "user"
discord_ids: "${{ env.oncall1 }},${{ env.oncall2 }}"
+4 -4
View File
@@ -2,7 +2,7 @@ name: Issue Needs Attention
# This workflow is triggered on issue comments.
on:
issue_comment:
types: [created]
types: created
permissions:
contents: read
@@ -10,15 +10,15 @@ permissions:
jobs:
applyNeedsAttentionLabel:
permissions:
contents: read # for actions/checkout to fetch code
issues: write # for react-native-community/needs-attention to label issues
contents: read # for actions/checkout to fetch code
issues: write # for hramos/needs-attention to label issues
name: Apply Needs Attention Label
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
steps:
- uses: actions/checkout@v4
- name: Apply Needs Attention Label
uses: react-native-community/needs-attention@v2.0.0
uses: hramos/needs-attention@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
response-required-label: "Needs: Author Feedback"
+52
View File
@@ -0,0 +1,52 @@
name: Nightlies Partners Feedback
env:
# Add accounts for users who are part of the nightlies program
allowed_users: >
[
"blakef",
"alanjhughes"
]
on:
workflow_dispatch:
inputs:
project:
description: 'What project is running against the nighties build?'
required: true
type: string
outcome:
description: 'Did the CI run: ["pass", "fail"]?'
required: true
type: string
stage:
description: 'Stage in the run that failed: ["build", "test"]?'
required: true
type: string
link:
description: 'URL to the failing test'
required: true
type: string
version:
description: 'What is the Nightlies version this was run against?'
required: true
type: string
jobs:
share-nightlies-feedback:
name: ${{ inputs.project}} 💨 Nightlies CI
runs-on: ubuntu-latest
permissions:
actions: write
steps:
- if: ${{ !contains(fromJSON(env.allowed_users), github.actor) }}
run: |
echo "Request from actor's login wasn't on the allowed_users list."
curl -X POST \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
https://api.github.com/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/cancel
- run: |
echo "Project: ${{ inputs.project }}"
echo "Outcome: ${{ inputs.outcome }}"
echo "Stage: ${{ inputs.stage }}"
echo "Link: ${{ inputs.link }}"
echo "Version: ${{ inputs.version }}"
[[ "${{ inputs.outcome }}" == "pass" ]] && { exit 0; } || { exit 1; }
-203
View File
@@ -1,203 +0,0 @@
name: Nightly
on:
workflow_dispatch:
# nightly build @ 2:15 AM UTC
schedule:
- cron: "15 2 * * *"
jobs:
set_release_type:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
outputs:
RELEASE_TYPE: ${{ steps.set_release_type.outputs.RELEASE_TYPE }}
env:
EVENT_NAME: ${{ github.event_name }}
REF: ${{ github.ref }}
steps:
- id: set_release_type
run: |
echo "Setting release type to nightly"
echo "RELEASE_TYPE=nightly" >> $GITHUB_OUTPUT
prepare_hermes_workspace:
runs-on: ubuntu-latest
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_VERSION_FILE: packages/react-native/sdks/.hermesversion
outputs:
react-native-version: ${{ steps.prepare-hermes-workspace.outputs.react-native-version }}
hermes-version: ${{ steps.prepare-hermes-workspace.outputs.hermes-version }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Prepare Hermes Workspace
id: prepare-hermes-workspace
uses: ./.github/actions/prepare-hermes-workspace
with:
hermes-ws-dir: ${{ env.HERMES_WS_DIR }}
hermes-version-file: ${{ env.HERMES_VERSION_FILE }}
build_hermesc_apple:
runs-on: macos-14
needs: prepare_hermes_workspace
env:
HERMES_WS_DIR: /tmp/hermes
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build HermesC Apple
uses: ./.github/actions/build-hermesc-apple
with:
hermes-version: ${{ needs.prepare_hermes_workspace.output.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.output.react-native-version }}
build_apple_slices_hermes:
runs-on: macos-14
needs: [build_hermesc_apple, prepare_hermes_workspace]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
HERMES_OSXBIN_ARTIFACTS_DIR: /tmp/hermes/osx-bin
IOS_DEPLOYMENT_TARGET: "15.1"
XROS_DEPLOYMENT_TARGET: "1.0"
MAC_DEPLOYMENT_TARGET: "10.15"
strategy:
fail-fast: false
matrix:
flavor: [Debug, Release]
slice: [macosx, iphoneos, iphonesimulator, appletvos, appletvsimulator, catalyst, xros, xrsimulator]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build Slice
uses: ./.github/actions/build-apple-slices-hermes
with:
flavor: ${{ matrix.flavor }}
slice: ${{ matrix.slice}}
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
build_hermes_macos:
runs-on: macos-14
needs: [build_apple_slices_hermes, prepare_hermes_workspace]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
continue-on-error: true
strategy:
fail-fast: false
matrix:
flavor: [Debug, Release]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build Hermes MacOS
uses: ./.github/actions/build-hermes-macos
with:
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
flavor: ${{ matrix.flavor }}
prebuild_apple_dependencies:
uses: ./.github/workflows/prebuild-ios-dependencies.yml
secrets: inherit
prebuild_react_native_core:
uses: ./.github/workflows/prebuild-ios-core.yml
secrets: inherit
needs: [prebuild_apple_dependencies, build_hermes_macos]
build_hermesc_linux:
runs-on: ubuntu-latest
needs: prepare_hermes_workspace
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build HermesC Linux
uses: ./.github/actions/build-hermesc-linux
with:
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
build_hermesc_windows:
runs-on: windows-2025
needs: prepare_hermes_workspace
env:
HERMES_WS_DIR: 'C:\tmp\hermes'
HERMES_TARBALL_ARTIFACTS_DIR: 'C:\tmp\hermes\hermes-runtime-darwin'
HERMES_OSXBIN_ARTIFACTS_DIR: 'C:\tmp\hermes\osx-bin'
ICU_URL: "https://github.com/unicode-org/icu/releases/download/release-64-2/icu4c-64_2-Win64-MSVC2017.zip"
MSBUILD_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin'
CMAKE_DIR: 'C:\Program Files\CMake\bin'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build HermesC Windows
uses: ./.github/actions/build-hermesc-windows
with:
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
build_android:
runs-on: 8-core-ubuntu
needs: [set_release_type]
container:
image: reactnativecommunity/react-native-android:latest
env:
TERM: "dumb"
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
ORG_GRADLE_PROJECT_SIGNING_PWD: ${{ secrets.ORG_GRADLE_PROJECT_SIGNING_PWD }}
ORG_GRADLE_PROJECT_SIGNING_KEY: ${{ secrets.ORG_GRADLE_PROJECT_SIGNING_KEY }}
ORG_GRADLE_PROJECT_SONATYPE_USERNAME: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPE_USERNAME }}
ORG_GRADLE_PROJECT_SONATYPE_PASSWORD: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPE_PASSWORD }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build Android
uses: ./.github/actions/build-android
with:
release-type: ${{ needs.set_release_type.outputs.RELEASE_TYPE }}
gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }}
build_npm_package:
runs-on: 8-core-ubuntu
needs:
[
set_release_type,
prepare_hermes_workspace,
build_hermes_macos,
build_hermesc_linux,
build_hermesc_windows,
build_android,
prebuild_apple_dependencies,
prebuild_react_native_core,
]
container:
image: reactnativecommunity/react-native-android:latest
env:
TERM: "dumb"
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
# By default we only build ARM64 to save time/resources. For release/nightlies, we override this value to build all archs.
ORG_GRADLE_PROJECT_reactNativeArchitectures: "arm64-v8a"
env:
HERMES_WS_DIR: /tmp/hermes
GHA_NPM_TOKEN: ${{ secrets.GHA_NPM_TOKEN }}
ORG_GRADLE_PROJECT_SIGNING_PWD: ${{ secrets.ORG_GRADLE_PROJECT_SIGNING_PWD }}
ORG_GRADLE_PROJECT_SIGNING_KEY: ${{ secrets.ORG_GRADLE_PROJECT_SIGNING_KEY }}
ORG_GRADLE_PROJECT_SONATYPE_USERNAME: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPE_USERNAME }}
ORG_GRADLE_PROJECT_SONATYPE_PASSWORD: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPE_PASSWORD }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build and Publish NPM Package
uses: ./.github/actions/build-npm-package
with:
hermes-ws-dir: ${{ env.HERMES_WS_DIR }}
release-type: ${{ needs.set_release_type.outputs.RELEASE_TYPE }}
gha-npm-token: ${{ env.GHA_NPM_TOKEN }}
gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }}
+1 -4
View File
@@ -2,7 +2,7 @@ name: On Issue Labeled
# This workflow is triggered when a label is added to an issue.
on:
issues:
types: [labeled]
types: labeled
permissions:
contents: write
@@ -21,7 +21,6 @@ jobs:
- name: Verify RN version
uses: actions/github-script@v6
with:
github-token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
script: |
const verifyVersion = require('./.github/workflow-scripts/verifyVersion.js')
const labelWithContext = await verifyVersion(github, context);
@@ -41,7 +40,6 @@ jobs:
- name: Add descriptive label
uses: actions/github-script@v6
with:
github-token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
script: |
const addDescriptiveLabel = require('./.github/workflow-scripts/addDescriptiveLabels.js')
await addDescriptiveLabel(github, context);
@@ -54,7 +52,6 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/github-script@v6
with:
github-token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
script: |
const actOnLabel = require('./.github/workflow-scripts/actOnLabel.js')
await actOnLabel(github, context, {label: context.payload.label.name})
-212
View File
@@ -1,212 +0,0 @@
name: Prebuild iOS Dependencies
on:
workflow_call: # this directive allow us to call this workflow from other workflows
jobs:
build-rn-slice:
runs-on: macos-14
strategy:
fail-fast: false
matrix:
flavor: ['Debug', 'Release']
slice: [
'ios',
'ios-simulator',
'mac-catalyst',
]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Restore cache if present
id: restore-ios-slice
uses: actions/cache/restore@v4
with:
key: v3-ios-core-${{ matrix.slice }}-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift', 'packages/react-native/scripts/ios-prebuild/setup.js', 'packages/react-native/React/**/*', 'packages/react-native/ReactCommon/**/*', 'packages/react-native/Libraries/**/*') }}
path: packages/react-native/
- name: Setup node.js
if: steps.restore-ios-slice.outputs.cache-hit != 'true'
uses: ./.github/actions/setup-node
- name: Setup xcode
if: steps.restore-ios-slice.outputs.cache-hit != 'true'
uses: ./.github/actions/setup-xcode
with:
xcode-version: '16.2.0'
- name: Yarn Install
if: steps.restore-ios-slice.outputs.cache-hit != 'true'
uses: ./.github/actions/yarn-install
- name: Download Hermes
if: steps.restore-ios-slice.outputs.cache-hit != 'true'
uses: actions/download-artifact@v4
with:
name: hermes-darwin-bin-${{ matrix.flavor }}
path: /tmp/hermes/hermes-runtime-darwin
- name: Extract Hermes
if: steps.restore-ios-slice.outputs.cache-hit != 'true'
shell: bash
run: |
HERMES_TARBALL_ARTIFACTS_DIR=/tmp/hermes/hermes-runtime-darwin
if [ ! -d $HERMES_TARBALL_ARTIFACTS_DIR ]; then
echo "Hermes tarball artifacts dir not present ($HERMES_TARBALL_ARTIFACTS_DIR)."
exit 0
fi
TARBALL_FILENAME=$(node ./packages/react-native/scripts/hermes/get-tarball-name.js --buildType "${{ matrix.flavor }}")
TARBALL_PATH=$HERMES_TARBALL_ARTIFACTS_DIR/$TARBALL_FILENAME
echo "Looking for $TARBALL_FILENAME in $HERMES_TARBALL_ARTIFACTS_DIR"
echo "$TARBALL_PATH"
if [ ! -f $TARBALL_PATH ]; then
echo "Hermes tarball not present ($TARBALL_PATH). Build Hermes from source."
exit 0
fi
echo "Found Hermes tarball at $TARBALL_PATH"
echo "HERMES_ENGINE_TARBALL_PATH=$TARBALL_PATH" >> $GITHUB_ENV
- name: Download ReactNativeDependencies
uses: actions/download-artifact@v4
with:
name: ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz
path: /tmp/third-party/
- name: Extract ReactNativeDependencies
if: steps.restore-ios-slice.outputs.cache-hit != 'true'
shell: bash
run: |
# Extract ReactNativeDependencies
tar -xzf /tmp/third-party/ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz -C /tmp/third-party/
# Create destination folder
mkdir -p packages/react-native/third-party/
# Move the XCFramework in the destination directory
mv /tmp/third-party/packages/react-native/third-party/ReactNativeDependencies.xcframework packages/react-native/third-party/ReactNativeDependencies.xcframework
VERSION=$(jq -r '.version' packages/react-native/package.json)
echo "$VERSION-${{matrix.flavor}}" > "packages/react-native/third-party/version.txt"
cat "packages/react-native/third-party/version.txt"
# Check destination directory
ls -lR packages/react-native/third-party/
- name: Setup the workspace
if: steps.restore-ios-slice.outputs.cache-hit != 'true'
shell: bash
run: |
cd packages/react-native
node scripts/ios-prebuild.js -s -f "${{ matrix.flavor }}"
- name: Build React Native
if: steps.restore-ios-slice.outputs.cache-hit != 'true'
shell: bash
run: |
# This is going to be replaced by a CLI script
cd packages/react-native
node scripts/ios-prebuild -b -f "${{ matrix.flavor }}" -p "${{ matrix.slice }}"
- name: Upload headers
uses: actions/upload-artifact@v4
with:
name: prebuild-ios-core-headers-${{ matrix.flavor }}-${{ matrix.slice }}
path:
packages/react-native/.build/headers
- name: Upload artifacts
uses: actions/upload-artifact@v4.3.4
with:
name: prebuild-ios-core-slice-${{ matrix.flavor }}-${{ matrix.slice }}
path: |
packages/react-native/.build/output/spm/${{ matrix.flavor }}/Build/Products
- name: Save Cache
uses: actions/cache/save@v4
if: ${{ github.ref == 'refs/heads/main' }} # To avoid that the cache explode
with:
key: v3-ios-core-${{ matrix.slice }}-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift', 'packages/react-native/scripts/ios-prebuild/setup.js', 'packages/react-native/React/**/*', 'packages/react-native/ReactCommon/**/*', 'packages/react-native/Libraries/**/*') }}
path: |
packages/react-native/.build/output/spm/${{ matrix.flavor }}/Build/Products
packages/react-native/.build/headers
compose-xcframework:
runs-on: macos-14
needs: [build-rn-slice]
strategy:
fail-fast: false
matrix:
flavor: ['Debug', 'Release']
env:
REACT_ORG_CODE_SIGNING_P12_CERT: ${{ secrets.REACT_ORG_CODE_SIGNING_P12_CERT }}
REACT_ORG_CODE_SIGNING_P12_CERT_PWD: ${{ secrets.REACT_ORG_CODE_SIGNING_P12_CERT_PWD }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Restore cache if present
id: restore-ios-xcframework
uses: actions/cache/restore@v4
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/setup.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
- name: Setup xcode
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
uses: ./.github/actions/setup-xcode
with:
xcode-version: '16.2.0'
- name: Yarn Install
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
uses: ./.github/actions/yarn-install
- name: Download slice artifacts
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
uses: actions/download-artifact@v4
with:
pattern: prebuild-ios-core-slice-${{ matrix.flavor }}-*
path: packages/react-native/.build/output/spm/${{ matrix.flavor }}/Build/Products
merge-multiple: true
- name: Download headers
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
uses: actions/download-artifact@v4
with:
pattern: prebuild-ios-core-headers-${{ matrix.flavor }}-*
path: packages/react-native/.build/headers
merge-multiple: true
- 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
with:
p12-file-base64: ${{ secrets.REACT_ORG_CODE_SIGNING_P12_CERT }}
p12-password: ${{ secrets.REACT_ORG_CODE_SIGNING_P12_CERT_PWD }}
- name: Create XCFramework
if: ${{ steps.restore-ios-xcframework.outputs.cache-hit != 'true' && env.REACT_ORG_CODE_SIGNING_P12_CERT == '' }}
run: |
cd packages/react-native
node scripts/ios-prebuild -c -f "${{ matrix.flavor }}"
- name: Create and Sign XCFramework
if: ${{ steps.restore-ios-xcframework.outputs.cache-hit != 'true' && env.REACT_ORG_CODE_SIGNING_P12_CERT != '' }}
run: |
cd packages/react-native
node scripts/ios-prebuild -c -f "${{ matrix.flavor }}" -i "React Org"
- 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
- 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: Upload XCFramework Artifact
uses: actions/upload-artifact@v4
with:
name: ReactCore${{ matrix.flavor }}.xcframework.tar.gz
path: packages/react-native/.build/output/xcframeworks/ReactCore${{matrix.flavor}}.xcframework.tar.gz
- name: Upload dSYM Artifact
uses: actions/upload-artifact@v4
with:
name: ReactCore${{ matrix.flavor }}.framework.dSYM.tar.gz
path: packages/react-native/.build/output/xcframeworks/ReactCore${{matrix.flavor}}.framework.dSYM.tar.gz
- name: Save cache if present
if: ${{ github.ref == 'refs/heads/main' }} # To avoid that the cache explode
uses: actions/cache/save@v4
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/setup.js', 'packages/react-native/React/**/*', 'packages/react-native/ReactCommon/**/*', 'packages/react-native/Libraries/**/*') }}
@@ -1,202 +0,0 @@
name: Prebuild iOS Dependencies
on:
workflow_call: # this directive allow us to call this workflow from other workflows
jobs:
prepare_workspace:
name: Prepare workspace
runs-on: macos-14
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup node.js
uses: ./.github/actions/setup-node
- name: Restore cache if present
id: restore-ios-prebuilds
uses: actions/cache/restore@v4
with:
path: packages/react-native/third-party/
key: v2-ios-dependencies-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js') }}
enableCrossOsArchive: true
- name: Yarn Install
if: steps.restore-ios-prebuilds.outputs.cache-hit != 'true'
uses: ./.github/actions/yarn-install
- name: Prepare Dependencies
if: steps.restore-ios-prebuilds.outputs.cache-hit != 'true'
run: |
node scripts/releases/prepare-ios-prebuilds.js -s
- name: Generate Package.swift
if: steps.restore-ios-prebuilds.outputs.cache-hit != 'true'
run: |
node scripts/releases/prepare-ios-prebuilds.js -w
- name: Upload Artifacts
uses: actions/upload-artifact@v4.3.4
with:
name: ios-prebuilds-workspace
path: packages/react-native/third-party/
- name: Save Cache
uses: actions/cache/save@v4
if: ${{ github.ref == 'refs/heads/main' }} # To avoid that the cache explode
with:
key: v2-ios-dependencies-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js') }}
enableCrossOsArchive: true
path: packages/react-native/third-party/
build-apple-slices:
name: Build Apple Slice
runs-on: macos-14
needs: [prepare_workspace]
strategy:
fail-fast: false
matrix:
flavor: ['Debug', 'Release']
slice: ['ios',
'ios-simulator',
'macos',
'mac-catalyst',
'tvos',
'tvos-simulator',
'xros',
'xros-simulator']
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup node.js
uses: ./.github/actions/setup-node
- name: Setup xcode
uses: ./.github/actions/setup-xcode
with:
xcode-version: '16.1'
- name: Restore slice folder
id: restore-slice-folder
uses: actions/cache/restore@v4
with:
path: packages/react-native/third-party/.build/Build/Products
key: v2-ios-dependencies-slice-folder-${{ matrix.slice }}-${{ matrix.flavor }}-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js') }}
- name: Yarn Install
if: steps.restore-slice-folder.outputs.cache-hit != 'true'
uses: ./.github/actions/yarn-install
- name: Restore workspace
if: steps.restore-slice-folder.outputs.cache-hit != 'true'
uses: actions/download-artifact@v4
with:
name: ios-prebuilds-workspace
path: packages/react-native/third-party/
- name: Print third-party folder structure
run: ls -lR packages/react-native/third-party
- name: Install VisionOS
if: ${{ steps.restore-slice-folder.outputs.cache-hit != 'true' && (matrix.slice == 'xros' || matrix.slice == 'xros-simulator') }}
run: |
# https://github.com/actions/runner-images/issues/10559
sudo xcodebuild -runFirstLaunch
sudo xcrun simctl list
sudo xcodebuild -downloadPlatform visionOS
sudo xcodebuild -runFirstLaunch
- name: Build slice ${{ matrix.slice }} for ${{ matrix.flavor }}
if: steps.restore-slice-folder.outputs.cache-hit != 'true'
run: node scripts/releases/prepare-ios-prebuilds.js -b -p ${{ matrix.slice }} -r ${{ matrix.flavor }}
- name: Upload Artifacts
uses: actions/upload-artifact@v4.3.4
with:
name: prebuild-slice-${{ matrix.flavor }}-${{ matrix.slice }}
path: |
packages/react-native/third-party/.build/Build/Products
- name: Save Cache
uses: actions/cache/save@v4
if: ${{ github.ref == 'refs/heads/main' }} # To avoid that the cache explode
with:
key: v2-ios-dependencies-slice-folder-${{ matrix.slice }}-${{ matrix.flavor }}-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js') }}
enableCrossOsArchive: true
path: |
packages/react-native/third-party/.build/Build/Products
create-xcframework:
name: Prepare XCFramework
runs-on: macos-14
needs: [build-apple-slices]
strategy:
fail-fast: false
matrix:
flavor: [Debug, Release]
env:
REACT_ORG_CODE_SIGNING_P12_CERT: ${{ secrets.REACT_ORG_CODE_SIGNING_P12_CERT }}
REACT_ORG_CODE_SIGNING_P12_CERT_PWD: ${{ secrets.REACT_ORG_CODE_SIGNING_P12_CERT_PWD }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup node.js
uses: ./.github/actions/setup-node
- name: Setup xcode
uses: ./.github/actions/setup-xcode
with:
xcode-version: '16.1'
- name: Restore XCFramework
id: restore-xcframework
uses: actions/cache/restore@v4
with:
path: |
packages/react-native/third-party/
key: v2-ios-dependencies-xcframework-${{ matrix.flavor }}-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js') }}
# If cache hit, we already have our binary. We don't need to do anything.
- name: Yarn Install
if: steps.restore-xcframework.outputs.cache-hit != 'true'
uses: ./.github/actions/yarn-install
- name: Restore workspace
if: steps.restore-xcframework.outputs.cache-hit != 'true'
uses: actions/download-artifact@v4
with:
name: ios-prebuilds-workspace
path: packages/react-native/third-party/
- name: Download slices
if: steps.restore-xcframework.outputs.cache-hit != 'true'
uses: actions/download-artifact@v4
with:
pattern: prebuild-slice-${{ matrix.flavor }}-*
path: packages/react-native/third-party/.build/Build/Products
merge-multiple: true
- name: Setup Keychain
if: ${{ steps.restore-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
with:
p12-file-base64: ${{ secrets.REACT_ORG_CODE_SIGNING_P12_CERT }}
p12-password: ${{ secrets.REACT_ORG_CODE_SIGNING_P12_CERT_PWD }}
- name: Create XCFramework
if: ${{ steps.restore-xcframework.outputs.cache-hit != 'true' && env.REACT_ORG_CODE_SIGNING_P12_CERT == '' }}
run: node scripts/releases/prepare-ios-prebuilds.js -c
- name: Create and Sign XCFramework
if: ${{ steps.restore-xcframework.outputs.cache-hit != 'true' && env.REACT_ORG_CODE_SIGNING_P12_CERT != '' }}
run: node scripts/releases/prepare-ios-prebuilds.js -c -i "React Org"
- name: Compress and Rename XCFramework
if: steps.restore-xcframework.outputs.cache-hit != 'true'
run: |
tar -cz -f packages/react-native/third-party/ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz \
packages/react-native/third-party/ReactNativeDependencies.xcframework
- name: Show Symbol folder content
if: steps.restore-xcframework.outputs.cache-hit != 'true'
run: ls -lR packages/react-native/third-party/Symbols
- name: Compress and Rename dSYM
if: steps.restore-xcframework.outputs.cache-hit != 'true'
run: |
tar -cz -f packages/react-native/third-party/Symbols/ReactNativeDependencies${{ matrix.flavor }}.framework.dSYM.tar.gz \
packages/react-native/third-party/Symbols/ReactNativeDependencies.framework.dSYM
- name: Upload XCFramework Artifact
uses: actions/upload-artifact@v4
with:
name: ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz
path: packages/react-native/third-party/ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz
- name: Upload dSYM Artifact
uses: actions/upload-artifact@v4
with:
name: ReactNativeDependencies${{ matrix.flavor }}.framework.dSYM.tar.gz
path: |
packages/react-native/third-party/Symbols/ReactNativeDependencies${{ matrix.flavor }}.framework.dSYM.tar.gz
- name: Save XCFramework in Cache
if: ${{ github.ref == 'refs/heads/main' }} # To avoid that the cache explode
uses: actions/cache/save@v4
with:
path: |
packages/react-native/third-party/ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz
packages/react-native/third-party/ReactNativeDependencies${{ matrix.flavor }}.framework.dSYM.tar.gz
key: v2-ios-dependencies-xcframework-${{ matrix.flavor }}-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js') }}
@@ -1,28 +0,0 @@
name: Publish Bumped Packages
on:
push:
branches:
- "main"
- "*-stable"
jobs:
publish_bumped_packages:
runs-on: ubuntu-latest
env:
GHA_NPM_TOKEN: ${{ secrets.GHA_NPM_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup node.js
uses: ./.github/actions/setup-node
- name: Run Yarn Install
uses: ./.github/actions/yarn-install
- name: Build packages
run: yarn build
- name: Build types
run: yarn build-types --skip-snapshot
- name: Set NPM auth token
run: echo "//registry.npmjs.org/:_authToken=$GHA_NPM_TOKEN" > ~/.npmrc
- name: Find and publish all bumped packages
run: node ./scripts/releases-ci/publish-updated-packages.js
-239
View File
@@ -1,239 +0,0 @@
name: Publish Release
on:
push:
tags:
- "v0.*.*" # This should match v0.X.Y
- "v0.*.*-rc.*" # This should match v0.X.Y-RC.0
jobs:
set_release_type:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
outputs:
RELEASE_TYPE: ${{ steps.set_release_type.outputs.RELEASE_TYPE }}
env:
EVENT_NAME: ${{ github.event_name }}
REF: ${{ github.ref }}
steps:
- id: set_release_type
run: |
echo "Setting release type to release"
echo "RELEASE_TYPE=release" >> $GITHUB_OUTPUT
prepare_hermes_workspace:
runs-on: ubuntu-latest
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_VERSION_FILE: packages/react-native/sdks/.hermesversion
outputs:
react-native-version: ${{ steps.prepare-hermes-workspace.outputs.react-native-version }}
hermes-version: ${{ steps.prepare-hermes-workspace.outputs.hermes-version }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Prepare Hermes Workspace
id: prepare-hermes-workspace
uses: ./.github/actions/prepare-hermes-workspace
with:
hermes-ws-dir: ${{ env.HERMES_WS_DIR }}
hermes-version-file: ${{ env.HERMES_VERSION_FILE }}
build_hermesc_apple:
runs-on: macos-14
needs: prepare_hermes_workspace
env:
HERMES_WS_DIR: /tmp/hermes
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build HermesC Apple
uses: ./.github/actions/build-hermesc-apple
with:
hermes-version: ${{ needs.prepare_hermes_workspace.output.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.output.react-native-version }}
build_apple_slices_hermes:
runs-on: macos-14
needs: [build_hermesc_apple, prepare_hermes_workspace]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
HERMES_OSXBIN_ARTIFACTS_DIR: /tmp/hermes/osx-bin
IOS_DEPLOYMENT_TARGET: "15.1"
XROS_DEPLOYMENT_TARGET: "1.0"
MAC_DEPLOYMENT_TARGET: "10.15"
strategy:
fail-fast: false
matrix:
flavor: [Debug, Release]
slice: [macosx, iphoneos, iphonesimulator, appletvos, appletvsimulator, catalyst, xros, xrsimulator]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build Slice
uses: ./.github/actions/build-apple-slices-hermes
with:
flavor: ${{ matrix.flavor }}
slice: ${{ matrix.slice}}
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
build_hermes_macos:
runs-on: macos-14
needs: [build_apple_slices_hermes, prepare_hermes_workspace]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
continue-on-error: true
strategy:
fail-fast: false
matrix:
flavor: [Debug, Release]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build Hermes MacOS
uses: ./.github/actions/build-hermes-macos
with:
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
flavor: ${{ matrix.flavor }}
prebuild_apple_dependencies:
uses: ./.github/workflows/prebuild-ios-dependencies.yml
secrets: inherit
prebuild_react_native_core:
uses: ./.github/workflows/prebuild-ios-core.yml
secrets: inherit
needs: [prebuild_apple_dependencies, build_hermes_macos]
build_hermesc_linux:
runs-on: ubuntu-latest
needs: prepare_hermes_workspace
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build HermesC Linux
uses: ./.github/actions/build-hermesc-linux
with:
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
build_hermesc_windows:
runs-on: windows-2025
needs: prepare_hermes_workspace
env:
HERMES_WS_DIR: 'C:\tmp\hermes'
HERMES_TARBALL_ARTIFACTS_DIR: 'C:\tmp\hermes\hermes-runtime-darwin'
HERMES_OSXBIN_ARTIFACTS_DIR: 'C:\tmp\hermes\osx-bin'
ICU_URL: "https://github.com/unicode-org/icu/releases/download/release-64-2/icu4c-64_2-Win64-MSVC2017.zip"
MSBUILD_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin'
CMAKE_DIR: 'C:\Program Files\CMake\bin'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build HermesC Windows
uses: ./.github/actions/build-hermesc-windows
with:
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
build_npm_package:
runs-on: 8-core-ubuntu
needs:
[
set_release_type,
prepare_hermes_workspace,
build_hermes_macos,
build_hermesc_linux,
build_hermesc_windows,
prebuild_apple_dependencies,
prebuild_react_native_core,
]
container:
image: reactnativecommunity/react-native-android:latest
env:
TERM: "dumb"
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
# By default we only build ARM64 to save time/resources. For release/nightlies, we override this value to build all archs.
ORG_GRADLE_PROJECT_reactNativeArchitectures: "arm64-v8a"
env:
HERMES_WS_DIR: /tmp/hermes
GHA_NPM_TOKEN: ${{ secrets.GHA_NPM_TOKEN }}
ORG_GRADLE_PROJECT_SIGNING_PWD: ${{ secrets.ORG_GRADLE_PROJECT_SIGNING_PWD }}
ORG_GRADLE_PROJECT_SIGNING_KEY: ${{ secrets.ORG_GRADLE_PROJECT_SIGNING_KEY }}
ORG_GRADLE_PROJECT_SONATYPE_USERNAME: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPE_USERNAME }}
ORG_GRADLE_PROJECT_SONATYPE_PASSWORD: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPE_PASSWORD }}
REACT_NATIVE_BOT_GITHUB_TOKEN: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Build and Publish NPM Package
uses: ./.github/actions/build-npm-package
with:
hermes-ws-dir: ${{ env.HERMES_WS_DIR }}
release-type: ${{ needs.set_release_type.outputs.RELEASE_TYPE }}
gha-npm-token: ${{ env.GHA_NPM_TOKEN }}
gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }}
- name: Publish @react-native-community/template
id: publish-template-to-npm
uses: actions/github-script@v6
with:
github-token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
script: |
const {publishTemplate} = require('./.github/workflow-scripts/publishTemplate.js')
const version = "${{ github.ref_name }}"
const isDryRun = false
await publishTemplate(github, version, isDryRun);
- name: Wait for template to be published
timeout-minutes: 3
uses: actions/github-script@v6
with:
github-token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
script: |
const {verifyPublishedTemplate, isLatest} = require('./.github/workflow-scripts/publishTemplate.js')
const version = "${{ github.ref_name }}"
await verifyPublishedTemplate(version, isLatest());
- name: Update rn-diff-purge to generate upgrade-support diff
run: |
curl -X POST https://api.github.com/repos/react-native-community/rn-diff-purge/dispatches \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: Bearer $REACT_NATIVE_BOT_GITHUB_TOKEN" \
-d "{\"event_type\": \"publish\", \"client_payload\": { \"version\": \"${{ github.ref_name }}\" }}"
- name: Verify Release is on NPM
timeout-minutes: 3
uses: actions/github-script@v6
with:
github-token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
script: |
const {verifyReleaseOnNpm} = require('./.github/workflow-scripts/verifyReleaseOnNpm.js');
const {isLatest} = require('./.github/workflow-scripts/publishTemplate.js');
const version = "${{ github.ref_name }}";
await verifyReleaseOnNpm(version, isLatest());
- name: Verify that artifacts are on Maven
uses: actions/github-script@v6
with:
script: |
const {verifyArtifactsAreOnMaven} = require('./.github/workflow-scripts/verifyArtifactsAreOnMaven.js');
const version = "${{ github.ref_name }}";
await verifyArtifactsAreOnMaven(version);
generate_changelog:
needs: build_npm_package
uses: ./.github/workflows/generate-changelog.yml
secrets: inherit
bump_podfile_lock:
needs: build_npm_package
uses: ./.github/workflows/bump-podfile-lock.yml
secrets: inherit
create_draft_release:
needs: generate_changelog
uses: ./.github/workflows/create-draft-release.yml
secrets: inherit
-19
View File
@@ -1,19 +0,0 @@
name: Retry workflow
# Based on https://stackoverflow.com/a/78314483
on:
workflow_dispatch:
inputs:
run_id:
required: true
jobs:
rerun:
runs-on: ubuntu-latest
steps:
- name: rerun ${{ inputs.run_id }}
env:
GH_REPO: ${{ github.repository }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh run watch ${{ inputs.run_id }} > /dev/null 2>&1
gh run rerun ${{ inputs.run_id }} --failed
+26
View File
@@ -0,0 +1,26 @@
name: Run E2E Tests
# This workflow is used to trigger E2E tests on a PR when a comment is made
# containing the text "#run-e2e-tests".
on:
issue_comment:
types: [created]
permissions:
contents: read
jobs:
rebase:
name: Trigger E2E Tests
permissions:
contents: write # for cirrus-actions/rebase to push code to rebase
pull-requests: read # for cirrus-actions/rebase to get info about PR
runs-on: ubuntu-latest
if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '#run-e2e-tests')
steps:
- name: Checkout the latest code
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0 # otherwise, you will fail to push refs to dest repo
- name: Push empty commit
run: |
git commit -m "#run-e2e-tests" --allow-empty
git push origin $(git branch --show-current)
+11 -11
View File
@@ -1,4 +1,4 @@
name: Stale bot
name: Mark stale issues and pull requests
on:
schedule:
- cron: "*/10 5 * * *"
@@ -10,12 +10,12 @@ jobs:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v9
- uses: actions/stale@v5
with:
repo-token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 180
stale-issue-message: 'This issue is stale because it has been open for 180 days with no activity. It will be closed in 7 days unless you comment on it or remove the "Stale" label.'
stale-pr-message: 'This PR is stale because it has been open for 180 days with no activity. It will be closed in 7 days unless you comment on it or remove the "Stale" label.'
stale-issue-message: 'This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.'
stale-pr-message: 'This PR is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.'
close-issue-message: 'This issue was closed because it has been stalled for 7 days with no activity.'
close-pr-message: 'This PR was closed because it has been stalled for 7 days with no activity.'
exempt-issue-labels: 'Help Wanted :octocat:, Good first issue, Never gets stale, Issue: Author Provided Repro'
@@ -27,10 +27,10 @@ jobs:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v9
- uses: actions/stale@v5
with:
ascending: true
repo-token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 180
stale-issue-message: 'This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.'
stale-pr-message: 'This PR is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.'
@@ -45,9 +45,9 @@ jobs:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v9
- uses: actions/stale@v5
with:
repo-token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
repo-token: ${{ secrets.GITHUB_TOKEN }}
any-of-labels: 'Needs: Author Feedback'
days-before-stale: 24
stale-issue-message: "This issue is waiting for author's feedback since 24 days. Please provide the requested feedback or this will be closed in 7 days."
@@ -63,10 +63,10 @@ jobs:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v9
- uses: actions/stale@v5
with:
ascending: true
repo-token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
repo-token: ${{ secrets.GITHUB_TOKEN }}
any-of-labels: 'Needs: Author Feedback'
days-before-stale: 24
stale-issue-message: "This issue is waiting for author's feedback since 24 days. Please provide the requested feedback or this will be closed in 7 days."

Some files were not shown because too many files have changed in this diff Show More