diff --git a/scripts/releases/README.md b/scripts/releases/README.md index 9d426897a66745..2c9f4ce06f8928 100644 --- a/scripts/releases/README.md +++ b/scripts/releases/README.md @@ -6,14 +6,18 @@ Scripts related to creating a React Native release. These are the lower level en For information on command arguments, run `node --help`. -### `remove-new-arch-flags.js` +### `remove-new-arch-flags` Updates native build files to disable the New Architecture. -### `set-rn-version.js` +### `set-version` + +Sets a singular version for the entire monorepo (including `react-native` package) + +### `set-rn-version` Updates relevant files in the `react-native` package and template to materialize the given release version. -### `update-template-package.js` +### `update-template-package` -Updates local dependencies in the template `package.json`. +Updates workspace dependencies in the template app`package.json` diff --git a/scripts/releases/__tests__/set-rn-version-test.js b/scripts/releases/__tests__/set-rn-version-test.js index aa3f29f1682edf..43dcc8b6a4c8e0 100644 --- a/scripts/releases/__tests__/set-rn-version-test.js +++ b/scripts/releases/__tests__/set-rn-version-test.js @@ -24,14 +24,25 @@ jest.mock('fs', () => ({ jest.mock('./../update-template-package', () => updateTemplatePackageMock); const {setReactNativeVersion} = require('../set-rn-version'); +const path = require('path'); + +const REPO_ROOT = path.resolve(__filename, '../../../..'); describe('setReactNativeVersion', () => { beforeAll(() => { - readFileMock.mockImplementation(path => { - if (path === 'packages/react-native/ReactAndroid/gradle.properties') { + readFileMock.mockImplementation(filePath => { + if ( + filePath === + path.join( + REPO_ROOT, + 'packages/react-native/ReactAndroid/gradle.properties', + ) + ) { return 'VERSION_NAME=1000.0.0\n'; } - if (path === 'packages/react-native/package.json') { + if ( + filePath === path.join(REPO_ROOT, 'packages/react-native/package.json') + ) { return JSON.stringify({ name: 'react-native', version: '1000.0.0', @@ -60,7 +71,10 @@ describe('setReactNativeVersion', () => { }); for (const [filePath, contents] of writeFileMock.mock.calls) { - expect(formatGeneratedFile(contents)).toMatchSnapshot(filePath); + // Make snapshot names resilient to platform path sep differences + expect(formatGeneratedFile(contents)).toMatchSnapshot( + path.relative(REPO_ROOT, filePath).split(path.sep).join('/'), + ); } }); @@ -73,7 +87,10 @@ describe('setReactNativeVersion', () => { }); for (const [filePath, contents] of writeFileMock.mock.calls) { - expect(formatGeneratedFile(contents)).toMatchSnapshot(filePath); + // Make snapshot names resilient to platform path sep differences + expect(formatGeneratedFile(contents)).toMatchSnapshot( + path.relative(REPO_ROOT, filePath).split(path.sep).join('/'), + ); } }); }); diff --git a/scripts/releases/set-rn-version.js b/scripts/releases/set-rn-version.js index 0d89895ee4f2ee..4873ff34df81de 100755 --- a/scripts/releases/set-rn-version.js +++ b/scripts/releases/set-rn-version.js @@ -19,9 +19,17 @@ const updateTemplatePackage = require('./update-template-package'); const {parseVersion, validateBuildType} = require('./utils/version-utils'); const {parseArgs} = require('@pkgjs/parseargs'); const {promises: fs} = require('fs'); - -const GRADLE_FILE_PATH = 'packages/react-native/ReactAndroid/gradle.properties'; -const REACT_NATIVE_PACKAGE_JSON = 'packages/react-native/package.json'; +const path = require('path'); + +const REPO_ROOT = path.join(path.dirname(__filename), '..', '..'); +const GRADLE_FILE_PATH = path.join( + REPO_ROOT, + 'packages/react-native/ReactAndroid/gradle.properties', +); +const REACT_NATIVE_PACKAGE_JSON = path.join( + REPO_ROOT, + 'packages/react-native/package.json', +); const config = { options: { @@ -101,36 +109,47 @@ async function setReactNativePackageVersion( packageJson.version = version; await fs.writeFile( - 'packages/react-native/package.json', + path.join(REPO_ROOT, 'packages/react-native/package.json'), JSON.stringify(packageJson, null, 2), 'utf-8', ); } -function updateSourceFiles(versionInfo /*: Version */) { +function updateSourceFiles( + versionInfo /*: Version */, +) /*: Promise>*/ { const templateData = {version: versionInfo}; return Promise.all([ fs.writeFile( - 'packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java', + path.join( + REPO_ROOT, + 'packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java', + ), require('./templates/ReactNativeVersion.java-template')(templateData), ), fs.writeFile( - 'packages/react-native/React/Base/RCTVersion.m', + path.join(REPO_ROOT, 'packages/react-native/React/Base/RCTVersion.m'), require('./templates/RCTVersion.m-template')(templateData), ), fs.writeFile( - 'packages/react-native/ReactCommon/cxxreact/ReactNativeVersion.h', + path.join( + REPO_ROOT, + 'packages/react-native/ReactCommon/cxxreact/ReactNativeVersion.h', + ), require('./templates/ReactNativeVersion.h-template')(templateData), ), fs.writeFile( - 'packages/react-native/Libraries/Core/ReactNativeVersion.js', + path.join( + REPO_ROOT, + 'packages/react-native/Libraries/Core/ReactNativeVersion.js', + ), require('./templates/ReactNativeVersion.js-template')(templateData), ), ]); } -async function updateGradleFile(version /*: string */) { +async function updateGradleFile(version /*: string */) /*: Promise */ { const contents = await fs.readFile(GRADLE_FILE_PATH, 'utf-8'); return fs.writeFile( @@ -141,6 +160,8 @@ async function updateGradleFile(version /*: string */) { module.exports = { setReactNativeVersion, + updateGradleFile, + updateSourceFiles, }; if (require.main === module) { diff --git a/scripts/releases/set-version/__tests__/__fixtures__/packages/react-native/ReactAndroid/gradle.properties b/scripts/releases/set-version/__tests__/__fixtures__/packages/react-native/ReactAndroid/gradle.properties new file mode 100644 index 00000000000000..0b2a27b00a7747 --- /dev/null +++ b/scripts/releases/set-version/__tests__/__fixtures__/packages/react-native/ReactAndroid/gradle.properties @@ -0,0 +1 @@ +VERSION_NAME=1000.0.0 diff --git a/scripts/releases/set-version/__tests__/__snapshots__/set-version-test.js.snap b/scripts/releases/set-version/__tests__/__snapshots__/set-version-test.js.snap index bbf805d8fc4bde..168a014540291c 100644 --- a/scripts/releases/set-version/__tests__/__snapshots__/set-version-test.js.snap +++ b/scripts/releases/set-version/__tests__/__snapshots__/set-version-test.js.snap @@ -1,28 +1,28 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`setVersion updates all public packages to version: monorepo-pkg-a 1`] = ` +exports[`setVersion updates monorepo for nightly: packages/monorepo-pkg-a/package.json 1`] = ` "{ \\"name\\": \\"@monorepo/pkg-a\\", - \\"version\\": \\"0.80.0\\", + \\"version\\": \\"0.81.0-nightly-29282302-abcd1234\\", \\"description\\": \\"@monorepo/pkg-a\\", \\"dependencies\\": { - \\"@monorepo/pkg-b\\": \\"0.80.0\\", + \\"@monorepo/pkg-b\\": \\"0.81.0-nightly-29282302-abcd1234\\", \\"@monorepo/other\\": \\"0.0.1\\" }, \\"devDependencies\\": { - \\"@monorepo/pkg-c\\": \\"0.80.0\\" + \\"@monorepo/pkg-c\\": \\"0.81.0-nightly-29282302-abcd1234\\" } } " `; -exports[`setVersion updates all public packages to version: monorepo-pkg-b 1`] = ` +exports[`setVersion updates monorepo for nightly: packages/monorepo-pkg-b/package.json 1`] = ` "{ \\"name\\": \\"@monorepo/pkg-b\\", - \\"version\\": \\"0.80.0\\", + \\"version\\": \\"0.81.0-nightly-29282302-abcd1234\\", \\"description\\": \\"@monorepo/pkg-b\\", \\"dependencies\\": { - \\"@monorepo/pkg-c\\": \\"0.80.0\\", + \\"@monorepo/pkg-c\\": \\"0.81.0-nightly-29282302-abcd1234\\", \\"metro-config\\": \\"^0.80.3\\", \\"metro-runtime\\": \\"^0.80.3\\" } @@ -30,10 +30,10 @@ exports[`setVersion updates all public packages to version: monorepo-pkg-b 1`] = " `; -exports[`setVersion updates all public packages to version: monorepo-pkg-c 1`] = ` +exports[`setVersion updates monorepo for nightly: packages/monorepo-pkg-c/package.json 1`] = ` "{ \\"name\\": \\"@monorepo/pkg-c\\", - \\"version\\": \\"0.80.0\\", + \\"version\\": \\"0.81.0-nightly-29282302-abcd1234\\", \\"description\\": \\"@monorepo/pkg-c\\", \\"dependencies\\": { \\"metro-config\\": \\"^0.80.3\\", @@ -43,15 +43,534 @@ exports[`setVersion updates all public packages to version: monorepo-pkg-c 1`] = " `; -exports[`setVersion updates all public packages to version: react-native 1`] = ` +exports[`setVersion updates monorepo for nightly: packages/react-native/Libraries/Core/ReactNativeVersion.js 1`] = ` +"/** + * 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. + * + * @flow strict + * @generated by scripts/releases/set-rn-version.js + */ + +const version: $ReadOnly<{ + major: number, + minor: number, + patch: number, + prerelease: string | null, +}> = { + major: 0, + minor: 81, + patch: 0, + prerelease: 'nightly-29282302-abcd1234', +}; + +module.exports = {version}; +" +`; + +exports[`setVersion updates monorepo for nightly: packages/react-native/React/Base/RCTVersion.m 1`] = ` +"/** + * 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. + * + * @generated by scripts/releases/set-rn-version.js + */ + +#import \\"RCTVersion.h\\" + +NSString* const RCTVersionMajor = @\\"major\\"; +NSString* const RCTVersionMinor = @\\"minor\\"; +NSString* const RCTVersionPatch = @\\"patch\\"; +NSString* const RCTVersionPrerelease = @\\"prerelease\\"; + + +NSDictionary* RCTGetReactNativeVersion(void) +{ + static NSDictionary* __rnVersion; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^(void){ + __rnVersion = @{ + RCTVersionMajor: @(0), + RCTVersionMinor: @(81), + RCTVersionPatch: @(0), + RCTVersionPrerelease: @\\"nightly-29282302-abcd1234\\", + }; + }); + return __rnVersion; +} +" +`; + +exports[`setVersion updates monorepo for nightly: packages/react-native/ReactAndroid/gradle.properties 1`] = ` +"VERSION_NAME=0.81.0-nightly-29282302-abcd1234 +" +`; + +exports[`setVersion updates monorepo for nightly: packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java 1`] = ` +"/** + * 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. + * + * @generated by scripts/releases/set-rn-version.js + */ + +package com.facebook.react.modules.systeminfo; + +import com.facebook.react.common.MapBuilder; + +import java.util.Map; + +public class ReactNativeVersion { + public static final Map VERSION = MapBuilder.of( + \\"major\\", 0, + \\"minor\\", 81, + \\"patch\\", 0, + \\"prerelease\\", \\"nightly-29282302-abcd1234\\"); +} +" +`; + +exports[`setVersion updates monorepo for nightly: packages/react-native/ReactCommon/cxxreact/ReactNativeVersion.h 1`] = ` +"/** + * 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. + * + * @generated by scripts/releases/set-rn-version.js + */ + +#pragma once + +#include +#include + +namespace facebook::react { + +constexpr struct { + int32_t Major = 0; + int32_t Minor = 81; + int32_t Patch = 0; + std::string_view Prerelease = \\"nightly-29282302-abcd1234\\"; +} ReactNativeVersion; + +} // namespace facebook::react +" +`; + +exports[`setVersion updates monorepo for nightly: packages/react-native/package.json 1`] = ` +"{ + \\"name\\": \\"react-native\\", + \\"version\\": \\"0.81.0-nightly-29282302-abcd1234\\", + \\"description\\": \\"fake react native package\\", + \\"dependencies\\": { + \\"@monorepo/pkg-a\\": \\"0.81.0-nightly-29282302-abcd1234\\", + \\"@monorepo/pkg-b\\": \\"0.81.0-nightly-29282302-abcd1234\\", + \\"@monorepo/pkg-c\\": \\"0.81.0-nightly-29282302-abcd1234\\", + \\"metro-config\\": \\"^0.80.3\\", + \\"metro-runtime\\": \\"^0.80.3\\" + } +} +" +`; + +exports[`setVersion updates monorepo for nightly: packages/react-native/template/package.json 1`] = ` +"{ + \\"name\\": \\"react-native-test-template\\", + \\"version\\": \\"0.0.1\\", + \\"private\\": true, + \\"dependencies\\": { + \\"react\\": \\"18.2.0\\", + \\"react-native\\": \\"0.81.0-nightly-29282302-abcd1234\\" + }, + \\"devDependencies\\": { + \\"@monorepo/pkg-a\\": \\"0.81.0-nightly-29282302-abcd1234\\", + \\"@monorepo/pkg-c\\": \\"0.81.0-nightly-29282302-abcd1234\\", + \\"@types/react\\": \\"^18.2.6\\", + \\"@types/react-test-renderer\\": \\"^18.0.0\\" + } +} +" +`; + +exports[`setVersion updates monorepo for release-candidate: packages/monorepo-pkg-a/package.json 1`] = ` +"{ + \\"name\\": \\"@monorepo/pkg-a\\", + \\"version\\": \\"0.80.0-rc.3\\", + \\"description\\": \\"@monorepo/pkg-a\\", + \\"dependencies\\": { + \\"@monorepo/pkg-b\\": \\"0.80.0-rc.3\\", + \\"@monorepo/other\\": \\"0.0.1\\" + }, + \\"devDependencies\\": { + \\"@monorepo/pkg-c\\": \\"0.80.0-rc.3\\" + } +} +" +`; + +exports[`setVersion updates monorepo for release-candidate: packages/monorepo-pkg-b/package.json 1`] = ` +"{ + \\"name\\": \\"@monorepo/pkg-b\\", + \\"version\\": \\"0.80.0-rc.3\\", + \\"description\\": \\"@monorepo/pkg-b\\", + \\"dependencies\\": { + \\"@monorepo/pkg-c\\": \\"0.80.0-rc.3\\", + \\"metro-config\\": \\"^0.80.3\\", + \\"metro-runtime\\": \\"^0.80.3\\" + } +} +" +`; + +exports[`setVersion updates monorepo for release-candidate: packages/monorepo-pkg-c/package.json 1`] = ` +"{ + \\"name\\": \\"@monorepo/pkg-c\\", + \\"version\\": \\"0.80.0-rc.3\\", + \\"description\\": \\"@monorepo/pkg-c\\", + \\"dependencies\\": { + \\"metro-config\\": \\"^0.80.3\\", + \\"metro-runtime\\": \\"^0.80.3\\" + } +} +" +`; + +exports[`setVersion updates monorepo for release-candidate: packages/react-native/Libraries/Core/ReactNativeVersion.js 1`] = ` +"/** + * 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. + * + * @flow strict + * @generated by scripts/releases/set-rn-version.js + */ + +const version: $ReadOnly<{ + major: number, + minor: number, + patch: number, + prerelease: string | null, +}> = { + major: 0, + minor: 80, + patch: 0, + prerelease: 'rc.3', +}; + +module.exports = {version}; +" +`; + +exports[`setVersion updates monorepo for release-candidate: packages/react-native/React/Base/RCTVersion.m 1`] = ` +"/** + * 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. + * + * @generated by scripts/releases/set-rn-version.js + */ + +#import \\"RCTVersion.h\\" + +NSString* const RCTVersionMajor = @\\"major\\"; +NSString* const RCTVersionMinor = @\\"minor\\"; +NSString* const RCTVersionPatch = @\\"patch\\"; +NSString* const RCTVersionPrerelease = @\\"prerelease\\"; + + +NSDictionary* RCTGetReactNativeVersion(void) +{ + static NSDictionary* __rnVersion; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^(void){ + __rnVersion = @{ + RCTVersionMajor: @(0), + RCTVersionMinor: @(80), + RCTVersionPatch: @(0), + RCTVersionPrerelease: @\\"rc.3\\", + }; + }); + return __rnVersion; +} +" +`; + +exports[`setVersion updates monorepo for release-candidate: packages/react-native/ReactAndroid/gradle.properties 1`] = ` +"VERSION_NAME=0.80.0-rc.3 +" +`; + +exports[`setVersion updates monorepo for release-candidate: packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java 1`] = ` +"/** + * 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. + * + * @generated by scripts/releases/set-rn-version.js + */ + +package com.facebook.react.modules.systeminfo; + +import com.facebook.react.common.MapBuilder; + +import java.util.Map; + +public class ReactNativeVersion { + public static final Map VERSION = MapBuilder.of( + \\"major\\", 0, + \\"minor\\", 80, + \\"patch\\", 0, + \\"prerelease\\", \\"rc.3\\"); +} +" +`; + +exports[`setVersion updates monorepo for release-candidate: packages/react-native/ReactCommon/cxxreact/ReactNativeVersion.h 1`] = ` +"/** + * 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. + * + * @generated by scripts/releases/set-rn-version.js + */ + +#pragma once + +#include +#include + +namespace facebook::react { + +constexpr struct { + int32_t Major = 0; + int32_t Minor = 80; + int32_t Patch = 0; + std::string_view Prerelease = \\"rc.3\\"; +} ReactNativeVersion; + +} // namespace facebook::react +" +`; + +exports[`setVersion updates monorepo for release-candidate: packages/react-native/package.json 1`] = ` +"{ + \\"name\\": \\"react-native\\", + \\"version\\": \\"0.80.0-rc.3\\", + \\"description\\": \\"fake react native package\\", + \\"dependencies\\": { + \\"@monorepo/pkg-a\\": \\"0.80.0-rc.3\\", + \\"@monorepo/pkg-b\\": \\"0.80.0-rc.3\\", + \\"@monorepo/pkg-c\\": \\"0.80.0-rc.3\\", + \\"metro-config\\": \\"^0.80.3\\", + \\"metro-runtime\\": \\"^0.80.3\\" + } +} +" +`; + +exports[`setVersion updates monorepo for release-candidate: packages/react-native/template/package.json 1`] = ` +"{ + \\"name\\": \\"react-native-test-template\\", + \\"version\\": \\"0.0.1\\", + \\"private\\": true, + \\"dependencies\\": { + \\"react\\": \\"18.2.0\\", + \\"react-native\\": \\"0.80.0-rc.3\\" + }, + \\"devDependencies\\": { + \\"@monorepo/pkg-a\\": \\"0.80.0-rc.3\\", + \\"@monorepo/pkg-c\\": \\"0.80.0-rc.3\\", + \\"@types/react\\": \\"^18.2.6\\", + \\"@types/react-test-renderer\\": \\"^18.0.0\\" + } +} +" +`; + +exports[`setVersion updates monorepo for stable version: packages/monorepo-pkg-a/package.json 1`] = ` +"{ + \\"name\\": \\"@monorepo/pkg-a\\", + \\"version\\": \\"0.80.1\\", + \\"description\\": \\"@monorepo/pkg-a\\", + \\"dependencies\\": { + \\"@monorepo/pkg-b\\": \\"0.80.1\\", + \\"@monorepo/other\\": \\"0.0.1\\" + }, + \\"devDependencies\\": { + \\"@monorepo/pkg-c\\": \\"0.80.1\\" + } +} +" +`; + +exports[`setVersion updates monorepo for stable version: packages/monorepo-pkg-b/package.json 1`] = ` +"{ + \\"name\\": \\"@monorepo/pkg-b\\", + \\"version\\": \\"0.80.1\\", + \\"description\\": \\"@monorepo/pkg-b\\", + \\"dependencies\\": { + \\"@monorepo/pkg-c\\": \\"0.80.1\\", + \\"metro-config\\": \\"^0.80.3\\", + \\"metro-runtime\\": \\"^0.80.3\\" + } +} +" +`; + +exports[`setVersion updates monorepo for stable version: packages/monorepo-pkg-c/package.json 1`] = ` +"{ + \\"name\\": \\"@monorepo/pkg-c\\", + \\"version\\": \\"0.80.1\\", + \\"description\\": \\"@monorepo/pkg-c\\", + \\"dependencies\\": { + \\"metro-config\\": \\"^0.80.3\\", + \\"metro-runtime\\": \\"^0.80.3\\" + } +} +" +`; + +exports[`setVersion updates monorepo for stable version: packages/react-native/Libraries/Core/ReactNativeVersion.js 1`] = ` +"/** + * 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. + * + * @flow strict + * @generated by scripts/releases/set-rn-version.js + */ + +const version: $ReadOnly<{ + major: number, + minor: number, + patch: number, + prerelease: string | null, +}> = { + major: 0, + minor: 80, + patch: 1, + prerelease: null, +}; + +module.exports = {version}; +" +`; + +exports[`setVersion updates monorepo for stable version: packages/react-native/React/Base/RCTVersion.m 1`] = ` +"/** + * 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. + * + * @generated by scripts/releases/set-rn-version.js + */ + +#import \\"RCTVersion.h\\" + +NSString* const RCTVersionMajor = @\\"major\\"; +NSString* const RCTVersionMinor = @\\"minor\\"; +NSString* const RCTVersionPatch = @\\"patch\\"; +NSString* const RCTVersionPrerelease = @\\"prerelease\\"; + + +NSDictionary* RCTGetReactNativeVersion(void) +{ + static NSDictionary* __rnVersion; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^(void){ + __rnVersion = @{ + RCTVersionMajor: @(0), + RCTVersionMinor: @(80), + RCTVersionPatch: @(1), + RCTVersionPrerelease: [NSNull null], + }; + }); + return __rnVersion; +} +" +`; + +exports[`setVersion updates monorepo for stable version: packages/react-native/ReactAndroid/gradle.properties 1`] = ` +"VERSION_NAME=0.80.1 +" +`; + +exports[`setVersion updates monorepo for stable version: packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java 1`] = ` +"/** + * 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. + * + * @generated by scripts/releases/set-rn-version.js + */ + +package com.facebook.react.modules.systeminfo; + +import com.facebook.react.common.MapBuilder; + +import java.util.Map; + +public class ReactNativeVersion { + public static final Map VERSION = MapBuilder.of( + \\"major\\", 0, + \\"minor\\", 80, + \\"patch\\", 1, + \\"prerelease\\", null); +} +" +`; + +exports[`setVersion updates monorepo for stable version: packages/react-native/ReactCommon/cxxreact/ReactNativeVersion.h 1`] = ` +"/** + * 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. + * + * @generated by scripts/releases/set-rn-version.js + */ + +#pragma once + +#include +#include + +namespace facebook::react { + +constexpr struct { + int32_t Major = 0; + int32_t Minor = 80; + int32_t Patch = 1; + std::string_view Prerelease = \\"\\"; +} ReactNativeVersion; + +} // namespace facebook::react +" +`; + +exports[`setVersion updates monorepo for stable version: packages/react-native/package.json 1`] = ` "{ \\"name\\": \\"react-native\\", - \\"version\\": \\"0.80.0\\", + \\"version\\": \\"0.80.1\\", \\"description\\": \\"fake react native package\\", \\"dependencies\\": { - \\"@monorepo/pkg-a\\": \\"0.80.0\\", - \\"@monorepo/pkg-b\\": \\"0.80.0\\", - \\"@monorepo/pkg-c\\": \\"0.80.0\\", + \\"@monorepo/pkg-a\\": \\"0.80.1\\", + \\"@monorepo/pkg-b\\": \\"0.80.1\\", + \\"@monorepo/pkg-c\\": \\"0.80.1\\", \\"metro-config\\": \\"^0.80.3\\", \\"metro-runtime\\": \\"^0.80.3\\" } @@ -59,18 +578,18 @@ exports[`setVersion updates all public packages to version: react-native 1`] = ` " `; -exports[`setVersion updates all public packages to version: template 1`] = ` +exports[`setVersion updates monorepo for stable version: packages/react-native/template/package.json 1`] = ` "{ \\"name\\": \\"react-native-test-template\\", \\"version\\": \\"0.0.1\\", \\"private\\": true, \\"dependencies\\": { \\"react\\": \\"18.2.0\\", - \\"react-native\\": \\"0.80.0\\" + \\"react-native\\": \\"0.80.1\\" }, \\"devDependencies\\": { - \\"@monorepo/pkg-a\\": \\"0.80.0\\", - \\"@monorepo/pkg-c\\": \\"0.80.0\\", + \\"@monorepo/pkg-a\\": \\"0.80.1\\", + \\"@monorepo/pkg-c\\": \\"0.80.1\\", \\"@types/react\\": \\"^18.2.6\\", \\"@types/react-test-renderer\\": \\"^18.0.0\\" } diff --git a/scripts/releases/set-version/__tests__/set-version-test.js b/scripts/releases/set-version/__tests__/set-version-test.js index c30ffcd1c9dfeb..dc4297de4cad15 100644 --- a/scripts/releases/set-version/__tests__/set-version-test.js +++ b/scripts/releases/set-version/__tests__/set-version-test.js @@ -28,17 +28,34 @@ describe('setVersion', () => { return { ...originalFs, - writeFileSync: (packagePath, content) => { - expect(content).toMatchSnapshot( - path.basename(path.join(packagePath, '..')), - ); + promises: { + ...originalFs.promises, + writeFile: (filePath, content) => { + expect(content).toMatchSnapshot( + // Make snapshot names resilient to platform path sep differences + path + .relative(path.join(__dirname, '__fixtures__'), filePath) + .split(path.sep) + .join('/'), + ); + }, }, }; }); }); - test('updates all public packages to version', () => { - setVersion('0.80.0'); + + test('updates monorepo for release-candidate', async () => { + await setVersion('0.80.0-rc.3'); + }); + + test('updates monorepo for stable version', async () => { + await setVersion('0.80.1'); }); + + test('updates monorepo for nightly', async () => { + await setVersion('0.81.0-nightly-29282302-abcd1234'); + }); + afterAll(() => { jest.unmock('path'); jest.unmock('fs'); diff --git a/scripts/releases/set-version/index.js b/scripts/releases/set-version/index.js index a0cdeee814effb..9e4c96f8591b15 100644 --- a/scripts/releases/set-version/index.js +++ b/scripts/releases/set-version/index.js @@ -12,7 +12,9 @@ 'use strict'; const forEachPackage = require('../../monorepo/for-each-package'); -const {readFileSync, writeFileSync} = require('fs'); +const {updateGradleFile, updateSourceFiles} = require('../set-rn-version'); +const {parseVersion} = require('../utils/version-utils'); +const {promises: fs, readFileSync} = require('fs'); const path = require('path'); const yargs = require('yargs'); @@ -30,8 +32,9 @@ function getPublicPackages() { return packages; } -function setVersion(version /*: string */) { +function updatePackages(version /*: string */) { const publicPackages = getPublicPackages(); + const writes = []; forEachPackage( (packageAbsolutePath, _, packageJson) => { @@ -57,10 +60,12 @@ function setVersion(version /*: string */) { } } - writeFileSync( - path.join(packageAbsolutePath, 'package.json'), - JSON.stringify(packageJson, null, 2) + '\n', - 'utf-8', + writes.push( + fs.writeFile( + path.join(packageAbsolutePath, 'package.json'), + JSON.stringify(packageJson, null, 2) + '\n', + 'utf-8', + ), ); // Update template package.json @@ -92,18 +97,36 @@ function setVersion(version /*: string */) { } } } - writeFileSync( - templatePackageJsonPath, - JSON.stringify(templatePackageJson, null, 2) + '\n', - 'utf-8', + writes.push( + fs.writeFile( + templatePackageJsonPath, + JSON.stringify(templatePackageJson, null, 2) + '\n', + 'utf-8', + ), ); } }, {includeReactNative: true}, ); + + return Promise.all(writes); } -module.exports = setVersion; +async function setVersion(version /*: string */) { + const parsedVersion = parseVersion(version); + + await updateSourceFiles(parsedVersion); + await updateGradleFile(parsedVersion.version); + await updatePackages(parsedVersion.version); +} + +/* + Sets a singular version for the entire monorepo (including `react-native` package) + * Update all public npm packages under `/packages` to specified version + * Update all npm dependencies of a `/packages` package to specified version + * Update npm dependencies of the template app (`packages/react-native/template`) to specified version + * Update `packages/react-native` native source and build files to specified version + */ if (require.main === module) { const {toVersion} = yargs(process.argv.slice(2)) @@ -113,10 +136,18 @@ if (require.main === module) { args => args.positional('to-version', { type: 'string', - description: 'Set the version of all packages to this value', + description: 'Sets entire monorepo to version provided', required: true, }), ) .parseSync(); - setVersion(toVersion); + setVersion(toVersion).then( + () => process.exit(0), + error => { + console.error(`Failed to set version ${toVersion}\n`, error); + process.exit(1); + }, + ); } + +module.exports = setVersion; diff --git a/scripts/releases/utils/__tests__/version-utils-test.js b/scripts/releases/utils/__tests__/version-utils-test.js index 28fdef07e96901..1dba46a6235361 100644 --- a/scripts/releases/utils/__tests__/version-utils-test.js +++ b/scripts/releases/utils/__tests__/version-utils-test.js @@ -4,6 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * + * @flow strict-local * @format * @oncall react_native */ @@ -15,19 +16,16 @@ const { validateBuildType, } = require('../version-utils'); -let execResult = null; jest.mock('shelljs', () => ({ exec: () => { return { - stdout: execResult, + stdout: null, }; }, echo: message => { console.log(message); }, - exit: exitCode => { - exit(exitCode); - }, + exit: jest.fn(), })); describe('version-utils', () => { @@ -44,17 +42,9 @@ describe('version-utils', () => { }); describe('parseVersion', () => { - it('should throw error if buildType is undefined', () => { - function testInvalidVersion() { - parseVersion('v0.10.5'); - } - expect(testInvalidVersion).toThrowErrorMatchingInlineSnapshot( - `"Unsupported build type: undefined"`, - ); - }); - it('should throw error if buildType is not `release`, `dry-run`, `prealpha`` or `nightly`', () => { function testInvalidVersion() { + // $FlowExpectedError[incompatible-call] parseVersion('v0.10.5', 'invalid_build_type'); } expect(testInvalidVersion).toThrowErrorMatchingInlineSnapshot( diff --git a/scripts/releases/utils/version-utils.js b/scripts/releases/utils/version-utils.js index 5eb34d2d5eac90..e37c74e0036121 100644 --- a/scripts/releases/utils/version-utils.js +++ b/scripts/releases/utils/version-utils.js @@ -37,16 +37,12 @@ export type Version = { */ function parseVersion( versionStr /*: string */, - buildType /*: BuildType */, + buildType /*: ?BuildType */, ) /*: Version */ { - if (!validateBuildType(buildType)) { - throw new Error(`Unsupported build type: ${buildType}`); - } - const match = extractMatchIfValid(versionStr); const [, version, major, minor, patch, prerelease] = match; - const versionObject = { + const parsedVersion = { version, major, minor, @@ -54,9 +50,14 @@ function parseVersion( prerelease, }; - validateVersion(versionObject, buildType); + if (buildType != null) { + if (!validateBuildType(buildType)) { + throw new Error(`Unsupported build type: ${buildType}`); + } + validateVersion(parsedVersion, buildType); + } - return versionObject; + return parsedVersion; } function validateBuildType(