react/scripts/devtools/publish-release.js

128 lines
3.5 KiB
JavaScript
Executable File

#!/usr/bin/env node
'use strict';
const chalk = require('chalk');
const {exec} = require('child-process-promise');
const {readJsonSync} = require('fs-extra');
const inquirer = require('inquirer');
const {join, relative} = require('path');
const {DRY_RUN, NPM_PACKAGES, ROOT_PATH} = require('./configuration');
const {
checkNPMPermissions,
clear,
confirm,
execRead,
logger,
readSavedBuildMetadata,
} = require('./utils');
// This is the primary control function for this script.
async function main() {
clear();
await confirm('Have you run the build-and-test script?', () => {
const buildAndTestScriptPath = join(__dirname, 'build-and-test.js');
const pathToPrint = relative(process.cwd(), buildAndTestScriptPath);
console.log('Begin by running the build-and-test script:');
console.log(chalk.bold.green(' ' + pathToPrint));
});
const {archivePath, buildID} = readSavedBuildMetadata();
await checkNPMPermissions();
await publishToNPM();
await printFinalInstructions(buildID, archivePath);
}
async function printFinalInstructions(buildID, archivePath) {
console.log('');
console.log(
'You are now ready to publish the extension to Chrome, Edge, and Firefox:'
);
console.log(
` ${chalk.blue.underline(
'https://fburl.com/publish-react-devtools-extensions'
)}`
);
console.log('');
console.log('When publishing to Firefox, remember the following:');
console.log(` Build id: ${chalk.bold(buildID)}`);
console.log(` Git archive: ${chalk.bold(archivePath)}`);
console.log('');
console.log('Also consider syncing this release to Facebook:');
console.log(` ${chalk.bold.green('js1 upgrade react-devtools')}`);
}
async function publishToNPM() {
const {otp} = await inquirer.prompt([
{
type: 'input',
name: 'otp',
message: 'Please provide an NPM two-factor auth token:',
},
]);
console.log('');
if (!otp) {
console.error(chalk.red(`Invalid OTP provided: "${chalk.bold(otp)}"`));
process.exit(0);
}
for (let index = 0; index < NPM_PACKAGES.length; index++) {
const npmPackage = NPM_PACKAGES[index];
const packagePath = join(ROOT_PATH, 'packages', npmPackage);
const {version} = readJsonSync(join(packagePath, 'package.json'));
// Check if this package version has already been published.
// If so we might be resuming from a previous run.
// We could infer this by comparing the build-info.json,
// But for now the easiest way is just to ask if this is expected.
const info = await execRead(`npm view ${npmPackage}@${version}`)
// Early versions of npm view gives empty response, but newer versions give 404 error.
// Catch the error to keep it consistent.
.catch(childProcessError => {
if (childProcessError.stderr.startsWith('npm ERR! code E404')) {
return null;
}
throw childProcessError;
});
if (info) {
console.log('');
console.log(
`${npmPackage} version ${chalk.bold(
version
)} has already been published.`
);
await confirm(`Is this expected (will skip ${npmPackage}@${version})?`);
continue;
}
if (DRY_RUN) {
console.log(`Publishing package ${chalk.bold(npmPackage)}`);
console.log(chalk.dim(` npm publish --otp=${otp}`));
} else {
const publishPromise = exec(`npm publish --otp=${otp}`, {
cwd: packagePath,
});
await logger(
publishPromise,
`Publishing package ${chalk.bold(npmPackage)}`,
{
estimate: 2500,
}
);
}
}
}
main();