np
np copied to clipboard
Support GPG password prompt
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)
-
issuehunt ($60.00)
Submitted pull Requests
Become a backer now!
Or submit a pull request to get the deposits!
Tips
- Checkout the Issuehunt explorer to discover more funded issues.
- Need some help from other developers? Add your repositories on IssueHunt to raise funds.
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.
- Submit pull request via IssueHunt to receive this reward.
- Want to contribute? Chip in to this issue via IssueHunt.
- Checkout the IssueHunt Issue Explorer to see more funded issues.
- Need help from developers? Add your repository on IssueHunt to raise funds.
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:
- set a suspend flag for the listr-tasks
- suspend the update-log, if suspend-flag for this task is active
- 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