mirror of
https://github.com/zebrajr/react.git
synced 2025-12-07 00:20:28 +01:00
It turns out npm sets the latest tag by default so simply removing it didn't change the previous behavior. The `latest` tag is typically used for stable release versions, and other tags for unstable versions such as prereleases. Since the compiler is still in prerelease, let's set the latest tag only for non-experimental releases to help signal which version is the safest to try out. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/31288). * #31289 * __->__ #31288
227 lines
7.2 KiB
JavaScript
Executable File
227 lines
7.2 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
|
|
'use strict';
|
|
|
|
const ora = require('ora');
|
|
const path = require('path');
|
|
const yargs = require('yargs');
|
|
const {hashElement} = require('folder-hash');
|
|
const promptForOTP = require('./prompt-for-otp');
|
|
const {PUBLISHABLE_PACKAGES} = require('./shared/packages');
|
|
const {
|
|
execHelper,
|
|
getDateStringForCommit,
|
|
spawnHelper,
|
|
} = require('./shared/utils');
|
|
const {buildPackages} = require('./shared/build-packages');
|
|
const {readJson, writeJson} = require('fs-extra');
|
|
|
|
/**
|
|
* Script for publishing PUBLISHABLE_PACKAGES to npm. By default, this runs in tarball mode, meaning
|
|
* the script will only print out what the contents of the files included in the npm tarball would
|
|
* be.
|
|
*
|
|
* Please run this first (ie `yarn npm:publish`) and double check the contents of the files that
|
|
* will be pushed to npm.
|
|
*
|
|
* If it looks good, you can run `yarn npm:publish --for-real` to really publish to npm. You must
|
|
* have 2FA enabled first and the script will prompt you to enter a 2FA code before proceeding.
|
|
* There's a small annoying delay before the packages are actually pushed to give you time to panic
|
|
* cancel. In this mode, we will bump the version field of each package's package.json, and git
|
|
* commit it. Then, the packages will be published to npm.
|
|
*
|
|
* Optionally, you can add the `--debug` flag to `yarn npm:publish --debug --for-real` to run all
|
|
* steps, but the final npm publish step will have the `--dry-run` flag added to it. This will make
|
|
* the command only report what it would have done, instead of actually publishing to npm.
|
|
*/
|
|
async function main() {
|
|
const argv = yargs(process.argv.slice(2))
|
|
.option('packages', {
|
|
description: 'which packages to publish, defaults to all',
|
|
choices: PUBLISHABLE_PACKAGES,
|
|
default: PUBLISHABLE_PACKAGES,
|
|
})
|
|
.option('for-real', {
|
|
alias: 'frfr',
|
|
description:
|
|
'whether to publish to npm (npm publish) or dryrun (npm publish --dry-run)',
|
|
type: 'boolean',
|
|
default: false,
|
|
})
|
|
.option('debug', {
|
|
description:
|
|
'If enabled, will always run npm commands in dry run mode irregardless of the for-real flag',
|
|
type: 'boolean',
|
|
default: false,
|
|
})
|
|
.option('ci', {
|
|
description: 'Publish packages via CI',
|
|
type: 'boolean',
|
|
default: false,
|
|
})
|
|
.option('tag', {
|
|
description: 'Tag to publish to npm',
|
|
type: 'choices',
|
|
choices: ['experimental', 'beta'],
|
|
default: 'experimental',
|
|
})
|
|
.option('version-name', {
|
|
description: 'Version name',
|
|
type: 'string',
|
|
default: '0.0.0',
|
|
})
|
|
.help('help')
|
|
.strict()
|
|
.parseSync();
|
|
|
|
if (argv.debug === false) {
|
|
const currBranchName = await execHelper('git rev-parse --abbrev-ref HEAD');
|
|
const isPristine = (await execHelper('git status --porcelain')) === '';
|
|
if (currBranchName !== 'main' || isPristine === false) {
|
|
throw new Error(
|
|
'This script must be run from the `main` branch with no uncommitted changes'
|
|
);
|
|
}
|
|
}
|
|
|
|
let pkgNames = argv.packages;
|
|
if (Array.isArray(argv.packages) === false) {
|
|
pkgNames = [argv.packages];
|
|
}
|
|
const spinner = ora(
|
|
`Preparing to publish ${argv.versionName}@${argv.tag} ${
|
|
argv.forReal === true ? '(for real)' : '(dry run)'
|
|
} [debug=${argv.debug}]`
|
|
).info();
|
|
|
|
await buildPackages(pkgNames);
|
|
|
|
if (argv.forReal === false) {
|
|
spinner.info('Dry run: Report tarball contents');
|
|
for (const pkgName of pkgNames) {
|
|
console.log(`\n========== ${pkgName} ==========\n`);
|
|
spinner.start(`Running npm pack --dry-run\n`);
|
|
try {
|
|
await spawnHelper('npm', ['pack', '--dry-run'], {
|
|
cwd: path.resolve(__dirname, `../../packages/${pkgName}`),
|
|
stdio: 'inherit',
|
|
});
|
|
} catch (e) {
|
|
spinner.fail(e.toString());
|
|
throw e;
|
|
}
|
|
spinner.stop(`Successfully packed ${pkgName} (dry run)`);
|
|
}
|
|
spinner.succeed(
|
|
'Please confirm contents of packages before publishing. You can run this command again with --for-real to publish to npm'
|
|
);
|
|
}
|
|
|
|
if (argv.forReal === true) {
|
|
const commit = await execHelper(
|
|
'git show -s --no-show-signature --format=%h',
|
|
{
|
|
cwd: path.resolve(__dirname, '..'),
|
|
}
|
|
);
|
|
const dateString = await getDateStringForCommit(commit);
|
|
const otp =
|
|
argv.ci === false && argv.debug === false ? await promptForOTP() : null;
|
|
const {hash} = await hashElement(path.resolve(__dirname, '../..'), {
|
|
encoding: 'hex',
|
|
folders: {exclude: ['node_modules']},
|
|
files: {exclude: ['.DS_Store']},
|
|
});
|
|
const truncatedHash = hash.slice(0, 7);
|
|
const newVersion = `${argv.versionName}-${argv.tag}-${truncatedHash}-${dateString}`;
|
|
|
|
for (const pkgName of pkgNames) {
|
|
const pkgDir = path.resolve(__dirname, `../../packages/${pkgName}`);
|
|
const pkgJsonPath = path.resolve(
|
|
__dirname,
|
|
`../../packages/${pkgName}/package.json`
|
|
);
|
|
|
|
spinner.start(`Writing package.json for ${pkgName}@${newVersion}`);
|
|
await writeJson(
|
|
pkgJsonPath,
|
|
{
|
|
...(await readJson(pkgJsonPath)),
|
|
version: newVersion,
|
|
},
|
|
{spaces: 2}
|
|
);
|
|
spinner.succeed(`Wrote package.json for ${pkgName}@${newVersion}`);
|
|
|
|
console.log(`\n========== ${pkgName} ==========\n`);
|
|
spinner.start(`Publishing ${pkgName}@${newVersion} to npm\n`);
|
|
|
|
let opts = [];
|
|
if (argv.debug === true) {
|
|
opts.push('--dry-run');
|
|
}
|
|
if (otp != null) {
|
|
opts.push(`--otp=${otp}`);
|
|
}
|
|
/**
|
|
* Typically, the `latest` tag is reserved for stable package versions. Since the the compiler
|
|
* is still pre-release, until we have a stable release let's only add the
|
|
* `latest` tag to non-experimental releases.
|
|
*
|
|
* `latest` is added by default, so we only override it for experimental releases so that
|
|
* those don't get the `latest` tag.
|
|
*
|
|
* TODO: Update this when we have a stable release.
|
|
*/
|
|
if (argv.tag === 'experimental') {
|
|
opts.push('--tag=experimental');
|
|
} else {
|
|
opts.push('--tag=latest');
|
|
}
|
|
try {
|
|
await spawnHelper(
|
|
'npm',
|
|
['publish', ...opts, '--registry=https://registry.npmjs.org'],
|
|
{
|
|
cwd: pkgDir,
|
|
stdio: 'inherit',
|
|
}
|
|
);
|
|
console.log('\n');
|
|
} catch (e) {
|
|
spinner.fail(e.toString());
|
|
throw e;
|
|
}
|
|
spinner.succeed(`Successfully published ${pkgName} to npm`);
|
|
|
|
spinner.start('Pushing tags to npm');
|
|
if (typeof argv.tag === 'string') {
|
|
try {
|
|
let opts = ['dist-tag', 'add', `${pkgName}@${newVersion}`, argv.tag];
|
|
if (otp != null) {
|
|
opts.push(`--otp=${otp}`);
|
|
}
|
|
if (argv.debug === true) {
|
|
spinner.info(`dry-run: npm ${opts.join(' ')}`);
|
|
} else {
|
|
await spawnHelper('npm', opts, {
|
|
cwd: pkgDir,
|
|
stdio: 'inherit',
|
|
});
|
|
}
|
|
} catch (e) {
|
|
spinner.fail(e.toString());
|
|
throw e;
|
|
}
|
|
spinner.succeed(
|
|
`Successfully pushed dist-tag ${argv.tag} for ${pkgName} to npm`
|
|
);
|
|
}
|
|
}
|
|
|
|
console.log('\n\n✅ All done');
|
|
}
|
|
}
|
|
|
|
main();
|