Skip to content

Commit 02f60c7

Browse files
authored
Fix publish OTP for Yarn Berry (#741)
1 parent af1a048 commit 02f60c7

File tree

4 files changed

+31
-6
lines changed

4 files changed

+31
-6
lines changed

source/index.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {asyncExitHook} from 'exit-hook';
1414
import logSymbols from 'log-symbols';
1515
import prerequisiteTasks from './prerequisite-tasks.js';
1616
import gitTasks from './git-tasks.js';
17-
import {getPackagePublishArguments} from './npm/publish.js';
17+
import {getPackagePublishArguments, runPublish} from './npm/publish.js';
1818
import enable2fa, {getEnable2faArguments} from './npm/enable-2fa.js';
1919
import handleNpmError from './npm/handle-npm-error.js';
2020
import releaseTaskHelper from './release-task-helper.js';
@@ -179,12 +179,12 @@ const np = async (input = 'patch', {packageManager, ...options}, {package_, root
179179
task(context, task) {
180180
let hasError = false;
181181

182-
return from(execa(...getPublishCommand(options)))
182+
return from(runPublish(getPublishCommand(options)))
183183
.pipe(
184184
catchError(error => handleNpmError(error, task, otp => {
185185
context.otp = otp;
186186

187-
return execa(...getPublishCommand({...options, otp}));
187+
return runPublish(getPublishCommand({...options, otp}));
188188
})),
189189
)
190190
.pipe(

source/npm/handle-npm-error.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ const handleNpmError = (error, task, message, executor) => {
99
}
1010

1111
// `one-time pass` is for npm and `Two factor authentication` is for Yarn.
12-
if (error.stderr.includes('one-time pass') || error.stdout.includes('Two factor authentication')) {
12+
if (
13+
error.stderr.includes('one-time pass') // Npm
14+
|| error.stdout.includes('Two factor authentication') // Yarn v1
15+
|| error.stdout.includes('One-time password:') // Yarn berry
16+
) {
1317
const {title} = task;
1418
task.title = `${title} ${chalk.yellow('(waiting for input…)')}`;
1519

source/npm/publish.js

+15
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import {execa} from 'execa';
2+
13
export const getPackagePublishArguments = options => {
24
const arguments_ = ['publish'];
35

@@ -19,3 +21,16 @@ export const getPackagePublishArguments = options => {
1921

2022
return arguments_;
2123
};
24+
25+
export function runPublish(arguments_) {
26+
const cp = execa(...arguments_);
27+
28+
cp.stdout.on('data', chunk => {
29+
// https://github.com/yarnpkg/berry/blob/a3e5695186f2aec3a68810acafc6c9b1e45191da/packages/plugin-npm/sources/npmHttpUtils.ts#L541
30+
if (chunk.toString('utf8').includes('One-time password:')) {
31+
cp.kill();
32+
}
33+
});
34+
35+
return cp;
36+
}

test/index.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,10 @@ test('skip enabling 2FA if the package exists', async t => {
6262
verifyWorkingTreeIsClean: sinon.stub(),
6363
},
6464
'../source/npm/enable-2fa.js': enable2faStub,
65-
'../source/npm/publish.js': sinon.stub().returns({pipe: sinon.stub()}),
65+
'../source/npm/publish.js': {
66+
getPackagePublishArguments: sinon.stub().returns([]),
67+
runPublish: sinon.stub().returns(fakeExecaReturn()),
68+
},
6669
});
6770

6871
await t.notThrowsAsync(npMock('1.0.0', {
@@ -91,7 +94,10 @@ test('skip enabling 2FA if the `2fa` option is false', async t => {
9194
verifyWorkingTreeIsClean: sinon.stub(),
9295
},
9396
'../source/npm/enable-2fa.js': enable2faStub,
94-
'../source/npm/publish.js': sinon.stub().returns({pipe: sinon.stub()}),
97+
'../source/npm/publish.js': {
98+
getPackagePublishArguments: sinon.stub().returns([]),
99+
runPublish: sinon.stub().returns(fakeExecaReturn()),
100+
},
95101
});
96102

97103
await t.notThrowsAsync(npMock('1.0.0', {

0 commit comments

Comments
 (0)