From b7b55854feabef02ef0a2ed1962739c0aaa2cfe3 Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Wed, 31 Jan 2024 03:36:02 -0800 Subject: [PATCH] Enable Flow on misc release scripts (#42736) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/42736 - Minimally enable Flow in these scripts. This would have caught outdated imports in D53001971 and D53228096. - Update `publish-npm` script with async `main()` function. - Also delete leftover `ReactNativeVersion.js.template` file. Changelog: [Internal] Reviewed By: cortinico Differential Revision: D53225162 fbshipit-source-id: 9521291b7c84728e3e05af510ebf3244a9a189e5 --- scripts/__tests__/publish-npm-test.js | 38 +++++++++---------- scripts/prepare-package-for-release.js | 9 +++++ scripts/publish-npm.js | 25 +++++++++--- scripts/scm-utils.js | 3 +- scripts/trigger-react-native-release.js | 16 ++++++-- .../ReactNativeVersion.js.template | 24 ------------ 6 files changed, 63 insertions(+), 52 deletions(-) delete mode 100644 scripts/versiontemplates/ReactNativeVersion.js.template diff --git a/scripts/__tests__/publish-npm-test.js b/scripts/__tests__/publish-npm-test.js index 1a5da6c6945..2c94df42374 100644 --- a/scripts/__tests__/publish-npm-test.js +++ b/scripts/__tests__/publish-npm-test.js @@ -44,7 +44,7 @@ jest const date = new Date('2023-04-20T23:52:39.543Z'); -const publishNpm = require('../publish-npm'); +const {publishNpm} = require('../publish-npm'); let consoleError; describe('publish-npm', () => { @@ -68,15 +68,15 @@ describe('publish-npm', () => { describe('publish-npm.js', () => { it('Fails when invalid build type is passed', () => { - expect(() => publishNpm('invalid')).toThrowError( + expect(publishNpm('invalid')).rejects.toThrow( 'Unsupported build type: invalid', ); }); }); describe('dry-run', () => { - it('should set version and not publish', () => { - publishNpm('dry-run'); + it('should set version and not publish', async () => { + await publishNpm('dry-run'); expect(removeNewArchFlags).not.toHaveBeenCalled(); expect(exitMock).toHaveBeenCalledWith(0); @@ -93,13 +93,13 @@ describe('publish-npm', () => { }); describe('nightly', () => { - it('should publish', () => { + it('should publish', async () => { execMock .mockReturnValueOnce({stdout: '0.81.0-rc.1\n', code: 0}) .mockReturnValueOnce({code: 0}); const expectedVersion = '0.82.0-nightly-20230420-currentco'; - publishNpm('nightly'); + await publishNpm('nightly'); expect(removeNewArchFlags).not.toHaveBeenCalled(); expect(publishAndroidArtifactsToMavenMock).toHaveBeenCalledWith( @@ -116,14 +116,14 @@ describe('publish-npm', () => { expect(exitMock).toHaveBeenCalledWith(0); }); - it('should fail to set version', () => { + it('should fail to set version', async () => { execMock.mockReturnValueOnce({stdout: '0.81.0-rc.1\n', code: 0}); const expectedVersion = '0.82.0-nightly-20230420-currentco'; setReactNativeVersionMock.mockImplementation(() => { throw new Error('something went wrong'); }); - publishNpm('nightly'); + await publishNpm('nightly'); expect(removeNewArchFlags).not.toHaveBeenCalled(); expect(publishAndroidArtifactsToMavenMock).not.toBeCalled(); @@ -140,19 +140,19 @@ describe('publish-npm', () => { describe('release', () => { it('should fail with invalid release version', () => { process.env.CIRCLE_TAG = '1.0.1'; - expect(() => { - publishNpm('release'); - }).toThrow('Version 1.0.1 is not valid for Release'); + expect(publishNpm('release')).rejects.toThrow( + 'Version 1.0.1 is not valid for Release', + ); expect(publishAndroidArtifactsToMavenMock).not.toBeCalled(); }); - it('should publish non-latest', () => { + it('should publish non-latest', async () => { execMock.mockReturnValueOnce({code: 0}); isTaggedLatestMock.mockReturnValueOnce(false); process.env.CIRCLE_TAG = '0.81.1'; process.env.NPM_CONFIG_OTP = 'otp'; - publishNpm('release'); + await publishNpm('release'); expect(removeNewArchFlags).not.toHaveBeenCalled(); const expectedVersion = '0.81.1'; @@ -171,13 +171,13 @@ describe('publish-npm', () => { expect(execMock.mock.calls).toHaveLength(1); }); - it('should publish latest stable', () => { + it('should publish latest stable', async () => { execMock.mockReturnValueOnce({code: 0}); isTaggedLatestMock.mockReturnValueOnce(true); process.env.CIRCLE_TAG = '0.81.1'; process.env.NPM_CONFIG_OTP = 'otp'; - publishNpm('release'); + await publishNpm('release'); expect(removeNewArchFlags).not.toHaveBeenCalled(); const expectedVersion = '0.81.1'; @@ -196,13 +196,13 @@ describe('publish-npm', () => { expect(execMock.mock.calls).toHaveLength(1); }); - it('should fail to publish latest stable', () => { + it('should fail to publish latest stable', async () => { execMock.mockReturnValueOnce({code: 1}); isTaggedLatestMock.mockReturnValueOnce(true); process.env.CIRCLE_TAG = '0.81.1'; process.env.NPM_CONFIG_OTP = 'otp'; - publishNpm('release'); + await publishNpm('release'); expect(removeNewArchFlags).not.toHaveBeenCalled(); const expectedVersion = '0.81.1'; @@ -219,13 +219,13 @@ describe('publish-npm', () => { expect(execMock.mock.calls).toHaveLength(1); }); - it('should publish next', () => { + it('should publish next', async () => { execMock.mockReturnValueOnce({code: 0}); isTaggedLatestMock.mockReturnValueOnce(true); process.env.CIRCLE_TAG = '0.81.0-rc.4'; process.env.NPM_CONFIG_OTP = 'otp'; - publishNpm('release'); + await publishNpm('release'); expect(removeNewArchFlags).not.toHaveBeenCalled(); const expectedVersion = '0.81.0-rc.4'; diff --git a/scripts/prepare-package-for-release.js b/scripts/prepare-package-for-release.js index f30c8e328e6..a1b607020f6 100755 --- a/scripts/prepare-package-for-release.js +++ b/scripts/prepare-package-for-release.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 * @format */ @@ -45,11 +46,19 @@ const argv = yargs }).argv; const branch = process.env.CIRCLE_BRANCH; +// $FlowFixMe[prop-missing] const remote = argv.remote; +// $FlowFixMe[prop-missing] const releaseVersion = argv.toVersion; +// $FlowFixMe[prop-missing] const isLatest = argv.latest; +// $FlowFixMe[prop-missing] const isDryRun = argv.dryRun; +if (branch == null) { + throw new Error('process.env.CIRCLE_BRANCH is not set'); +} + const buildType = isDryRun ? 'dry-run' : isReleaseBranch(branch) diff --git a/scripts/publish-npm.js b/scripts/publish-npm.js index 143321b4edf..ef82a401314 100755 --- a/scripts/publish-npm.js +++ b/scripts/publish-npm.js @@ -5,10 +5,15 @@ * LICENSE file in the root directory of this source tree. * * @format + * @flow */ 'use strict'; +/*:: +import type {BuildType} from './releases/version-utils'; +*/ + const getAndUpdatePackages = require('./monorepo/get-and-update-packages'); const {getNpmInfo, publishPackage} = require('./npm-utils'); const { @@ -43,7 +48,7 @@ const yargs = require('yargs'); * * or otherwise `{major}.{minor}-stable` */ -if (require.main === module) { +async function main() { const argv = yargs .option('t', { alias: 'builtType', @@ -53,12 +58,13 @@ if (require.main === module) { }) .strict().argv; + // $FlowFixMe[prop-missing] const buildType = argv.builtType; - publishNpm(buildType); + await publishNpm(buildType); } -function publishNpm(buildType) { +async function publishNpm(buildType /*: BuildType */) /*: Promise */ { const {version, tag} = getNpmInfo(buildType); if (buildType === 'prealpha') { @@ -70,12 +76,13 @@ function publishNpm(buildType) { if (['dry-run', 'nightly', 'prealpha'].includes(buildType)) { // Publish monorepo nightlies and prealphas if there are updates, returns the new version for each package const monorepoVersions = + // $FlowFixMe[incompatible-call] buildType === 'dry-run' ? null : getAndUpdatePackages(version, buildType); try { // Update the react-native and template packages with the react-native version // and nightly versions of monorepo deps - setReactNativeVersion(version, monorepoVersions, buildType); + await setReactNativeVersion(version, monorepoVersions, buildType); } catch (e) { console.error(`Failed to set version number to ${version}`); console.error(e); @@ -96,6 +103,7 @@ function publishNpm(buildType) { const packagePath = path.join(__dirname, '..', 'packages', 'react-native'); const result = publishPackage(packagePath, { + // $FlowFixMe[incompatible-call] tags: [tag], otp: process.env.NPM_CONFIG_OTP, }); @@ -109,4 +117,11 @@ function publishNpm(buildType) { } } -module.exports = publishNpm; +module.exports = { + publishNpm, +}; + +if (require.main === module) { + // eslint-disable-next-line no-void + void main(); +} diff --git a/scripts/scm-utils.js b/scripts/scm-utils.js index 106b40c7cc1..2e7b228716b 100644 --- a/scripts/scm-utils.js +++ b/scripts/scm-utils.js @@ -38,7 +38,8 @@ function exitIfNotOnGit /*::*/( command /*: () => T */, errorMessage /*: string */, gracefulExit /*: boolean */ = false, -) /*: ?T */ { + // $FlowFixMe[incompatible-return] Asserts return value +) /*: T */ { if (isGitRepo()) { return command(); } else { diff --git a/scripts/trigger-react-native-release.js b/scripts/trigger-react-native-release.js index b917a2fbb4c..1df4dd4bbd8 100644 --- a/scripts/trigger-react-native-release.js +++ b/scripts/trigger-react-native-release.js @@ -5,6 +5,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * + * @flow * @format */ @@ -54,7 +55,7 @@ let argv = yargs return true; }).argv; -function exitIfNotOnReleaseBranch(branch) { +function exitIfNotOnReleaseBranch(branch /*: string */) { if (!isReleaseBranch(branch)) { console.log( 'This script must be run in a react-native git repository checkout and on a release branch', @@ -64,7 +65,11 @@ function exitIfNotOnReleaseBranch(branch) { } const buildExecutor = - (packageAbsolutePath, packageRelativePathFromRoot, packageManifest) => + ( + packageAbsolutePath /*: string */, + packageRelativePathFromRoot /*: string */, + packageManifest /*: $FlowFixMe */, + ) => async () => { const {name: packageName} = packageManifest; if (packageManifest.private) { @@ -109,7 +114,7 @@ async function exitIfUnreleasedPackages() { } } -function triggerReleaseWorkflow(options) { +function triggerReleaseWorkflow(options /*: $FlowFixMe */) { return new Promise((resolve, reject) => { request(options, function (error, response, body) { if (error) { @@ -144,7 +149,9 @@ async function main() { exit(1); } + // $FlowFixMe[prop-missing] const token = argv.token; + // $FlowFixMe[prop-missing] const releaseVersion = argv.toVersion; failIfTagExists(releaseVersion, 'release'); @@ -155,6 +162,7 @@ async function main() { }); if (!pushed) { + // $FlowFixMe[prop-missing] console.log(`Please run 'git push ${argv.remote} ${branch}'`); exit(1); return; @@ -206,6 +214,7 @@ async function main() { // See response: https://circleci.com/docs/api/v2/#operation/triggerPipeline const body = await triggerReleaseWorkflow(options); console.log( + // $FlowFixMe[incompatible-use] `Monitor your release workflow: https://app.circleci.com/pipelines/github/facebook/react-native/${body.number}`, ); @@ -215,6 +224,7 @@ async function main() { // - Verify RN-diff publish is through } +// $FlowFixMe[unused-promise] main().then(() => { exit(0); }); diff --git a/scripts/versiontemplates/ReactNativeVersion.js.template b/scripts/versiontemplates/ReactNativeVersion.js.template deleted file mode 100644 index 59933c03175..00000000000 --- a/scripts/versiontemplates/ReactNativeVersion.js.template +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @generated by scripts/set-rn-version.js - * - * 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 - */ - -const version: $ReadOnly<{ - major: number, - minor: number, - patch: number, - prerelease: string | null, -}> = { - major: ${major}, - minor: ${minor}, - patch: ${patch}, - prerelease: ${prerelease}, -}; - -module.exports = {version};