Skip to content

ci: add setup-node for npm OIDC trusted publishing#6

Merged
rhuanbarreto merged 1 commit intomainfrom
fix/npm-oidc-setup-node
Feb 23, 2026
Merged

ci: add setup-node for npm OIDC trusted publishing#6
rhuanbarreto merged 1 commit intomainfrom
fix/npm-oidc-setup-node

Conversation

@rhuanbarreto
Copy link
Copy Markdown
Contributor

Summary

  • Adds actions/setup-node@v4 with registry-url: 'https://registry.npmjs.org' to the release job, immediately before the simple-release-action publish step
  • Without this step, npm has no .npmrc configured and cannot exchange the GitHub OIDC token for a publish token, causing ENEEDAUTH
  • id-token: write was already set; this was the only missing piece for trusted publishing to work

Test plan

  • Merge into main and verify the release workflow completes without ENEEDAUTH

🤖 Generated with Claude Code

actions/setup-node with registry-url is required to configure .npmrc
so that npm CLI can exchange the GitHub OIDC token for a publish token.
Without it, npm has no auth config and fails with ENEEDAUTH.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@rhuanbarreto rhuanbarreto merged commit f398d3e into main Feb 23, 2026
1 check failed
rhuanbarreto added a commit that referenced this pull request Feb 28, 2026
actions/setup-node with registry-url is required to configure .npmrc
so that npm CLI can exchange the GitHub OIDC token for a publish token.
Without it, npm has no auth config and fails with ENEEDAUTH.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
rhuanbarreto added a commit that referenced this pull request Mar 3, 2026
actions/setup-node with registry-url is required to configure .npmrc
so that npm CLI can exchange the GitHub OIDC token for a publish token.
Without it, npm has no auth config and fails with ENEEDAUTH.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
rhuanbarreto added a commit that referenced this pull request Mar 4, 2026
actions/setup-node with registry-url is required to configure .npmrc
so that npm CLI can exchange the GitHub OIDC token for a publish token.
Without it, npm has no auth config and fails with ENEEDAUTH.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
rhuanbarreto added a commit that referenced this pull request Apr 16, 2026
On Windows (and anywhere the runtime honours timer handles), every
command that exits naturally through `main()` returning — i.e. every
command except `check` and `upgrade` — used to linger ~3 seconds
after its output appeared. Root causes + fixes below.

## Timer leaks (Phase 1)

`flushTelemetry`, `gitCredentialFill`, the WSL fallback in
`resolveCommand`, and the per-rule timeout in the check runner all
race a spawn/shutdown against a `setTimeout`/`Bun.sleep` that's
never cancelled when the race winner resolves. The stray timer
keeps the event loop alive for its full duration. Each site now
captures the timer id and clears it in a `.finally`.

`flushSentry` wraps `Sentry.flush` with the same cancellable race
pattern as defence-in-depth against leaks inside the SDK.

`main()` now finishes with an explicit `process.exit(0)` after
flushes complete so a future leaked handle in a third-party SDK
can't regress this class of bug.

## Lazy SDK loading (Phase 2 #6)

`posthog-node` and `@sentry/node-core/light` are now loaded via
dynamic `import()` inside `initTelemetry` / `initSentry`. The
`ARCHGATE_TELEMETRY=0` path skips the parse and init cost entirely.
Both inits run concurrently via `Promise.all` in `cli.ts`.

## Startup trimming (Phase 2)

- `installGit` short-circuits on `Bun.which("git")` before falling
  back to the async cross-env resolver (avoids a WSL subprocess on
  Windows in the 99% happy path).
- `getRepoContext` now fires all four git probes in parallel
  instead of gating on `rev-parse --is-inside-work-tree`, saving
  one serial spawn on git repos.

## Check hot path (Phase 3)

- `getGitTrackedFiles` is cached per project root — `resolveScopedFiles`
  used to spawn `git ls-files` once per ADR (16 spawns in this repo).
- `ensureRulesShim` compares existing `rules.d.ts` content and skips
  the write when unchanged.
- New `parseAllAdrs(projectRoot)` caches the readdir + parse of every
  ADR once per process. `loadRuleAdrs`, `loadAllAdrs` (in context.ts),
  and `adr list` now share that cache, so `review-context --run-checks`
  no longer reads the ADR directory twice.
- `adr list` uses the shared cache — one readdir instead of two.
- `buildSummary` is built once in `check.ts` and passed into every
  reporter + `getExitCode` instead of being recomputed three times.

## Telemetry payload (Phase 4)

- `getCommonProperties` now splits into a cached "static" snapshot
  (platform, install method, CI, locale) and a fresh "dynamic"
  overlay (project context, repo snapshot). Cuts redundant
  `getPlatformInfo` / `detectInstallMethod` / `Intl.DateTimeFormat`
  calls when multiple events are emitted per command.
- The opportunistic update check at startup now uses a 5s fetch
  timeout (down from 15s) so a slow network never extends exit
  time. The explicit `archgate upgrade` path keeps the 15s default.

## Measured impact (Windows, this repo)

| Command          | Before  | After   |
|------------------|---------|---------|
| adr list         | 3.60 s  | 0.82 s  |
| adr show         | 3.60 s  | 0.72 s  |
| doctor           | 3.90 s  | 1.06 s  |
| telemetry status | 3.70 s  | 0.72 s  |
| check            | 0.88 s  | 0.85 s  |
| adr list (tel off)| 0.59 s  | 0.42 s  |
| doctor (tel off) | 3.50 s  | 0.80 s  |

