1/**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 * @format
8 */
9
10'use strict';
11
12/**
13 * This script prepares a release package to be pushed to npm
14 * It is triggered to run on CircleCI
15 * It will:
16 *    * It updates the version in json/gradle files and makes sure they are consistent between each other (set-rn-version)
17 *    * Updates podfile for RNTester
18 *    * Commits changes and tags with the next version based off of last version tag.
19 *      This in turn will trigger another CircleCI job to publish to npm
20 */
21const {echo, exec, exit} = require('shelljs');
22const yargs = require('yargs');
23const {isReleaseBranch, parseVersion} = require('./version-utils');
24const {failIfTagExists} = require('./release-utils');
25
26const argv = yargs
27  .option('r', {
28    alias: 'remote',
29    default: 'origin',
30  })
31  .option('v', {
32    alias: 'to-version',
33    type: 'string',
34    required: true,
35  })
36  .option('l', {
37    alias: 'latest',
38    type: 'boolean',
39    default: false,
40  })
41  .option('d', {
42    alias: 'dry-run',
43    type: 'boolean',
44    default: false,
45  }).argv;
46
47const branch = process.env.CIRCLE_BRANCH;
48const remote = argv.remote;
49const releaseVersion = argv.toVersion;
50const isLatest = argv.latest;
51const isDryRun = argv.dryRun;
52
53const buildType = isDryRun
54  ? 'dry-run'
55  : isReleaseBranch(branch)
56  ? 'release'
57  : 'nightly';
58
59failIfTagExists(releaseVersion, buildType);
60
61if (branch && !isReleaseBranch(branch) && !isDryRun) {
62  console.error(`This needs to be on a release branch. On branch: ${branch}`);
63  exit(1);
64} else if (!branch && !isDryRun) {
65  console.error('This needs to be on a release branch.');
66  exit(1);
67}
68
69const {version} = parseVersion(releaseVersion, buildType);
70if (version == null) {
71  console.error(`Invalid version provided: ${releaseVersion}`);
72  exit(1);
73}
74
75if (
76  exec(
77    `node scripts/set-rn-version.js --to-version ${version} --build-type ${buildType}`,
78  ).code
79) {
80  echo(`Failed to set React Native version to ${version}`);
81  exit(1);
82}
83
84// Release builds should commit the version bumps, and create tags.
85echo('Updating RNTester Podfile.lock...');
86if (exec('source scripts/update_podfile_lock.sh && update_pods').code) {
87  echo('Failed to update RNTester Podfile.lock.');
88  echo('Fix the issue, revert and try again.');
89  exit(1);
90}
91
92echo(`Local checkout has been prepared for release version ${version}.`);
93if (isDryRun) {
94  echo('Changes will not be committed because --dry-run was set to true.');
95  exit(0);
96}
97
98// Make commit [0.21.0-rc] Bump version numbers
99if (exec(`git commit -a -m "[${version}] Bump version numbers"`).code) {
100  echo('failed to commit');
101  exit(1);
102}
103
104// Add tag v0.21.0-rc.1
105if (exec(`git tag -a v${version} -m "v${version}"`).code) {
106  echo(
107    `failed to tag the commit with v${version}, are you sure this release wasn't made earlier?`,
108  );
109  echo('You may want to rollback the last commit');
110  echo('git reset --hard HEAD~1');
111  exit(1);
112}
113
114// If `isLatest`, this git tag will also set npm release as `latest`
115if (isLatest) {
116  exec('git tag -d latest');
117  exec(`git push ${remote} :latest`);
118
119  // This will be pushed with the `--follow-tags`
120  exec('git tag -a latest -m "latest"');
121}
122
123exec(`git push ${remote} ${branch} --follow-tags`);
124
125exit(0);
126