react/scripts/release/publish-commands/publish-to-npm.js

85 lines
2.5 KiB
JavaScript

#!/usr/bin/env node
'use strict';
const chalk = require('chalk');
const {readJson} = require('fs-extra');
const {join} = require('path');
const semver = require('semver');
const {execRead, execUnlessDry, logPromise} = require('../utils');
const push = async ({cwd, dry, packages, version, tag}) => {
const errors = [];
const isPrerelease = semver.prerelease(version);
if (tag === undefined) {
// No tag was provided. Default to `latest` for stable releases and `next`
// for prereleases
tag = isPrerelease ? 'next' : 'latest';
} else if (tag === 'latest' && isPrerelease) {
throw new Error('The tag `latest` can only be used for stable versions.');
}
const publishProject = async project => {
try {
const path = join(cwd, 'build', 'node_modules', project);
await execUnlessDry(`npm publish --tag ${tag}`, {cwd: path, dry});
const packagePath = join(
cwd,
'build',
'node_modules',
project,
'package.json'
);
const packageJSON = await readJson(packagePath);
const packageVersion = packageJSON.version;
if (!dry) {
// Wait a couple of seconds before querying NPM for status;
// Anecdotally, querying too soon can result in a false negative.
await new Promise(resolve => setTimeout(resolve, 5000));
const status = JSON.parse(
await execRead(`npm info ${project} dist-tags --json`)
);
const remoteVersion = status[tag];
// Compare remote version to package.json version,
// To better handle the case of pre-release versions.
if (remoteVersion !== packageVersion) {
throw Error(
chalk`Published version {yellow.bold ${packageVersion}} for ` +
chalk`{bold ${project}} but NPM shows {yellow.bold ${remoteVersion}}`
);
}
// If we've just published a stable release,
// Update the @next tag to also point to it (so @next doesn't lag behind).
if (!isPrerelease) {
await execUnlessDry(
`npm dist-tag add ${project}@${packageVersion} next`,
{cwd: path, dry}
);
}
}
} catch (error) {
errors.push(error.stack);
}
};
await Promise.all(packages.map(publishProject));
if (errors.length > 0) {
throw Error(
chalk`
Failure publishing to NPM
{white ${errors.join('\n\n')}}`
);
}
};
module.exports = async params => {
return logPromise(push(params), 'Publishing packages to NPM');
};