Skip to content

Commit

Permalink
Merge pull request #1878 from intuit/npm-token-errors
Browse files Browse the repository at this point in the history
better error message for no NPM_token in CI
  • Loading branch information
hipstersmoothie authored Mar 15, 2021
2 parents eaf28cb + 614945d commit 26354a7
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 10 deletions.
8 changes: 7 additions & 1 deletion packages/core/src/utils/exec-promise.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,13 @@ export default async function execPromise(
} else {
// Tools can occasionally print to stderr but not fail, so print that just in case.
if (allStderr.length) {
log.log.warn(allStderr);
if (allStderr.includes("Failed to replace env in config")) {
const error = new Error(allStderr);
error.stack = (error.stack || "") + callSite;
reject(error);
} else {
log.log.warn(allStderr);
}
}

// Resolve the string of the whole stdout
Expand Down
2 changes: 2 additions & 0 deletions plugins/npm/__tests__/npm-next.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ describe("next", () => {
},
]);
execPromise.mockResolvedValueOnce("");
execPromise.mockResolvedValueOnce("");
execPromise.mockResolvedValueOnce("1.2.4-next.0");

plugin.apply(({
Expand Down Expand Up @@ -330,6 +331,7 @@ describe("next", () => {
]);
// isMonorepo
execPromise.mockResolvedValueOnce("");
execPromise.mockResolvedValueOnce("");
execPromise.mockResolvedValueOnce("1.2.4-next.0");

plugin.apply(({
Expand Down
13 changes: 7 additions & 6 deletions plugins/npm/__tests__/npm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,7 @@ describe("canary", () => {
canaryIdentifier: "canary.123.1",
});
expect(execPromise.mock.calls[1]).toContain("npm");
expect(execPromise.mock.calls[1][1]).toContain("1.2.4-canary.123.1.0");
expect(execPromise.mock.calls[2][1]).toContain("1.2.4-canary.123.1.0");
});

test("prints canary version in dry run", async () => {
Expand Down Expand Up @@ -924,15 +924,16 @@ describe("canary", () => {

// first version exists
execPromise.mockReturnValueOnce(true);
execPromise.mockReturnValueOnce(true);
// second doesn't
execPromise.mockReturnValueOnce(false);

await hooks.canary.promise({
bump: Auto.SEMVER.patch,
canaryIdentifier: "canary.123.1",
});
expect(execPromise.mock.calls[2]).toContain("npm");
expect(execPromise.mock.calls[2][1]).toContain("1.2.4-canary.123.1.1");
expect(execPromise.mock.calls[3]).toContain("npm");
expect(execPromise.mock.calls[3][1]).toContain("1.2.4-canary.123.1.1");
});

test("legacy auth work", async () => {
Expand Down Expand Up @@ -1000,8 +1001,8 @@ describe("canary", () => {
bump: Auto.SEMVER.patch,
canaryIdentifier: "canary.123.1",
});
expect(execPromise.mock.calls[1]).toContain("npm");
expect(execPromise.mock.calls[1][1]).toContain("1.2.4-canary.123.1.0");
expect(execPromise.mock.calls[2]).toContain("npm");
expect(execPromise.mock.calls[2][1]).toContain("1.2.4-canary.123.1.0");
});

test("use lerna for monorepo package", async () => {
Expand Down Expand Up @@ -1040,7 +1041,7 @@ describe("canary", () => {
bump: Auto.SEMVER.patch,
canaryIdentifier: "",
});
expect(execPromise.mock.calls[1][1]).toContain("lerna");
expect(execPromise.mock.calls[2][1]).toContain("lerna");
// @ts-ignore
expect(value.newVersion).toBe("1.2.3-canary.0");
});
Expand Down
1 change: 1 addition & 0 deletions plugins/npm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"@auto-it/core": "link:../../packages/core",
"@auto-it/package-json-utils": "link:../../packages/package-json-utils",
"await-to-js": "^2.1.1",
"endent": "^2.0.1",
"env-ci": "^5.0.1",
"fp-ts": "^2.5.3",
"get-monorepo-packages": "^1.1.0",
Expand Down
34 changes: 31 additions & 3 deletions plugins/npm/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import envCi from "env-ci";
import * as fs from "fs";
import path from "path";
import endent from "endent";
import { Memoize as memoize } from "typescript-memoize";
import { RestEndpointMethodTypes } from "@octokit/rest";
import * as t from "io-ts";
Expand Down Expand Up @@ -983,7 +984,7 @@ export default class NPMPlugin implements IPlugin {
this.name,
async ({ bump, canaryIdentifier, dryRun, quiet }) => {
if (this.setRcToken) {
await setTokenOnCI(auto.logger);
await this.setTokenOnCI(auto);
auto.logger.verbose.info("Set CI NPM_TOKEN");
}

Expand Down Expand Up @@ -1181,7 +1182,7 @@ export default class NPMPlugin implements IPlugin {
this.name,
async (preReleaseVersions, { bump, dryRun }) => {
if (this.setRcToken) {
await setTokenOnCI(auto.logger);
await this.setTokenOnCI(auto);
auto.logger.verbose.info("Set CI NPM_TOKEN");
}

Expand Down Expand Up @@ -1360,7 +1361,7 @@ export default class NPMPlugin implements IPlugin {
}

if (this.setRcToken) {
await setTokenOnCI(auto.logger);
await this.setTokenOnCI(auto);
auto.logger.verbose.info("Set CI NPM_TOKEN");
}

Expand Down Expand Up @@ -1495,4 +1496,31 @@ export default class NPMPlugin implements IPlugin {
}
});
}

/** The the NPM token */
private async setTokenOnCI(auto: Auto) {
try {
await setTokenOnCI(auto.logger);
// This will make NPM actually check if the npmrc is valid for the env
await execPromise("npm", ["root"]);
} catch (error) {
if (
// eslint-disable-next-line no-template-curly-in-string
error.message?.includes("Failed to replace env in config: ${NPM_TOKEN}")
) {
auto.logger.log.error(endent`
Uh oh! It looks like you don\'t have a NPM_TOKEN available in your environment.
To fix:
- Ensure you've added a NPM_TOKEN environment variable
- Ensure that it's exposed to your CI step
`);
auto.logger.verbose.error(error);
process.exit(1);
} else {
throw error;
}
}
}
}

0 comments on commit 26354a7

Please sign in to comment.