## Not changed

The `await initTelemetry()` in `main()` — PR #211 added it so
`command_executed` / `command_completed` carry `repo_id`. Keeping
the await; lazy-loading plus parallel init keeps the added startup
cost bounded.

## Validation

`bun run validate` passes (lint + typecheck + format + 662 tests
+ 22/22 ADR rules + build check).
rhuanbarreto added a commit that referenced this pull request Apr 16, 2026
* perf(cli): remove 3s exit tail and trim startup overhead

On Windows (and anywhere the runtime honours timer handles), every
command that exits naturally through `main()` returning — i.e. every
command except `check` and `upgrade` — used to linger ~3 seconds
after its output appeared. Root causes + fixes below.

## Timer leaks (Phase 1)

`flushTelemetry`, `gitCredentialFill`, the WSL fallback in
`resolveCommand`, and the per-rule timeout in the check runner all
race a spawn/shutdown against a `setTimeout`/`Bun.sleep` that's
never cancelled when the race winner resolves. The stray timer
keeps the event loop alive for its full duration. Each site now
captures the timer id and clears it in a `.finally`.

`flushSentry` wraps `Sentry.flush` with the same cancellable race
pattern as defence-in-depth against leaks inside the SDK.

`main()` now finishes with an explicit `process.exit(0)` after
flushes complete so a future leaked handle in a third-party SDK
can't regress this class of bug.

## Lazy SDK loading (Phase 2 #6)

`posthog-node` and `@sentry/node-core/light` are now loaded via
dynamic `import()` inside `initTelemetry` / `initSentry`. The
`ARCHGATE_TELEMETRY=0` path skips the parse and init cost entirely.
Both inits run concurrently via `Promise.all` in `cli.ts`.

## Startup trimming (Phase 2)

- `installGit` short-circuits on `Bun.which("git")` before falling
  back to the async cross-env resolver (avoids a WSL subprocess on
  Windows in the 99% happy path).
- `getRepoContext` now fires all four git probes in parallel
  instead of gating on `rev-parse --is-inside-work-tree`, saving
  one serial spawn on git repos.

## Check hot path (Phase 3)

- `getGitTrackedFiles` is cached per project root — `resolveScopedFiles`
  used to spawn `git ls-files` once per ADR (16 spawns in this repo).
- `ensureRulesShim` compares existing `rules.d.ts` content and skips
  the write when unchanged.
- New `parseAllAdrs(projectRoot)` caches the readdir + parse of every
  ADR once per process. `loadRuleAdrs`, `loadAllAdrs` (in context.ts),
  and `adr list` now share that cache, so `review-context --run-checks`
  no longer reads the ADR directory twice.
- `adr list` uses the shared cache — one readdir instead of two.
- `buildSummary` is built once in `check.ts` and passed into every
  reporter + `getExitCode` instead of being recomputed three times.

## Telemetry payload (Phase 4)

- `getCommonProperties` now splits into a cached "static" snapshot
  (platform, install method, CI, locale) and a fresh "dynamic"
  overlay (project context, repo snapshot). Cuts redundant
  `getPlatformInfo` / `detectInstallMethod` / `Intl.DateTimeFormat`
  calls when multiple events are emitted per command.
- The opportunistic update check at startup now uses a 5s fetch
  timeout (down from 15s) so a slow network never extends exit
  time. The explicit `archgate upgrade` path keeps the 15s default.

## Measured impact (Windows, this repo)

| Command          | Before  | After   |
|------------------|---------|---------|
| adr list         | 3.60 s  | 0.82 s  |
| adr show         | 3.60 s  | 0.72 s  |
| doctor           | 3.90 s  | 1.06 s  |
| telemetry status | 3.70 s  | 0.72 s  |
| check            | 0.88 s  | 0.85 s  |
| adr list (tel off)| 0.59 s  | 0.42 s  |
| doctor (tel off) | 3.50 s  | 0.80 s  |

## Not changed

The `await initTelemetry()` in `main()` — PR #211 added it so
`command_executed` / `command_completed` carry `repo_id`. Keeping
the await; lazy-loading plus parallel init keeps the added startup
cost bounded.

## Validation

`bun run validate` passes (lint + typecheck + format + 662 tests
+ 22/22 ADR rules + build check).

* test(perf): regression guard for the 3s exit tail

Spawns the real CLI via `bun run src/cli.ts --version` / `--help`,
asserts the median of 3 runs stays under 4s. The historical
regression (un-cancelled `setTimeout` / `Bun.sleep` in the
telemetry / Sentry / credential / WSL flush paths) pushed these
commands to ~3.5s on Windows; normal runs sit well under 2s even
on slow CI.

`NODE_ENV=test` suppresses real event delivery but leaves the
telemetry + Sentry SDK init/flush path active, which is where
the regression lives. `ARCHGATE_TELEMETRY` is intentionally NOT
set to 0 so the test exercises the enabled code path.

Threshold chosen to catch the regression (always ≥3000ms) with
enough headroom that slow runners don't flake.
@github-actions github-actions bot mentioned this pull request Apr 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant