Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add OTP prompt during publish #2084

Merged
merged 2 commits into from May 13, 2019
Merged

Add OTP prompt during publish #2084

merged 2 commits into from May 13, 2019

Conversation

rbuckton
Copy link
Contributor

@rbuckton rbuckton commented May 12, 2019

Description

Adds a prompt for a one-time-password (OTP) when requested from registries that use two-factor authentication (2FA).

Motivation and Context

It is currently marginally possible to publish using 2FA without this prompt, however this requires setting an environment variable prior to calling lerna publish, which could expire during the process of publishing packages.

How Has This Been Tested?

I've added tests for @lerna/otplease and have tested publishing a monorepo for an account that requires a one-time password.

Fixes: #1091

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

@rbuckton
Copy link
Contributor Author

@evocateur: The only issue seems to be that the prompt gets lost in among other messages:

? Are you sure you want to publish these packages? Yes
lerna info execute Skipping GitHub releases
lerna info git Pushing tags...
lerna info publish Publishing packages to npm...
info Verifying npm credentials
http fetch GET 200 https://registry.npmjs.org/-/npm/v1/user 1911ms.
http fetch GET 200 https://registry.npmjs.org/-/org/rbuckton/package?format=cli 228ms
http fetch PUT 401 https://registry.npmjs.org/@esfx%2fdisposable 346mspat packages\reflect-metadata-compat
? This operation requires a one-time password.
http fetch PUT 401 https://registry.npmjs.org/@esfx%2finternal-murmur3 471msckages\reflect-metadata-compat
http fetch PUT 401 https://registry.npmjs.org/@esfx%2finternal-integers 1809ms
? This operation requires a one-time password.
Enter OTP: 123456

As I was typing the OTP the text kept getting replaced with the progress message from npmlog. I'm not familiar enough with @lerna/prompt or npmlog to know if there's anything I need to change to improve the experience.

@rbuckton
Copy link
Contributor Author

I thought it might be the newline I added in the prompt, but I'm still seeing the issue after removing it:

? Are you sure you want to publish these packages? Yes
lerna info execute Skipping GitHub releases
lerna info git Pushing tags...
lerna info publish Publishing packages to npm...
info Verifying npm credentials
http fetch GET 200 https://registry.npmjs.org/-/npm/v1/user 1026ms.
http fetch GET 200 https://registry.npmjs.org/-/org/rbuckton/package?format=cli 164ms
http fetch PUT 401 https://registry.npmjs.org/@esfx%2finternal-integers 298mskages\reflect-metadata-compat
? This operation requires a one-time password: http fetch PUT 401 https://registry.npmjs.org/@esfx%2fcancelable 310ms
http fetch PUT 401 https://registry.npmjs.org/@esfx%2finternal-murmur3 1154mskages\reflect-metadata-compat
http fetch PUT 401 https://registry.npmjs.org/@esfx%2fdisposable 536mspat packages\reflect-metadata-compat
[     .............] - publish: verb packed @esfx/reflect-metadata-compat packages\reflect-metadata-compat

It seems like some of the messages sent to npmlog are being written even after log.pause() is called in prompt.input.

@rbuckton
Copy link
Contributor Author

Ah, I think I figured out the reason. @lerna/publish and @lerna/npm-publish had duplicate installs of npmlog locally (non-deduped), so the log sent to libnpmpublish was a different instance and wasn't disabled.

Unfortunately the steps in CONTRIBUTING.md don't clearly say how to set up the local dev copy of lerna, so I most likely didn't set up the local copy of the repo correctly to ensure each package's dependencies were installed in the correct place.

@rbuckton rbuckton marked this pull request as ready for review May 12, 2019 20:03
Copy link
Member

@evocateur evocateur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm gobsmacked, this is so great!

I will look into the logging issues, but otherwise this looks good to go.

})

// basic single-entry semaphore
const semaphore = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brilliant!

@@ -56,7 +57,7 @@ function npmPublish(pkg, tarFilePath, _opts) {
manifest.publishConfig.tag = opts.tag;
}

return publish(manifest, tarData, opts).catch(err => {
return otplease(opts => publish(manifest, tarData, opts), opts, otpCache).catch(err => {
opts.log.silly("", err);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps the logging problems are related to the default npmlog export and this.logger from the command instance? I've previously had problems with one or the other not quite responding consistently to "shut up now" and "ok spew now" methods...

@evocateur
Copy link
Member

As for duplicate npmlog, I only see two (after npm ci, which should be all that's necessary to set up local dev):

$ npm ls -lp npmlog
${PWD}/node_modules/npmlog:npmlog@4.1.2:undefined
${PWD}/node_modules/fsevents/node_modules/npmlog:npmlog@4.1.2:undefined

The http fetch PUT 401 logs are coming from libnpmpublish's opts.log, which should default to npmlog's default export. Maybe...

Could it be pulse-til-done's interval interfering with the prompt? So when @lerna/prompt calls log.pause(), it should probably also call log.clearProgress() (and when it calls log.resume(), call log.showProgress())? The npm source seems to indicate this is necessary.

@rbuckton
Copy link
Contributor Author

@evocateur as I said, the issue was with how I had set up the local repo. I've since fixed my local repo and things work correctly.
This could become a problem in the future if npm is unable to dedupe npmlog due to version clashes with another package. It may be better to pass the logger via opts.log, which is something supported by libnpmpublish via npm-registry-fetch (https://github.com/npm/npm-registry-fetch/blob/latest/README.md#fetch-opts)

@evocateur
Copy link
Member

Okay, that's also something I was noodling about. I'm in the process of rebasing and fixing the lint errors, etc. Excited to merge!

@rbuckton
Copy link
Contributor Author

Do you have an idea as to when you might publish a new version with this feature?

@evocateur
Copy link
Member

evocateur commented May 14, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support 2FA --otp=123456
2 participants