diff --git a/scripts/release-manager/Readme.md b/scripts/release-manager/Readme.md index 02755b1c08..2062b9f491 100644 --- a/scripts/release-manager/Readme.md +++ b/scripts/release-manager/Readme.md @@ -31,6 +31,13 @@ Cherry-picks PRs that are set to the `15-next` milestone. Handles merge conflict Bumps the version in all the places that need it. +### `npm-publish` + +Publishes all built packages to npm (`next` dist-tag) and then for stable releases, also updates the `latest` dist-tag. + +**Prereqs:** +- Have done everything else required for releasing (updating version, etc) and run `grunt build` or `grunt release`. + ### `q` A secret alias to `exit` because `q` is faster. diff --git a/scripts/release-manager/cli.js b/scripts/release-manager/cli.js index b7f5790db8..44c7b312ba 100755 --- a/scripts/release-manager/cli.js +++ b/scripts/release-manager/cli.js @@ -115,6 +115,7 @@ const app = { 'q', 'stable-prs', 'version', + 'npm-publish', ].forEach((command) => { vorpal.use(require(`./commands/${command}`)(vorpal, app)); }); diff --git a/scripts/release-manager/commands/npm-publish.js b/scripts/release-manager/commands/npm-publish.js new file mode 100644 index 0000000000..53f9c7489f --- /dev/null +++ b/scripts/release-manager/commands/npm-publish.js @@ -0,0 +1,74 @@ + +// Publishes the built npm packages from build/packages +// 1. Show checklist (automate later) +// 2. Prompt to ensure build is complete +// 3. Prompt for dist-tag? + + +'use strict'; + +const path = require('path'); +const semver = require('semver'); + +const chalk = require('chalk'); +const glob = require('glob'); + + +module.exports = function(vorpal, app) { + vorpal + .command('npm-publish') + .description('Update the version of React, useful while publishing') + .action(function (args) { + return new Promise((resolve, reject) => { + const currentVersion = app.getReactVersion(); + const isStable = semver.prerelease(currentVersion) === null; + + this.log(`Preparing to publish v${currentVersion}…`); + if (isStable) { + this.log(`"latest" dist-tag will be added to this version`); + } + + // TODO: show checklist + this.prompt([ + { + type: 'confirm', + message: 'Did you run `grunt build` or `grunt release` and bump the version number?', + name: 'checklist' + }, + ]).then((answers) => { + if (!answers.checklist) { + return reject('Complete the build process first') + } + + // We'll grab all the tarballs and publish those directly. This + // is how we've historically done it, though in the past it was + // just npm publish pkg1.tgz && npm publish pkg2.tgz. This + // avoided the need to cd and publish. + const tgz = glob.sync('build/packages/*.tgz', { + cwd: app.PATH_TO_REPO + }); + + // Just in case they didn't actually prep this. + // TODO: verify packages? + if (tgz.length === 0) { + reject('No built packages found'); + } + + // TODO: track success + tgz.forEach((file) => { + this.log(app.execInRepo(`npm publish ${file} --tag=next`)); + }); + + if (isStable) { + tgz.forEach((file) => { + const pkg = path.parse(file).name + this.log(app.execInRepo(`npm dist-tag add ${pkg}@${currentVersion} latest`)); + }); + } + + resolve(); + }) + }); + + }); +} diff --git a/scripts/release-manager/package.json b/scripts/release-manager/package.json index 1495326a71..83050be41c 100644 --- a/scripts/release-manager/package.json +++ b/scripts/release-manager/package.json @@ -8,6 +8,7 @@ "chalk": "^1.1.3", "colors": "^1.1.2", "github-api": "^2.2.0", + "glob": "^7.0.5", "semver": "^5.3.0", "vorpal": "^1.10.10" },