Use one time password when publishing to npm (#20701)

Summary:
This pull request addresses the failing publish-npm.js script from earlier this week. For background, last month we reset all npm access tokens for any package related to Facebook, and we now require all accounts with publish permissions to have two factor enabled.

The publish-npm.js script relied on one such token that is configured in Circle CI as a envvar. The token has been updated in Circle CI, but we now need a way of passing the one time password to npm.

With this PR, we can now grab the otp from Circle CI's envvars. Considering otps are ephemeral, this requires the NPM_CONFIG_OTP envvar to be set by someone with publishing permissions anytime a new release will be pushed to npm. The token is short lived, but it would still be good to clear the envvar after the package is published. Circle CI envvars are not passed on to PR/forked builds.

This PR is effectively a breaking change for the release process, as the publish step will not succeed if the OTP is not valid.

OTPs are short-lived, and the publish_npm_package job will definitely outlive the token. Unfortunately this will require some timing to get right, but the alternative is to ssh into the Circle CI machine and re-run the `npm publish --otp` command, which again would still require someone with publish access to provide the otp.
Pull Request resolved: https://github.com/facebook/react-native/pull/20701

Differential Revision: D9478488

Pulled By: hramos

fbshipit-source-id: 6af631a9cb425271b98c03d158aec390ebc95304
This commit is contained in:
Héctor Ramos 2018-08-22 23:20:05 -07:00 committed by Facebook Github Bot
parent 8103c431c8
commit aae3a7816e
2 changed files with 29 additions and 17 deletions

View File

@ -596,8 +596,10 @@ jobs:
publish_npm_package:
<<: *android_defaults
steps:
- attach_workspace:
at: ~/react-native
- checkout
- restore-cache: *restore-yarn-cache
- run: *yarn
# Configure Android SDK and related dependencies
- run: *configure-android-path
@ -624,13 +626,19 @@ jobs:
- run: *yarn
- run:
name: Publish React Native Package
name: Authenticate with npm
command: echo "//registry.npmjs.org/:_authToken=${CIRCLE_NPM_TOKEN}" > ~/.npmrc
- run:
name: Authenticate git user
command: |
echo "//registry.npmjs.org/:_authToken=${CIRCLE_NPM_TOKEN}" > ~/.npmrc
git config --global user.email "reactjs-bot@users.noreply.github.com"
git config --global user.email "react-native-bot@users.noreply.github.com"
git config --global user.name "npm Deployment Script"
echo "machine github.com login reactjs-bot password $GITHUB_TOKEN" > ~/.netrc
node ./scripts/publish-npm.js
echo "machine github.com login react-native-bot password $GITHUB_TOKEN" > ~/.netrc
- run:
name: Publish React Native Package
command: node ./scripts/publish-npm.js
# Workflows enables us to run multiple jobs in parallel
workflows:

View File

@ -51,6 +51,7 @@
require('shelljs/global');
const buildBranch = process.env.CIRCLE_BRANCH;
const otp = process.env.NPM_CONFIG_OTP;
let branchVersion;
if (buildBranch.indexOf('-stable') !== -1) {
@ -79,7 +80,7 @@ const tagsWithVersion = exec(`git ls-remote origin | grep ${currentCommit}`, {
if (tagsWithVersion.length === 0) {
echo(
"Error: Can't find version tag in current commit. To deploy to NPM you must add tag v0.XY.Z[-rc] to your commit",
'Error: Cannot find version tag in current commit. To deploy to NPM you must add tag v0.XY.Z[-rc] to your commit',
);
exit(1);
}
@ -96,7 +97,7 @@ if (tagsWithVersion[0].indexOf('-rc') === -1) {
// -------- Generating Android Artifacts with JavaDoc
if (exec('./gradlew :ReactAndroid:installArchives').code) {
echo("Couldn't generate artifacts");
echo('Could not generate artifacts');
exit(1);
}
@ -121,15 +122,18 @@ artifacts.forEach(name => {
}
});
if (releaseVersion.indexOf('-rc') === -1) {
// release, package will be installed by default
exec('npm publish');
// if version contains -rc, tag as prerelease
const tagFlag = releaseVersion.indexOf('-rc') === -1 ? '' : '--tag next';
// use otp from envvars if available
const otpFlag = otp ? `--otp ${otp}` : '';
if (exec(`npm publish ${tagFlag} ${otpFlag}`).code) {
echo('Failed to publish package to npm');
exit(1);
} else {
// RC release, package will be installed only if users specifically do it
exec('npm publish --tag next');
echo(`Published to npm ${releaseVersion}`);
exit(0);
}
echo(`Published to npm ${releaseVersion}`);
exit(0);
/*eslint-enable no-undef */