Np: Support GPG password prompt

Created on 9 Aug 2016  ยท  15Comments  ยท  Source: sindresorhus/np


Issuehunt badges

I'm trying to publish this package using np major, but it hangs on the "Bumping version" step. When I exit the process and run git log I see that it has created a commit for v1.0.0, but it hasn't created a tag, so it seems to fail on the tagging part. I'm using git v2.7.0 and Node v6.3.1.

$ np major
 โœ” Prerequisite check
 โœ” Git
 โœ” Cleanup
 โœ” Installing dependencies
 โœ” Running tests
 โœ” Prerequisite check
 โœ” Git
 โœ” Cleanup
 โœ” Installing dependencies
 โœ” Running tests
 โ ฆ Bumping version
   โ†’ v1.0.0
   Publishing package
   Pushing tags

Is there a debug/verbose flag that I can set to get more detailed output? Could the precommit hook I have in place (through husky) have something to do with it?

For now I have tagged and published my package manually.




IssueHunt Summary

Backers (Total: $60.00)

- #448 solution for issue #79 gpg-password-prompt

Become a backer now!

Or submit a pull request to get the deposits!

Tips

IssueHunt has been backed by the following sponsors. Become a sponsor


Funded on Issuehunt bug help wanted

Most helpful comment

@silvenon Got the same issue and blind typing on Bumping version did the trick ๐Ÿ˜„

All 15 comments

I suspect it's something with the precommit hook. The "Bumping version" step just calls npm version major which handles all that. We don't have any verbose flag, but that could definitely be useful.

Right, I tried npm version patch. I have npm configured to use GPG commit signing, so it asks me to enter my password. np does not allow me to provide that password, therefore it hangs waiting for stdin. I'll try to replace the secret key to not require a password.

You need a passphrase to unlock the secret key for
user: "******"
2048-bit RSA key, ID ******, created 2015-07-20

Yeah, we should support entering GPG password. I don't have GPG set up, so I won't be able to do it, but pull request welcome :)

Okay, I'm willing to look into it. Looks like this is a listr or execa thing.

After some fiddling, here's what I came up with:

task: () => new Observable(observer => {
    const child = execa('npm', ['version', 'patch', '--force']);
    let data = '';
    child.stdout.on('data', chunk => {
        data += chunk.toString();
        observer.next(data);
    });
    child.stdout.on('close', () => {
        observer.complete();
    })
    process.stdin.setRawMode(true);
    process.stdin.pipe(child.stdin);
    setTimeout(observer.complete, 10000); // in case the child never exits
})

While I tested this to work with a simple node script that prompts for a password and exits on newline, it doesn't work with npm version. For some reason npm version only sends the bumped version number to stdout, not the password prompt. The password prompt only appears in my shell after the parent process finished.

Update: After investigating npm version, it seems the chain method they use gobbles up the stdout. If I wrap my node script in a chain, the script itself still works normally when called directly, but fails to output data when I call it with execa (child.stdout.on('data', () => { ... }) is never invoked).

Here's what works when I use my node script wrapped in a chain (like npm version):

task: () => new Observable(observer => {
    const child = spawn('node', ['password'], { stdio: [process.stdin, 'pipe', 'pipe'] });
    const timeout = setTimeout(() => {
        child.kill();
        observer.error('Error: Task timed out');
    }, 60000);

    let data = '';
    child.stdout.on('data', chunk => {
        data += chunk.toString();
        observer.next(data);
    });
    child.stderr.on('data', chunk => {
        clearTimeout(timeout);
        child.kill();
        observer.error(chunk.toString());
    });
    child.on('close', () => {
        clearTimeout(timeout);
        child.kill();
        observer.complete();
    });
})

Unfortunately this doesn't work with npm version because it sends the GPG prompt via stderr instead of stdout. Also it is limited to only one line because that's all Listr supports. I'm kind of out of ideas other than dropping Listr or forking it to add support for this kind of thing, but that seems a bit drastic.

Another idea is to just recommend people use a GPG GUI password prompt.

@SamVerschueren Maybe Listr could have a method to make the child-process output fullscreen and replace the list temporarily? Might be overkill, but I could see other tools wanting prompts of some kind.

I totally missed this issue. But since today, Listr supports custom renderers and even 3rd party renderers. The default renderer for example is extracted to a separate package listr-update-renderer. So it should be possible to do something like this without messing with the internals of Listr.

Just typing in the password works! In case that wasn't known.

@silvenon Got the same issue and blind typing on Bumping version did the trick ๐Ÿ˜„

It worked for me too, but it would be nice if np was explicitly asking a passphrase. Do you think it would be easy to detect commit signing and do so?

In case someone wants to tackle this, I created listr-input which we use for the one-time password of npm. Should be doable with that one I guess.

@issuehunt has funded $60.00 to this issue.


I start working on this issue. I actually had the same issue
with using pinentry-curses or pinentry-tty as the pinentry-program.
The cause was the listr-update-renderer, which overwrites the output of the pinentry-program.

My solution would look like:

  1. set a suspend flag for the listr-tasks
  2. suspend the update-log, if suspend-flag for this task is active
  3. if the task is completed, activate the listr-update-renderer again

Another idea is to just recommend people use a GPG GUI password prompt.

Per this, using a GUI password prompt works fine. On my macOS machine, I installed brew install pinentry-mac, and configured it with GPG by adding to ~/.gnupg/gpg-agent.conf

pinentry-program /usr/local/bin/pinentry-mac
Was this page helpful?
0 / 5 - 0 ratings

Related issues

janpio picture janpio  ยท  6Comments

fregante picture fregante  ยท  5Comments

mikehardy picture mikehardy  ยท  6Comments

bennycode picture bennycode  ยท  4Comments

doug-wade picture doug-wade  ยท  5Comments