Compare commits

..
Author SHA1 Message Date
Mike Grabowski 27ebc7f786 [0.47.2] Bump version numbers 2017-08-22 10:59:41 +02:00
Valentin SherginandMike Grabowski e3fd144b4a TextInput: Refined contentSize calculation
Summary: This fixes pretty bad issue when contentSize is calculated based on an intrinsic horizontal (width) limitation, not on a real/current horizontal (width) one.

Reviewed By: mmmulani

Differential Revision: D5422114

fbshipit-source-id: 0eb582aeb59d29530990d4faabf2f41baa79c058
2017-08-22 10:30:59 +02:00
Mike Grabowski 7442dc8899 [0.47.1] Bump version numbers 2017-08-02 14:22:57 +02:00
Parashuram NandMike Grabowski b461bde9f9 Updating the usage of inquirer API
Summary:
Inquirer was changed to a later version in https://github.com/facebook/react-native/commit/bada25d158e070fd683a10b8ff9cdcb8d2498b14. However, the API also needed to be updated to use a promise based version.
Closes https://github.com/facebook/react-native/pull/14848

Differential Revision: D5375663

Pulled By: javache

fbshipit-source-id: 635798a43905301c65db5f63b9cfba1c16964870
2017-08-02 14:22:52 +02:00
Hector RamosandMike Grabowski 4223f116fa Fix navigation menu regression on mobile
Summary:
Regression introduced in 75eb55096e and identified by Conor O'Donnell (https://twitter.com/ronocod/status/892400271980146689).

Verify mobile layout on iPhone 6, iPhone 7 Plus, Galaxy S5, Nexus 5.
<img width="269" alt="screen shot 2017-08-01 at 9 13 42 am" src="https://user-images.githubusercontent.com/165856/28835318-cdd20cc8-7699-11e7-9232-a657a93cfb1c.png">

Verify desktop layout at widths ranging from 400px to 1400px.

<img width="1303" alt="screen shot 2017-08-01 at 9 14 44 am" src="https://user-images.githubusercontent.com/165856/28835352-e33a97e2-7699-11e7-969e-db607e9a0162.png">
Closes https://github.com/facebook/react-native/pull/15314

Differential Revision: D5537209

Pulled By: hramos

fbshipit-source-id: 3ccf71a90dda4b9b1a059178a400bea9f253bf14
2017-08-02 14:20:23 +02:00
Mike Grabowski 8c3fbfa3b2 [0.47.0] Bump version numbers 2017-08-01 17:19:50 +02:00
Benjamin DobellandMike Grabowski 1cf9482032 Request toolbar layout after drawable loads
Summary:
Fixes #11209

Updating action items in a `ToolbarAndroid`, or more specifically the native `ReactToolbar`, after the initial render presently will not always work as expected - typically manifesting itself as new action items not being displayed at all (under certain circumstances).

This seems to be happening because Fresco gets back to us asynchronously and updates the `MenuItem` in a listener. However when a keyboard is displayed the `Toolbar` is in a weird state where updating the `MenuItem` doesn't automatically trigger a layout.

The solution is to trigger one manually.

This is a bit wacky, so I created a sample project:

https://github.com/Benjamin-Dobell/DynamicToolbar

`master` demonstrates the problem. Run the project, the toolbar action item is scheduled to update every 2 seconds. It works fine _until_ you give the `TextInput` focus. Once you give it focus the action item disappears and it never recovers (despite on-going renders due to state changes).

