@anolilab/semantic-release-pnpm 3.2.0 → 3.2.1

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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## @anolilab/semantic-release-pnpm [3.2.1](https://github.com/anolilab/semantic-release/compare/@anolilab/semantic-release-pnpm@3.2.0...@anolilab/semantic-release-pnpm@3.2.1) (2025-12-05)
2
+
3
+ ### Bug Fixes
4
+
5
+ * implement caching for whoami results in verifyAuth ([e8a482f](https://github.com/anolilab/semantic-release/commit/e8a482fec317dc829f9a373804b99110abafd1b2))
6
+
1
7
  ## @anolilab/semantic-release-pnpm [3.2.0](https://github.com/anolilab/semantic-release/compare/@anolilab/semantic-release-pnpm@3.1.0...@anolilab/semantic-release-pnpm@3.2.0) (2025-12-04)
2
8
 
3
9
  ### Bug Fixes
package/README.md CHANGED
@@ -76,6 +76,7 @@ When publishing to the [official registry](https://registry.npmjs.org/), it is r
76
76
 
77
77
  > [!IMPORTANT]
78
78
  > **First-time releases with OIDC**: npm requires a package to exist before you can configure OIDC trusted publishing. If you're releasing a package for the first time with OIDC, you have two options:
79
+ >
79
80
  > 1. Publish a dummy version manually first (e.g., `pnpm publish --tag dummy`), then configure OIDC trusted publishing, and then use semantic-release for subsequent releases.
80
81
  > 2. Use the [`setup-npm-trusted-publish`](https://github.com/azu/setup-npm-trusted-publish) tool to automatically create and publish a placeholder package for OIDC setup purposes.
81
82
  >
package/dist/index.js CHANGED
@@ -26,10 +26,10 @@ import { rc } from '@anolilab/rc';
26
26
  import normalizeUrl from 'normalize-url';
27
27
  import { findPackageJson, getPackageManagerVersion } from '@visulima/package';
28
28
  import SemanticReleaseError from '@semantic-release/error';
29
+ import getAuthToken from 'registry-auth-token';
29
30
  import { getIDToken } from '@actions/core';
30
31
  import envCi from 'env-ci';
31
32
  import { stringify } from 'ini';
32
- import getAuthToken from 'registry-auth-token';
33
33
  const {
34
34
  URL
35
35
  } = __cjs_getBuiltinModule("node:url");
@@ -502,6 +502,34 @@ email = \${NPM_EMAIL}`
502
502
  };
503
503
 
504
504
  const debug$2 = dbg("semantic-release-pnpm:verify-auth");
505
+ const whoamiCache = /* @__PURE__ */ new Map();
506
+ const getCacheKey = (registry, context) => {
507
+ const normalizedRegistry = normalizeUrl(registry);
508
+ const {
509
+ env: { NPM_PASSWORD, NPM_TOKEN, NPM_USERNAME }
510
+ } = context;
511
+ if (NPM_TOKEN) {
512
+ const tokenId = NPM_TOKEN.length > 12 ? `${NPM_TOKEN.slice(0, 8)}...${NPM_TOKEN.slice(-4)}` : NPM_TOKEN.slice(0, 8);
513
+ return `${normalizedRegistry}:token:${tokenId}`;
514
+ }
515
+ if (NPM_USERNAME && NPM_PASSWORD) {
516
+ return `${normalizedRegistry}:user:${NPM_USERNAME}`;
517
+ }
518
+ try {
519
+ const { config } = rc("npm", {
520
+ config: context.env.NPM_CONFIG_USERCONFIG ?? resolve(context.cwd, ".npmrc"),
521
+ cwd: context.cwd,
522
+ defaults: { registry: OFFICIAL_REGISTRY }
523
+ });
524
+ const token = getAuthToken(registry, { npmrc: config });
525
+ if (token) {
526
+ const tokenId = token.length > 12 ? `${token.slice(0, 8)}...${token.slice(-4)}` : token.slice(0, 8);
527
+ return `${normalizedRegistry}:token:${tokenId}`;
528
+ }
529
+ } catch {
530
+ }
531
+ return `${normalizedRegistry}:default`;
532
+ };
505
533
  const isConnectionError = (error) => {
506
534
  const errorMessage = error instanceof Error ? error.message : String(error);
507
535
  const errorCode = error?.code || "";
@@ -509,32 +537,55 @@ const isConnectionError = (error) => {
509
537
  return isTimedOut || errorCode === "ECONNREFUSED" || errorCode === "ETIMEDOUT" || errorMessage.includes("ECONNREFUSED") || errorMessage.includes("ETIMEDOUT") || errorMessage.includes("getaddrinfo ENOTFOUND") || errorMessage.includes("timed out");
510
538
  };
511
539
  const verifyAuthContextAgainstRegistry = async (npmrc, registry, context) => {
512
- const { cwd, env, logger, stderr, stdout } = context;
513
- try {
514
- logger.log(`Running "pnpm whoami" to verify authentication on registry "${registry}"`);
515
- const whoamiResult = await execa("pnpm", ["whoami", "--registry", registry], {
516
- cwd,
517
- env: {
518
- ...env,
519
- NPM_CONFIG_USERCONFIG: npmrc
520
- },
521
- preferLocal: true,
522
- timeout: 5e3
523
- // 5 second timeout to prevent hanging when registry is unavailable
524
- });
525
- if (whoamiResult.stdout) {
526
- stdout.write(whoamiResult.stdout);
540
+ const cacheKey = getCacheKey(registry, context);
541
+ if (whoamiCache.has(cacheKey)) {
542
+ debug$2(`Using cached whoami result for registry "${registry}"`);
543
+ const cachedResult = whoamiCache.get(cacheKey);
544
+ try {
545
+ await cachedResult;
546
+ return;
547
+ } catch {
548
+ debug$2(`Cached whoami result failed, retrying for registry "${registry}"`);
549
+ whoamiCache.delete(cacheKey);
527
550
  }
528
- if (whoamiResult.stderr) {
529
- stderr.write(whoamiResult.stderr);
551
+ }
552
+ const verificationPromise = (async () => {
553
+ const { cwd, env, logger, stderr, stdout } = context;
554
+ try {
555
+ logger.log(`Running "pnpm whoami" to verify authentication on registry "${registry}"`);
556
+ const whoamiResult = await execa("pnpm", ["whoami", "--registry", registry], {
557
+ cwd,
558
+ env: {
559
+ ...env,
560
+ NPM_CONFIG_USERCONFIG: npmrc
561
+ },
562
+ preferLocal: true,
563
+ timeout: 5e3
564
+ // 5 second timeout to prevent hanging when registry is unavailable
565
+ });
566
+ if (whoamiResult.stdout) {
567
+ stdout.write(whoamiResult.stdout);
568
+ }
569
+ if (whoamiResult.stderr) {
570
+ stderr.write(whoamiResult.stderr);
571
+ }
572
+ } catch (error) {
573
+ if (isConnectionError(error)) {
574
+ const semanticError2 = getError("EINVALIDNPMAUTH", { registry });
575
+ throw new AggregateError([semanticError2], semanticError2.message);
576
+ }
577
+ const semanticError = getError("EINVALIDNPMTOKEN", { registry });
578
+ throw new AggregateError([semanticError], semanticError.message);
530
579
  }
580
+ })();
581
+ whoamiCache.set(cacheKey, verificationPromise);
582
+ try {
583
+ await verificationPromise;
531
584
  } catch (error) {
532
585
  if (isConnectionError(error)) {
533
- const semanticError2 = getError("EINVALIDNPMAUTH", { registry });
534
- throw new AggregateError([semanticError2], semanticError2.message);
586
+ whoamiCache.delete(cacheKey);
535
587
  }
536
- const semanticError = getError("EINVALIDNPMTOKEN", { registry });
537
- throw new AggregateError([semanticError], semanticError.message);
588
+ throw error;
538
589
  }
539
590
  };
540
591
  const isAuthErrorMessage = (message) => message.includes("requires you to be logged in") || message.includes("authentication") || message.includes("Unauthorized") || message.includes("401") || message.includes("403");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anolilab/semantic-release-pnpm",
3
- "version": "3.2.0",
3
+ "version": "3.2.1",
4
4
  "description": "Semantic-release plugin to publish a npm package with pnpm.",
5
5
  "keywords": [
6
6
  "anolilab",