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

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 +37 -0
  2. package/dist/index.js +108 -38
  3. package/package.json +6 -6
package/CHANGELOG.md CHANGED
@@ -1,3 +1,29 @@
1
+ ## @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)
2
+
3
+ ### Bug Fixes
4
+
5
+ * enhance integration and unit tests for npm authentication ([79ae50d](https://github.com/anolilab/semantic-release/commit/79ae50d47362159a426d31acc9432ba3ac31993e))
6
+ * update package dependencies and configurations ([fed735c](https://github.com/anolilab/semantic-release/commit/fed735c729647a595d587eaa162d2c44ff9948f1))
7
+
8
+ ### Miscellaneous Chores
9
+
10
+ * add '@types/env-ci' dependency and refine type handling ([f897d6c](https://github.com/anolilab/semantic-release/commit/f897d6c26436790504bcb8ca98095e4ab3f2bd61))
11
+ * update '@actions/core' dependency in semantic-release-pnpm ([50cc6e0](https://github.com/anolilab/semantic-release/commit/50cc6e09e2d1959acdcfc6475c1ecfbcb0fdb406))
12
+ * update '@actions/core' dependency to production in pnpm configuration ([bfec287](https://github.com/anolilab/semantic-release/commit/bfec287c74f048f41bcb0517353d3d4dede451a0))
13
+ * update Node.js version and refine dependencies in pnpm-workspace ([cbd6172](https://github.com/anolilab/semantic-release/commit/cbd617234ac6e5f5a14b70fbf6d6aec3bcd38fe0))
14
+
15
+ ### Code Refactoring
16
+
17
+ * clean up whitespace and comments in get-config.ts and verify-auth.ts ([26dc037](https://github.com/anolilab/semantic-release/commit/26dc037917f281f24d096d9790b671262f432b24))
18
+ * enhance inline plugin creator with consistent git root handling ([4ebaea4](https://github.com/anolilab/semantic-release/commit/4ebaea46d35bb89a0adcb4bf58c6df559e35f107))
19
+ * Ensure consistent cwd handling across all plugin hooks ([3028b71](https://github.com/anolilab/semantic-release/commit/3028b71f6f16244968bd6646b042ac893ffa5bb9))
20
+ * update test cases and improve type handling ([328c392](https://github.com/anolilab/semantic-release/commit/328c39278c609fd9169df79f3f48bbd8038d2e64))
21
+
22
+
23
+ ### Dependencies
24
+
25
+ * **@anolilab/rc:** upgraded to 3.0.0-alpha.3
26
+
1
27
  ## @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
28
 
3
29
  ### Features
@@ -31,6 +57,17 @@
31
57
 
32
58
  * **@anolilab/rc:** upgraded to 3.0.0-alpha.1
33
59
 
60
+ ## @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)
61
+
62
+ ### Bug Fixes
63
+
64
+ * update package dependencies and configurations ([d94ebd8](https://github.com/anolilab/semantic-release/commit/d94ebd8869c34106aa0c11beb0f7410bbc86367f))
65
+
66
+
67
+ ### Dependencies
68
+
69
+ * **@anolilab/rc:** upgraded to 2.0.5
70
+
34
71
  ## @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
72
 
36
73
  ### Bug Fixes
package/dist/index.js CHANGED
@@ -1,26 +1,24 @@
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';
@@ -28,10 +26,8 @@ import normalizeUrl from 'normalize-url';
28
26
  import { findPackageJson, getPackageManagerVersion } from '@visulima/package';
29
27
  import SemanticReleaseError from '@semantic-release/error';
30
28
  import envCi from 'env-ci';
31
- const {
32
- stringify
33
- } = __cjs_require("ini");
34
- const getAuthToken = __cjs_require("registry-auth-token");
29
+ import { stringify } from 'ini';
30
+ import getAuthToken from 'registry-auth-token';
35
31
  const {
36
32
  URL
37
33
  } = __cjs_getBuiltinModule("node:url");
@@ -114,9 +110,12 @@ const addChannel$1 = async (pluginConfig, packageJson, context) => {
114
110
  const distributionTag = getChannel(channel);
115
111
  logger.log(`Adding version ${version} to npm registry on dist-tag ${distributionTag}`);
116
112
  const npmrc = getNpmrcPath(cwd, env);
117
- const result = execa("pnpm", ["dist-tag", "add", `${packageJson.name}@${version}`, distributionTag, "--userconfig", npmrc, "--registry", registry], {
113
+ const result = execa("pnpm", ["dist-tag", "add", `${packageJson.name}@${version}`, distributionTag, "--registry", registry], {
118
114
  cwd,
119
- env,
115
+ env: {
116
+ ...env,
117
+ NPM_CONFIG_USERCONFIG: npmrc
118
+ },
120
119
  preferLocal: true
121
120
  });
122
121
  result.stdout.pipe(stdout, { end: false });
@@ -201,7 +200,7 @@ const publish$1 = async (pluginConfig, packageJson, context) => {
201
200
  return false;
202
201
  };
203
202
 
204
- const homepage = "https://github.com/anolilab/semantic-release/tree/main/packages/semantic-release-pnpm";
203
+ var homepage = "https://github.com/anolilab/semantic-release/tree/main/packages/semantic-release-pnpm";
205
204
  const packageJson = {
206
205
  homepage: homepage};
207
206
 
@@ -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-alpha.3",
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-alpha.3",
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"