@anolilab/semantic-release-pnpm 3.0.0-alpha.2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/dist/index.js +109 -39
  3. package/package.json +6 -6
package/CHANGELOG.md CHANGED
@@ -1,3 +1,71 @@
1
+ ## @anolilab/semantic-release-pnpm [3.0.0](https://github.com/anolilab/semantic-release/compare/@anolilab/semantic-release-pnpm@2.0.5...@anolilab/semantic-release-pnpm@3.0.0) (2025-11-20)
2
+
3
+ ### ⚠ BREAKING CHANGES
4
+
5
+ * - node-versions: the minimum node version for the v24 range is now v24.10.0
6
+ - deps: a minimum of node v22.14 is now required
7
+
8
+ ### Features
9
+
10
+ * enhance npm authentication and trusted publishing support ([440d032](https://github.com/anolilab/semantic-release/commit/440d032f90c281da4640f07b991a963ba8cf5f5e))
11
+ * update dependencies in pnpm-lock.yaml and pnpm-workspace.yaml ([7e73992](https://github.com/anolilab/semantic-release/commit/7e739923afdd7deea2621d97feac2713ca63eccc))
12
+
13
+ ### Bug Fixes
14
+
15
+ * enhance integration and unit tests for npm authentication ([79ae50d](https://github.com/anolilab/semantic-release/commit/79ae50d47362159a426d31acc9432ba3ac31993e))
16
+ * update dependencies and configurations across multiple packages ([c37a51f](https://github.com/anolilab/semantic-release/commit/c37a51f53899c7088140d398867ed9ab7b291acf))
17
+ * update dependencies and node version across multiple packages ([cbfde4b](https://github.com/anolilab/semantic-release/commit/cbfde4b18e22a3994c70f145e9a9a6c71f4539c8))
18
+ * update package dependencies and configurations ([fed735c](https://github.com/anolilab/semantic-release/commit/fed735c729647a595d587eaa162d2c44ff9948f1))
19
+
20
+ ### Miscellaneous Chores
21
+
22
+ * add '@types/env-ci' dependency and refine type handling ([f897d6c](https://github.com/anolilab/semantic-release/commit/f897d6c26436790504bcb8ca98095e4ab3f2bd61))
23
+ * **release:** @anolilab/semantic-release-pnpm@3.0.0-alpha.1 [skip ci]\n\n## @anolilab/semantic-release-pnpm [3.0.0-alpha.1](https://github.com/anolilab/semantic-release/compare/@anolilab/semantic-release-pnpm@2.0.4...@anolilab/semantic-release-pnpm@3.0.0-alpha.1) (2025-10-14) ([9bb7063](https://github.com/anolilab/semantic-release/commit/9bb70635b0ae006601904268ae544fe26c710c72))
24
+ * **release:** @anolilab/semantic-release-pnpm@3.0.0-alpha.2 [skip ci]\n\n## @anolilab/semantic-release-pnpm [3.0.0-alpha.2](https://github.com/anolilab/semantic-release/compare/@anolilab/semantic-release-pnpm@3.0.0-alpha.1...@anolilab/semantic-release-pnpm@3.0.0-alpha.2) (2025-10-21) ([37b9d43](https://github.com/anolilab/semantic-release/commit/37b9d4395188554e200928de4347e8a092dc994d))
25
+ * **release:** @anolilab/semantic-release-pnpm@3.0.0-alpha.3 [skip ci]\n\n## @anolilab/semantic-release-pnpm [3.0.0-alpha.3](https://github.com/anolilab/semantic-release/compare/@anolilab/semantic-release-pnpm@3.0.0-alpha.2...@anolilab/semantic-release-pnpm@3.0.0-alpha.3) (2025-11-20) ([e475a24](https://github.com/anolilab/semantic-release/commit/e475a24dc1899e9dd55d3e05c0d25ddca045bdb2))
26
+ * update '@actions/core' dependency in semantic-release-pnpm ([50cc6e0](https://github.com/anolilab/semantic-release/commit/50cc6e09e2d1959acdcfc6475c1ecfbcb0fdb406))
27
+ * update '@actions/core' dependency to production in pnpm configuration ([bfec287](https://github.com/anolilab/semantic-release/commit/bfec287c74f048f41bcb0517353d3d4dede451a0))
28
+ * update Node.js version and refine dependencies in pnpm-workspace ([cbd6172](https://github.com/anolilab/semantic-release/commit/cbd617234ac6e5f5a14b70fbf6d6aec3bcd38fe0))
29
+
30
+ ### Code Refactoring
31
+
32
+ * clean up whitespace and comments in get-config.ts and verify-auth.ts ([26dc037](https://github.com/anolilab/semantic-release/commit/26dc037917f281f24d096d9790b671262f432b24))
33
+ * enhance inline plugin creator with consistent git root handling ([4ebaea4](https://github.com/anolilab/semantic-release/commit/4ebaea46d35bb89a0adcb4bf58c6df559e35f107))
34
+ * enhance type handling and logging in multi-semantic-release ([b6b34c2](https://github.com/anolilab/semantic-release/commit/b6b34c22fd835478f7009e3204a61abb953a9fb4))
35
+ * Ensure consistent cwd handling across all plugin hooks ([3028b71](https://github.com/anolilab/semantic-release/commit/3028b71f6f16244968bd6646b042ac893ffa5bb9))
36
+ * update test cases and improve type handling ([328c392](https://github.com/anolilab/semantic-release/commit/328c39278c609fd9169df79f3f48bbd8038d2e64))
37
+
38
+
39
+ ### Dependencies
40
+
41
+ * **@anolilab/rc:** upgraded to 3.0.0
42
+
43
+ ## @anolilab/semantic-release-pnpm [3.0.0-alpha.3](https://github.com/anolilab/semantic-release/compare/@anolilab/semantic-release-pnpm@3.0.0-alpha.2...@anolilab/semantic-release-pnpm@3.0.0-alpha.3) (2025-11-20)
44
+
45
+ ### Bug Fixes
46
+
47
+ * enhance integration and unit tests for npm authentication ([79ae50d](https://github.com/anolilab/semantic-release/commit/79ae50d47362159a426d31acc9432ba3ac31993e))
48
+ * update package dependencies and configurations ([fed735c](https://github.com/anolilab/semantic-release/commit/fed735c729647a595d587eaa162d2c44ff9948f1))
49
+
50
+ ### Miscellaneous Chores
51
+
52
+ * add '@types/env-ci' dependency and refine type handling ([f897d6c](https://github.com/anolilab/semantic-release/commit/f897d6c26436790504bcb8ca98095e4ab3f2bd61))
53
+ * update '@actions/core' dependency in semantic-release-pnpm ([50cc6e0](https://github.com/anolilab/semantic-release/commit/50cc6e09e2d1959acdcfc6475c1ecfbcb0fdb406))
54
+ * update '@actions/core' dependency to production in pnpm configuration ([bfec287](https://github.com/anolilab/semantic-release/commit/bfec287c74f048f41bcb0517353d3d4dede451a0))
55
+ * update Node.js version and refine dependencies in pnpm-workspace ([cbd6172](https://github.com/anolilab/semantic-release/commit/cbd617234ac6e5f5a14b70fbf6d6aec3bcd38fe0))
56
+
57
+ ### Code Refactoring
58
+
59
+ * clean up whitespace and comments in get-config.ts and verify-auth.ts ([26dc037](https://github.com/anolilab/semantic-release/commit/26dc037917f281f24d096d9790b671262f432b24))
60
+ * enhance inline plugin creator with consistent git root handling ([4ebaea4](https://github.com/anolilab/semantic-release/commit/4ebaea46d35bb89a0adcb4bf58c6df559e35f107))
61
+ * Ensure consistent cwd handling across all plugin hooks ([3028b71](https://github.com/anolilab/semantic-release/commit/3028b71f6f16244968bd6646b042ac893ffa5bb9))
62
+ * update test cases and improve type handling ([328c392](https://github.com/anolilab/semantic-release/commit/328c39278c609fd9169df79f3f48bbd8038d2e64))
63
+
64
+
65
+ ### Dependencies
66
+
67
+ * **@anolilab/rc:** upgraded to 3.0.0-alpha.3
68
+
1
69
  ## @anolilab/semantic-release-pnpm [3.0.0-alpha.2](https://github.com/anolilab/semantic-release/compare/@anolilab/semantic-release-pnpm@3.0.0-alpha.1...@anolilab/semantic-release-pnpm@3.0.0-alpha.2) (2025-10-21)
2
70
 
3
71
  ### Features
@@ -31,6 +99,17 @@
31
99
 
32
100
  * **@anolilab/rc:** upgraded to 3.0.0-alpha.1
33
101
 
102
+ ## @anolilab/semantic-release-pnpm [2.0.5](https://github.com/anolilab/semantic-release/compare/@anolilab/semantic-release-pnpm@2.0.4...@anolilab/semantic-release-pnpm@2.0.5) (2025-11-01)
103
+
104
+ ### Bug Fixes
105
+
106
+ * update package dependencies and configurations ([d94ebd8](https://github.com/anolilab/semantic-release/commit/d94ebd8869c34106aa0c11beb0f7410bbc86367f))
107
+
108
+
109
+ ### Dependencies
110
+
111
+ * **@anolilab/rc:** upgraded to 2.0.5
112
+
34
113
  ## @anolilab/semantic-release-pnpm [2.0.4](https://github.com/anolilab/semantic-release/compare/@anolilab/semantic-release-pnpm@2.0.3...@anolilab/semantic-release-pnpm@2.0.4) (2025-09-22)
35
114
 
36
115
  ### Bug Fixes
package/dist/index.js CHANGED
@@ -1,37 +1,34 @@
1
1
  import { createRequire as __cjs_createRequire } from "node:module";
2
+
2
3
  const __cjs_require = __cjs_createRequire(import.meta.url);
3
4
 
4
- // Runtime capability helpers
5
+ const __cjs_getProcess = typeof globalThis !== "undefined" && typeof globalThis.process !== "undefined" ? globalThis.process : process;
6
+
5
7
  const __cjs_getBuiltinModule = (module) => {
6
8
  // Check if we're in Node.js and version supports getBuiltinModule
7
- if ("object" !== "undefined" && process.versions?.node) {
8
- const [major, minor] = process.versions.node.split(".").map(Number);
9
+ if (typeof __cjs_getProcess !== "undefined" && __cjs_getProcess.versions && __cjs_getProcess.versions.node) {
10
+ const [major, minor] = __cjs_getProcess.versions.node.split(".").map(Number);
9
11
  // Node.js 20.16.0+ and 22.3.0+
10
12
  if (major > 22 || (major === 22 && minor >= 3) || (major === 20 && minor >= 16)) {
11
- return process.getBuiltinModule(module);
13
+ return __cjs_getProcess.getBuiltinModule(module);
12
14
  }
13
15
  }
14
16
  // Fallback to createRequire
15
17
  return __cjs_require(module);
16
18
  };
17
19
 
18
- const __cjs_getProcess = typeof globalThis !== "undefined" && typeof globalThis.process !== "undefined" ? globalThis.process : process;
19
20
  import { execa } from 'execa';
20
- const {
21
- validRange,
22
- gte
23
- } = __cjs_require("semver");
21
+ import { validRange, gte } from 'semver';
24
22
  import { isAccessibleSync, ensureFileSync, move, writeFile } from '@visulima/fs';
25
23
  import { resolve } from '@visulima/path';
26
24
  import { rc } from '@anolilab/rc';
27
25
  import normalizeUrl from 'normalize-url';
28
26
  import { findPackageJson, getPackageManagerVersion } from '@visulima/package';
29
27
  import SemanticReleaseError from '@semantic-release/error';
28
+ import { getIDToken } from '@actions/core';
30
29
  import envCi from 'env-ci';
31
- const {
32
- stringify
33
- } = __cjs_require("ini");
34
- const getAuthToken = __cjs_require("registry-auth-token");
30
+ import { stringify } from 'ini';
31
+ import getAuthToken from 'registry-auth-token';
35
32
  const {
36
33
  URL
37
34
  } = __cjs_getBuiltinModule("node:url");
@@ -114,9 +111,12 @@ const addChannel$1 = async (pluginConfig, packageJson, context) => {
114
111
  const distributionTag = getChannel(channel);
115
112
  logger.log(`Adding version ${version} to npm registry on dist-tag ${distributionTag}`);
116
113
  const npmrc = getNpmrcPath(cwd, env);
117
- const result = execa("pnpm", ["dist-tag", "add", `${packageJson.name}@${version}`, distributionTag, "--userconfig", npmrc, "--registry", registry], {
114
+ const result = execa("pnpm", ["dist-tag", "add", `${packageJson.name}@${version}`, distributionTag, "--registry", registry], {
118
115
  cwd,
119
- env,
116
+ env: {
117
+ ...env,
118
+ NPM_CONFIG_USERCONFIG: npmrc
119
+ },
120
120
  preferLocal: true
121
121
  });
122
122
  result.stdout.pipe(stdout, { end: false });
@@ -201,7 +201,7 @@ const publish$1 = async (pluginConfig, packageJson, context) => {
201
201
  return false;
202
202
  };
203
203
 
204
- const homepage = "https://github.com/anolilab/semantic-release/tree/main/packages/semantic-release-pnpm";
204
+ var homepage = "https://github.com/anolilab/semantic-release/tree/main/packages/semantic-release-pnpm";
205
205
  const packageJson = {
206
206
  homepage: homepage};
207
207
 
@@ -346,7 +346,6 @@ const exchangeGithubActionsToken = async (packageName, logger) => {
346
346
  let idToken;
347
347
  logger.log("Verifying OIDC context for publishing from GitHub Actions");
348
348
  try {
349
- const { getIDToken } = await import('@actions/core');
350
349
  idToken = await getIDToken("npm:registry.npmjs.org");
351
350
  } catch (error) {
352
351
  logger.log(`Retrieval of GitHub Actions OIDC token failed: ${error.message}`);
@@ -354,6 +353,8 @@ const exchangeGithubActionsToken = async (packageName, logger) => {
354
353
  return void 0;
355
354
  }
356
355
  if (!idToken) {
356
+ logger.log("NPM_ID_TOKEN environment variable is not set");
357
+ logger.log("Configure trusted publishing in your GitLab project settings and set the NPM_ID_TOKEN variable");
357
358
  return void 0;
358
359
  }
359
360
  return exchangeIdToken(idToken, packageName, logger);
@@ -367,7 +368,16 @@ const exchangeGitlabPipelinesToken = async (packageName, logger) => {
367
368
  return exchangeIdToken(idToken, packageName, logger);
368
369
  };
369
370
  const tokenExchange = (pkg, { logger }) => {
370
- const { name: ciProviderName } = envCi();
371
+ if (!pkg.name || typeof pkg.name !== "string" || pkg.name.trim() === "") {
372
+ logger.log("Invalid package name provided for OIDC token exchange");
373
+ return Promise.resolve(void 0);
374
+ }
375
+ const ciEnv = envCi();
376
+ const ciProviderName = typeof ciEnv === "object" && ciEnv !== null && typeof ciEnv.name === "string" ? ciEnv.name : void 0;
377
+ if (!ciProviderName) {
378
+ logger.log("Unable to detect CI provider for OIDC token exchange");
379
+ return Promise.resolve(void 0);
380
+ }
371
381
  if (GITHUB_ACTIONS_PROVIDER_NAME === ciProviderName) {
372
382
  return exchangeGithubActionsToken(pkg.name, logger);
373
383
  }
@@ -411,9 +421,12 @@ const setNpmrcAuth = async (npmrc, registry, { cwd, env: { NPM_CONFIG_USERCONFIG
411
421
  return;
412
422
  }
413
423
  if (NPM_USERNAME && NPM_PASSWORD && NPM_EMAIL) {
414
- await writeFile(npmrc, `${Object.keys(config).length > 0 ? `${stringify(config)}
415
- ` : ""}_auth = \${LEGACY_TOKEN}
416
- email = \${NPM_EMAIL}`);
424
+ await writeFile(
425
+ npmrc,
426
+ `${Object.keys(config).length > 0 ? `${stringify(config)}
427
+ ` : ""}${nerfDart(registry)}:_auth = \${LEGACY_TOKEN}
428
+ email = \${NPM_EMAIL}`
429
+ );
417
430
  logger.log(`Wrote NPM_USERNAME, NPM_PASSWORD, and NPM_EMAIL to ${npmrc}`);
418
431
  } else if (NPM_TOKEN) {
419
432
  await writeFile(npmrc, `${Object.keys(config).length > 0 ? `${stringify(config)}
@@ -425,20 +438,25 @@ email = \${NPM_EMAIL}`);
425
438
  }
426
439
  };
427
440
 
441
+ const isConnectionError = (error) => {
442
+ const errorMessage = error instanceof Error ? error.message : String(error);
443
+ const errorCode = error?.code || "";
444
+ const isTimedOut = error?.timedOut === true;
445
+ return isTimedOut || errorCode === "ECONNREFUSED" || errorCode === "ETIMEDOUT" || errorMessage.includes("ECONNREFUSED") || errorMessage.includes("ETIMEDOUT") || errorMessage.includes("getaddrinfo ENOTFOUND") || errorMessage.includes("timed out");
446
+ };
428
447
  const verifyAuthContextAgainstRegistry = async (npmrc, registry, context) => {
429
- const {
430
- cwd,
431
- env: { ...environment },
432
- logger,
433
- stderr,
434
- stdout
435
- } = context;
448
+ const { cwd, env, logger, stderr, stdout } = context;
436
449
  try {
437
450
  logger.log(`Running "pnpm whoami" to verify authentication on registry "${registry}"`);
438
- const whoamiResult = await execa("pnpm", ["whoami", "--userconfig", npmrc, "--registry", registry], {
451
+ const whoamiResult = await execa("pnpm", ["whoami", "--registry", registry], {
439
452
  cwd,
440
- env: environment,
441
- preferLocal: true
453
+ env: {
454
+ ...env,
455
+ NPM_CONFIG_USERCONFIG: npmrc
456
+ },
457
+ preferLocal: true,
458
+ timeout: 5e3
459
+ // 5 second timeout to prevent hanging when registry is unavailable
442
460
  });
443
461
  if (whoamiResult.stdout) {
444
462
  stdout.write(whoamiResult.stdout);
@@ -446,23 +464,75 @@ const verifyAuthContextAgainstRegistry = async (npmrc, registry, context) => {
446
464
  if (whoamiResult.stderr) {
447
465
  stderr.write(whoamiResult.stderr);
448
466
  }
449
- } catch {
467
+ } catch (error) {
468
+ if (isConnectionError(error)) {
469
+ const semanticError2 = getError("EINVALIDNPMAUTH", { registry });
470
+ throw new AggregateError([semanticError2], semanticError2.message);
471
+ }
450
472
  const semanticError = getError("EINVALIDNPMTOKEN", { registry });
451
473
  throw new AggregateError([semanticError], semanticError.message);
452
474
  }
453
475
  };
476
+ const isAuthErrorMessage = (message) => message.includes("requires you to be logged in") || message.includes("authentication") || message.includes("Unauthorized") || message.includes("401") || message.includes("403");
477
+ const handlePublishError = (error, registry) => {
478
+ if (error instanceof AggregateError) {
479
+ throw error;
480
+ }
481
+ const errorStderrRaw = error?.stderr;
482
+ const errorStderr = Array.isArray(errorStderrRaw) ? errorStderrRaw.join("\n") : errorStderrRaw || "";
483
+ const errorMessage = error instanceof Error ? error.message : String(error);
484
+ const combinedMessage = `${errorStderr} ${errorMessage}`;
485
+ if (isConnectionError(error)) {
486
+ const semanticError = getError("EINVALIDNPMAUTH", { registry });
487
+ throw new AggregateError([semanticError], semanticError.message);
488
+ }
489
+ if (isAuthErrorMessage(combinedMessage)) {
490
+ const semanticError = getError("EINVALIDNPMAUTH", { registry });
491
+ throw new AggregateError([semanticError], semanticError.message);
492
+ }
493
+ throw error;
494
+ };
495
+ const verifyAuthContextAgainstCustomRegistry = async (npmrc, registry, context, pkgRoot = ".") => {
496
+ const { cwd, env, logger, stderr, stdout } = context;
497
+ try {
498
+ logger.log(`Running "pnpm publish --dry-run" to verify authentication on registry "${registry}"`);
499
+ const publishArgs = ["publish", pkgRoot, "--dry-run", "--tag=semantic-release-auth-check", "--registry", registry];
500
+ const publishOptions = {
501
+ cwd,
502
+ env: {
503
+ ...env,
504
+ NPM_CONFIG_USERCONFIG: npmrc
505
+ },
506
+ preferLocal: true,
507
+ timeout: 5e3
508
+ // 5 second timeout to prevent hanging when registry is unavailable
509
+ };
510
+ const publishResult = await execa("pnpm", publishArgs, publishOptions);
511
+ const stdoutString = Array.isArray(publishResult.stdout) ? publishResult.stdout.join("\n") : publishResult.stdout || "";
512
+ const stderrString = Array.isArray(publishResult.stderr) ? publishResult.stderr.join("\n") : publishResult.stderr || "";
513
+ if (stdoutString) {
514
+ stdout.write(stdoutString);
515
+ }
516
+ if (stderrString) {
517
+ stderr.write(stderrString);
518
+ if (isAuthErrorMessage(stderrString)) {
519
+ const semanticError = getError("EINVALIDNPMAUTH", { registry });
520
+ throw new AggregateError([semanticError], semanticError.message);
521
+ }
522
+ }
523
+ } catch (error) {
524
+ handlePublishError(error, registry);
525
+ }
526
+ };
454
527
  const verifyAuth = async (npmrc, package_, context, pkgRoot) => {
455
528
  const registry = getRegistry(package_, context);
456
529
  if (package_.name && await oidcContext(registry, package_, context)) {
457
530
  return;
458
531
  }
459
532
  await setNpmrcAuth(npmrc, registry, context);
460
- const {
461
- env: { DEFAULT_NPM_REGISTRY = OFFICIAL_REGISTRY }
462
- } = context;
463
- if (normalizeUrl(registry) === normalizeUrl(DEFAULT_NPM_REGISTRY)) {
464
- await verifyAuthContextAgainstRegistry(npmrc, registry, context);
465
- }
533
+ const normalizedRegistry = normalizeUrl(registry);
534
+ const normalizedOfficialRegistry = normalizeUrl(OFFICIAL_REGISTRY);
535
+ await (normalizedRegistry === normalizedOfficialRegistry ? verifyAuthContextAgainstRegistry(npmrc, registry, context) : verifyAuthContextAgainstCustomRegistry(npmrc, registry, context, pkgRoot));
466
536
  };
467
537
 
468
538
  const isString = (value) => typeof value === "string";
@@ -521,7 +591,7 @@ const verify = async (pluginConfig, context) => {
521
591
  const packageJson = await getPackage(pluginConfig, context);
522
592
  if (shouldPublish(pluginConfig, packageJson)) {
523
593
  const npmrc = getNpmrcPath(context.cwd, context.env);
524
- await verifyAuth(npmrc, packageJson, context);
594
+ await verifyAuth(npmrc, packageJson, context, pluginConfig.pkgRoot);
525
595
  }
526
596
  } catch (error) {
527
597
  const typedError = error;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anolilab/semantic-release-pnpm",
3
- "version": "3.0.0-alpha.2",
3
+ "version": "3.0.0",
4
4
  "description": "Semantic-release plugin to publish a npm package with pnpm.",
5
5
  "keywords": [
6
6
  "anolilab",
@@ -47,14 +47,14 @@
47
47
  ],
48
48
  "dependencies": {
49
49
  "@actions/core": "^1.11.1",
50
- "@anolilab/rc": "3.0.0-alpha.2",
50
+ "@anolilab/rc": "3.0.0",
51
51
  "@semantic-release/error": "^4.0.0",
52
- "@visulima/fs": "^4.0.2",
53
- "@visulima/package": "^4.1.2",
54
- "@visulima/path": "^2.0.1",
52
+ "@visulima/fs": "^4.0.4",
53
+ "@visulima/package": "^4.1.4",
54
+ "@visulima/path": "^2.0.3",
55
55
  "env-ci": "^11.2.0",
56
56
  "execa": "^9.6.0",
57
- "ini": "^5.0.0",
57
+ "ini": "^6.0.0",
58
58
  "normalize-url": "^8.1.0",
59
59
  "registry-auth-token": "^5.1.0",
60
60
  "semver": "^7.7.3"