You can then checkout the `fixed` branch, run `yarn` again, and see that problem is fixed. This branch is using a prebuilt version of React Native with this patch applied. Of course you could (and probably should) also modify `master` to use a version of RN built by the Facebook CI (assuming that's a thing you guys do).
Closes https://github.com/facebook/react-native/pull/13876

Differential Revision: D5476858

Pulled By: shergin

fbshipit-source-id: 6634d8cb3ee18fd99f7dc4e1eef348accc1c45ad
2017-08-01 17:19:42 +02:00
Krzysztof MagieraandMike Grabowski 02a8882270 Stop native driver animations when value is set.
Summary:
This diff changes the behaviour of natively driven animations in case the node that they are being run for has its value changed using `setValue` or as a result of an incoming event.

The reason for changing that is to match the JS implementation of `setValue` which behaves as described above (see relevant code here: https://github.com/facebook/react-native/blob/7cdd4d48c89ad642a1c107e0b40c25eb75682175/Libraries/Animated/src/AnimatedImplementation.js#L743)

**Test Plan:**
Use this sample app: https://snack.expo.io/B1V7RX9r-
Change: `USE_NATIVE_DRIVER` const between `true` and `false`.
See the animation stops regardless of the state of `USE_NATIVE_DRIVER` unlike before when it would stop only when `USE_NATIVE_DRIVER` was set to `false`
Closes https://github.com/facebook/react-native/pull/15054

Differential Revision: D5463750

Pulled By: hramos

fbshipit-source-id: e164c5299588ba8cac2937260c9ba9f6053b04e5
2017-08-01 17:19:19 +02:00
Hector Ramos e24536688f Remove styleguide. 2017-07-28 11:44:22 -07:00
Hector Ramos 293bf4a852 What to Expect from Maintainers
Summary:
Adds a new maintainers guide, and updates the contributor's guide to be consistent with regards to this new guide.

Some additional style changes made in order to support the display of bot commands. Changed the wording for the "Edit this page on GitHub" link.

Finally, the contributor's guide is now synced to `CONTRIBUTING.md` on the repo.

```
cd website && npm start
```

Verify that `CONTRIBUTING.md` is updated whenever the website is regenerated.

Verify everything rendered correctly. Expand the details below to see screenshots.

<details>

![screencapture-localhost-8079-react-native-docs-contributing-html-1501016495792](https://user-images.githubusercontent.com/165856/28593706-33d1e03c-7142-11e7-9878-04ead7561abc.png)

![screencapture-localhost-8079-react-native-docs-maintainers-html-1501016508744](https://user-images.githubusercontent.com/165856/28593719-3812d7fa-7142-11e7-9db2-f9599057d726.png)
</details>
Closes https://github.com/facebook/react-native/pull/15202

Differential Revision: D5494246

Pulled By: hramos

fbshipit-source-id: e28d5624d1e4795e212f10e8d5713d91a0eae15f
2017-07-28 11:44:11 -07:00
James Ide 0aa7743b5f [0.47.0-rc.5] Bump version numbers 2017-07-26 16:56:28 -07:00
sm2017andJames Ide 048a5fd57c Update WebSocketModule.java
Summary:
Convert to base64 not utf8

<!--
Thank you for sending the PR!

If you changed any code, please provide us with clear instructions on how you verified your changes work. In other words, a test plan is *required*. Bonus points for screenshots and videos!

Please read the Contribution Guidelines at https://github.com/facebook/react-native/blob/master/CONTRIBUTING.md to learn more about contributing to React Native.

Happy contributing!
-->
Closes https://github.com/facebook/react-native/pull/15046

Differential Revision: D5451398

Pulled By: javache

fbshipit-source-id: b8c6c7b0fb50ca9558e92d3f63a088e343791b7f
2017-07-26 16:55:38 -07:00
James Ide 9194b9da80 Control whether Metro tells Babel to lookup .babelrc files
Summary:
This adds support to RN's configuration file to let people turn off Babel's behavior of looking up .babelrc files. Most of the support for this feature is in Metro (https://github.com/facebook/metro-bundler/pull/31).
Closes https://github.com/facebook/react-native/pull/15136

Differential Revision: D5483241

Pulled By: jeanlauliac

fbshipit-source-id: c78096c1574c9f844c9f34aff73e6f97cb0b5e45
2017-07-26 16:53:21 -07:00
Hector RamosandHector Ramos 07de8556a5 How to Contribute updates
Summary:
Rename "Testing" guide. Add docs for several new GitHub bot commands. Format commands table.

Built website and verified everything looks good.
Closes https://github.com/facebook/react-native/pull/15111

Differential Revision: D5458660

Pulled By: hramos

fbshipit-source-id: 151ea0cbd18489bc527193682464ca291d6ab467
2017-07-20 09:50:58 -07:00
Hector Ramos 48a537ca70 How to Contribute updates
Summary:
Rename "Testing" guide. Add docs for several new GitHub bot commands. Format commands table.

Built website and verified everything looks good.
Closes https://github.com/facebook/react-native/pull/15111

Differential Revision: D5458660

Pulled By: hramos

fbshipit-source-id: 151ea0cbd18489bc527193682464ca291d6ab467
2017-07-20 09:12:18 -07:00
Pieter De BaetsandHector Ramos db9c84480e Update podspec integration instructions
Summary:
You need to add CxxBridge or BatchedBridge as a dependency while we have both. When we stop shipping the BatchedBridge in OSS, this requirement will disappear again.
Closes https://github.com/facebook/react-native/pull/15084

Differential Revision: D5446885

Pulled By: javache

fbshipit-source-id: aa0023cc08e97fc59e2071a3750f98026e34fd0d
2017-07-19 14:33:55 -07:00
Hector Ramos e0fe9ea97d Move CONTRIBUTING guidelines to a standalone doc in the website.
Reviewed By: TheSavior

Differential Revision: D5448961

fbshipit-source-id: c8491b003413e8af22987ea578d6f7bbe1552b31
2017-07-19 12:54:24 -07:00
Mike Grabowski 26208b0e68 [0.47.0-rc.4] Bump version numbers 2017-07-17 14:01:56 -07:00
Brian VaughnandMike Grabowski 87f699dc76 React sync for revisions cb32253...5495e49
Reviewed By: acdlite

Differential Revision: D5416055

fbshipit-source-id: c69de0d699f11dec4a71fb6e3f924ade3446bba0
2017-07-17 14:01:41 -07:00
James Ide e681f30080 [0.47.0-rc.3] Bump version numbers 2017-07-12 17:53:05 -07:00
Steffen MatthischkeandJames Ide 5c9cf44556 Podspec: add required "DevSupport" dependency "InspectorInterfaces.{cpp,h}
Summary:
This PR fixes #14975.
* Podspec: add InspectorInterfaces.h/cpp to the "jschelpers_legacy" subspec.

1. lint the Podspecs: `./scripts/process-podspecs.sh`
2. check that an iOS project can integrate "DevSupport" via Cocoapods again. I'll already checked it on this branch of the demo project: https://github.com/HeEAaD/Demo-ReactNative-0.47.0-rc2-Podspec-issue/tree/fix
Closes https://github.com/facebook/react-native/pull/14988

Differential Revision: D5411733

Pulled By: javache

fbshipit-source-id: bb46cf3461e0857c7508264dafa204067af182c6
2017-07-12 17:52:37 -07:00
Mike Grabowski 3bc500f021 [0.47.0-rc.2] Bump version numbers 2017-07-11 15:18:27 -07:00
Seth FitzsimmonsandMike Grabowski 5f8c3e0291 Replace React.createClass with create-react-class
Summary:
This replaces all uses of `React.createClass` with `createReactClass` from the `create-react-class` package, attempting to match use of `var` and `const` according to local style.

Fixes #14620
Refs #14712
Closes https://github.com/facebook/react-native/pull/14729

Differential Revision: D5321810

Pulled By: hramos

fbshipit-source-id: ae7b40640b2773fd89c3fb727ec87f688bebf585
2017-07-11 15:17:46 -07:00
James Ide d2cb63dbc8 [0.47.0-rc.1] Bump version numbers 2017-07-07 12:42:49 -07:00
Pieter De BaetsandJames Ide cc4fadac5f Fix Travis podspec CI for Cxx bridge
Summary:
Fixed the test script to properly setup our third-party deps and tweaked the third-party specs a bit so they work correctly.

This currently works for projects using static libraries, but fails when using dynamic libraries (`--use-libraries`)

cc mhorowitz alloy
Closes https://github.com/facebook/react-native/pull/14100

Differential Revision: D5380728

Pulled By: javache

fbshipit-source-id: e78b6bd4466ebf2bf30b7e361eff10ec14b36a55
2017-07-07 12:41:25 -07:00
Marc HorowitzandJames Ide 0877f2c4de Make OSS CocoaPods build work with or without use_frameworks!
Reviewed By: javache

Differential Revision: D5361624

fbshipit-source-id: c2e5e8985827208a43e06932f746c6b9ccb146ad
2017-07-07 12:39:09 -07:00
Marc HorowitzandJames Ide 5470bb2c30 OSS build fix: use #import "..." instead of #import <RCTText/...>
Reviewed By: javache

Differential Revision: D5361615

fbshipit-source-id: 90d08eb5dea81253c1f7ea582ed2508eec1ba117
2017-07-07 12:38:59 -07:00
Mike Grabowski 8373e630c9 [0.47.0-rc.0] Bump version numbers 2017-07-05 21:44:15 +02:00
9156 changed files with 334183 additions and 900653 deletions
-8
View File
@@ -1,8 +0,0 @@
{
"presets": [
"module:@react-native/babel-preset"
],
"plugins": [
"babel-plugin-transform-flow-enums"
]
}
+12
View File
@@ -0,0 +1,12 @@
[android]
target = Google Inc.:Google APIs:23
[download]
max_number_of_retries = 3
[maven_repositories]
central = https://repo1.maven.org/maven2
[alias]
rntester = //RNTester/android/app:app
+1
View File
@@ -0,0 +1 @@
-Xmx512m -XX:+HeapDumpOnOutOfMemoryError
-2
View File
@@ -1,2 +0,0 @@
BUNDLE_PATH: "vendor/bundle"
BUNDLE_FORCE_RUBY_PLATFORM: 1
-4
View File
@@ -1,4 +0,0 @@
# Circle CI
This directory was home to the Circle CI configuration files.
In July 2024 we moved to GitHub Actions, and week this folder for backward compatibility, as we want to keep on using Circle CI for the release of React Native <= 0.74.
-13
View File
@@ -1,13 +0,0 @@
version: 2.1
workflows:
version: 2
stub:
jobs:
- circleci-stub
jobs:
circleci-stub:
docker:
- image: debian:bullseye
steps:
- run: echo "There is nothing here, just an empty job. Everything has been moved to GitHub Action"
-93
View File
@@ -1,93 +0,0 @@
---
AccessModifierOffset: -1
AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: true
AlignOperands: false
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: true
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: false
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ForEachMacros: [ FOR_EACH_RANGE, FOR_EACH, ]
IncludeCategories:
- Regex: '^<.*\.h(pp)?>'
Priority: 1
- Regex: '^<.*'
Priority: 2
- Regex: '.*'
Priority: 3
IndentCaseLabels: true
IndentWidth: 2
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 8
UseTab: Never
QualifierAlignment: Left
---
Language: ObjC
ColumnLimit: 120
BreakBeforeBraces: WebKit
PointerAlignment: Right
...
+1 -7
View File
@@ -1,4 +1,4 @@
# EditorConfig is awesome: https://EditorConfig.org
# EditorConfig is awesome: http://EditorConfig.org
# top-most EditorConfig file
root = true
@@ -12,9 +12,3 @@ indent_size = 2
[*.gradle]
indent_size = 4
[*.kts]
indent_size = 4
[BUCK]
indent_size = 4
+5 -16
View File
@@ -1,17 +1,6 @@
**/main.js
# node_modules ignored by default
**/staticBundle.js
docs/generatedComponentApiDocs.js
packages/react-native/flow/
packages/react-native/sdks/
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/debugger-frontend/dist/**/*
packages/react-native-codegen/lib
tools/eslint/rules/sort-imports.js
**/Pods/*
**/*.macos.js
**/*.windows.js
**/main.js
Libraries/vendor/**/*
packager/src/worker-farm/**/*
+246
View File
@@ -0,0 +1,246 @@
{
"parser": "babel-eslint",
"ecmaFeatures": {
"jsx": true
},
"env": {
"es6": true,
"jasmine": true,
},
"plugins": [
"react"
],
// Map from global var to bool specifying if it can be redefined
"globals": {
"__DEV__": true,
"__dirname": false,
"__fbBatchedBridgeConfig": false,
"alert": false,
"cancelAnimationFrame": false,
"cancelIdleCallback": false,
"clearImmediate": true,
"clearInterval": false,
"clearTimeout": false,
"console": false,
"document": false,
"escape": false,
"Event": false,
"EventTarget": false,
"exports": false,
"fetch": false,
"FormData": false,
"global": false,
"jest": false,
"Map": true,
"module": false,
"navigator": false,
"process": false,
"Promise": true,
"requestAnimationFrame": true,
"requestIdleCallback": true,
"require": false,
"Set": true,
"setImmediate": true,
"setInterval": false,
"setTimeout": false,
"window": false,
"XMLHttpRequest": false,
"pit": false,
// Flow global types.
"ReactComponent": false,
"ReactClass": false,
"ReactElement": false,
"ReactPropsCheckType": false,
"ReactPropsChainableTypeChecker": false,
"ReactPropTypes": false,
"SyntheticEvent": false,
"$Either": false,
"$All": false,
"$ArrayBufferView": false,
"$Tuple": false,
"$Supertype": false,
"$Subtype": false,
"$Shape": false,
"$Diff": false,
"$Keys": false,
"$Enum": false,
"$Exports": false,
"$FlowIssue": false,
"$FlowFixMe": false,
"$FixMe": false
},
"rules": {
"comma-dangle": 0, // disallow trailing commas in object literals
"no-cond-assign": 1, // disallow assignment in conditional expressions
"no-console": 0, // disallow use of console (off by default in the node environment)
"no-const-assign": 2, // disallow assignment to const-declared variables
"no-constant-condition": 0, // disallow use of constant expressions in conditions
"no-control-regex": 1, // disallow control characters in regular expressions
"no-debugger": 1, // disallow use of debugger
"no-dupe-keys": 1, // disallow duplicate keys when creating object literals
"no-empty": 0, // disallow empty statements
"no-ex-assign": 1, // disallow assigning to the exception in a catch block
"no-extra-boolean-cast": 1, // disallow double-negation boolean casts in a boolean context
"no-extra-parens": 0, // disallow unnecessary parentheses (off by default)
"no-extra-semi": 1, // disallow unnecessary semicolons
"no-func-assign": 1, // disallow overwriting functions written as function declarations
"no-inner-declarations": 0, // disallow function or variable declarations in nested blocks
"no-invalid-regexp": 1, // disallow invalid regular expression strings in the RegExp constructor
"no-negated-in-lhs": 1, // disallow negation of the left operand of an in expression
"no-obj-calls": 1, // disallow the use of object properties of the global object (Math and JSON) as functions
"no-regex-spaces": 1, // disallow multiple spaces in a regular expression literal
"no-reserved-keys": 0, // disallow reserved words being used as object literal keys (off by default)
"no-sparse-arrays": 1, // disallow sparse arrays
"no-unreachable": 1, // disallow unreachable statements after a return, throw, continue, or break statement
"use-isnan": 1, // disallow comparisons with the value NaN
"valid-jsdoc": 0, // Ensure JSDoc comments are valid (off by default)
"valid-typeof": 1, // Ensure that the results of typeof are compared against a valid string
// Best Practices
// These are rules designed to prevent you from making mistakes. They either prescribe a better way of doing something or help you avoid footguns.
"block-scoped-var": 0, // treat var statements as if they were block scoped (off by default)
"complexity": 0, // specify the maximum cyclomatic complexity allowed in a program (off by default)
"consistent-return": 0, // require return statements to either always or never specify values
"curly": 1, // specify curly brace conventions for all control statements
"default-case": 0, // require default case in switch statements (off by default)
"dot-notation": 1, // encourages use of dot notation whenever possible
"eqeqeq": [1, "allow-null"], // require the use of === and !==
"guard-for-in": 0, // make sure for-in loops have an if statement (off by default)
"no-alert": 1, // disallow the use of alert, confirm, and prompt
"no-caller": 1, // disallow use of arguments.caller or arguments.callee
"no-div-regex": 1, // disallow division operators explicitly at beginning of regular expression (off by default)
"no-else-return": 0, // disallow else after a return in an if (off by default)
"no-eq-null": 0, // disallow comparisons to null without a type-checking operator (off by default)
"no-eval": 1, // disallow use of eval()
"no-extend-native": 1, // disallow adding to native types
"no-extra-bind": 1, // disallow unnecessary function binding
"no-fallthrough": 1, // disallow fallthrough of case statements
"no-floating-decimal": 1, // disallow the use of leading or trailing decimal points in numeric literals (off by default)
"no-implied-eval": 1, // disallow use of eval()-like methods
"no-labels": 1, // disallow use of labeled statements
"no-iterator": 1, // disallow usage of __iterator__ property
"no-lone-blocks": 1, // disallow unnecessary nested blocks
"no-loop-func": 0, // disallow creation of functions within loops
"no-multi-str": 0, // disallow use of multiline strings
"no-native-reassign": 0, // disallow reassignments of native objects
"no-new": 1, // disallow use of new operator when not part of the assignment or comparison
"no-new-func": 1, // disallow use of new operator for Function object
"no-new-wrappers": 1, // disallows creating new instances of String,Number, and Boolean
"no-octal": 1, // disallow use of octal literals
"no-octal-escape": 1, // disallow use of octal escape sequences in string literals, such as var foo = "Copyright \251";
"no-proto": 1, // disallow usage of __proto__ property
"no-redeclare": 0, // disallow declaring the same variable more then once
"no-return-assign": 1, // disallow use of assignment in return statement
"no-script-url": 1, // disallow use of javascript: urls.
"no-self-compare": 1, // disallow comparisons where both sides are exactly the same (off by default)
"no-sequences": 1, // disallow use of comma operator
"no-unused-expressions": 0, // disallow usage of expressions in statement position
"no-void": 1, // disallow use of void operator (off by default)
"no-warning-comments": 0, // disallow usage of configurable warning terms in comments": 1, // e.g. TODO or FIXME (off by default)
"no-with": 1, // disallow use of the with statement
"radix": 1, // require use of the second argument for parseInt() (off by default)
"semi-spacing": 1, // require a space after a semi-colon
"vars-on-top": 0, // requires to declare all vars on top of their containing scope (off by default)
"wrap-iife": 0, // require immediate function invocation to be wrapped in parentheses (off by default)
"yoda": 1, // require or disallow Yoda conditions
// Variables
// These rules have to do with variable declarations.
"no-catch-shadow": 1, // disallow the catch clause parameter name being the same as a variable in the outer scope (off by default in the node environment)
"no-delete-var": 1, // disallow deletion of variables
"no-label-var": 1, // disallow labels that share a name with a variable
"no-shadow": 1, // disallow declaration of variables already declared in the outer scope
"no-shadow-restricted-names": 1, // disallow shadowing of names such as arguments
"no-undef": 2, // disallow use of undeclared variables unless mentioned in a /*global */ block
"no-undefined": 0, // disallow use of undefined variable (off by default)
"no-undef-init": 1, // disallow use of undefined when initializing variables
"no-unused-vars": [1, {"vars": "all", "args": "none"}], // disallow declaration of variables that are not used in the code
"no-use-before-define": 0, // disallow use of variables before they are defined
// Node.js
// These rules are specific to JavaScript running on Node.js.
"handle-callback-err": 1, // enforces error handling in callbacks (off by default) (on by default in the node environment)
"no-mixed-requires": 1, // disallow mixing regular variable and require declarations (off by default) (on by default in the node environment)
"no-new-require": 1, // disallow use of new operator with the require function (off by default) (on by default in the node environment)
"no-path-concat": 1, // disallow string concatenation with __dirname and __filename (off by default) (on by default in the node environment)
"no-process-exit": 0, // disallow process.exit() (on by default in the node environment)
"no-restricted-modules": 1, // restrict usage of specified node modules (off by default)
"no-sync": 0, // disallow use of synchronous methods (off by default)
// Stylistic Issues
// These rules are purely matters of style and are quite subjective.
"key-spacing": 0,
"keyword-spacing": 1, // enforce spacing before and after keywords
"jsx-quotes": [1, "prefer-double"],
"comma-spacing": 0,
"no-multi-spaces": 0,
"brace-style": 0, // enforce one true brace style (off by default)
"camelcase": 0, // require camel case names
"consistent-this": [1, "self"], // enforces consistent naming when capturing the current execution context (off by default)
"eol-last": 1, // enforce newline at the end of file, with no multiple empty lines
"func-names": 0, // require function expressions to have a name (off by default)
"func-style": 0, // enforces use of function declarations or expressions (off by default)
"new-cap": 0, // require a capital letter for constructors
"new-parens": 1, // disallow the omission of parentheses when invoking a constructor with no arguments
"no-nested-ternary": 0, // disallow nested ternary expressions (off by default)
"no-array-constructor": 1, // disallow use of the Array constructor
"no-lonely-if": 0, // disallow if as the only statement in an else block (off by default)
"no-new-object": 1, // disallow use of the Object constructor
"no-spaced-func": 1, // disallow space between function identifier and application
"no-ternary": 0, // disallow the use of ternary operators (off by default)
"no-trailing-spaces": 1, // disallow trailing whitespace at the end of lines
"no-underscore-dangle": 0, // disallow dangling underscores in identifiers
"no-mixed-spaces-and-tabs": 1, // disallow mixed spaces and tabs for indentation
"quotes": [1, "single", "avoid-escape"], // specify whether double or single quotes should be used
"quote-props": 0, // require quotes around object literal property names (off by default)
"semi": 1, // require or disallow use of semicolons instead of ASI
"sort-vars": 0, // sort variables within the same declaration block (off by default)
"space-in-brackets": 0, // require or disallow spaces inside brackets (off by default)
"space-in-parens": 0, // require or disallow spaces inside parentheses (off by default)
"space-infix-ops": 1, // require spaces around operators
"space-unary-ops": [1, { "words": true, "nonwords": false }], // require or disallow spaces before/after unary operators (words on by default, nonwords off by default)
"max-nested-callbacks": 0, // specify the maximum depth callbacks can be nested (off by default)
"one-var": 0, // allow just one var statement per function (off by default)
"wrap-regex": 0, // require regex literals to be wrapped in parentheses (off by default)
// Legacy
// The following rules are included for compatibility with JSHint and JSLint. While the names of the rules may not match up with the JSHint/JSLint counterpart, the functionality is the same.
"max-depth": 0, // specify the maximum depth that blocks can be nested (off by default)
"max-len": 0, // specify the maximum length of a line in your program (off by default)
"max-params": 0, // limits the number of parameters that can be used in the function declaration. (off by default)
"max-statements": 0, // specify the maximum number of statement allowed in a function (off by default)
"no-bitwise": 1, // disallow use of bitwise operators (off by default)
"no-plusplus": 0, // disallow use of unary operators, ++ and -- (off by default)
// React Plugin
// The following rules are made available via `eslint-plugin-react`.
"react/display-name": 0,
"react/jsx-boolean-value": 0,
"react/jsx-no-duplicate-props": 2,
"react/jsx-no-undef": 1,
"react/jsx-sort-props": 0,
"react/jsx-uses-react": 1,
"react/jsx-uses-vars": 1,
"react/no-did-mount-set-state": 1,
"react/no-did-update-set-state": 1,
"react/no-multi-comp": 0,
"react/no-string-refs": 1,
"react/no-unknown-property": 0,
"react/prop-types": 0,
"react/react-in-jsx-scope": 1,
"react/self-closing-comp": 1,
"react/wrap-multilines": 0,
}
}
-118
View File
@@ -1,118 +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 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/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'],
parser: 'hermes-eslint',
rules: {
// These rules are not required with hermes-eslint
'ft-flow/define-flow-type': 0,
'ft-flow/use-flow-type': 0,
'lint/sort-imports': 1,
// flow handles this check for us, so it's not required
'no-undef': 0,
},
},
{
files: ['package.json'],
parser: 'jsonc-eslint-parser',
},
{
files: ['package.json'],
rules: {
'lint/react-native-manifest': 2,
},
},
{
files: ['flow-typed/**/*.js'],
rules: {
'lint/valid-flow-typed-signature': 2,
'no-unused-vars': 0,
quotes: 0,
},
},
{
files: [
'packages/react-native/Libraries/**/*.js',
'packages/react-native/src/**/*.js',
],
rules: {
'@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,
},
},
{
files: [
'**/__fixtures__/**/*.js',
'**/__mocks__/**/*.js',
'**/__tests__/**/*.js',
'packages/react-native/jest/**/*.js',
'packages/rn-tester/**/*.js',
],
globals: {
// Expose some Jest globals for test helpers
afterAll: true,
afterEach: true,
beforeAll: true,
beforeEach: true,
expect: true,
jest: true,
},
},
{
files: ['**/__tests__/**/*-test.js'],
env: {
jasmine: true,
jest: true,
},
},
{
files: ['**/*.{ts,tsx}'],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint/eslint-plugin'],
rules: {
'@typescript-eslint/no-unused-vars': 'off',
'react-native/no-inline-styles': 'off',
'@typescript-eslint/no-shadow': 'off',
'no-self-compare': 'off',
'react/self-closing-comp': 'off',
},
},
{
files: ['**/*.d.ts'],
plugins: ['redundant-undefined'],
rules: {
'no-dupe-class-members': 'off',
'redundant-undefined/redundant-undefined': [
'error',
{followExactOptionalPropertyTypes: true},
],
},
},
],
};
+23 -73
View File
@@ -1,99 +1,49 @@
[ignore]
; Ignore build cache folder
<PROJECT_ROOT>/packages/react-native/sdks/.*
; We fork some components by platform
.*/*[.]android.js
; Ignore the codegen e2e tests
<PROJECT_ROOT>/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeEnumTurboModule.js
; Ignore templates for 'react-native init'
.*/local-cli/templates/.*
; Ignore the Dangerfile
<PROJECT_ROOT>/packages/react-native-bots/dangerfile.js
; Ignore the website subdir
<PROJECT_ROOT>/website/.*
; Ignore "BUCK" generated dirs
<PROJECT_ROOT>/\.buckd/
; Ignore other platform suffixes
.*\.macos\.js$
.*\.windows\.js$
; Ignore unexpected extra "@providesModule"
.*/node_modules/.*/node_modules/fbjs/.*
.*/node_modules/resolve/test/resolver/malformed_package_json/package\.json$
; Checked-in build output
<PROJECT_ROOT>/packages/debugger-frontend/dist/
; Generated build output
<PROJECT_ROOT>/packages/.*/dist
; helloworld
<PROJECT_ROOT>/packages/helloworld/ios/Pods/
; Ignore rn-tester Pods
<PROJECT_ROOT>/packages/rn-tester/Pods/
[untyped]
.*/node_modules/@react-native-community/cli/.*/.*
; Ignore duplicate module providers
; For RN Apps installed via npm, "Libraries" folder is inside
; "node_modules/react-native" but in the source repo it is in the root
.*/Libraries/react-native/React.js
[include]
[declarations]
.*/node_modules/.*
[libs]
flow-typed/
packages/react-native/interface.js
packages/react-native/flow/
Libraries/react-native/react-native-interface.js
flow/
[options]
enums=true
as_const=true
casting_syntax=both
emoji=true
exact_by_default=true
format.bracket_spacing=false
module.file_ext=.js
module.file_ext=.json
experimental.multi_platform=true
experimental.multi_platform.extensions=.ios
experimental.multi_platform.extensions=.android
module.system=haste
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.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\)$' -> 'RelativeImageStub'
suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FlowFixMeProps
suppress_type=$FlowFixMeState
suppress_type=$FlowFixMeEmpty
suppress_type=$FixMe
ban_spread_key_props=true
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(4[0-9]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native_oss[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(4[0-9]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native_oss[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
[lints]
sketchy-null-number=warn
sketchy-null-mixed=warn
sketchy-number=warn
untyped-type-import=warn
nonstrict-import=warn
deprecated-type=error
unsafe-getters-setters=warn
unnecessary-invariant=warn
unused-promise=error
[strict]
deprecated-type
nonstrict-import
sketchy-null
unclear-type
unsafe-getters-setters
untyped-import
untyped-type-import
unsafe.enable_getters_and_setters=true
[version]
^0.255.0
^0.49.1
+6
View File
@@ -0,0 +1,6 @@
# Force LF line endings for Bash scripts. On Windows the rest of the source
# files will typically have CR+LF endings (Git default on Windows), but Bash
# scripts need to have LF endings to work (under Cygwin), thus override to force
# that.
gradlew text eol=lf
*.sh text eol=lf
+123 -3
View File
@@ -1,4 +1,124 @@
✋ To keep the backlog clean and actionable, issues will be
🚫 closed if they do not follow one of the issue templates:
👉 https://github.com/facebook/react-native/issues/new/choose
<!--
PLEASE DON'T DELETE THIS TEMPLATE UNTIL YOU HAVE READ THE FIRST SECTION.
-->
### Is this a bug report?
(write your answer here)
<!--
If you answered "Yes":
We expect that it will take you about 30 minutes to produce a high-quality bug report.
While this may seem like a lot, putting care into issues helps us fix them faster.
For bug reports, it is REQUIRED to fill the rest of this template, or the issue will be closed.
If you answered "No":
We use GitHub Issues exclusively for tracking bugs in React Native. If you're looking for help,
check out the How to Get In Touch section of the following guide:
https://facebook.github.io/react-native/docs/contributing.html#how-to-get-in-touch
Now scroll below!
-->
### Have you read the Bugs section of the How to Contribute guide?
(Write your answer here.)
<!--
Please read through the bug reporting guidelines thoroughly:
https://facebook.github.io/react-native/docs/contributing.html#bugs
-->
### Environment
<!--
Please fill in all the relevant fields by running these commands in terminal.
-->
1. `react-native -v`:
2. `node -v`:
3. `npm -v`:
4. `yarn --version`<!-- (if you use Yarn) -->:
Then, specify:
<!-- (What platform are you building for? Choose any from iOS, Android, AppleTV.) -->
- Target Platform:
<!-- Which operating system are you using? Specify macOS, Windows, or Linux, along with specific release versions -->
- Development Operating System:
<!-- Include any additional relevant information. Are you using Xcode or Android Studio to build native code? Is the issue specific to a particular iOS or Android SDK? -->
- Build tools:
### Steps to Reproduce
<!--
How would you describe your issue to someone who doesnt know you or your project?
Try to write a sequence of steps that anybody can repeat to see the issue.
Be specific! If the bug cannot be reproduced, your issue may be closed.
-->
(Write your steps here:)
1.
2.
3.
### Expected Behavior
<!--
How did you expect your project to behave?
Its fine if youre not sure your understanding is correct.
Just write down what you thought would happen.
-->
(Write what you thought would happen.)
### Actual Behavior
<!--
Did something go wrong?
Is something broken, or not behaving as you expected?
Describe this section in detail, and attach screenshots if possible.
Don't just say "it doesn't work"!
-->
(Write what happened. Add screenshots!)
### Reproducible Demo
<!--
Please share a project that reproduces the issue.
There are two ways to do it:
* Create a new app using https://snack.expo.io/ and try to reproduce the issue in it.
This is useful if you roughly know where the problem is, or cant share the real code.
* Or, copy your app and remove things until youre left with the minimal reproducible demo.
This is useful for finding the root cause. You may then optionally create a Snack.
This is a good guide to creating bug demos: https://stackoverflow.com/help/mcve
Once youre done, copy and paste the link to the Snack or a public GitHub repository below:
-->
(Paste the link to an example project and exact instructions to reproduce the issue.)
<!--
What happens if you skip this step?
Someone will read your bug report, and maybe will be able to help you,
but its unlikely that it will get much attention from the team. Eventually,
the issue will likely get closed in favor of issues that have reproducible demos.
Please remember that:
* Issues without reproducible demos have a very low priority.
* The person fixing the bug would have to do that anyway. Please be respectful of their time.
* You might figure out the issues yourself as you work on extracting it.
Thanks for helping us help you!
-->
-123
View File
@@ -1,123 +0,0 @@
name: 🐛 React Native - Bug Report
description: Report a reproducible bug or regression in React Native.
labels: ["Needs: Triage :mag:"]
body:
- type: markdown
attributes:
value: "## Reporting a bug to React Native"
- type: markdown
attributes:
value: |
Thank you for taking the time to report an issue for React Native, your contribution will help
make the framework better for everyone.
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'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** (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.
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:
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 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: 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.73.0"
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**.
-26
View File
@@ -1,26 +0,0 @@
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: |
If you're using Expo in your project, please report the issue first in the Expo issue tracker.
- name: 📃 Documentation Issue
url: https://github.com/facebook/react-native-website/issues
about: Please report documentation issues in the React Native website repository.
- name: 📦 Metro Issue
url: https://github.com/facebook/metro/issues/new
about: |
If you've encountered a module resolution problem, e.g. "Error: Unable to resolve module ...", or something else that might be related to Metro, please open an issue in the Metro repo instead.
- name: 🤔 Questions and Help
url: https://reactnative.dev/help
about: Looking for help with your app? Please refer to the React Native community's support resources.
- name: 💫 New Architecture - Questions & Technical Deep dive insights
url: https://github.com/reactwg/react-native-new-architecture
about: Questions and doubts related to technical questions for the New Architecture should be directed to the Working Group. Instructions on how to join are available in the README.
- name: 🚀 Discussions and Proposals
url: https://github.com/react-native-community/discussions-and-proposals
about: Discuss the future of React Native in the React Native community's discussions and proposals repository.
@@ -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 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: 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**.
@@ -1,135 +0,0 @@
name: 💫 New Architecture - Bug Report
description: Report a reproducible bug or a build issue when using the New Architecture (Fabric & TurboModules) in React Native.
labels: ["Needs: Triage :mag:", "Type: New Architecture"]
body:
- type: markdown
attributes:
value: "## New Architecture Related Bugs"
- type: markdown
attributes:
value: |
Thank you for taking the time to report an issue for [the New Architecture of React Native](https://reactnative.dev/docs/the-new-architecture/landing-page),
your contribution will help make the framework better for everyone.
If you're **NOT** using the New Architecture, please use this [other bug type](https://github.com/facebook/react-native/issues/new?template=bug_report.yml).
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** (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.
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:
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 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: 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.73.0"
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: dropdown
id: areas
attributes:
label: Areas
description: Which areas of the New Architecture are affected by this bug report?
multiple: true
options:
- Fabric - The New Renderer
- TurboModule - The New Native Module System
- JSI - Javascript Interface
- Bridgeless - The New Initialization Flow
- Codegen
- 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**.
+5 -17
View File
@@ -1,21 +1,9 @@
<!-- 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. -->
<!--
Thank you for sending the PR!
## Summary:
If you changed any code, please provide us with clear instructions on how you verified your changes work. In other words, a test plan is *required*. Bonus points for screenshots and videos!
<!-- Explain the **motivation** for making this change. What existing problem does the pull request solve? -->
Please read the Contribution Guidelines at https://github.com/facebook/react-native/blob/master/CONTRIBUTING.md to learn more about contributing to React Native.
## 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
Happy contributing!
-->
## Test Plan:
<!-- Demonstrate the code is solid. Example: The exact commands you ran and their output, screenshots / videos if the pull request changes the user interface. -->
-23
View File
@@ -1,23 +0,0 @@
<!-- Template for pre-release GitHub release -->
<!-- TODO Post about this release to https://github.com/reactwg/react-native-releases/discussions) -->
- <!-- TODO List out notable picks for this patch -->
---
To test it, run:
npx react-native init RN__SHORT_VERSION__ --version __VERSION__
---
You can participate in the conversation on the status of this release in the [working group](https://github.com/reactwg/react-native-releases/discussions).
---
To help you upgrade to this version, you can use the [upgrade helper](https://react-native-community.github.io/upgrade-helper/) ⚛️
---
See changes from this release in the [changelog PR](https://github.com/facebook/react-native/labels/%F0%9F%93%9D%20Changelog)
-35
View File
@@ -1,35 +0,0 @@
Thanks for using React Native! If you need help with your React Native app, the right place to go depends on the type of help that you need.
## 🤔 I have a question or need help with my React Native app.
If you have a coding question related to React Native, it might be better suited for Stack Overflow. It's a great place to browse through [frequent questions about using React Native](https://stackoverflow.com/questions/tagged/react-native?sort=frequent&pageSize=15), as well as [ask for help with specific questions](https://stackoverflow.com/questions/tagged/react-native).
[Reactiflux](https://www.reactiflux.com/) is an active community of React and React Native developers. If you are looking for immediate assistance or have a general question about React Native, the #react-native channel is a good place to start.
## 📃 I found something that seems wrong in the documentation.
The React Native website is hosted on a [separate repository](https://github.com/facebook/react-native-website). If you want to report something that is wrong or missing from the documentation, [please open a new issue there](https://github.com/facebook/react-native-website/issues).
## 🐛 I found a bug in React Native.
If you want to report a reproducible bug or regression in the React Native library, you can [create a new issue](https://github.com/facebook/react-native/issues/new?labels=Type%3A+Bug+Report&template=bug_report.md). It's a good idea to look through [open issues](https://github.com/facebook/react-native/issues) before doing so, as someone else may have reported a similar issue.
## 🚀 I want to discuss the future of React Native.
If you'd like to discuss topics related to the future of React Native, please check out the [React Native Community Discussions and Proposals](https://github.com/react-native-community/discussions-and-proposals) repository.
## 💬 I want to talk to other React Native developers.
If you want to participate in casual discussions about the use of React Native, consider participating in one of the following forums:
- [Reactiflux Discord Server](https://www.reactiflux.com)
- [Spectrum Chat](https://spectrum.chat/react-native)
- [React Native Community Facebook Group](https://www.facebook.com/groups/react.native.community)
> For a full list of community resources, check out [React Native's Community page](https://reactnative.dev/help).
-109
View File
@@ -1,109 +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.
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-with-cache
- 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"
- 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-hermes-debug
path: packages/rn-tester/android/app/build/outputs/apk/hermes/debug/
compression-level: 0
- name: Upload RNTester APK - hermes-release
if: ${{ always() }}
uses: actions/upload-artifact@v4.3.4
with:
name: rntester-hermes-release
path: packages/rn-tester/android/app/build/outputs/apk/hermes/release/
compression-level: 0
- name: Upload RNTester APK - jsc-debug
if: ${{ always() }}
uses: actions/upload-artifact@v4.3.4
with:
name: rntester-jsc-debug
path: packages/rn-tester/android/app/build/outputs/apk/jsc/debug/
compression-level: 0
- name: Upload RNTester APK - jsc-release
if: ${{ always() }}
uses: actions/upload-artifact@v4.3.4
with:
name: rntester-jsc-release
path: packages/rn-tester/android/app/build/outputs/apk/jsc/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-with-cache
- 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,37 +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: 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,49 +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 cmake build-essential \
libreadline-dev libicu-dev jq zip python3
- 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: 'D:\tmp\hermes'
- name: Set up workspace
shell: powershell
run: |
mkdir -p D:\tmp\hermes\osx-bin
mkdir -p .\packages\react-native\sdks\hermes
cp -r -Force D:\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: v2-hermes-${{ github.job }}-windows-${{ inputs.hermes-version }}-${{ inputs.react-native-version }}
path: |
D:\tmp\hermes\win64-bin\
D:\tmp\hermes\hermes\icu\
D:\tmp\hermes\hermes\deps\
D:\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: Build HermesC for Windows
shell: powershell
run: |
if (-not(Test-Path -Path $Env:HERMES_WS_DIR\win64-bin\hermesc.exe)) {
choco install --no-progress cmake --version 3.14.7 --allow-downgrade
if (-not $?) { throw "Failed to install CMake" }
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 16 2019' -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: D:\tmp\hermes\win64-bin\
@@ -1,148 +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: ''
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: Setup node.js
uses: ./.github/actions/setup-node
- name: Setup gradle
uses: ./.github/actions/setup-gradle
- name: Install dependencies
uses: ./.github/actions/yarn-install-with-cache
- name: Build packages
shell: bash
run: yarn build
# 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-with-cache
- 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
-44
View File
@@ -1,44 +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: "18"
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: Yarn install
shell: bash
run: yarn install --non-interactive --frozen-lockfile
- 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: ./scripts/circleci/exec_swallow_error.sh yarn lint --format junit -o ./reports/junit/eslint/results.xml
- name: Lint java
shell: bash
run: ./scripts/circleci/exec_swallow_error.sh yarn lint-java --check
- 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: ./scripts/circleci/check_license.sh
- name: Check formatting
shell: bash
run: yarn run format-check
@@ -1,84 +0,0 @@
name: Maestro E2E Android
description: Runs E2E Tests on iOS 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
jsengine:
required: true
description: The js engine we are using
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.36.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
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 24
arch: x86
ram-size: '4096M'
disk-size: '10G'
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@v3
if: always()
with:
name: e2e_android_${{ steps.normalize-app-id.outputs.app-id }}_report_${{ inputs.jsengine }}_${{ inputs.flavor }}
path: |
report.xml
screen.mp4
- name: Store Logs
if: failure() && 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.jsengine }}-${{ inputs.flavor }}
path: /tmp/MaestroLogs
-121
View File
@@ -1,121 +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
jsengine:
required: true
description: The js engine we are using
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.36.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 jq
- name: Set up JDK 11
uses: actions/setup-java@v2
with:
java-version: '17'
distribution: 'zulu'
- name: Start Metro in Debug
shell: bash
if: ${{ inputs.flavor == 'Debug' }}
run: |
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
echo "Launching iOS Simulator: iPhone 15 Pro"
xcrun simctl boot "iPhone 15 Pro"
echo "Installing app on Simulator"
xcrun simctl install booted "${{ inputs.app-path }}"
echo "Retrieving device UDID"
UDID=$(xcrun simctl list devices booted -j | jq -r '[.devices[]] | add | first | .udid')
echo "UDID is $UDID"
echo "Bring simulator in foreground"
open -a simulator
echo "Launch the app"
xcrun simctl launch $UDID ${{ inputs.app-id }}
if [[ ${{ inputs.flavor }} == 'Debug' ]]; then
# To give the app time to warm the metro's cache
sleep 20
fi
echo "Running tests with Maestro"
export MAESTRO_DRIVER_STARTUP_TIMEOUT=1500000 # 25 min. CI is extremely slow
# Add retries for flakyness
MAX_ATTEMPTS=5
CURR_ATTEMPT=0
RESULT=1
while [[ $CURR_ATTEMPT -lt $MAX_ATTEMPTS ]] && [[ $RESULT -ne 0 ]]; do
CURR_ATTEMPT=$((CURR_ATTEMPT+1))
echo "Attempt number $CURR_ATTEMPT"
echo "Start video record using pid: video_record_${{ inputs.jsengine }}_$CURR_ATTEMPT.pid"
xcrun simctl io booted recordVideo video_record_$CURR_ATTEMPT.mov & echo $! > video_record_${{ inputs.jsengine }}_$CURR_ATTEMPT.pid
echo '$HOME/.maestro/bin/maestro --udid=$UDID test ${{ inputs.maestro-flow }} --format junit -e APP_ID=${{ inputs.app-id }}'
$HOME/.maestro/bin/maestro --udid=$UDID test ${{ inputs.maestro-flow }} --format junit -e APP_ID=${{ inputs.app-id }} --debug-output /tmp/MaestroLogs
RESULT=$?
# Stop video
kill -SIGINT $(cat video_record_${{ inputs.jsengine }}_$CURR_ATTEMPT.pid)
done
exit $RESULT
- name: Store video record
if: always()
uses: actions/upload-artifact@v4.3.4
with:
name: e2e_ios_${{ inputs.app-id }}_report_${{ inputs.jsengine }}_${{ inputs.flavor }}
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.jsengine }}-${{ inputs.flavor }}
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-with-cache
- 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/.
-20
View File
@@ -1,20 +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"
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' }}
# Temporarily disabling to try resolve a cache cleanup failure
# gradle-home-cache-cleanup: true
add-job-summary-as-pr-comment: on-failure
-14
View File
@@ -1,14 +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: '18'
runs:
using: "composite"
steps:
- name: Setup node.js
uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
@@ -1,28 +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
runs:
using: composite
steps:
- name: See commands.yml with_xcodebuild_cache
shell: bash
run: echo "See commands.yml with_xcodebuild_cache"
- name: Prepare Xcodebuild cache
shell: bash
run: |
WEEK=$(date +"%U")
YEAR=$(date +"%Y")
echo "$WEEK-$YEAR" > /tmp/week_year
- name: Cache podfile lock
uses: actions/cache@v4
with:
path: packages/rn-tester/Podfile.lock
key: v11-podfilelock-${{ github.job }}-${{ hashfiles('packages/rn-tester/Podfile') }}-${{ hashfiles('/tmp/week_year') }}-${{ inputs.hermes-version }}
- name: Cache cocoapods
uses: actions/cache@v4
with:
path: packages/rn-tester/Pods
key: v13-cocoapods-${{ github.job }}-${{ 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: '15.2'
runs:
using: "composite"
steps:
- name: Setup xcode
uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd
with:
xcode-version: ${{ inputs.xcode-version }}
@@ -1,93 +0,0 @@
name: test-ios-helloworld
description: Test iOS Hello World
inputs:
jsengine:
description: Which JavaScript engine to use. Must be one of "Hermes", "JSC".
default: Hermes
use-frameworks:
description: The dependency building and linking strategy to use. Must be one of "StaticLibraries", "DynamicFrameworks"
default: StaticLibraries
architecture:
description: The React Native architecture to Test. RNTester has always Fabric enabled, but we want to run integration test with the old arch setup. Must be one of "OldArch" or "NewArch"
default: OldArch
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-with-cache
- name: Setup ruby
uses: ruby/setup-ruby@v1.170.0
with:
ruby-version: ${{ inputs.ruby-version }}
- name: Install iOS dependencies - Configuration ${{ inputs.flavor }}; New Architecture ${{ inputs.architecture }}; JS Engine ${{ inputs.jsengine }}
shell: bash
run: |
cd packages/helloworld
args=()
if [[ ${{ inputs.architecture }} == "OldArch" ]]; then
args+=(--arch old)
fi
if [[ ${{ inputs.use-frameworks }} == "DynamicFrameworks" ]]; then
args+=(--frameworks dynamic)
fi
if [[ ${{ inputs.jsengine }} == "JSC" ]]; then
args+=(--jsvm jsc)
yarn bootstrap ios "${args[@]}" | cat
else
# 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 ../react-native/scripts/hermes/get-tarball-name.js --buildType "$BUILD_TYPE")
HERMES_PATH="$HERMES_WS_DIR/hermes-runtime-darwin/$TARBALL_FILENAME"
HERMES_ENGINE_TARBALL_PATH="$HERMES_PATH" yarn bootstrap ios "${args[@]}" | cat
fi
- name: Build HelloWorld project
shell: bash
run: |
cd packages/helloworld
args=()
if [[ ${{ inputs.flavor }} == "Release" ]]; then
args+=(--prod)
fi
yarn build ios "${args[@]}" | cat
yarn bundle ios "${args[@]}" | cat
@@ -1,166 +0,0 @@
name: test-ios-rntester
description: Test iOS RNTester
inputs:
jsengine:
description: Which JavaScript engine to use. Must be one of "Hermes", "JSC".
default: Hermes
use-frameworks:
description: The dependency building and linking strategy to use. Must be one of "StaticLibraries", "DynamicFrameworks"
default: StaticLibraries
architecture:
description: The React Native architecture to Test. RNTester has always Fabric enabled, but we want to run integration test with the old arch setup
default: NewArch
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-with-cache
- 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.170.0
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: Setup xcode build cache
uses: ./.github/actions/setup-xcode-build-cache
with:
hermes-version: ${{ inputs.hermes-version }}
- name: Install CocoaPods dependencies
shell: bash
run: |
if [[ ${{ inputs.jsengine }} == "JSC" ]]; then
export USE_HERMES=0
else
export HERMES_ENGINE_TARBALL_PATH=$HERMES_ENGINE_TARBALL_PATH
fi
if [[ ${{ inputs.use-frameworks }} == "DynamicFrameworks" ]]; then
export USE_FRAMEWORKS=dynamic
fi
if [[ ${{ inputs.architecture }} == "NewArch" ]]; then
export RCT_NEW_ARCH_ENABLED=1
fi
cd packages/rn-tester
bundle install
bundle exec pod install
- name: Build RNTester
if: ${{ inputs.run-unit-tests != 'true' && inputs.run-e2e-tests == 'false' }}
shell: bash
run: |
xcodebuild build \
-workspace packages/rn-tester/RNTesterPods.xcworkspace \
-scheme RNTester \
-sdk iphonesimulator
- name: Build RNTester (E2E Tests)
shell: bash
if: ${{ inputs.run-e2e-tests == 'true' }}
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"
find "/tmp/RNTesterBuild" -type d -name "*.app"
- 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: 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: "18"
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-with-cache
- 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,46 +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 }}
- 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
- 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
@@ -1,28 +0,0 @@
name: yarn-install-with-cache
inputs:
update-cache:
description: Update the cache, only do this if you are update-node-modules-cache.yml
default: "false"
description: Only update node_modules if on main
runs:
using: composite
steps:
- name: Load node_modules from cache
# Restore for all branches, but save for 'main'.
uses: actions/cache/restore@v4
with:
path: node_modules/
key: node-modules-${{ hashFiles('package.json') }}
- name: Install dependencies
shell: bash
run: yarn install --non-interactive
- name: Save node_modules to the cache
if: github.ref == 'refs/heads/main' && inputs.update-cache == 'true'
uses: actions/cache/save@v4
with:
path: node_modules/
# We're assuming that variations on branches will slightly vary from main,
# so it's always important to run yarn install --non-interactive after this
# cache is restored.
key: node-modules-v1-${{ hashFiles('package.json') }}
enableCrossOsArchive: true
@@ -1,158 +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 silence = () => {};
jest.mock('../utils.js', () => ({
log: silence,
run: mockRun,
sleep: mockSleep,
getNpmPackageInfo: mockGetNpmPackageInfo,
}));
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;
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.77.0';
await verifyPublishedTemplate(version, NOT_LATEST);
expect(mockGetNpmPackageInfo).toHaveBeenLastCalledWith(
'@react-native-community/template',
version,
);
});
it('waits on npm updating version and latest tag', async () => {
const IS_LATEST = true;
const version = '0.77.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 verifyPublishedTemplate(version, IS_LATEST);
expect(mockGetNpmPackageInfo).toHaveBeenCalledWith(
'@react-native-community/template',
'latest',
);
});
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(() =>
verifyPublishedTemplate('0.77.0', true, 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 verifyPublishedTemplate('0.77.0', IS_LATEST, RETRIES);
}).rejects.toThrowError('process.exit(1) called!');
expect(mockGetNpmPackageInfo).toHaveBeenCalledTimes(RETRIES);
});
});
});
-136
View File
@@ -1,136 +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
*/
module.exports = async (github, context, labelWithContext) => {
const closeIssue = async () => {
await github.rest.issues.update({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
state: 'closed',
});
};
const addComment = async comment => {
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment,
});
};
const requestAuthorFeedback = async () => {
// Remove the triage label if it exists (ignore the 404 if not; it's not expected to always be there)
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'Needs: Triage :mag:',
});
} catch {}
await github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['Needs: Author Feedback'],
});
};
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.`,
);
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/).`,
);
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.`,
);
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.`,
);
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.`,
);
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.`,
);
await requestAuthorFeedback();
return;
case 'Newer Patch Available':
await addComment(
`> [!TIP]\n` +
`> **Newer version available**: 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.`,
);
await requestAuthorFeedback();
return;
case 'Needs: Repro':
await addComment(
`> [!WARNING]\n` +
`> **Missing reproducer**: 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/upgrade related: a project using our [Reproducer Template](https://github.com/react-native-community/reproducer-react-native/generate)</li><li>Otherwise 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></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.`,
);
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.`,
);
await closeIssue();
return;
default:
// No action needed
return;
}
};
@@ -1,153 +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
*/
module.exports = async (github, context) => {
const issue = context.payload.issue;
const title = issue?.title?.toLowerCase();
if (!title) return;
const addLabels = async labelsToAdd => {
await github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: labelsToAdd,
});
};
const labelsToAdd = [];
for (const component of components) {
if (title.includes(component.toLowerCase())) {
labelsToAdd.push(`Component: ${component}`);
}
}
for (const api of apis) {
if (title.includes(api.toLowerCase())) {
labelsToAdd.push(`API: ${api}`);
}
}
for (const topic of Object.keys(topics)) {
if (title.includes(topic.toLowerCase())) {
labelsToAdd.push(topics[topic]);
}
}
if (labelsToAdd.length > 0) {
await addLabels(labelsToAdd);
}
};
const labelAndroid = 'Platform: Android';
const labelIos = 'Platform: iOS';
const labelTvos = 'Platform: tvOS';
const labelNetworking = '🌐Networking';
const labelBundler = '📦Bundler';
const labelCli = '💻CLI';
const labelRegression = 'Impact: Regression';
const components = [
'ActivityIndicator',
'Button',
'DatePickerIOS',
'DrawerLayoutAndroid',
'FlatList',
'Image',
'ImageBackground',
'InputAccessoryView',
'KeyboardAvoidingView',
'ListView',
'MaskedViewIOS',
'Modal',
'NavigatorIOS',
'Picker',
'PickerIOS',
'ProgressBarAndroid',
'ProgressViewIOS',
'RefreshControl',
'SafeAreaView',
'ScrollView',
'SectionList',
'SegmentedControlIOS',
'Slider',
'SnapshotViewIOS',
'StatusBar',
'Switch',
'TabBarIOS',
'TextInput',
'ToolbarAndroid',
'TouchableHighlight',
'TouchableNativeFeedback',
'TouchableOpacity',
'TouchableWithoutFeedback',
'ViewPagerAndroid',
'VirtualizedList',
'WebView',
];
const apis = [
'AccessibilityInfo',
'ActionSheetIOS',
'Alert',
'AlertIOS',
'Animated',
'AppRegistry',
'AppState',
'AsyncStorage',
'BackAndroid',
'BackHandler',
'CameraRoll',
'Clipboard',
'DatePickerAndroid',
'Dimensions',
'Easing',
'Geolocation',
'ImageEditor',
'ImagePickerIOS',
'ImageStore',
'InteractionManager',
'Keyboard',
'LayoutAnimation',
'Linking',
'ListViewDataSource',
'NetInfo',
'PanResponder',
'PermissionsAndroid',
'PixelRatio',
'PushNotificationIOS',
'Settings',
'Share',
'StatusBarIOS',
'StyleSheet',
'Systrace',
'TimePickerAndroid',
'ToastAndroid',
'Transforms',
'Vibration',
'VibrationIOS',
];
const topics = {
Flow: 'Flow',
'Flow-Strict': 'Flow',
xhr: labelNetworking,
netinfo: labelNetworking,
fetch: labelNetworking,
okhttp: labelNetworking,
http: labelNetworking,
bundle: labelBundler,
bundling: labelBundler,
packager: labelBundler,
'unable to resolve module': labelBundler,
android: labelAndroid,
ios: labelIos,
tvos: labelTvos,
'react-native-cli': labelCli,
'react-native upgrade': labelCli,
'react-native link': labelCli,
regression: labelRegression,
};
@@ -1,100 +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 NEEDS_REPRO_LABEL = 'Needs: Repro';
const NEEDS_AUTHOR_FEEDBACK_LABEL = 'Needs: Author Feedback';
const SKIP_ISSUES_OLDER_THAN = '2023-07-01T00:00:00Z';
module.exports = async (github, context) => {
const issueData = {
issue_number: context.payload.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
};
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;
if (isDateBefore(issueDate, SKIP_ISSUES_OLDER_THAN)) {
return;
}
const maintainerChangedLabel = await hasMaintainerChangedLabel(
github,
issueData,
author,
);
if (maintainerChangedLabel) {
return;
}
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 hasExpoSnackLink = containsPattern(
entity.body,
`https?:\\/\\/snack\\.expo\\.dev\\/[^\\s)\\]]+`,
);
const hasGithubRepoLink = containsPattern(
entity.body,
`https?:\\/\\/github\\.com\\/(${entity.user.login})\\/[^/]+\\/?\\s?`,
);
return hasExpoSnackLink || hasGithubRepoLink;
});
if (hasValidReproducer) {
try {
await github.rest.issues.removeLabel({
...issueData,
name: NEEDS_REPRO_LABEL,
});
} catch (error) {
if (!/Label does not exist/.test(error.message)) {
throw error;
}
}
} else {
await github.rest.issues.addLabels({
...issueData,
labels: [NEEDS_REPRO_LABEL, NEEDS_AUTHOR_FEEDBACK_LABEL],
});
}
};
function containsPattern(body, pattern) {
const regexp = new RegExp(pattern, 'gm');
return body.search(regexp) !== -1;
}
// Prevents the bot from responding when maintainer has changed the 'Needs: Repro' label
async function hasMaintainerChangedLabel(github, issueData, author) {
const timeline = await github.rest.issues.listEventsForTimeline(issueData);
const labeledEvents = timeline.data.filter(
event => event.event === 'labeled' || event.event === 'unlabeled',
);
const userEvents = labeledEvents.filter(event => event.actor.type !== 'Bot');
return userEvents.some(
event =>
event.actor.login !== author && event.label.name === NEEDS_REPRO_LABEL,
);
}
function isDateBefore(firstDate, secondDate) {
const date1 = new Date(firstDate);
const date2 = new Date(secondDate);
return date1.getTime() < date2.getTime();
}
-108
View File
@@ -1,108 +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 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];
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,
});
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'});
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 {
childProcess.execSync(
`MAESTRO_DRIVER_STARTUP_TIMEOUT=120000 $HOME/.maestro/bin/maestro test ${MAESTRO_FLOW} --format junit -e APP_ID=${APP_ID} --debug-output /tmp/MaestroLogs`,
{stdio: 'inherit'},
);
} 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`);
process.exit();
}
}
if (error) {
throw error;
}
}
function sleep(ms) {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
}
main();
-103
View File
@@ -1,103 +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, getNpmPackageInfo, log} = require('./utils.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 SLEEP_S = 10;
const MAX_RETRIES = 3 * 6; // 3 minutes
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,
) => {
log(`🔍 Is ${TEMPLATE_NPM_PKG}@${version} on npm?`);
let count = retries;
while (count-- > 0) {
try {
const json = await getNpmPackageInfo(
TEMPLATE_NPM_PKG,
latest ? 'latest' : version,
);
log(`🎉 Found ${TEMPLATE_NPM_PKG}@${version} on npm`);
if (!latest) {
return;
}
if (json.version === version) {
log(`🎉 ${TEMPLATE_NPM_PKG}@latest → ${version} on npm`);
return;
}
log(
`🐌 ${TEMPLATE_NPM_PKG}@latest → ${pkg.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 ${TEMPLATE_NPM_PKG}@${version} on npm`;
if (latest) {
msg += ' and latest tag points to this version.';
}
log(msg);
process.exit(1);
};
-29
View File
@@ -1,29 +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');
function run(cmd) {
return execSync(cmd, 'utf8').toString().trim();
}
module.exports.run = run;
async function sleep(seconds) {
return new Promise(resolve => setTimeout(resolve, seconds * 1000));
}
module.exports.sleep = sleep;
async function getNpmPackageInfo(pkg, versionOrTag) {
return fetch(`https://registry.npmjs.org/${pkg}/${versionOrTag}`).then(resp =>
resp.json(),
);
}
module.exports.getNpmPackageInfo = getNpmPackageInfo;
module.exports.log = (...args) => console.log(...args);
-140
View File
@@ -1,140 +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
*/
module.exports = async (github, context) => {
const issue = context.payload.issue;
const issueVersionUnparsed =
getReactNativeVersionFromIssueBodyIfExists(issue);
const issueVersion = parseVersionFromString(issueVersionUnparsed);
// Nightly versions are always supported
if (reportedVersionIsNightly(issueVersionUnparsed, issueVersion)) return;
if (!issueVersion) {
return {label: 'Needs: Version Info'};
}
// Ensure the version matches one we support
const recentReleases = (
await github.rest.repos.listReleases({
owner: context.repo.owner,
repo: context.repo.repo,
})
).data.map(release => release.name);
const latestRelease = (
await github.rest.repos.getLatestRelease({
owner: context.repo.owner,
repo: context.repo.repo,
})
).data;
const latestVersion = parseVersionFromString(latestRelease.name);
// We want to "insta-close" an issue if RN version provided is too old. And encourage users to upgrade.
if (isVersionTooOld(issueVersion, latestVersion)) {
return {label: 'Type: Too Old Version'};
}
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}`,
};
}
};
/**
* Check if the RN version provided in an issue is supported.
*
* "We support `N-2` minor versions, and the `latest` major".
*/
function isVersionSupported(actualVersion, latestVersion) {
return (
actualVersion.major >= latestVersion.major &&
actualVersion.minor >= latestVersion.minor - 2
);
}
/**
* Check if the RN version provided in an issue is too old.
* "We support `N-2` minor versions, and the `latest` major".
*
* A RN version is *too old* if it's:
* - `1` or more *major* behind the *latest major*.
* - `5` or more *minor* behind the *latest minor* in the *same major*. Less aggressive.
* (e.g. If `0.72.0` is the current latest then `0.67.0` and lower is too old for `0.72.0`)
*/
function isVersionTooOld(actualVersion, latestVersion) {
return (
latestVersion.major - actualVersion.major >= 1 ||
latestVersion.minor - actualVersion.minor >= 5
);
}
// 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]*/;
const rnVersionMatch = issue.body.match(rnVersionRegex);
if (!rnVersionMatch || !rnVersionMatch.groups.version) return;
return rnVersionMatch.groups.version;
}
function reportedVersionIsNightly(unparsedVersionString, version) {
if (!unparsedVersionString && !version) return false;
const nightlyRegex = /nightly/i;
const nightlyMatch = unparsedVersionString.match(nightlyRegex);
const versionIsNightly = nightlyMatch && nightlyMatch[0];
const versionIsZero =
version && version.major == 0 && version.minor == 0 && version.patch == 0;
return versionIsZero || versionIsNightly;
}
function parseVersionFromString(version) {
if (!version) return;
// This will match the standard x.x.x semver format, as well as the non-standard prerelease x.x.x-rc.x
const semverRegex =
/(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(-[rR]{1}[cC]{1}\.(?<prerelease>\d+))?/;
const versionMatch = version.match(semverRegex);
if (!versionMatch) return;
const {major, minor, patch, prerelease} = versionMatch.groups;
return {
major: parseInt(major),
minor: parseInt(minor),
patch: parseInt(patch),
prerelease: parseInt(prerelease),
};
}
-27
View File
@@ -1,27 +0,0 @@
name: Automatic Rebase
# This workflow is used to automatically rebase a PR when a comment is made
# containing the text "/rebase". It uses the cirrus-actions/rebase action.
# See https://github.com/cirrus-actions/rebase
on:
issue_comment:
types: [created]
permissions:
contents: read
jobs:
rebase:
name: Rebase
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, '/rebase')
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: Automatic Rebase
uses: cirrus-actions/rebase@1.8
env:
GITHUB_TOKEN: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
-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: Use Node.js 18
uses: actions/setup-node@v4
- name: Trim the cache
run: node scripts/clean-gha-cache.js
@@ -1,19 +0,0 @@
name: Check for reproducer
# This workflow is triggered when issue is created or edited.
on:
issues:
types: [opened, edited]
jobs:
check-for-reproducer:
runs-on: ubuntu-latest
if: |
github.repository == 'facebook/react-native' && github.event.issue.pull_request == null && github.event.issue.state == 'open' && !contains(github.event.issue.labels.*.name, ':open_umbrella: Umbrella')
steps:
- uses: actions/checkout@v4
- uses: actions/github-script@v6
with:
github-token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
script: |
const checkForReproducer = require('./.github/workflow-scripts/checkForReproducer.js')
await checkForReproducer(github, context)
-32
View File
@@ -1,32 +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 Nigthlies
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
-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]
});
-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 }}
-28
View File
@@ -1,28 +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: 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.REACT_NATIVE_BOT_GITHUB_TOKEN }}
-28
View File
@@ -1,28 +0,0 @@
name: Issue Needs Attention
# This workflow is triggered on issue comments.
on:
issue_comment:
types: [created]
permissions:
contents: read
jobs:
applyNeedsAttentionLabel:
permissions:
contents: read # for actions/checkout to fetch code
issues: write # for react-native-community/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
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
response-required-label: "Needs: Author Feedback"
needs-attention-label: "Needs: Attention"
id: needs-attention
- name: Result
run: echo '${{ steps.needs-attention.outputs.result }}'
-190
View File
@@ -1,190 +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-13
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-13
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 }}
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-2019
needs: prepare_hermes_workspace
env:
HERMES_WS_DIR: 'D:\tmp\hermes'
HERMES_TARBALL_ARTIFACTS_DIR: 'D:\tmp\hermes\hermes-runtime-darwin'
HERMES_OSXBIN_ARTIFACTS_DIR: 'D:\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 }}
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,
]
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/prealpha, 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 }}
-60
View File
@@ -1,60 +0,0 @@
name: On Issue Labeled
# This workflow is triggered when a label is added to an issue.
on:
issues:
types: [labeled]
permissions:
contents: write
issues: write
jobs:
# Runs automatic checks on issues labeled with "Needs: Triage",
# then invokes actOnLabel to react to any added labels
triage-issue:
runs-on: ubuntu-latest
if: "${{ github.repository == 'facebook/react-native' && contains(github.event.label.name, 'Needs: Triage :mag:') }}"
steps:
- name: Checkout code
uses: actions/checkout@v4
- 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);
if(labelWithContext && labelWithContext.label) {
await github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: [labelWithContext.label]
})
const actOnLabel = require('./.github/workflow-scripts/actOnLabel.js')
await actOnLabel(github, context, labelWithContext)
}
- 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);
# Reacts to the label that triggered this workflow (added manually or via other workflows)
act-on-label:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
steps:
- 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})
@@ -1,26 +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-with-cache
- name: Build packages
run: yarn build
- 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
-216
View File
@@ -1,216 +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-13
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-13
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 }}
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-2019
needs: prepare_hermes_workspace
env:
HERMES_WS_DIR: 'D:\tmp\hermes'
HERMES_TARBALL_ARTIFACTS_DIR: 'D:\tmp\hermes\hermes-runtime-darwin'
HERMES_OSXBIN_ARTIFACTS_DIR: 'D:\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 }}
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,
]
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/prealpha, 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 }}
- 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 }}\" }}"
-77
View File
@@ -1,77 +0,0 @@
name: Stale bot
on:
schedule:
- cron: "*/10 5 * * *"
jobs:
stale:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.REACT_NATIVE_BOT_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.'
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'
exempt-pr-labels: 'Help Wanted :octocat:, Never gets stale'
stale-asc:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v9
with:
ascending: true
repo-token: ${{ secrets.REACT_NATIVE_BOT_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.'
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'
exempt-pr-labels: 'Help Wanted :octocat:, Never gets stale'
stale-needs-author-feedback:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.REACT_NATIVE_BOT_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."
stale-pr-message: "This PR is waiting for author's feedback since 24 days. Please provide the requested feedback or this will be closed in 7 days"
close-issue-message: "This issue was closed because the author hasn't provided the requested feedback after 7 days."
close-pr-message: "This PR was closed because the author hasn't provided the requested feedback after 7 days."
exempt-issue-labels: "Help Wanted :octocat:, Good first issue, Never gets stale, Issue: Author Provided Repro"
exempt-pr-labels: "Help Wanted :octocat:, Never gets stale"
stale-needs-author-feedback-asc:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v9
with:
ascending: true
repo-token: ${{ secrets.REACT_NATIVE_BOT_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."
stale-pr-message: "This PR is waiting for author's feedback since 24 days. Please provide the requested feedback or this will be closed in 7 days"
close-issue-message: "This issue was closed because the author hasn't provided the requested feedback after 7 days."
close-pr-message: "This PR was closed because the author hasn't provided the requested feedback after 7 days."
exempt-issue-labels: "Help Wanted :octocat:, Good first issue, Never gets stale, Issue: Author Provided Repro"
exempt-pr-labels: "Help Wanted :octocat:, Never gets stale"
-618
View File
@@ -1,618 +0,0 @@
name: Test All
on:
workflow_dispatch:
inputs:
run-e2e-tests:
description: Whether to run E2E tests or not
type: boolean
default: false
pull_request:
push:
branches:
- main
- "*-stable"
jobs:
set_release_type:
runs-on: ubuntu-latest
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: |
if [[ $EVENT_NAME == "schedule" ]]; then
echo "Setting release type to nightly"
echo "RELEASE_TYPE=nightly" >> $GITHUB_OUTPUT
elif [[ $EVENT_NAME == "push" && $REF == refs/tags/v* ]]; then
echo "Setting release type to release"
echo "RELEASE_TYPE=release" >> $GITHUB_OUTPUT
else
echo "Setting release type to dry-run"
echo "RELEASE_TYPE=dry-run" >> $GITHUB_OUTPUT
fi
echo "Should I run E2E tests? ${{ inputs.run-e2e-tests }}"
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-13
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.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.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-13
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 }}
test_ios_rntester_ruby_3_2_0:
runs-on: macos-13
needs:
[build_apple_slices_hermes, prepare_hermes_workspace, build_hermes_macos]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run it
uses: ./.github/actions/test-ios-rntester
with:
ruby-version: "3.2.0"
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
test_ios_rntester_dynamic_frameworks:
runs-on: macos-13
needs:
[build_apple_slices_hermes, prepare_hermes_workspace, build_hermes_macos]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
continue-on-error: true
strategy:
fail-fast: false
matrix:
jsengine: [Hermes, JSC]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run it
uses: ./.github/actions/test-ios-rntester
with:
jsengine: ${{ matrix.jsengine }}
use-frameworks: DynamicFrameworks
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
test_ios_rntester:
runs-on: macos-13
needs:
[build_apple_slices_hermes, prepare_hermes_workspace, build_hermes_macos]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
continue-on-error: true
strategy:
fail-fast: false
matrix:
jsengine: [Hermes, JSC]
architecture: [NewArch, OldArch]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run it
uses: ./.github/actions/test-ios-rntester
with:
jsengine: ${{ matrix.jsengine }}
architecture: ${{ matrix.architecture }}
run-unit-tests: "false"
use-frameworks: StaticLibraries
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
test_e2e_ios_rntester:
if: ${{ github.ref == 'refs/heads/main' || contains(github.ref, 'stable') || inputs.run-e2e-tests }}
runs-on: macos-13-large
needs:
[build_apple_slices_hermes, prepare_hermes_workspace, build_hermes_macos]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
continue-on-error: true
strategy:
fail-fast: false
matrix:
jsengine: [Hermes, JSC]
architecture: [NewArch]
flavor: [Debug, Release]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run it
uses: ./.github/actions/test-ios-rntester
with:
jsengine: ${{ matrix.jsengine }}
architecture: ${{ matrix.architecture }}
run-unit-tests: "false"
use-frameworks: StaticLibraries
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
run-e2e-tests: "true"
flavor: ${{ matrix.flavor }}
- name: Run E2E Tests
uses: ./.github/actions/maestro-ios
with:
app-path: "/tmp/RNTesterBuild/Build/Products/${{ matrix.flavor }}-iphonesimulator/RNTester.app"
app-id: com.meta.RNTester.localDevelopment
jsengine: ${{ matrix.jsengine }}
maestro-flow: ./packages/rn-tester/.maestro/
flavor: ${{ matrix.flavor }}
test_e2e_ios_templateapp:
if: ${{ github.ref == 'refs/heads/main' || contains(github.ref, 'stable') || inputs.run-e2e-tests }}
runs-on: macos-13-large
needs: build_npm_package
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
continue-on-error: true
strategy:
fail-fast: false
matrix:
jsengine: [Hermes, JSC]
flavor: [Debug, Release]
steps:
- name: Checkout
uses: actions/checkout@v4
- 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-with-cache
- name: Setup ruby
uses: ruby/setup-ruby@v1.170.0
with:
ruby-version: 2.6.10
- name: Download Hermes
uses: actions/download-artifact@v4
with:
name: hermes-darwin-bin-${{matrix.flavor}}
path: /tmp/react-native-tmp
- name: Download React Native Package
uses: actions/download-artifact@v4
with:
name: react-native-package
path: /tmp/react-native-tmp
- name: Print /tmp folder
run: ls -lR /tmp/react-native-tmp
- name: Prepare artifacts
run: |
REACT_NATIVE_PKG=$(find /tmp/react-native-tmp -type f -name "*.tgz")
echo "React Native tgs is $REACT_NATIVE_PKG"
HERMES_PATH=$(find /tmp/react-native-tmp -type f -name "*.tar.gz")
echo "Hermes path is $HERMES_PATH"
# For stable branches, we want to use the stable branch of the template
# In all the other cases, we want to use "main"
BRANCH=${{ github.ref_name }}
if ! [[ $BRANCH == *-stable* ]]; then
BRANCH=main
fi
node ./scripts/e2e/init-project-e2e.js --projectName RNTestProject --currentBranch $BRANCH --directory /tmp/RNTestProject --pathToLocalReactNative $REACT_NATIVE_PKG
cd /tmp/RNTestProject/ios
bundle install
HERMES_ENGINE_TARBALL_PATH=$HERMES_PATH bundle exec pod install
xcodebuild \
-scheme "RNTestProject" \
-workspace RNTestProject.xcworkspace \
-configuration "${{ matrix.flavor }}" \
-sdk "iphonesimulator" \
-destination "generic/platform=iOS Simulator" \
-derivedDataPath "/tmp/RNTestProject"
- name: Run E2E Tests
uses: ./.github/actions/maestro-ios
with:
app-path: "/tmp/RNTestProject/Build/Products/${{ matrix.flavor }}-iphonesimulator/RNTestProject.app"
app-id: org.reactjs.native.example.RNTestProject
jsengine: ${{ matrix.jsengine }}
maestro-flow: ./scripts/e2e/.maestro/
flavor: ${{ matrix.flavor }}
working-directory: /tmp/RNTestProject
test_e2e_android_templateapp:
if: ${{ github.ref == 'refs/heads/main' || contains(github.ref, 'stable') || inputs.run-e2e-tests }}
runs-on: 4-core-ubuntu
needs: build_npm_package
continue-on-error: true
strategy:
fail-fast: false
matrix:
jsengine: [Hermes, JSC]
flavor: [debug, release]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup node.js
uses: ./.github/actions/setup-node
- name: Run yarn
uses: ./.github/actions/yarn-install-with-cache
- name: Set up JDK 17
uses: actions/setup-java@v2
with:
java-version: '17'
distribution: 'zulu'
- name: Download Maven Local
uses: actions/download-artifact@v4
with:
name: maven-local
path: /tmp/react-native-tmp/maven-local
- name: Download React Native Package
uses: actions/download-artifact@v4
with:
name: react-native-package
path: /tmp/react-native-tmp
- name: Print /tmp folder
run: ls -lR /tmp/react-native-tmp
- name: Prepare artifacts
id: prepare-artifacts
run: |
REACT_NATIVE_PKG=$(find /tmp/react-native-tmp -type f -name "*.tgz")
echo "React Native tgs is $REACT_NATIVE_PKG"
MAVEN_LOCAL=/tmp/react-native-tmp/maven-local
echo "Maven local path is $MAVEN_LOCAL"
# For stable branches, we want to use the stable branch of the template
# In all the other cases, we want to use "main"
BRANCH=${{ github.ref_name }}
if ! [[ $BRANCH == *-stable* ]]; then
BRANCH=main
fi
node ./scripts/e2e/init-project-e2e.js --projectName RNTestProject --currentBranch $BRANCH --directory /tmp/RNTestProject --pathToLocalReactNative $REACT_NATIVE_PKG
echo "Feed maven local to gradle.properties"
cd /tmp/RNTestProject
echo "react.internal.mavenLocalRepo=$MAVEN_LOCAL" >> android/gradle.properties
# Build
cd android
CAPITALIZED_FLAVOR=$(echo "${{ matrix.flavor }}" | awk '{print toupper(substr($0, 1, 1)) substr($0, 2)}')
./gradlew assemble$CAPITALIZED_FLAVOR --no-daemon -PreactNativeArchitectures=x86
- name: Run E2E Tests
uses: ./.github/actions/maestro-android
with:
app-path: /tmp/RNTestProject/android/app/build/outputs/apk/${{ matrix.flavor }}/app-${{ matrix.flavor }}.apk
app-id: com.rntestproject
jsengine: ${{ matrix.jsengine }}
maestro-flow: ./scripts/e2e/.maestro/
install-java: 'false'
flavor: ${{ matrix.flavor }}
working-directory: /tmp/RNTestProject
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-2019
needs: prepare_hermes_workspace
env:
HERMES_WS_DIR: 'D:\tmp\hermes'
HERMES_TARBALL_ARTIFACTS_DIR: 'D:\tmp\hermes\hermes-runtime-darwin'
HERMES_OSXBIN_ARTIFACTS_DIR: 'D:\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 }}
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 }}
run-e2e-tests: ${{ github.ref == 'refs/heads/main' || contains(github.ref, 'stable') || inputs.run-e2e-tests }}
test_e2e_android_rntester:
# Temporarily disable RNTester tests on Android as they are quite flaky and they make CI always red
# if: ${{ github.ref == 'refs/heads/main' || contains(github.ref, 'stable') || inputs.run-e2e-tests }}
if: ${{ contains(github.ref, 'stable') || inputs.run-e2e-tests }}
runs-on: ubuntu-latest
needs: [build_android]
strategy:
fail-fast: false
matrix:
jsengine: [hermes, jsc]
flavor: [debug, release]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup node.js
uses: ./.github/actions/setup-node
- name: Install node dependencies
uses: ./.github/actions/yarn-install-with-cache
- name: Download APK
uses: actions/download-artifact@v4
with:
name: rntester-${{ matrix.jsengine }}-${{ matrix.flavor }}
path: ./packages/rn-tester/android/app/build/outputs/apk/${{ matrix.jsengine }}/${{ matrix.flavor }}/
- name: Print folder structure
run: ls -lR ./packages/rn-tester/android/app/build/outputs/apk/${{ matrix.jsengine }}/${{ matrix.flavor }}/
- name: Run E2E Tests
uses: ./.github/actions/maestro-android
with:
app-path: ./packages/rn-tester/android/app/build/outputs/apk/${{ matrix.jsengine }}/${{ matrix.flavor }}/app-${{ matrix.jsengine }}-x86-${{ matrix.flavor }}.apk
app-id: com.facebook.react.uiapp
jsengine: ${{ matrix.jsengine }}
maestro-flow: ./packages/rn-tester/.maestro
flavor: ${{ matrix.flavor }}
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,
]
container:
image: reactnativecommunity/react-native-android:latest
env:
TERM: "dumb"
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
env:
HERMES_WS_DIR: /tmp/hermes
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build 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 }}
test_android_helloworld:
runs-on: 4-core-ubuntu
needs: build_npm_package
container:
image: reactnativecommunity/react-native-android:latest
env:
# Set the encoding to resolve a known character encoding issue with decompressing tar.gz files in conatiners
# via Gradle: https://github.com/gradle/gradle/issues/23391#issuecomment-1878979127
LC_ALL: C.UTF8
YARN_ENABLE_IMMUTABLE_INSTALLS: false
TERM: "dumb"
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
TARGET_ARCHITECTURE: "arm64-v8a"
continue-on-error: true
strategy:
fail-fast: false
matrix:
flavor: [Debug, Release]
architecture: [NewArch, OldArch]
jsengine: [Hermes, JSC]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup git safe folders
run: git config --global --add safe.directory '*'
- name: Download npm package artifact
uses: actions/download-artifact@v4.1.3
with:
name: react-native-package
path: build
- name: Download maven-local artifact
uses: actions/download-artifact@v4.1.3
with:
name: maven-local
path: /tmp/maven-local
- name: Setup gradle
uses: ./.github/actions/setup-gradle
- name: Run yarn install
uses: ./.github/actions/yarn-install-with-cache
- name: Prepare the Helloworld application
shell: bash
run: node ./scripts/e2e/init-project-e2e.js --useHelloWorld --pathToLocalReactNative "$GITHUB_WORKSPACE/build/$(cat build/react-native-package-version)"
- name: Build the Helloworld application for ${{ matrix.flavor }} with Architecture set to ${{ matrix.architecture }}, and using the ${{ matrix.jsengine }} JS engine.
shell: bash
run: |
cd packages/helloworld/android
args=()
if [[ ${{ matrix.architecture }} == "OldArch" ]]; then
args+=(--arch old)
fi
if [[ ${{ matrix.jsengine }} == "JSC" ]]; then
args+=(--jsvm jsc)
fi
if [[ ${{ matrix.flavor }} == "Release" ]]; then
args+=(--prod)
fi
yarn build android "${args[@]}" -P reactNativeArchitectures="$TARGET_ARCHITECTURE" -P react.internal.mavenLocalRepo="/tmp/maven-local"
- name: Upload artifact
uses: actions/upload-artifact@v4.3.4
with:
name: helloworld-apk-${{ matrix.flavor }}-${{ matrix.architecture }}-${{ matrix.jsengine }}
path: ./packages/helloworld/android/app/build/outputs/apk/
compression-level: 0
test_ios_helloworld_with_ruby_3_2_0:
runs-on: macos-13
needs: [prepare_hermes_workspace, build_hermes_macos] # prepare_hermes_workspace must be there because we need its reference to retrieve a couple of outputs
env:
PROJECT_NAME: iOSTemplateProject
HERMES_WS_DIR: /tmp/hermes
YARN_ENABLE_IMMUTABLE_INSTALLS: false
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: ./.github/actions/test-ios-helloworld
with:
ruby-version: 3.2.0
architecture: NewArch
flavor: Debug
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
test_ios_helloworld:
runs-on: macos-13
needs: [prepare_hermes_workspace, build_hermes_macos] # prepare_hermes_workspace must be there because we need its reference to retrieve a couple of outputs
strategy:
matrix:
flavor: [Debug, Release]
jsengine: [Hermes, JSC]
use_frameworks: [StaticLibraries, DynamicFrameworks]
exclude:
# This config is tested with Ruby 3.2.0. Let's not double test it.
- flavor: Debug
jsengine: Hermes
use_frameworks: StaticLibraries
env:
PROJECT_NAME: iOSTemplateProject
HERMES_WS_DIR: /tmp/hermes
YARN_ENABLE_IMMUTABLE_INSTALLS: false
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: ./.github/actions/test-ios-helloworld
with:
flavor: ${{ matrix.flavor }}
jsengine: ${{ matrix.jsengine }}
use-frameworks: ${{ matrix.use_frameworks }}
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
test_js:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node-version: ["20", "18"]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Test JS
uses: ./.github/actions/test-js
with:
node-version: ${{ matrix.node-version }}
lint:
runs-on: ubuntu-latest
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run all the Linters
uses: ./.github/actions/lint
with:
github-token: ${{ env.GH_TOKEN }}
@@ -1,75 +0,0 @@
name: Test Libraries on Nightlies
on:
workflow_call:
jobs:
test-library-on-nightly-android:
name: "[Android] ${{ matrix.library }}"
runs-on: ubuntu-latest
continue-on-error: true
strategy:
matrix:
library: [
"react-native-async-storage",
"react-native-blob-util",
"@react-native-clipboard/clipboard",
"@react-native-community/datetimepicker",
"react-native-gesture-handler",
"react-native-image-picker",
"react-native-linear-gradient",
"@react-native-masked-view/masked-view",
"react-native-maps",
"@react-native-community/netinfo",
"react-native-reanimated",
"react-native-svg",
"react-native-video",
"react-native-webview",
"react-native-mmkv",
"react-native-screens",
"react-native-pager-view",
"@react-native-community/slider"
]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Test ${{ inputs.library-name }}
uses: ./.github/actions/test-library-on-nightly
with:
library-npm-package: ${{ matrix.library }}
platform: android
test-library-on-nightly-ios:
name: "[iOS] ${{ matrix.library }}"
runs-on: macos-13-large
continue-on-error: true
strategy:
matrix:
library: [
"react-native-async-storage",
"react-native-blob-util",
"@react-native-clipboard/clipboard",
"@react-native-community/datetimepicker",
"react-native-gesture-handler",
"react-native-image-picker",
"react-native-linear-gradient",
"@react-native-masked-view/masked-view",
"react-native-maps",
"@react-native-community/netinfo",
"react-native-reanimated",
"react-native-svg",
"react-native-video",
"react-native-webview",
"react-native-mmkv",
"react-native-screens",
"react-native-pager-view",
"@react-native-community/slider"
]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Test ${{ inputs.library-name }}
uses: ./.github/actions/test-library-on-nightly
with:
library-npm-package: ${{ matrix.library }}
platform: ios
@@ -1,45 +0,0 @@
name: Trigger E2E Tests on Comment
# This workflow is used to automatically trigger E2E tests when a comment is made
# containing the text "/run-e2e-tests".
on:
issue_comment:
types: [created]
permissions:
contents: read
jobs:
trigger-e2e-tests:
name: Trigger E2E Tests
runs-on: ubuntu-latest
if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/test-e2e')
steps:
# This is needed because of https://github.com/actions/runner-images/issues/6283
# TL;DR: brew is not in the PATH anymore.
- name: Setup Homebrew
uses: Homebrew/actions/setup-homebrew@master
- name: Install jq
run: brew install jq
- name: Run E2E Tests
run: |
# Github does not provide the branch of a PR when a comment on a PR is made
# So, given the issue number, which is the PR number, we can retrieve the branch with
# a quick API call
echo "Retrieving branch"
BRANCH=$(curl -L \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/facebook/react-native/pulls/$PR_NUMBER | jq -r '.head.ref')
echo "Trigger Test All workflow for branch $BRANCH"
curl -L \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/facebook/react-native/actions/workflows/test-all.yml/dispatches \
-d "{\"ref\": \"$BRANCH\", \"inputs\": {\"run-e2e-tests\": \"true\"}}"
env:
GITHUB_TOKEN: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.issue.number }}
@@ -1,18 +0,0 @@
name: Update node modules cache
on:
workflow_dispatch:
push:
branches:
- main
jobs:
update_node_modules_cache:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install yarn dependencies and update cache
uses: ./.github/actions/yarn-install-with-cache
with:
update-cache: "true"
+10 -111
View File
@@ -20,141 +20,40 @@ DerivedData
*.ipa
*.xcuserstate
project.xcworkspace
**/.xcode.env.local
# Gradle
/build/
/packages/rn-tester/build
/packages/rn-tester/android/app/.cxx/
/packages/rn-tester/android/app/build/
/packages/rn-tester/android/app/gradle/
/packages/rn-tester/android/app/gradlew
/packages/rn-tester/android/app/gradlew.bat
/packages/react-native/ReactAndroid/build/
/packages/react-native/ReactAndroid/.cxx/
/packages/react-native/ReactAndroid/gradle/
/packages/react-native/ReactAndroid/gradlew
/packages/react-native/ReactAndroid/gradlew.bat
/packages/react-native/ReactAndroid/external-artifacts/build/
/packages/react-native/ReactAndroid/external-artifacts/artifacts/
/packages/react-native/ReactAndroid/hermes-engine/build/
/packages/react-native/ReactAndroid/hermes-engine/.cxx/
/packages/helloworld/android/app/build/
/packages/helloworld/android/build/
/packages/react-native-popup-menu-android/android/build/
/packages/react-native-test-library/android/build/
/RNTester/android/app/build/
/RNTester/android/app/gradle/
/RNTester/android/app/gradlew
/RNTester/android/app/gradlew.bat
/ReactAndroid/build/
# Buck
.buckd
buck-out
/.lsp.buckd
/.lsp-buck-out
/packages/react-native/ReactAndroid/src/main/jni/prebuilt/lib/
/packages/react-native/ReactAndroid/src/main/gen
/.cpplsp.buckd
# Android Studio
.project
.settings
.classpath
# Watchman
.watchmanconfig
/ReactAndroid/src/main/jni/prebuilt/lib/armeabi-v7a/
/ReactAndroid/src/main/jni/prebuilt/lib/x86/
/ReactAndroid/src/main/gen
# Android
.idea
.gradle
local.properties
*.iml
/packages/react-native/android/*
!/packages/react-native/android/README.md
/android/
# Node
node_modules
*.log
.nvm
package-lock.json
# OS X
.DS_Store
# Test generated files
/ReactAndroid/src/androidTest/assets/AndroidTestBundle.js
*.js.meta
/coverage
/third-party
# Test Reports
/reports
# Stack Dumps generated when programs crash (Ex. bash.exe.stackdump on Win)
*.stackdump
# Root dir shouldn't have Xcode project
/*.xcodeproj
# ReactCommon subdir shouldn't have Xcode project
/packages/react-native/ReactCommon/**/*.xcodeproj
# Libs that shouldn't have Xcode project
/packages/react-native/Libraries/FBLazyVector/**/*.xcodeproj
/packages/react-native/Libraries/Required/**/*.xcodeproj
/packages/react-native/React/CoreModules/**/*.xcodeproj
/packages/react-native/React/FBReactNativeSpec/**/*.xcodeproj
/packages/react-native-codegen/**/*.xcodeproj
/packages/rn-tester/**/*.xcodeproj
# Ruby Gems (Bundler)
/packages/react-native/vendor
/packages/helloworld/vendor
.ruby-version
/**/.ruby-version
vendor/
# iOS / CocoaPods
/packages/helloworld/ios/build/
/packages/helloworld/ios/Pods/
/packages/helloworld/ios/Podfile.lock
/packages/rn-tester/Gemfile.lock
/packages/**/RCTLegacyInteropComponents.mm
# Ignore RNTester specific Pods, but keep the __offline_mirrors__ here.
/packages/rn-tester/Pods/*
!/packages/rn-tester/Pods/__offline_mirrors_hermes__
!/packages/rn-tester/Pods/__offline_mirrors_jsc__
# @react-native/codegen
/packages/react-native/React/FBReactNativeSpec/
/packages/react-native-codegen/lib
/packages/react-native-codegen/tmp/
/packages/react-native/ReactCommon/react/renderer/components/rncore/
/packages/rn-tester/NativeModuleExample/ScreenshotManagerSpec*
/**/RCTThirdPartyFabricComponentsProvider.*
# @react-native/codegen-typescript-test
/packages/react-native-codegen-typescript-test/lib
# Additional SDKs
/packages/react-native/sdks/download
/packages/react-native/sdks/hermes
/packages/react-native/sdks/hermesc
/packages/react-native/sdks/hermes-engine/hermes-engine-from-local-source-dir.tar.gz
# Visual Studio Code (config dir - if present, this merges user defined
# workspace settings on top of react-native.code-workspace)
/.vscode
# Visual Studio
.vs
# Android memory profiler files
*.hprof
# Temporary files created by Metro to check the health of the file watcher
.metro-health-check*
# CircleCI
.circleci/generated_config.yml
# Jest Integration
/jest/integration/build/
+3
View File
@@ -0,0 +1,3 @@
# rnpm
/local-cli/rnpm
/local-cli/server/middleware/heapCapture/bundle.js
-11
View File
@@ -1,11 +0,0 @@
# Ignore Pods
**/Pods
# Ignore hermes as it is downloaded from the react_native_pods
**/sdks/hermes
**/sdks/downloads
packages/*/dist
vendor
packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeEnumTurboModule.js
-26
View File
@@ -1,26 +0,0 @@
{
"arrowParens": "avoid",
"bracketSameLine": true,
"bracketSpacing": false,
"requirePragma": true,
"singleQuote": true,
"trailingComma": "all",
"endOfLine": "lf",
"overrides": [
{
"files": ["*.code-workspace"],
"options": {
"parser": "json"
}
},
{
"files": [
"*.js",
"*.js.flow"
],
"options": {
"parser": "hermes"
}
}
]
}
+48
View File
@@ -0,0 +1,48 @@
language: objective-c
osx_image: xcode8.3
install:
- nvm install 7
- rm -Rf "${TMPDIR}/jest_preprocess_cache"
- wget https://github.com/yarnpkg/yarn/releases/download/v0.16.0/yarn-0.16.0.js
- export yarn="node $(pwd)/yarn-0.16.0.js"
- $yarn install
script:
- if [[ "$TEST_TYPE" = objc-ios ]]; then travis_retry travis_wait 30 ./scripts/objc-test-ios.sh test; fi
- if [[ "$TEST_TYPE" = objc-tvos ]]; then travis_retry travis_wait 30 ./scripts/objc-test-tvos.sh; fi
- if [[ "$TEST_TYPE" = e2e-objc ]]; then node ./scripts/run-ci-e2e-tests.js --ios --js --retries 3; fi
- if [[ ( "$TEST_TYPE" = podspecs ) && ( "$TRAVIS_PULL_REQUEST" = "false" ) ]]; then gem install cocoapods && travis_wait 30 ./scripts/process-podspecs.sh; fi
cache:
- cocoapods
- yarn
matrix:
- fast_finish: true # Fail the whole build as soon as one test type fails. Should help with Travis capacity issues (very long queues).
# The order of these tests says which are more likely to run first and fail the whole build fast.
env:
- TEST_TYPE=objc-ios
- TEST_TYPE=podspecs
- TEST_TYPE=e2e-objc
- TEST_TYPE=objc-tvos
branches:
only:
- master
- /^.*-stable$/
notifications:
email:
recipients:
- douglowder@mac.com # Doug Lowder built and maintains Apple TV specific code and wants to be notified about tvOS failures.
- eloy@artsy.net # Eloy Durán maintains the podspecs test and wants to be notified about failures.
on_failure: change
on_success: change
slack:
secure: oQL2C966v7/DtxNqfM7WowjY0R5mgLHR2qHkoucwK5iVrmaptnHr8fq01xlj7VT0kDwNLqT3n4+gtCviGw89lq71m3W76c8Pms/10jpjw+LwAfQPVizNw/Bx8MFNNmjDauK/auFxaybiLZupi7zd4xFGOZvScmFdfD4CAAp2OOA=
on_pull_requests: false
on_failure: change
on_success: change
-2316
View File
File diff suppressed because it is too large Load Diff
-2434
View File
File diff suppressed because it is too large Load Diff
-4211
View File
File diff suppressed because it is too large Load Diff
-77
View File
@@ -1,77 +0,0 @@
# Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to make participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies within all project spaces, and it also applies when
an individual is representing the project or its community in public spaces.
Examples of representing a project or community include using an official
project e-mail address, posting via an official social media account, or acting
as an appointed representative at an online or offline event. Representation of
a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at <opensource-conduct@fb.com>. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1,
available at https://www.contributor-covenant.org/version/2/1/code_of_conduct/
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq
+217 -4
View File
@@ -1,7 +1,220 @@
# Contributing to React Native
Thank you for your interest in contributing to React Native! From commenting on and triaging issues, to reviewing and sending Pull Requests, all contributions are welcome.
We aim to build a vibrant and inclusive [ecosystem of partners, core contributors, and community](ECOSYSTEM.md) that goes beyond the main React Native GitHub repository.
<!-- generated_contributing_start -->
React Native is one of Facebook's first open source projects that is both under very active development and is also being used to ship code to everybody using Facebook's mobile apps. If you're interested in contributing to React Native, hopefully this document makes the process for contributing clear.
To learn more about how to contribute check out the Contributing section on the React Native website:
* https://reactnative.dev/contributing/overview
Core contributors to React Native meet monthly and post their meeting notes on the [React Native blog](https://facebook.github.io/react-native/blog). You can also find ad hoc discussions in the [React Native Core Contributors](https://www.facebook.com/groups/reactnativeoss/) Facebook group.
## [Code of Conduct](https://code.facebook.com/codeofconduct)
Facebook has adopted a Code of Conduct that we expect project participants to adhere to. Please read [the full text](https://code.facebook.com/codeofconduct) so that you can understand what actions will and will not be tolerated.
## How to contribute
There are many ways to contribute to React Native, and many of them do not involve writing any code. Here's a few ideas to get started:
* Simply start using React Native. Go through the [Getting Started](http://facebook.github.io/react-native/docs/getting-started.html) guide. Does everything work as expected? If not, we're always looking for improvements. Let us know by [opening an issue](http://facebook.github.io/react-native/docs/contributing.html#reporting-new-issues).
* Look through the [open issues](https://github.com/facebook/react-native/issues). Provide workarounds, ask for clarification, or suggest labels. Help [triage issues](http://facebook.github.io/react-native/docs/contributing.html#triaging-issues-and-pull-requests).
* If you find an issue you would like to fix, [open a pull request](http://facebook.github.io/react-native/docs/contributing.html#your-first-pull-request). Issues tagged as [`Good First Task`](https://github.com/facebook/react-native/labels/Good%20First%20Task) are a good place to get started.
* Read through the [React Native docs](http://facebook.github.io/react-native/docs). If you find anything that is confusing or can be improved, you can make edits by clicking "Improve this page" at the bottom of most docs.
* Browse [Stack Overflow](https://stackoverflow.com/questions/tagged/react-native) and answer questions. This will help you get familiarized with common pitfalls or misunderstandings, which can be useful when contributing updates to the documentation.
* Take a look at the [features requested](https://react-native.canny.io/feature-requests) by others in the community and consider opening a pull request if you see something you want to work on.
Contributions are very welcome. If you think you need help planning your contribution, please hop into [#react-native](https://discord.gg/0ZcbPKXt5bZjGY5n) and let people know you're looking for a mentor.
### Triaging issues and pull requests
One great way you can contribute to the project without writing any code is to help triage issues and pull requests as they come in.
* Ask for more information if the issue does not provide all the details required by the template.
* Suggest [labels](https://github.com/facebook/react-native/labels) that can help categorize issues.
* Flag issues that are stale or that should be closed.
* Ask for test plans and review code.
Adding labels, closing and reopening issues, and merging pull requests is, as you may expect, limited to a subset of contributors. Simply commenting on the issue or pull request can still go a long way towards helping us keep the number of outstanding issues under control.
Once you have become an active contributor in the community, you may gain access to the Facebook GitHub Bot, allowing you to perform some of these operations yourself. You can learn more about the bot in the [maintainer's guide](docs/maintainers.html#facebook-github-bot).
## Our development process
Some of the core team will be working directly on [GitHub](https://github.com/facebook/react-native). These changes will be public from the beginning. Other changesets will come via a bridge with Facebook's internal source control. This is a necessity as it allows engineers at Facebook outside of the core team to move fast and contribute from an environment they are comfortable in.
When a change made on GitHub is approved, it will first be imported into Facebook's internal source control. The change will eventually sync back to GitHub as a single commit once it has passed all internal tests.
### Branch organization
We will do our best to keep `master` in good shape, with tests passing at all times. But in order to move fast, we will make API changes that your application might not be compatible with. We will do our best to [communicate these changes](https://github.com/facebook/react-native/releases) and version appropriately so you can lock into a specific version if need be.
To see what changes are coming and provide better feedback to React Native contributors, use the [latest release candidate](http://facebook.github.io/react-native/versions.html) when possible. By the time a release candidate is released, the changes it contains will have been shipped in production Facebook apps for over two weeks.
## Bugs
We use [GitHub Issues](https://github.com/facebook/react-native/issues) for our public bugs. If you would like to report a problem, take a look around and see if someone already opened an issue about it. If you a are certain this is a new, unreported bug, you can submit a [bug report](http://facebook.github.io/react-native/docs/contributing.html#reporting-new-issues).
If you have questions about using React Native, the [help page](http://facebook.github.io/react-native/support.html) list various resources that should help you get started.
We also have a [place where you can request features or enhancements](https://react-native.canny.io/feature-requests). If you see anything you'd like to be implemented, vote it up and explain your use case.
## Reporting new issues
When [opening a new issue](https://github.com/facebook/react-native/issues/new), always make sure to fill out the [issue template](https://raw.githubusercontent.com/facebook/react-native/master/.github/ISSUE_TEMPLATE.md). **This step is very important!** Not doing so may result in your issue getting closed. Don't take this personally if this happens, and feel free to open a new issue once you've gathered all the information required by the template.
* **One issue, one bug:** Please report a single bug per issue.
* **Provide a Snack:** The best way to get attention on your issue is to provide a reduced test case. You can use [Snack](https://snack.expo.io/) to demonstrate the issue.
* **Provide reproduction steps:** List all the steps necessary to reproduce the issue. Provide a Snack or upload a sample project to GitHub. The person reading your bug report should be able to follow these steps to reproduce your issue with minimal effort.
* **Try out the latest version:** Verify that the issue can be reproduced locally by updating your project to use [React Native from `master`](http://facebook.github.io/react-native/versions.html). The bug may have already been fixed!
We're not able to provide support through GitHub Issues. If you're looking for help with your code, consider asking on [Stack Overflow](http://stackoverflow.com/questions/tagged/react-native) or reaching out to the community through [other channels](https://facebook.github.io/react-native/support.html).
### Security bugs
Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe disclosure of security bugs. With that in mind, please do not file public issues; go through the process outlined on that page.
## Pull requests
### Your first pull request
So you have decided to contribute code back to upstream by opening a pull request. You've invested a good chunk of time, and we appreciate it. We will do our best to work with you and get the PR looked at.
Working on your first Pull Request? You can learn how from this free video series:
[**How to Contribute to an Open Source Project on GitHub**](https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github)
We have a list of [beginner friendly issues](https://github.com/facebook/react-native/labels/Good%20First%20Task) to help you get your feet wet in the React Native codebase and familiar with our contribution process. This is a great place to get started.
### Proposing a change
If you would like to request a new feature or enhancement but are not yet thinking about opening a pull request, we have a [place to track feature requests](https://react-native.canny.io/feature-requests).
If you intend to change the public API, or make any non-trivial changes to the implementation, we recommend [filing an issue](https://github.com/facebook/react-native/issues/new). This lets us reach an agreement on your proposal before you put significant effort into it.
If you're only fixing a bug, it's fine to submit a pull request right away but we still recommend to file an issue detailing what you're fixing. This is helpful in case we don't accept that specific fix but want to keep track of the issue.
### Sending a pull request
Small pull requests are much easier to review and more likely to get merged. Make sure the PR does only one thing, otherwise please split it.
**Before submitting a pull request**, please make sure the following is done:
1. Fork [the repository](https://github.com/facebook/react-native) and create your branch from `master`.
2. Add the copyright notice to the top of any new files you've added.
3. Describe your [**test plan**](https://facebook.github.io/react-native/docs/contributing.html#test-plan) in your commit.
4. Ensure [**tests pass**](https://facebook.github.io/react-native/docs/contributing.html#contrinuous-integration-tests) on both Travis and Circle CI.
5. Make sure your code lints (`npm run lint`).
6. If you haven't already, [sign the CLA](https://code.facebook.com/cla).
All pull requests should be opened against the `master` branch.
> **Note:** It is not necessary to keep clicking `Merge master to your branch` on the PR page. You would want to merge master if there are conflicts or tests are failing. The Facebook-GitHub-Bot ultimately squashes all commits to a single one before merging your PR.
#### Test plan
A good test plan has the exact commands you ran and their output, provides screenshots or videos if the pull request changes UI or updates the website.
* If you've added code that should be tested, add tests!
* If you've changed APIs, update the documentation.
* If you've updated the docs, verify the website locally and submit screenshots if applicable (see [website/README.md](https://github.com/facebook/react-native/blob/master/website/README.md))
See [What is a Test Plan?](https://medium.com/@martinkonicek/what-is-a-test-plan-8bfc840ec171#.y9lcuqqi9) to learn more.
#### Continuous integration tests
Make sure all **tests pass** on both [Travis][travis] and [Circle CI][circle]. PRs that break tests are unlikely to be merged. Learn more about [testing your changes here](https://facebook.github.io/react-native/docs/testing.html).
[travis]: https://travis-ci.org/facebook/react-native
[circle]: http://circleci.com/gh/facebook/react-native
#### Breaking changes
When adding a new breaking change, follow this template in your pull request:
```
### New breaking change here
* **Who does this affect**:
* **How to migrate**:
* **Why make this breaking change**:
* **Severity (number of people affected x effort)**:
```
If your pull request is merged, a core contributor will update the [list of breaking changes](https://github.com/facebook/react-native/wiki/Breaking-Changes) which is then used to populate the release notes.
#### Copyright Notice for files
Copy and paste this to the top of your new file(s):
```JS
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
```
If you've added a new module, add a `@providesModule <moduleName>` at the end of the comment. This will allow the haste package manager to find it.
#### Contributor License Agreement (CLA)
In order to accept your pull request, we need you to submit a CLA. You only need to do this once, so if you've done this for another Facebook open source project, you're good to go. If you are submitting a pull request for the first time, the Facebook GitHub Bot will reply with a link to the CLA form. You may also [complete your CLA here](https://code.facebook.com/cla).
### What happens next?
The core team will be monitoring for pull requests. Read [what to expect from maintainers](https://facebook.github.io/react-native/docs/maintainers.html#handling-pull-requests) to understand what may happen after you open a pull request.
## Style Guide
Our linter will catch most styling issues that may exist in your code. You can check the status of your code styling by simply running `npm run lint`.
However, there are still some styles that the linter cannot pick up.
### Code Conventions
#### General
* **Most important: Look around.** Match the style you see used in the rest of the project. This includes formatting, naming things in code, naming things in documentation.
* Add trailing commas,
* 2 spaces for indentation (no tabs)
* "Attractive"
#### JavaScript
* Use semicolons;
* `'use strict';`
* Prefer `'` over `"`
* Do not use the optional parameters of `setTimeout` and `setInterval`
* 80 character line length
#### JSX
* Prefer `"` over `'` for string literal props
* When wrapping opening tags over multiple lines, place one prop per line
* `{}` of props should hug their values (no spaces)
* Place the closing `>` of opening tags on the same line as the last prop
* Place the closing `/>` of self-closing tags on their own line and left-align them with the opening `<`
#### Objective-C
* Space after `@property` declarations
* Brackets on *every* `if`, on the *same* line
* `- method`, `@interface`, and `@implementation` brackets on the following line
* *Try* to keep it around 80 characters line length (sometimes it's just not possible...)
* `*` operator goes with the variable name (e.g. `NSObject *variableName;`)
#### Java
* If a method call spans multiple lines closing bracket is on the same line as the last argument.
* If a method header doesn't fit on one line each argument goes on a separate line.
* 100 character line length
### Documentation
* Do not wrap lines at 80 characters - configure your editor to soft-wrap when editing documentation.
## License
By contributing to React Native, you agree that your contributions will be licensed under its BSD license.
<!-- generated_contributing_end -->
+54
View File
@@ -0,0 +1,54 @@
FROM containership/android-base:latest
# set default environment variables
ENV GRADLE_OPTS="-Dorg.gradle.jvmargs=\"-Xmx512m -XX:+HeapDumpOnOutOfMemoryError\""
ENV JAVA_TOOL_OPTIONS="-Dfile.encoding=UTF8"
# add ReactAndroid directory
ADD .buckconfig /app/.buckconfig
ADD .buckjavaargs /app/.buckjavaargs
ADD ReactAndroid /app/ReactAndroid
ADD ReactCommon /app/ReactCommon
ADD keystores /app/keystores
# set workdir
WORKDIR /app
# run buck fetches
RUN buck fetch ReactAndroid/src/test/java/com/facebook/react/modules
RUN buck fetch ReactAndroid/src/main/java/com/facebook/react
RUN buck fetch ReactAndroid/src/main/java/com/facebook/react/shell
RUN buck fetch ReactAndroid/src/test/...
RUN buck fetch ReactAndroid/src/androidTest/...
# build app
RUN buck build ReactAndroid/src/main/java/com/facebook/react
RUN buck build ReactAndroid/src/main/java/com/facebook/react/shell
ADD gradle /app/gradle
ADD gradlew /app/gradlew
ADD settings.gradle /app/settings.gradle
ADD build.gradle /app/build.gradle
ADD react.gradle /app/react.gradle
# run gradle downloads
RUN ./gradlew :ReactAndroid:downloadBoost :ReactAndroid:downloadDoubleConversion :ReactAndroid:downloadFolly :ReactAndroid:downloadGlog :ReactAndroid:downloadJSCHeaders
# compile native libs with Gradle script, we need bridge for unit and integration tests
RUN ./gradlew :ReactAndroid:packageReactNdkLibsForBuck -Pjobs=1 -Pcom.android.build.threadPoolSize=1
# add all react-native code
ADD . /app
WORKDIR /app
# https://github.com/npm/npm/issues/13306
RUN cd $(npm root -g)/npm && npm install fs-extra && sed -i -e s/graceful-fs/fs-extra/ -e s/fs.rename/fs.move/ ./lib/utils/rename.js
# build node dependencies
RUN npm install
RUN npm install github@0.2.4
WORKDIR /app/website
RUN npm install
WORKDIR /app
+101
View File
@@ -0,0 +1,101 @@
FROM library/ubuntu:16.04
# set default build arguments
ARG ANDROID_VERSION=25.2.3
ARG BUCK_VERSION=f3452a6a7ab15a60e94c962e686293acbe677473
ARG NDK_VERSION=10e
ARG NODE_VERSION=6.2.0
ARG WATCHMAN_VERSION=4.7.0
# set default environment variables
ENV ADB_INSTALL_TIMEOUT=10
ENV PATH=${PATH}:/opt/buck/bin/
ENV ANDROID_HOME=/opt/android
ENV ANDROID_SDK_HOME=${ANDROID_HOME}
ENV PATH=${PATH}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools
ENV ANDROID_NDK=/opt/ndk/android-ndk-r$NDK_VERSION
ENV PATH=${PATH}:${ANDROID_NDK}
# install system dependencies
RUN apt-get update && apt-get install ant autoconf automake curl g++ gcc git libqt5widgets5 lib32z1 lib32stdc++6 make maven npm openjdk-8* python-dev python3-dev qml-module-qtquick-controls qtdeclarative5-dev unzip -y
# configure npm
RUN npm config set spin=false
RUN npm config set progress=false
# install node
RUN npm install n -g
RUN n $NODE_VERSION
# download buck
RUN git clone https://github.com/facebook/buck.git /opt/buck
WORKDIR /opt/buck
RUN git checkout $BUCK_VERSION
# build buck
RUN ant
# download watchman
RUN git clone https://github.com/facebook/watchman.git /opt/watchman
WORKDIR /opt/watchman
RUN git checkout v$WATCHMAN_VERSION
# build watchman
RUN ./autogen.sh
RUN ./configure
RUN make
RUN make install
# download and unpack android
RUN mkdir /opt/android
WORKDIR /opt/android
RUN curl --silent https://dl.google.com/android/repository/tools_r$ANDROID_VERSION-linux.zip > android.zip
RUN unzip android.zip
RUN rm android.zip
# download and unpack NDK
RUN mkdir /opt/ndk
WORKDIR /opt/ndk
RUN curl --silent https://dl.google.com/android/repository/android-ndk-r$NDK_VERSION-linux-x86_64.zip > ndk.zip
RUN unzip ndk.zip
# cleanup NDK
RUN rm ndk.zip
# Add android SDK tools
# Android SDK Platform-tools, revision 25.0.4
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "Android SDK Platform-tools, revision 25.0.4" | awk '{ print $1 }' | sed 's/.$//')
# Android SDK Build-tools, revision 23.0.1
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "Android SDK Build-tools, revision 23.0.1" | awk '{ print $1 }' | sed 's/.$//')
# SDK Platform Android 6.0, API 23, revision 3
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "SDK Platform Android 6.0, API 23" | awk '{ print $1 }' | sed 's/.$//')
# SDK Platform Android 4.4.2, API 19, revision 4
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "SDK Platform Android 4.4.2, API 19, revision 4" | awk '{ print $1 }' | sed 's/.$//')
# ARM EABI v7a System Image, Android API 19, revision 5
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "ARM EABI v7a System Image, Android API 19, revision 5" | awk '{ print $1 }' | sed 's/.$//')
# Intel x86 Atom System Image, Android API 19, revision 5
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "Intel x86 Atom System Image, Android API 19, revision 5" | awk '{ print $1 }' | sed 's/.$//')
# Google APIs, Android API 23, revision 1
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "Google APIs, Android API 23, revision 1" | awk '{ print $1 }' | sed 's/.$//')
# Android Support Repository, revision 45
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "Android Support Repository" | awk '{ print $1 }' | sed 's/.$//')
# Link adb executable
RUN ln -s /opt/android/platform-tools/adb /usr/bin/adb
# Install google-chrome
RUN curl -fsSL https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
&& echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list \
&& apt-get update \
&& apt-get install -y google-chrome-stable
# clean up unnecessary directories
RUN rm -rf /opt/android/system-images/android-19/default/x86
+19
View File
@@ -0,0 +1,19 @@
FROM library/node:6.9.2
ENV YARN_VERSION=0.19.1
# install dependencies
RUN apt-get update && apt-get install ocaml libelf-dev -y
RUN npm install yarn@$YARN_VERSION -g
# add code
RUN mkdir /app
ADD . /app
WORKDIR /app
RUN yarn install --ignore-engines
WORKDIR website
RUN yarn install --ignore-engines --ignore-platform
WORKDIR /app
@@ -0,0 +1,163 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
/**
* This script runs instrumentation tests one by one with retries
* Instrumentation tests tend to be flaky, so rerunning them individually increases
* chances for success and reduces total average execution time.
*
* We assume that all instrumentation tests are flat in one folder
* Available arguments:
* --path - path to all .java files with tests
* --package - com.facebook.react.tests
* --retries [num] - how many times to retry possible flaky commands: npm install and running tests, default 1
*/
/*eslint-disable no-undef */
const argv = require('yargs').argv;
const async = require('async');
const child_process = require('child_process');
const fs = require('fs');
const path = require('path');
const colors = {
GREEN: '\x1b[32m',
RED: '\x1b[31m',
RESET: '\x1b[0m'
};
const test_opts = {
FILTER: new RegExp(argv.filter || '.*', 'i'),
IGNORE: argv.ignore || null,
PACKAGE: argv.package || 'com.facebook.react.tests',
PATH: argv.path || './ReactAndroid/src/androidTest/java/com/facebook/react/tests',
RETRIES: parseInt(argv.retries || 2, 10),
TEST_TIMEOUT: parseInt(argv['test-timeout'] || 1000 * 60 * 10),
OFFSET: argv.offset,
COUNT: argv.count
}
let max_test_class_length = Number.NEGATIVE_INFINITY;
let testClasses = fs.readdirSync(path.resolve(process.cwd(), test_opts.PATH))
.filter((file) => {
return file.endsWith('.java');
}).map((clazz) => {
return path.basename(clazz, '.java');
});
if (test_opts.IGNORE) {
test_opts.IGNORE = new RegExp(test_opts.IGNORE, 'i');
testClasses = testClasses.filter(className => {
return !test_opts.IGNORE.test(className);
});
}
testClasses = testClasses.map((clazz) => {
return test_opts.PACKAGE + '.' + clazz;
}).filter((clazz) => {
return test_opts.FILTER.test(clazz);
});
// only process subset of the tests at corresponding offset and count if args provided
if (test_opts.COUNT != null && test_opts.OFFSET != null) {
const testCount = testClasses.length;
const start = test_opts.COUNT * test_opts.OFFSET;
const end = start + test_opts.COUNT;
if (start >= testClasses.length) {
testClasses = [];
} else if (end >= testClasses.length) {
testClasses = testClasses.slice(start);
} else {
testClasses = testClasses.slice(start, end);
}
}
return async.mapSeries(testClasses, (clazz, callback) => {
if(clazz.length > max_test_class_length) {
max_test_class_length = clazz.length;
}
return async.retry(test_opts.RETRIES, (retryCb) => {
const test_process = child_process.spawn('./ContainerShip/scripts/run-instrumentation-tests-via-adb-shell.sh', [test_opts.PACKAGE, clazz], {
stdio: 'inherit'
})
const timeout = setTimeout(() => {
test_process.kill();
}, test_opts.TEST_TIMEOUT);
test_process.on('error', (err) => {
clearTimeout(timeout);
retryCb(err);
});
test_process.on('exit', (code) => {
clearTimeout(timeout);
if(code !== 0) {
return retryCb(new Error(`Process exited with code: ${code}`));
}
return retryCb();
});
}, (err) => {
return callback(null, {
name: clazz,
status: err ? 'failure' : 'success'
});
});
}, (err, results) => {
print_test_suite_results(results);
const failures = results.filter((test) => {
return test.status === 'failure';
});
return failures.length === 0 ? process.exit(0) : process.exit(1);
});
function print_test_suite_results(results) {
console.log('\n\nTest Suite Results:\n');
let color;
let failing_suites = 0;
let passing_suites = 0;
function pad_output(num_chars) {
let i = 0;
while(i < num_chars) {
process.stdout.write(' ');
i++;
}
}
results.forEach((test) => {
if(test.status === 'success') {
color = colors.GREEN;
passing_suites++;
} else if(test.status === 'failure') {
color = colors.RED;
failing_suites++;
}
process.stdout.write(color);
process.stdout.write(test.name);
pad_output((max_test_class_length - test.name.length) + 8);
process.stdout.write(test.status);
process.stdout.write(`${colors.RESET}\n`);
});
console.log(`\n${passing_suites} passing, ${failing_suites} failing!`);
}
@@ -0,0 +1,35 @@
#!/bin/bash
# for buck gen
mount -o remount,exec /dev/shm
AVD_UUID=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1)
# create virtual device
echo no | android create avd -n $AVD_UUID -f -t android-19 --abi default/armeabi-v7a
# emulator setup
emulator64-arm -avd $AVD_UUID -no-skin -no-audio -no-window -no-boot-anim &
bootanim=""
until [[ "$bootanim" =~ "stopped" ]]; do
sleep 5
bootanim=$(adb -e shell getprop init.svc.bootanim 2>&1)
echo "boot animation status=$bootanim"
done
set -x
# solve issue with max user watches limit
echo 65536 | tee -a /proc/sys/fs/inotify/max_user_watches
watchman shutdown-server
# integration tests
# build JS bundle for instrumentation tests
node local-cli/cli.js bundle --platform android --dev true --entry-file ReactAndroid/src/androidTest/js/TestBundle.js --bundle-output ReactAndroid/src/androidTest/assets/AndroidTestBundle.js
# build test APK
source ./scripts/circle-ci-android-setup.sh && NO_BUCKD=1 retry3 buck install ReactAndroid/src/androidTest/buck-runner:instrumentation-tests --config build.threads=1
# run installed apk with tests
node ./ContainerShip/scripts/run-android-ci-instrumentation-tests.js $*
exit $?
@@ -0,0 +1,12 @@
#!/bin/bash
# set default environment variables
UNIT_TESTS_BUILD_THREADS="${UNIT_TESTS_BUILD_THREADS:-1}"
# for buck gen
mount -o remount,exec /dev/shm
set -x
# run unit tests
buck test ReactAndroid/src/test/... --config build.threads=$UNIT_TESTS_BUILD_THREADS
+253
View File
@@ -0,0 +1,253 @@
#!/bin/bash
set -ex
# set default environment variables
ROOT=$(pwd)
SCRIPTS=$(pwd)/scripts
RUN_ANDROID=0
RUN_CLI_INSTALL=1
RUN_IOS=0
RUN_JS=0
RETRY_COUNT=${RETRY_COUNT:-2}
AVD_UUID=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1)
ANDROID_NPM_DEPS="appium@1.5.1 mocha@2.4.5 wd@0.3.11 colors@1.0.3 pretty-data2@0.40.1"
CLI_PACKAGE=$ROOT/react-native-cli/react-native-cli-*.tgz
PACKAGE=$ROOT/react-native-*.tgz
# solve issue with max user watches limit
echo 65536 | tee -a /proc/sys/fs/inotify/max_user_watches
watchman shutdown-server
# retries command on failure
# $1 -- max attempts
# $2 -- command to run
function retry() {
local -r -i max_attempts="$1"; shift
local -r cmd="$@"
local -i attempt_num=1
until $cmd; do
if (( attempt_num == max_attempts )); then
echo "Execution of '$cmd' failed; no more attempts left"
return 1
else
(( attempt_num++ ))
echo "Execution of '$cmd' failed; retrying for attempt number $attempt_num..."
fi
done
}
# parse command line args & flags
while :; do
case "$1" in
--android)
RUN_ANDROID=1
shift
;;
--ios)
RUN_IOS=1
shift
;;
--js)
RUN_JS=1
shift
;;
--skip-cli-install)
RUN_CLI_INSTALL=0
shift
;;
--tvos)
RUN_IOS=1
shift
;;
*)
break
esac
done
function e2e_suite() {
cd $ROOT
if [ $RUN_ANDROID -eq 0 ] && [ $RUN_IOS -eq 0 ] && [ $RUN_JS -eq 0 ]; then
echo "No e2e tests specified!"
return 0
fi
# create temp dir
TEMP_DIR=$(mktemp -d /tmp/react-native-XXXXXXXX)
# To make sure we actually installed the local version
# of react-native, we will create a temp file inside the template
# and check that it exists after `react-native init
IOS_MARKER=$(mktemp $ROOT/local-cli/templates/HelloWorld/ios/HelloWorld/XXXXXXXX)
ANDROID_MARKER=$(mktemp ${ROOT}/local-cli/templates/HelloWorld/android/XXXXXXXX)
# install CLI
cd react-native-cli
npm pack
cd ..
# can skip cli install for non sudo mode
if [ $RUN_CLI_INSTALL -ne 0 ]; then
npm install -g $CLI_PACKAGE
if [ $? -ne 0 ]; then
echo "Could not install react-native-cli globally, please run in su mode"
echo "Or with --skip-cli-install to skip this step"
return 1
fi
fi
if [ $RUN_ANDROID -ne 0 ]; then
set +ex
# create virtual device
if ! android list avd | grep "$AVD_UUID" > /dev/null; then
echo no | android create avd -n $AVD_UUID -f -t android-19 --abi default/armeabi-v7a
fi
# newline at end of adb devices call and first line is headers
DEVICE_COUNT=$(adb devices | wc -l)
((DEVICE_COUNT -= 2))
# will always kill an existing emulator if one exists for fresh setup
if [[ $DEVICE_COUNT -ge 1 ]]; then
adb emu kill
fi
# emulator setup
emulator64-arm -avd $AVD_UUID -no-skin -no-audio -no-window -no-boot-anim &
bootanim=""
until [[ "$bootanim" =~ "stopped" ]]; do
sleep 5
bootanim=$(adb -e shell getprop init.svc.bootanim 2>&1)
echo "boot animation status=$bootanim"
done
set -ex
./gradlew :ReactAndroid:installArchives -Pjobs=1 -Dorg.gradle.jvmargs="-Xmx512m -XX:+HeapDumpOnOutOfMemoryError"
if [ $? -ne 0 ]; then
echo "Failed to compile Android binaries"
return 1
fi
fi
npm pack
if [ $? -ne 0 ]; then
echo "Failed to pack react-native"
return 1
fi
cd $TEMP_DIR
retry $RETRY_COUNT react-native init EndToEndTest --version $PACKAGE --npm
if [ $? -ne 0 ]; then
echo "Failed to execute react-native init"
echo "Most common reason is npm registry connectivity, try again"
return 1
fi
cd EndToEndTest
# android tests
if [ $RUN_ANDROID -ne 0 ]; then
echo "Running an Android e2e test"
echo "Installing e2e framework"
retry $RETRY_COUNT npm install --save-dev $ANDROID_NPM_DEPS --silent >> /dev/null
if [ $? -ne 0 ]; then
echo "Failed to install appium"
echo "Most common reason is npm registry connectivity, try again"
return 1
fi
cp $SCRIPTS/android-e2e-test.js android-e2e-test.js
cd android
echo "Downloading Maven deps"
./gradlew :app:copyDownloadableDepsToLibs
cd ..
keytool -genkey -v -keystore android/keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"
node ./node_modules/.bin/appium >> /dev/null &
APPIUM_PID=$!
echo "Starting appium server $APPIUM_PID"
echo "Building app"
buck build android/app
# hack to get node unhung (kill buckd)
kill -9 $(pgrep java)
if [ $? -ne 0 ]; then
echo "could not execute Buck build, is it installed and in PATH?"
return 1
fi
echo "Starting packager server"
npm start >> /dev/null &
SERVER_PID=$!
sleep 15
echo "Executing android e2e test"
retry $RETRY_COUNT node node_modules/.bin/_mocha android-e2e-test.js
if [ $? -ne 0 ]; then
echo "Failed to run Android e2e tests"
echo "Most likely the code is broken"
return 1
fi
# kill packager process
if kill -0 $SERVER_PID; then
echo "Killing packager $SERVER_PID"
kill -9 $SERVER_PID
fi
# kill appium process
if kill -0 $APPIUM_PID; then
echo "Killing appium $APPIUM_PID"
kill -9 $APPIUM_PID
fi
fi
# ios tests
if [ $RUN_IOS -ne 0 ]; then
echo "Running ios e2e tests not yet implemented for docker!"
fi
# js tests
if [ $RUN_JS -ne 0 ]; then
# Check the packager produces a bundle (doesn't throw an error)
react-native bundle --max-workers 1 --platform android --dev true --entry-file index.android.js --bundle-output android-bundle.js
if [ $? -ne 0 ]; then
echo "Could not build android bundle"
return 1
fi
react-native bundle --max-workers 1 --platform ios --dev true --entry-file index.ios.js --bundle-output ios-bundle.js
if [ $? -ne 0 ]; then
echo "Could not build iOS bundle"
return 1
fi
fi
# directory cleanup
rm $IOS_MARKER
rm $ANDROID_MARKER
return 0
}
retry $RETRY_COUNT e2e_suite
@@ -0,0 +1,65 @@
#!/bin/bash
# Python script to run instrumentation tests, copied from https://github.com/circleci/circle-dummy-android
# Example: ./scripts/run-android-instrumentation-tests.sh com.facebook.react.tests com.facebook.react.tests.ReactPickerTestCase
#
export PATH="$ANDROID_HOME/platform-tools:$ANDROID_HOME/tools:$PATH"
# clear the logs
adb logcat -c
# run tests and check output
python - $1 $2 << END
import re
import subprocess as sp
import sys
import threading
import time
done = False
test_app = sys.argv[1]
test_class = None
if len(sys.argv) > 2:
test_class = sys.argv[2]
def update():
# prevent CircleCI from killing the process for inactivity
while not done:
time.sleep(5)
print "Running in background. Waiting for 'adb' command reponse..."
t = threading.Thread(target=update)
t.dameon = True
t.start()
def run():
sp.Popen(['adb', 'wait-for-device']).communicate()
if (test_class != None):
p = sp.Popen('adb shell am instrument -w -e class %s %s/android.support.test.runner.AndroidJUnitRunner'
% (test_class, test_app), shell=True, stdout=sp.PIPE, stderr=sp.PIPE, stdin=sp.PIPE)
else :
p = sp.Popen('adb shell am instrument -w %s/android.support.test.runner.AndroidJUnitRunner'
% (test_app), shell=True, stdout=sp.PIPE, stderr=sp.PIPE, stdin=sp.PIPE)
return p.communicate()
success = re.compile(r'OK \(\d+ test(s)?\)')
stdout, stderr = run()
done = True
print stderr
print stdout
if success.search(stderr + stdout):
sys.exit(0)
else:
# dump the logs
sp.Popen(['adb', 'logcat', '-d']).communicate()
sys.exit(1) # make sure we fail if the test failed
END
RETVAL=$?
exit $RETVAL
+96
View File
@@ -0,0 +1,96 @@
# Dockerfile Tests
This is a high level overview of the test configuration using docker. It explains how to run the tests locally
and how they integrate with the Jenkins Pipeline script to run the automated tests on ContainerShip <https://www.containership.io/>.
## Docker Installation
It is required to have Docker running on your machine in order to build and run the tests in the Dockerfiles.
See <https://docs.docker.com/engine/installation/> for more information on how to install.
## Convenience NPM Run Scripts
We have added a number of default run scripts to the `package.json` file to simplify building and running your tests.
`npm run test-android-setup` - Pulls down the base android docker image used for running the tests
`npm run test-android-build` - Builds the docker image used to run the tests
`npm run test-android-run-unit` - Runs all the unit tests that have been built in the latest react/android docker image (note: you need to run test-android-build before executing this, if the image does not exist it will fail)
`npm run test-android-run-instrumentation` - Runs all the instrumentation tests that have been built in the latest react/android docker image (note: you need to run test-android-build before executing this, if the image does not exist it will fail). You can also pass additional flags to filter which tests instrumentation tests are run. Ex: `npm run test-android-run-instrumentation -- --filter=TestIdTestCase` to only run the TestIdTestCase instrumentation test. See below for more information
on the instrumentation test flags.
`npm run test-android-run-e2e` - Runs all the end to end tests that have been built in the latest react/android docker image (note: you need to run test-android-build before executing this, if the image does not exist it will fail)
`npm run test-android-unit` - Builds and runs the android unit tests.
`npm run test-android-instrumentation` - Builds and runs the android instrumentation tests.
`npm run test-android-e2e` - Builds and runs the android end to end tests.
## Detailed Android Setup
There are two Dockerfiles for use with the Android codebase.
The `Dockerfile.android-base` contains all the necessary prerequisites required to run the React Android tests. It is
separated out into a separate Dockerfile because these are dependencies that rarely change and also because it is quite
a beastly image since it contains all the Android depedencies for running android and the emulators (~9GB).
The good news is you should rarely have to build or pull down the base image! All iterative code updates happen as
part of the `Dockerfile.android` image build.
So step one...
`docker pull containership/android-base:latest`
This will take quite some time depending on your connection and you need to ensure you have ~10GB of free disk space.
Once this is done, you can run tests locally by executing two simple commands:
1. `docker build -t react/android -f ./ContainerShip/Dockerfile.android .`
2. `docker run --cap-add=SYS_ADMIN -it react/android bash ContainerShip/scripts/run-android-docker-unit-tests.sh`
> Note: `--cap-add=SYS_ADMIN` flag is required for the `ContainerShip/scripts/run-android-docker-unit-tests.sh` and
`ContainerShip/scripts/run-android-docker-instrumentation-tests.sh` in order to allow the remounting of `/dev/shm` as writeable
so the `buck` build system may write temporary output to that location
Every time you make any modifications to the codebase, you should re-run the `docker build ...` command in order for your
updates to be included in your local docker image.
The following shell scripts have been provided for android testing:
`ContainerShip/scripts/run-android-docker-unit-tests.sh` - Runs the standard android unit tests
`ContainerShip/scripts/run-android-docker-instrumentation-tests.sh` - Runs the android instrumentation tests on the emulator. *Note* that these
tests take quite some time to run so there are various flags you can pass in order to filter which tests are run (see below)
`ContainerShip/scripts/run-ci-e2e-tests.sh` - Runs the android end to end tests
#### ContainerShip/scripts/run-android-docker-instrumentation-tests.sh
The instrumentation test script accepts the following flags in order to customize the execution of the tests:
`--filter` - A regex that filters which instrumentation tests will be run. (Defaults to .*)
`--package` - Name of the java package containing the instrumentation tests (Defaults to com.facebook.react.tests)
`--path` - Path to the directory containing the instrumentation tests. (Defaults to ./ReactAndroid/src/androidTest/java/com/facebook/react/tests)
`--retries` - Number of times to retry a failed test before declaring a failure (Defaults to 2)
For example, if locally you only wanted to run the InitialPropsTestCase, you could do the following:
`docker run --cap-add=SYS_ADMIN -it react/android bash ContainerShip/scripts/run-android-docker-instrumentation-tests.sh --filter="InitialPropsTestCase"`
# Javascript Setup
There is a single Dockerfile for use with the javascript codebase.
The `Dockerfile.javascript` base requires all the necessary dependencies for running Javascript tests.
Any time you make an update to the codebase, you can build and run the javascript tests with the following three commands:
1. `docker build -t react/js -f ./ContainerShip/Dockerfile.javascript .`
2. `docker run -it react/js yarn test --maxWorkers=4`
3. `docker run -it react/js yarn run flow -- check`
-85
View File
@@ -1,85 +0,0 @@
# The React Native Ecosystem
We aim to build a vibrant and inclusive ecosystem of partners, core contributors, and community that goes beyond the main React Native GitHub repository. This document explains the roles and responsibilities of various stakeholders and provides guidelines for the community organization. The structure outlined in this document has been in place for a while but had not been written down before.
There are three types of stakeholders:
* **Partners:** Companies significantly invested in React Native and take responsibility for the React Native vision and community.
* **Core Contributors:** Individual people who contribute to the React Native project.
* **Community Contributors:** Individuals who support projects in the [react-native-community](https://github.com/react-native-community) organization.
## Partners
Partners are companies that are significantly invested in React Native and demonstrate ownership. Informed by their use of React Native, they push for improvements of the core and/or the ecosystem around it. Examples of this may include large scale contributions to `react-native` or owning essential tools or libraries.
Partners think of React Native as a product; they understand the trade offs that the project makes as well as future plans and goals. Together we shape the vision for React Native to make it the best way to build applications.
### Application process
To become a React Native partner, an existing partner needs to refer and champion your application. Partners will undergo a 3 month incubating period, after which Partners will vote to convert to full membership.
Partnership is not a status symbol, it is a commitment to invest significant resources into improving React Native.
Maintaining partner status requires consistently meeting the baseline responsibilities, including:
* Attending monthly meeting.
* Contributing to the release process.
* Engaging in the core contributor Discord.
Examples of contributing to the release include being a [community releaser](https://reactnative.dev/contributing/release-roles-responsibilities#release-role-2-community-releaser), testing new releases, and technical support for release issues.
### Current partners:
* **[Coinbase](https://www.coinbase.com/):** Publishes [posts](https://blog.coinbase.com/tagged/react-native) advocating React Native usage. Supports `@react-native-community/datetimepicker` and other community modules to migrate to the new architecture. Supports releases in testing and feedback.
* **[Callstack](https://callstack.com/):** Maintains the [React Native CLI](https://github.com/react-native-community/react-native-cli) and [other community libraries](https://github.com/callstack), organizes [React Native EU](https://react-native.eu/) and hosts [The React Native Show podcast](https://www.callstack.com/podcast-react-native-show)
* **[Expo](https://expo.dev/):** Builds [Expo Go and SDK](https://github.com/expo/expo), [Snack](https://snack.expo.dev/), and [Expo Application Services](https://expo.dev/eas). Maintains [React Native Directory](https://reactnative.directory/), stewards [React Navigation](https://reactnavigation.org/) along with other partners.
* **[Infinite Red](https://infinite.red/):** Maintains the [ignite cli/boilerplate](https://github.com/infinitered/ignite), organizes [Chain React Conf](https://cr.infinite.red/), hosts the [React Native Radio podcast](https://reactnativeradio.com), publishes the [React Native Newsletter](https://reactnativenewsletter.com)
* **[Meta](https://opensource.fb.com/):** Oversees the React Native product and maintains the [React Native core repo](https://reactnative.dev/)
* **[Microsoft](https://twitter.com/ReactNativeMSFT):** Develops [React Native Windows](https://github.com/Microsoft/react-native-windows) and [React Native macOS](https://github.com/microsoft/react-native-macos) for building apps that target Windows and macOS; maintains [rnx-kit](https://github.com/microsoft/rnx-kit), [react-native-test-app](https://github.com/microsoft/react-native-test-app) and coordinates cross-companies efforts such as the [bundle working group](https://github.com/microsoft/rnx-kit/discussions/categories/bundle-working-group).
* **[Shopify](https://www.shopify.com/):** Maintains React Native open source libraries such as [flash-list](https://github.com/Shopify/flash-list) or [@shopify/react-native-skia](https://github.com/Shopify/react-native-skia) and sponsors Software Mansion.
* **[Software Mansion](https://swmansion.com/):** Maintain core infrastructure including JSC, Animated, and other popular third-party plugins and organizes [App.js Conf](https://appjs.co/)
* **[Wix.com](https://wix.engineering/open-source):** Maintains a variety of React Native open source projects ([see all](https://github.com/orgs/wix/repositories?q=react-native)), including: [Detox](https://wix.github.io/Detox/) end-to-end testing library for React Native apps, [RN UILib](https://wix.github.io/react-native-ui-lib/), [RN Navigation](https://wix.github.io/react-native-navigation/), [RN Calendars](https://wix.github.io/react-native-calendars/) and [RN Notifications](https://github.com/wix/react-native-notifications).
### Incubating partners:
* **[Expensify](https://expensify.com/):** Developing [Expensify Chat](https://github.com/Expensify/App), an open-source React Native app built by the community, while [sponsoring dependencies](https://github.com/orgs/Expensify/sponsoring), conferences, and New Architecture advancements.
* **[Sentry](https://sentry.io/for/react-native/):** Develops Error and Performance Monitoring [SDK for React Native](https://github.com/getsentry/sentry-react-native) and [New Architecture Turbo Modules Mixed Stack Traces](https://github.com/reactwg/react-native-new-architecture/discussions/122).
When you are contributing to React Native, you'll most likely meet somebody who works at one of the partner companies and who is a core contributor.
## Core Contributors
Core contributors are individuals who contribute to the React Native project. A core contributor is somebody who displayed a lasting commitment to the evolution and maintenance of React Native. The work done by core contributors includes responsibilities mentioned in the “Partners” section above, and concretely means that they:
* Consistently contribute high quality changes, fixes and improvements
* Actively review changes and provide quality feedback to contributors
* Manage the release process of React Native by maintaining release branches, communicating changes to users and publishing releases
* Love to help out other users with issues on GitHub
* Mentor and encourage first time contributors
* Identify React Native community members who could be effective core contributors
* Help build an inclusive community with people from all backgrounds
* Are great at communicating with other contributors and the community in general
These are behaviors we have observed in our existing core contributors. They aren't strict rules but rather outline their usual responsibilities. We do not expect every core contributor to do all of the above things all the time. Most importantly, we want to create a supportive and friendly environment that fosters collaboration. Above all else, **we are always polite and friendly.**
Core contributor status is attained after consistently contributing and taking on the responsibilities outlined above and granted by other core contributors. Similarly, after a long period of inactivity (~6 months or more), a core contributor may be contacted to understand if theyre still interested in being part of the program.
You can use this [form](https://forms.gle/4jpA4QeNUvAUDnNe8) to either:
* Apply yourself to become a Core Contributor. Make sure to include a list of valuable contributions you did to the React Native repository and ecosystem.
* Nominate someone to become a Core Contributor.
As a core contributor, you will have access to the core contributor Discord which is used for light-weight coordination and discussion.
**We aim to make contributing to React Native as easy and transparent as possible.** We have discussion groups dedicated to the [new architecture rollout](https://github.com/reactwg/react-native-new-architecture), [releases](https://github.com/reactwg/react-native-releases), and [general questions and proposals](https://github.com/react-native-community/discussions-and-proposals). We are always looking for active, enthusiastic members of the React Native community to become core contributors.
## Community Contributors
Community contributors are individuals who support projects in the [react-native-community](https://github.com/react-native-community) organization. This organization exists as an incubator for high quality components that extend the capabilities of React Native with functionality that many but not all applications require. Meta engineers will provide guidance to help build a vibrant community of people and components that make React Native better.
This structure has multiple benefits:
* Keep the core of React Native small, which improves performance and reduces the surface area
* Provide visibility to projects through shared representation, for example on the React Native website or on Twitter
* Ensure a consistent and high standard for code, documentation, user experience, stability and contributions for third-party components
* Upgrade the most important components right away when we make breaking changes and move the ecosystem forward at a fast pace
* Find new maintainers for projects that are important but were abandoned by previous owners
Additionally, some companies may choose to sponsor the development of one or many of the packages that are part of the community organization. They will commit to maintain projects, triage issues, fix bugs and develop features. In turn, they will be able to gain visibility for their work, for example through a mention of active maintainers in the README of individual projects after a consistent period of contributions. Such a mention may be removed if maintainers abandon the project.
If you are working on a popular component and would like to move it to the React Native community, please create an issue on the [discussions-and-proposals repository](https://github.com/react-native-community/discussions-and-proposals).
-8
View File
@@ -1,8 +0,0 @@
source 'https://rubygems.org'
# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
ruby ">= 2.6.10"
gem 'cocoapods', '~> 1.13', '!= 1.15.0', '!= 1.15.1'
gem 'activesupport', '>= 6.1.7.5', '< 7.1.0'
gem 'xcodeproj', '< 1.26.0'
-99
View File
@@ -1,99 +0,0 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.6)
rexml
activesupport (7.0.8)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
addressable (2.8.5)
public_suffix (>= 2.0.2, < 6.0)
algoliasearch (1.27.5)
httpclient (~> 2.8, >= 2.8.3)
json (>= 1.5.1)
atomos (0.1.3)
claide (1.1.0)
cocoapods (1.14.2)
addressable (~> 2.8)
claide (>= 1.0.2, < 2.0)
cocoapods-core (= 1.14.2)
cocoapods-deintegrate (>= 1.0.3, < 2.0)
cocoapods-downloader (>= 2.0)
cocoapods-plugins (>= 1.0.0, < 2.0)
cocoapods-search (>= 1.0.0, < 2.0)
cocoapods-trunk (>= 1.6.0, < 2.0)
cocoapods-try (>= 1.1.0, < 2.0)
colored2 (~> 3.1)
escape (~> 0.0.4)
fourflusher (>= 2.3.0, < 3.0)
gh_inspector (~> 1.0)
molinillo (~> 0.8.0)
nap (~> 1.0)
ruby-macho (>= 2.3.0, < 3.0)
xcodeproj (>= 1.23.0, < 2.0)
cocoapods-core (1.14.2)
activesupport (>= 5.0, < 8)
addressable (~> 2.8)
algoliasearch (~> 1.0)
concurrent-ruby (~> 1.1)
fuzzy_match (~> 2.0.4)
nap (~> 1.0)
netrc (~> 0.11)
public_suffix (~> 4.0)
typhoeus (~> 1.0)
cocoapods-deintegrate (1.0.5)
cocoapods-downloader (2.0)
cocoapods-plugins (1.0.0)
nap
cocoapods-search (1.0.1)
cocoapods-trunk (1.6.0)
nap (>= 0.8, < 2.0)
netrc (~> 0.11)
cocoapods-try (1.2.0)
colored2 (3.1.2)
concurrent-ruby (1.2.2)
escape (0.0.4)
ethon (0.16.0)
ffi (>= 1.15.0)
ffi (1.16.3)
fourflusher (2.3.1)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
httpclient (2.8.3)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
json (2.6.3)
minitest (5.20.0)
molinillo (0.8.0)
nanaimo (0.3.0)
nap (1.1.0)
netrc (0.11.0)
public_suffix (4.0.7)
rexml (3.2.6)
ruby-macho (2.5.1)
typhoeus (1.4.0)
ethon (>= 0.9.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
xcodeproj (1.23.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.3.0)
rexml (~> 3.2.4)
PLATFORMS
ruby
DEPENDENCIES
activesupport (>= 6.1.7.5, < 7.1.0)
cocoapods (~> 1.13, != 1.15.1, != 1.15.0)
RUBY VERSION
ruby 3.2.0p0
BUNDLED WITH
2.4.12
@@ -0,0 +1,52 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
* @providesModule AccessibilityManagerTest
*/
'use strict';
const React = require('react');
const ReactNative = require('react-native');
const { View } = ReactNative;
const RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
const {
TestModule,
AccessibilityManager,
} = ReactNative.NativeModules;
class AccessibilityManagerTest extends React.Component {
componentDidMount() {
AccessibilityManager.setAccessibilityContentSizeMultipliers({
'extraSmall': 1.0,
'small': 2.0,
'medium': 3.0,
'large': 4.0,
'extraLarge': 5.0,
'extraExtraLarge': 6.0,
'extraExtraExtraLarge': 7.0,
'accessibilityMedium': 8.0,
'accessibilityLarge': 9.0,
'accessibilityExtraLarge': 10.0,
'accessibilityExtraExtraLarge': 11.0,
'accessibilityExtraExtraExtraLarge': 12.0,
});
RCTDeviceEventEmitter.addListener('didUpdateDimensions', update => {
TestModule.markTestPassed(update.window.fontScale === 4.0);
});
}
render(): React.Element<any> {
return <View />;
}
}
AccessibilityManagerTest.displayName = 'AccessibilityManagerTest';
module.exports = AccessibilityManagerTest;
+74
View File
@@ -0,0 +1,74 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule AppEventsTest
* @flow
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var {
NativeAppEventEmitter,
StyleSheet,
Text,
View,
} = ReactNative;
var { TestModule } = ReactNative.NativeModules;
var deepDiffer = require('deepDiffer');
var TEST_PAYLOAD = {foo: 'bar'};
type AppEvent = { data: Object, ts: number, };
type State = {
sent: 'none' | AppEvent,
received: 'none' | AppEvent,
elapsed?: string,
};
class AppEventsTest extends React.Component {
state: State = {sent: 'none', received: 'none'};
componentDidMount() {
NativeAppEventEmitter.addListener('testEvent', this.receiveEvent);
var event = {data: TEST_PAYLOAD, ts: Date.now()};
TestModule.sendAppEvent('testEvent', event);
this.setState({sent: event});
}
receiveEvent = (event: any) => {
if (deepDiffer(event.data, TEST_PAYLOAD)) {
throw new Error('Received wrong event: ' + JSON.stringify(event));
}
var elapsed = (Date.now() - event.ts) + 'ms';
this.setState({received: event, elapsed}, () => {
TestModule.markTestCompleted();
});
};
render() {
return (
<View style={styles.container}>
<Text>
{JSON.stringify(this.state, null, ' ')}
</Text>
</View>
);
}
}
AppEventsTest.displayName = 'AppEventsTest';
var styles = StyleSheet.create({
container: {
margin: 40,
},
});
module.exports = AppEventsTest;
+203
View File
@@ -0,0 +1,203 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
* @providesModule AsyncStorageTest
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var {
AsyncStorage,
Text,
View,
} = ReactNative;
var { TestModule } = ReactNative.NativeModules;
var deepDiffer = require('deepDiffer');
var DEBUG = false;
var KEY_1 = 'key_1';
var VAL_1 = 'val_1';
var KEY_2 = 'key_2';
var VAL_2 = 'val_2';
var KEY_MERGE = 'key_merge';
var VAL_MERGE_1 = {'foo': 1, 'bar': {'hoo': 1, 'boo': 1}, 'moo': {'a': 3}};
var VAL_MERGE_2 = {'bar': {'hoo': 2}, 'baz': 2, 'moo': {'a': 3}};
var VAL_MERGE_EXPECT =
{'foo': 1, 'bar': {'hoo': 2, 'boo': 1}, 'baz': 2, 'moo': {'a': 3}};
// setup in componentDidMount
var done = (result : ?boolean) => {};
var updateMessage = (message : string ) => {};
function runTestCase(description : string, fn) {
updateMessage(description);
fn();
}
function expectTrue(condition : boolean, message : string) {
if (!condition) {
throw new Error(message);
}
}
function expectEqual(lhs, rhs, testname : string) {
expectTrue(
!deepDiffer(lhs, rhs),
'Error in test ' + testname + ': expected\n' + JSON.stringify(rhs) +
'\ngot\n' + JSON.stringify(lhs)
);
}
function expectAsyncNoError(place, err) {
if (err instanceof Error) {
err = err.message;
}
expectTrue(err === null, 'Unexpected error in ' + place + ': ' + JSON.stringify(err));
}
function testSetAndGet() {
AsyncStorage.setItem(KEY_1, VAL_1, (err1) => {
expectAsyncNoError('testSetAndGet/setItem', err1);
AsyncStorage.getItem(KEY_1, (err2, result) => {
expectAsyncNoError('testSetAndGet/getItem', err2);
expectEqual(result, VAL_1, 'testSetAndGet setItem');
updateMessage('get(key_1) correctly returned ' + result);
runTestCase('should get null for missing key', testMissingGet);
});
});
}
function testMissingGet() {
AsyncStorage.getItem(KEY_2, (err, result) => {
expectAsyncNoError('testMissingGet/setItem', err);
expectEqual(result, null, 'testMissingGet');
updateMessage('missing get(key_2) correctly returned ' + result);
runTestCase('check set twice results in a single key', testSetTwice);
});
}
function testSetTwice() {
AsyncStorage.setItem(KEY_1, VAL_1, ()=>{
AsyncStorage.setItem(KEY_1, VAL_1, ()=>{
AsyncStorage.getItem(KEY_1, (err, result) => {
expectAsyncNoError('testSetTwice/setItem', err);
expectEqual(result, VAL_1, 'testSetTwice');
updateMessage('setTwice worked as expected');
runTestCase('test removeItem', testRemoveItem);
});
});
});
}
function testRemoveItem() {
AsyncStorage.setItem(KEY_1, VAL_1, ()=>{
AsyncStorage.setItem(KEY_2, VAL_2, ()=>{
AsyncStorage.getAllKeys((err, result) => {
expectAsyncNoError('testRemoveItem/getAllKeys', err);
expectTrue(
result.indexOf(KEY_1) >= 0 && result.indexOf(KEY_2) >= 0,
'Missing KEY_1 or KEY_2 in ' + '(' + result + ')'
);
updateMessage('testRemoveItem - add two items');
AsyncStorage.removeItem(KEY_1, (err2) => {
expectAsyncNoError('testRemoveItem/removeItem', err2);
updateMessage('delete successful ');
AsyncStorage.getItem(KEY_1, (err3, result2) => {
expectAsyncNoError('testRemoveItem/getItem', err3);
expectEqual(
result2,
null,
'testRemoveItem: key_1 present after delete'
);
updateMessage('key properly removed ');
AsyncStorage.getAllKeys((err4, result3) => {
expectAsyncNoError('testRemoveItem/getAllKeys', err4);
expectTrue(
result3.indexOf(KEY_1) === -1,
'Unexpected: KEY_1 present in ' + result3
);
updateMessage('proper length returned.');
runTestCase('should merge values', testMerge);
});
});
});
});
});
});
}
function testMerge() {
AsyncStorage.setItem(KEY_MERGE, JSON.stringify(VAL_MERGE_1), (err1) => {
expectAsyncNoError('testMerge/setItem', err1);
AsyncStorage.mergeItem(KEY_MERGE, JSON.stringify(VAL_MERGE_2), (err2) => {
expectAsyncNoError('testMerge/mergeItem', err2);
AsyncStorage.getItem(KEY_MERGE, (err3, result) => {
expectAsyncNoError('testMerge/setItem', err3);
expectEqual(JSON.parse(result), VAL_MERGE_EXPECT, 'testMerge');
updateMessage('objects deeply merged\nDone!');
runTestCase('multi set and get', testOptimizedMultiGet);
});
});
});
}
function testOptimizedMultiGet() {
let batch = [[KEY_1, VAL_1], [KEY_2, VAL_2]];
let keys = batch.map(([key, value]) => key);
AsyncStorage.multiSet(batch, (err1) => {
// yes, twice on purpose
;[1, 2].forEach((i) => {
expectAsyncNoError(`${i} testOptimizedMultiGet/multiSet`, err1);
AsyncStorage.multiGet(keys, (err2, result) => {
expectAsyncNoError(`${i} testOptimizedMultiGet/multiGet`, err2);
expectEqual(result, batch, `${i} testOptimizedMultiGet multiGet`);
updateMessage('multiGet([key_1, key_2]) correctly returned ' + JSON.stringify(result));
done();
});
});
});
}
class AsyncStorageTest extends React.Component {
state = {
messages: 'Initializing...',
done: false,
};
componentDidMount() {
done = () => this.setState({done: true}, () => {
TestModule.markTestCompleted();
});
updateMessage = (msg) => {
this.setState({messages: this.state.messages.concat('\n' + msg)});
DEBUG && console.log(msg);
};
AsyncStorage.clear(testSetAndGet);
}
render() {
return (
<View style={{backgroundColor: 'white', padding: 40}}>
<Text>
{this.constructor.displayName + ': '}
{this.state.done ? 'Done' : 'Testing...'}
{'\n\n' + this.state.messages}
</Text>
</View>
);
}
}
AsyncStorageTest.displayName = 'AsyncStorageTest';
module.exports = AsyncStorageTest;
+116
View File
@@ -0,0 +1,116 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
* @providesModule ImageCachePolicyTest
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var {
Image,
View,
Text,
StyleSheet,
} = ReactNative;
var { TestModule } = ReactNative.NativeModules;
/*
* The reload and force-cache tests don't actually verify that the complete functionality.
*
* reload: Should have the server set a long cache header, then swap the image on next load
* with the test comparing the old image to the new image and making sure they are different.
*
* force-cache: Should do the above but set a no-cache header. The test should compare the first
* image with the new one and make sure they are the same.
*/
const TESTS = ['only-if-cached', 'default', 'reload', 'force-cache'];
type Props = {}
type State = {
'only-if-cached'?: boolean,
'default'?: boolean,
'reload'?: boolean,
'force-cache'?: boolean,
}
class ImageCachePolicyTest extends React.Component {
state = {}
shouldComponentUpdate(nextProps: Props, nextState: State) {
const results: Array<?boolean> = TESTS.map(x => nextState[x]);
if (!results.includes(undefined)) {
const result: boolean = results.reduce((x,y) => x === y === true, true)
TestModule.markTestPassed(result);
}
return false;
}
testComplete(name: string, pass: boolean) {
this.setState({[name]: pass});
}
render() {
return (
<View style={{flex: 1}}>
<Text>Hello</Text>
<Image
source={{
uri: 'https://facebook.github.io/react/img/logo_small_2x.png?cacheBust=notinCache' + Date.now(),
cache: 'only-if-cached'
}}
onLoad={() => this.testComplete('only-if-cached', false)}
onError={() => this.testComplete('only-if-cached', true)}
style={styles.base}
/>
<Image
source={{
uri: 'https://facebook.github.io/react/img/logo_small_2x.png?cacheBust=notinCache' + Date.now(),
cache: 'default'
}}
onLoad={() => this.testComplete('default', true)}
onError={() => this.testComplete('default', false)}
style={styles.base}
/>
<Image
source={{
uri: 'https://facebook.github.io/react/img/logo_small_2x.png?cacheBust=notinCache' + Date.now(),
cache: 'reload'
}}
onLoad={() => this.testComplete('reload', true)}
onError={() => this.testComplete('reload', false)}
style={styles.base}
/>
<Image
source={{
uri: 'https://facebook.github.io/react/img/logo_small_2x.png?cacheBust=notinCache' + Date.now(),
cache: 'force-cache'
}}
onLoad={() => this.testComplete('force-cache', true)}
onError={() => this.testComplete('force-cache', false)}
style={styles.base}
/>
</View>
);
}
}
const styles = StyleSheet.create({
base: {
width: 100,
height: 100,
},
});
ImageCachePolicyTest.displayName = 'ImageCachePolicyTest';
module.exports = ImageCachePolicyTest;
+45
View File
@@ -0,0 +1,45 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
* @providesModule ImageSnapshotTest
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var {
Image,
View,
} = ReactNative;
var { TestModule } = ReactNative.NativeModules;
class ImageSnapshotTest extends React.Component {
componentDidMount() {
if (!TestModule.verifySnapshot) {
throw new Error('TestModule.verifySnapshot not defined.');
}
}
done = (success : boolean) => {
TestModule.markTestPassed(success);
};
render() {
return (
<Image
source={require('./blue_square.png')}
defaultSource={require('./red_square.png')}
onLoad={() => TestModule.verifySnapshot(this.done)} />
);
}
}
ImageSnapshotTest.displayName = 'ImageSnapshotTest';
module.exports = ImageSnapshotTest;
@@ -0,0 +1,75 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
* @providesModule IntegrationTestHarnessTest
*/
'use strict';
var requestAnimationFrame = require('fbjs/lib/requestAnimationFrame');
var React = require('react');
var PropTypes = require('prop-types');
var ReactNative = require('react-native');
var {
Text,
View,
} = ReactNative;
var { TestModule } = ReactNative.NativeModules;
class IntegrationTestHarnessTest extends React.Component {
props: {
shouldThrow?: boolean,
waitOneFrame?: boolean,
};
static propTypes = {
shouldThrow: PropTypes.bool,
waitOneFrame: PropTypes.bool,
};
state = {
done: false,
};
componentDidMount() {
if (this.props.waitOneFrame) {
requestAnimationFrame(this.runTest);
} else {
this.runTest();
}
}
runTest = () => {
if (this.props.shouldThrow) {
throw new Error('Throwing error because shouldThrow');
}
if (!TestModule) {
throw new Error('RCTTestModule is not registered.');
} else if (!TestModule.markTestCompleted) {
throw new Error('RCTTestModule.markTestCompleted not defined.');
}
this.setState({done: true}, () => {
TestModule.markTestCompleted();
});
};
render() {
return (
<View style={{backgroundColor: 'white', padding: 40}}>
<Text>
{this.constructor.displayName + ': '}
{this.state.done ? 'Done' : 'Testing...'}
</Text>
</View>
);
}
}
IntegrationTestHarnessTest.displayName = 'IntegrationTestHarnessTest';
module.exports = IntegrationTestHarnessTest;
+106
View File
@@ -0,0 +1,106 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
* @providesModule IntegrationTestsApp
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var {
AppRegistry,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View,
} = ReactNative;
// Keep this list in sync with RNTesterIntegrationTests.m
var TESTS = [
require('./IntegrationTestHarnessTest'),
require('./TimersTest'),
require('./AsyncStorageTest'),
require('./LayoutEventsTest'),
require('./AppEventsTest'),
require('./SimpleSnapshotTest'),
require('./ImageCachePolicyTest'),
require('./ImageSnapshotTest'),
require('./PromiseTest'),
require('./SyncMethodTest'),
require('./WebSocketTest'),
require('./AccessibilityManagerTest'),
];
TESTS.forEach(
(test) => AppRegistry.registerComponent(test.displayName, () => test)
);
// Modules required for integration tests
require('LoggingTestModule');
type Test = any;
class IntegrationTestsApp extends React.Component {
state = {
test: (null: ?Test),
};
render() {
if (this.state.test) {
return (
<ScrollView>
<this.state.test />
</ScrollView>
);
}
return (
<View style={styles.container}>
<Text style={styles.row}>
Click on a test to run it in this shell for easier debugging and
development. Run all tests in the testing environment with cmd+U in
Xcode.
</Text>
<View style={styles.separator} />
<ScrollView>
{TESTS.map((test) => [
<TouchableOpacity
onPress={() => this.setState({test})}
style={styles.row}>
<Text style={styles.testName}>
{test.displayName}
</Text>
</TouchableOpacity>,
<View style={styles.separator} />
])}
</ScrollView>
</View>
);
}
}
var styles = StyleSheet.create({
container: {
backgroundColor: 'white',
marginTop: 40,
margin: 15,
},
row: {
padding: 10,
},
testName: {
fontWeight: '500',
},
separator: {
height: 1,
backgroundColor: '#bbbbbb',
},
});
AppRegistry.registerComponent('IntegrationTestsApp', () => IntegrationTestsApp);
+190
View File
@@ -0,0 +1,190 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule LayoutEventsTest
* @flow
*/
'use strict';
var React = require('react');
var createReactClass = require('create-react-class');
var ReactNative = require('react-native');
var {
Image,
LayoutAnimation,
StyleSheet,
Text,
View,
} = ReactNative;
var { TestModule } = ReactNative.NativeModules;
var deepDiffer = require('deepDiffer');
function debug(...args) {
// console.log.apply(null, arguments);
}
type Layout = {
x: number;
y: number;
width: number;
height: number;
};
type LayoutEvent = {
nativeEvent: {
layout: Layout;
};
};
type Style = {
margin?: number,
padding?: number,
borderColor?: string,
borderWidth?: number,
backgroundColor?: string,
width?: number,
};
type State = {
didAnimation: boolean,
extraText?: string,
imageLayout?: Layout,
textLayout?: Layout,
viewLayout?: Layout,
viewStyle?: Style,
containerStyle?: Style,
};
var LayoutEventsTest = createReactClass({
displayName: 'LayoutEventsTest',
getInitialState(): State {
return {
didAnimation: false,
};
},
animateViewLayout: function() {
debug('animateViewLayout invoked');
LayoutAnimation.configureNext(
LayoutAnimation.Presets.spring,
() => {
debug('animateViewLayout done');
this.checkLayout(this.addWrapText);
}
);
this.setState({viewStyle: {margin: 60}});
},
addWrapText: function() {
debug('addWrapText invoked');
this.setState(
{extraText: ' And a bunch more text to wrap around a few lines.'},
() => this.checkLayout(this.changeContainer)
);
},
changeContainer: function() {
debug('changeContainer invoked');
this.setState(
{containerStyle: {width: 280}},
() => this.checkLayout(TestModule.markTestCompleted)
);
},
checkLayout: function(next?: ?Function) {
if (!this.isMounted()) {
return;
}
this.refs.view.measure((x, y, width, height) => {
this.compare('view', {x, y, width, height}, this.state.viewLayout);
if (typeof next === 'function') {
next();
} else if (!this.state.didAnimation) {
// Trigger first state change after onLayout fires
this.animateViewLayout();
this.state.didAnimation = true;
}
});
this.refs.txt.measure((x, y, width, height) => {
this.compare('txt', {x, y, width, height}, this.state.textLayout);
});
this.refs.img.measure((x, y, width, height) => {
this.compare('img', {x, y, width, height}, this.state.imageLayout);
});
},
compare: function(node: string, measured: any, onLayout: any): void {
if (deepDiffer(measured, onLayout)) {
var data = {measured, onLayout};
throw new Error(
node + ' onLayout mismatch with measure ' +
JSON.stringify(data, null, ' ')
);
}
},
onViewLayout: function(e: LayoutEvent) {
debug('received view layout event\n', e.nativeEvent);
this.setState({viewLayout: e.nativeEvent.layout}, this.checkLayout);
},
onTextLayout: function(e: LayoutEvent) {
debug('received text layout event\n', e.nativeEvent);
this.setState({textLayout: e.nativeEvent.layout}, this.checkLayout);
},
onImageLayout: function(e: LayoutEvent) {
debug('received image layout event\n', e.nativeEvent);
this.setState({imageLayout: e.nativeEvent.layout}, this.checkLayout);
},
render: function() {
var viewStyle = [styles.view, this.state.viewStyle];
var textLayout = this.state.textLayout || {width: '?', height: '?'};
var imageLayout = this.state.imageLayout || {x: '?', y: '?'};
debug('viewLayout', this.state.viewLayout);
return (
<View style={[styles.container, this.state.containerStyle]}>
<View ref="view" onLayout={this.onViewLayout} style={viewStyle}>
<Image
ref="img"
onLayout={this.onImageLayout}
style={styles.image}
source={{uri: 'uie_thumb_big.png'}}
/>
<Text ref="txt" onLayout={this.onTextLayout} style={styles.text}>
A simple piece of text.{this.state.extraText}
</Text>
<Text>
{'\n'}
Text w/h: {textLayout.width}/{textLayout.height + '\n'}
Image x/y: {imageLayout.x}/{imageLayout.y}
</Text>
</View>
</View>
);
}
});
var styles = StyleSheet.create({
container: {
margin: 40,
},
view: {
margin: 20,
padding: 12,
borderColor: 'black',
borderWidth: 0.5,
backgroundColor: 'transparent',
},
text: {
alignSelf: 'flex-start',
borderColor: 'rgba(0, 0, 255, 0.2)',
borderWidth: 0.5,
},
image: {
width: 50,
height: 50,
marginBottom: 10,
alignSelf: 'center',
},
});
LayoutEventsTest.displayName = 'LayoutEventsTest';
module.exports = LayoutEventsTest;
+46
View File
@@ -0,0 +1,46 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule LoggingTestModule
*/
'use strict';
var BatchedBridge = require('BatchedBridge');
var warning = require('fbjs/lib/warning');
var invariant = require('fbjs/lib/invariant');
var LoggingTestModule = {
logToConsole: function(str) {
console.log(str);
},
logToConsoleAfterWait: function(str,timeout_ms) {
setTimeout(function() {
console.log(str);
}, timeout_ms);
},
warning: function(str) {
warning(false, str);
},
invariant: function(str) {
invariant(false, str);
},
logErrorToConsole: function(str) {
console.error(str);
},
throwError: function(str) {
throw new Error(str);
}
};
BatchedBridge.registerCallableModule(
'LoggingTestModule',
LoggingTestModule
);
module.exports = LoggingTestModule;

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