Skip to content

Commit 761d4db

Browse files
committed
Merge branch 'master' of github.com:semantic-release/npm into alpha
2 parents 197693e + a71fe44 commit 761d4db

File tree

4 files changed

+212
-6
lines changed

4 files changed

+212
-6
lines changed

package-lock.json

Lines changed: 116 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"lodash-es": "^4.17.21",
2727
"nerf-dart": "^1.0.0",
2828
"normalize-url": "^8.0.0",
29-
"npm": "^11.5.1",
29+
"npm": "^11.6.2",
3030
"rc": "^1.2.8",
3131
"read-pkg": "^9.0.0",
3232
"registry-auth-token": "^5.0.0",
@@ -47,10 +47,11 @@
4747
"semantic-release": "24.2.9",
4848
"sinon": "21.0.0",
4949
"stream-buffers": "3.0.3",
50-
"strip-ansi": "7.1.2"
50+
"strip-ansi": "7.1.2",
51+
"testdouble": "3.20.2"
5152
},
5253
"engines": {
53-
"node": "^22.14.0 || >= 24.2.0"
54+
"node": "^22.14.0 || >= 24.10.0"
5455
},
5556
"files": [
5657
"lib",

test/integration.test.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,26 @@ test("Throws error if NPM token is invalid", async (t) => {
111111
t.is(error.message, "Invalid npm authentication.");
112112
});
113113

114+
test("Throws error if NPM token is not provided", async (t) => {
115+
const cwd = temporaryDirectory();
116+
const env = { DEFAULT_NPM_REGISTRY: npmRegistry.url };
117+
const pkg = { name: "published", version: "1.0.0", publishConfig: { registry: npmRegistry.url } };
118+
await fs.outputJson(path.resolve(cwd, "package.json"), pkg);
119+
120+
const {
121+
errors: [error],
122+
} = await t.throwsAsync(
123+
t.context.m.verifyConditions(
124+
{},
125+
{ cwd, env, options: {}, stdout: t.context.stdout, stderr: t.context.stderr, logger: t.context.logger }
126+
)
127+
);
128+
129+
t.is(error.name, "SemanticReleaseError");
130+
t.is(error.code, "ENONPMTOKEN");
131+
t.is(error.message, "No npm token specified.");
132+
});
133+
114134
test("Skip Token validation if the registry configured is not the default one", async (t) => {
115135
const cwd = temporaryDirectory();
116136
const env = { NPM_TOKEN: "wrong_token" };

test/verify-auth.test.js

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import test from "ava";
2+
import * as td from "testdouble";
3+
4+
let execa, verifyAuth, getRegistry, setNpmrcAuth;
5+
const DEFAULT_NPM_REGISTRY = "https://registry.npmjs.org/";
6+
const npmrc = "npmrc contents";
7+
const pkg = {};
8+
const otherEnvVars = { foo: "bar" };
9+
const env = { DEFAULT_NPM_REGISTRY, ...otherEnvVars };
10+
const cwd = "./path/to/current/working/directory";
11+
const context = { env, cwd };
12+
13+
test.beforeEach(async (t) => {
14+
({ execa } = await td.replaceEsm("execa"));
15+
({ default: getRegistry } = await td.replaceEsm("../lib/get-registry.js"));
16+
({ default: setNpmrcAuth } = await td.replaceEsm("../lib/set-npmrc-auth.js"));
17+
18+
({ default: verifyAuth } = await import("../lib/verify-auth.js"));
19+
});
20+
21+
test.afterEach.always((t) => {
22+
td.reset();
23+
});
24+
25+
test.serial(
26+
"that the provided token is verified with `npm whoami` when trusted publishing is not established for the official registry",
27+
async (t) => {
28+
td.when(getRegistry(pkg, context)).thenReturn(DEFAULT_NPM_REGISTRY);
29+
td.when(
30+
execa("npm", ["whoami", "--userconfig", npmrc, "--registry", DEFAULT_NPM_REGISTRY], {
31+
cwd,
32+
env: otherEnvVars,
33+
preferLocal: true,
34+
})
35+
).thenReturn({
36+
stdout: { pipe: () => undefined },
37+
stderr: { pipe: () => undefined },
38+
});
39+
40+
await t.notThrowsAsync(verifyAuth(npmrc, pkg, context));
41+
}
42+
);
43+
44+
test.serial(
45+
"that the auth context for the official registry is considered invalid when no token is provided and trusted publishing is not established",
46+
async (t) => {
47+
td.when(getRegistry(pkg, context)).thenReturn(DEFAULT_NPM_REGISTRY);
48+
td.when(
49+
execa("npm", ["whoami", "--userconfig", npmrc, "--registry", DEFAULT_NPM_REGISTRY], {
50+
cwd,
51+
env: otherEnvVars,
52+
preferLocal: true,
53+
})
54+
).thenThrow(new Error());
55+
56+
const {
57+
errors: [error],
58+
} = await t.throwsAsync(verifyAuth(npmrc, pkg, context));
59+
60+
t.is(error.name, "SemanticReleaseError");
61+
t.is(error.code, "EINVALIDNPMTOKEN");
62+
t.is(error.message, "Invalid npm token.");
63+
}
64+
);
65+
66+
// since alternative registries are not consistent in implementing `npm whoami`,
67+
// we do not attempt to verify the provided token when publishing to them
68+
test.serial("that `npm whoami` is not invoked when publishing to a custom registry", async (t) => {
69+
td.when(getRegistry(pkg, context)).thenReturn("https://other.registry.org");
70+
71+
await t.notThrowsAsync(verifyAuth(npmrc, pkg, context));
72+
});

0 commit comments

Comments
 (0)