From 51c8a75d79dbd55979486840d8bd58caac84ef94 Mon Sep 17 00:00:00 2001 From: Nate Fischer Date: Tue, 30 Jan 2018 13:46:28 -0800 Subject: [PATCH] refactor: change order for publishing (#6) This completely changes the order of steps we follow for publishing a package. The goal here is to move `npm publish` as close as possible to the beginning so that we can error-out early if it fails (e.g. 2FA errors). At a high level, our new steps are: * npm version (bump version, commit, make tag) * echo npm publish * if successful, push commit & tag * if failed, undo commit & tag In the case of failure, we still provide the same granularity of error output: we check to see if the user is logged in, if they're owner/contributor, etc. In addition, we also provide some error output if the user is outside of a git repo (the usual cause for `npm version` failures). While this refactor is done to enable supporting 2FA, this does not itself provide OTP support. This refactor also adds TODOs for other bugs, which will be resolved in follow-up PRs. Issue #5 --- index.js | 89 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 23 deletions(-) diff --git a/index.js b/index.js index a8b28d6..01b6b24 100755 --- a/index.js +++ b/index.js @@ -1,40 +1,83 @@ #!/usr/bin/env node require('shelljs/global'); -// require npm user -// bump package version -// commit -// create tag -// push commit & tag -// publish +var path = require('path'); + +// npm version (bump version, commit, make tag) +// echo npm publish +// - if successful, push commit & tag +// - if failed, undo commit & tag function usage() { - echo(""); - echo(" Usage: node " + process.argv[1] + " "); + echo(''); + echo(' Usage: node ' + process.argv[1] + ' '); } config.silent = true; function run(version) { - var npm_user = exec('npm whoami').trimRight(); - var is_collaborator = exec('npm access ls-collaborators').grep('.*' + npm_user + '.*:.*write.*').trimRight(); - var is_owner = exec('npm owner ls').grep('.*' + npm_user + ' <.*').trimRight(); - - if (npm_user) { - config.silent = false; - if (is_collaborator || is_owner) { - echo('Publishing new ' + version + ' version as ' + npm_user + '.'); + config.silent = false; + config.fatal = true; + try { + // TODO(nfischer): only allow releases from master branch (issue #4) + echo('Publishing new ' + version + ' version'); + echo(''); + exec('npm version ' + version); + } catch (e) { + echo(''); + echo('Unable to bump version, is your repo clean?'); + exit(1); + } + + try { + exec('npm publish'); + } catch (e) { + config.fatal = false; + echo(''); + echo('Unable to publish, restoring previous repo state'); + + // Clean up + var newVersion = require(path.resolve('.', 'package.json')).version; + var tagName = 'v' + newVersion; + + // Delete the tag and undo the commit + echo('Removing git tag...'); + exec('git tag -d ' + tagName); + echo('Removing git commit...'); + exec('git reset --hard HEAD~1'); + var npm_user = exec('npm whoami', { silent: true }).trimRight(); + if (npm_user.toString() === '') { + config.silent = false; echo(''); - exec('npm version ' + version); - exec('git push'); - exec('git push --follow-tags'); - exec('npm publish'); - } else { + echo('You must be logged in to NPM to publish, run "npm login" first.'); + exit(1); + } + config.silent = true; + var is_collaborator = exec('npm access ls-collaborators') + .grep('.*' + npm_user + '.*:.*write.*') + .trimRight(); + var is_owner = exec('npm owner ls').grep('.*' + npm_user + ' <.*') + .trimRight(); + if (is_collaborator + is_owner === '') { + // Neither collaborator nor owner + config.silent = false; echo(npm_user + ' does not have NPM write access. Request access from one of these fine folk:'); echo(''); exec('npm owner ls'); + exit(1); } - } else { - echo('You must be logged in to NPM to publish, run "npm login" first.'); + + echo('Unknown error: ' + e); + } + + config.silent = false; + try { + // TODO(nfischer): this currently requires upstream tracking (issue #2) + exec('git push'); + exec('git push --tags'); + } catch (e) { + echo(''); + echo('Version has been released, but commit/tag could not be pushed.'); + echo('Please push these manually.'); } }