Skip to content

Commit fdded8e

Browse files
author
Joost van der Waal
committed
fix: Added yarn npm publish otp check
1 parent abb4c5e commit fdded8e

1 file changed

Lines changed: 49 additions & 7 deletions

File tree

  • workspaces/packages/gitversion/src/plugins/embedded/node

workspaces/packages/gitversion/src/plugins/embedded/node/yarn.ts

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,19 @@ export class YarnBerryPlugin implements IPlugin, IPackManager {
6060
this.application.logger.reportDryrun(`Would be publishing ${packedPackage.packageName} using release tag ${releaseTag}`);
6161
return;
6262
} else {
63+
// Check if running in CI environment
64+
const isCI = process.env.CI === 'true' ||
65+
process.env.GITHUB_ACTIONS === 'true' ||
66+
process.env.GITLAB_CI === 'true' ||
67+
process.env.CIRCLECI === 'true' ||
68+
process.env.TRAVIS === 'true' ||
69+
process.env.JENKINS_URL !== undefined ||
70+
process.env.BUILDKITE === 'true';
71+
72+
if (isCI && !process.stdin.isTTY) {
73+
this.application.logger.reportInfo('Running in CI environment - ensuring non-interactive mode');
74+
}
75+
6376
const registry = npmConfigUtils.getPublishRegistry(yarnWorkspace.manifest, { configuration: this.yarnConfiguration });
6477
const gitHead = await npmPublishUtils.getGitHead(yarnWorkspace.cwd);
6578

@@ -74,13 +87,42 @@ export class YarnBerryPlugin implements IPlugin, IPackManager {
7487

7588
if (yarnWorkspace.manifest.name) {
7689
const url = npmHttpUtils.getIdentUrl(yarnWorkspace.manifest.name);
77-
await npmHttpUtils.put(url, body, {
78-
configuration: this.yarnConfiguration,
79-
registry,
80-
ident: yarnWorkspace.manifest.name,
81-
// otp: this.otp,
82-
jsonResponse: true,
83-
});
90+
91+
try {
92+
await npmHttpUtils.put(url, body, {
93+
configuration: this.yarnConfiguration,
94+
registry,
95+
ident: yarnWorkspace.manifest.name,
96+
// otp: this.otp,
97+
jsonResponse: true,
98+
});
99+
} catch (error) {
100+
// Check if error is related to OTP/2FA
101+
const errorMessage = error instanceof Error ? error.message : String(error);
102+
const errorString = JSON.stringify(error);
103+
104+
if (isCI && !process.stdin.isTTY &&
105+
(errorMessage.includes('one-time password') ||
106+
errorMessage.includes('OTP') ||
107+
errorMessage.includes('otpRequired') ||
108+
errorString.includes('EOTP'))) {
109+
throw new Error(
110+
'Publishing failed: npm registry is requesting a one-time password (OTP) in CI environment.\n' +
111+
'This typically happens when:\n' +
112+
' 1. Your npm account has 2FA enabled (good!)\n' +
113+
' 2. The NPM_AUTH_TOKEN is a "Classic" or "Publish" token that requires OTP\n' +
114+
'\n' +
115+
'To fix this:\n' +
116+
' 1. Log in to npmjs.com\n' +
117+
' 2. Go to Access Tokens → Generate New Token\n' +
118+
' 3. Select "Automation" token type (bypasses OTP for CI/CD)\n' +
119+
' 4. Update your NPM_AUTH_TOKEN secret with this new automation token\n' +
120+
'\n' +
121+
`Original error: ${errorMessage}`,
122+
);
123+
}
124+
throw error;
125+
}
84126
}
85127
}
86128
}

0 commit comments

Comments
 (0)