Skip to content

fix(build): swap Vite for tsup to fix DOMParser ReferenceError#163

Merged
derekmisler merged 3 commits into
mainfrom
fix/tsup-bundler-aws-sdk-domparser
May 4, 2026
Merged

fix(build): swap Vite for tsup to fix DOMParser ReferenceError#163
derekmisler merged 3 commits into
mainfrom
fix/tsup-bundler-aws-sdk-domparser

Conversation

@docker-agent
Copy link
Copy Markdown
Contributor

Problem

The Setup credentials step was failing in production with:

ReferenceError: DOMParser is not defined

Failing run: https://github.com/docker/cagent-action/actions/runs/25329159765/job/74257978215

Root cause

Vite (the previous bundler) was resolving the AWS SDK's browser export condition instead of the node one. The Smithy XML codec used by @aws-sdk/client-secrets-manager contains a reference to DOMParser — a browser-only global that does not exist in Node.js. Because the action runs as a composite GHA step (node dist/credentials.js) with no node_modules, the bundled output was shipping browser code into a pure Node runtime.

Fix

Swap Vite → tsup with explicit Node targeting:

  • platform: 'node' — tells esbuild to resolve the node export condition from every package
  • target: 'node24' — matches the GHA runner Node version; enables modern JS output
  • noExternal: [/.*/] — bundles all npm deps (required; action has no node_modules at runtime)
  • splitting: false / format: 'esm' — single-file ESM bundles per entry point
  • Entry points auto-discovered: src/*/index.tsdist/credentials.js + dist/signed-commit.js

Also bump @aws-sdk/client-secrets-manager 3.787.0 → 3.972.0 to align with the @aws-sdk/credential-provider-web-identity 3.972.x family already in the lockfile, so all SDK packages share a single Smithy runtime instance and avoid version-mismatch issues.

vite.config.ts is deleted; its Vitest configuration is extracted into the new vitest.config.ts.

Verification

  • pnpm build — tsup v8.5.1, builds dist/credentials.js (1.99 MB) + dist/signed-commit.js (148 KB) cleanly
  • ✅ 30/30 unit tests pass (pnpm test)
  • ✅ 0 DOMParser references in dist output
  • pnpm typecheck + biome ci pass

cc @derekmisler

The Vite-bundled output of `dist/credentials.js` was pulling in the
browser-targeted Smithy XML codec from the AWS SDK, which references
`DOMParser` — undefined in Node.js. The action runs as a composite GHA
step (`node dist/credentials.js`) so the build must produce
Node-targeted output.

Swap Vite → tsup with `platform: 'node'` and `target: 'node24'` so
esbuild resolves the AWS SDK's `node` export condition. Bundle every
npm dep (`noExternal: [/.*/]`) since the action runs without
node_modules.

Also bump @aws-sdk/client-secrets-manager 3.787.0 → 3.972.0 to match
the @aws-sdk/credential-provider-web-identity 3.972.x family already in
use, so all SDK packages share one Smithy runtime.

Verified: dist builds cleanly, 0 DOMParser refs in output, 30/30 unit
tests pass, typecheck + biome ci pass.

Assisted-By: docker-agent
@docker-agent
Copy link
Copy Markdown
Contributor Author

cc @derekmisler — ready for review when you are

@derekmisler derekmisler marked this pull request as ready for review May 4, 2026 17:39
@derekmisler derekmisler requested a review from a team as a code owner May 4, 2026 17:39
Copy link
Copy Markdown
Contributor

@docker-agent docker-agent Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assessment: 🟢 APPROVE

The Vite → tsup migration correctly resolves the DOMParser is not defined ReferenceError. Setting platform: 'node' forces esbuild to resolve the Node.js export conditions in AWS SDK packages (preventing the browser DOMParser-using Smithy XML codec from being bundled), and noExternal: [/.*/] correctly ensures all npm dependencies are self-contained in the output for a GHA environment without node_modules.

Key verifications performed:

  • noExternal: [/.*/] + platform: 'node' is safe: esbuild unconditionally keeps all Node.js built-ins (including node:-prefixed forms) external at the esbuild core layer — noExternal only affects tsup's externalizeDepsPlugin layer and cannot override esbuild's built-in exclusion. ✅
  • Vitest config extraction to vitest.config.ts is complete and functionally equivalent. ✅
  • tsconfig.json exclude list correctly swapped vite.config.ts for tsup.config.ts and vitest.config.ts. ✅
  • @aws-sdk/client-secrets-manager bump to 3.972.0 is consistent with the lockfile. ✅

Minor notes (no action required):

  • splitting: false with two entry points means each output file is fully self-contained, which the PR description acknowledges. The AWS SDK will be present in both dist/credentials.js and dist/signed-commit.js even though the latter doesn't use it. This is an intentional trade-off for simplicity and self-containment.
  • There is a minor patch-level version skew between the direct @aws-sdk/credential-provider-web-identity@3.972.29 and the transitive @3.972.0 pulled by client-secrets-manager. Both patch versions will be bundled, which is harmless for correctness given the minor patch delta.

No bugs found in the changed code.

…ndles

- Align @aws-sdk/credential-provider-web-identity 3.972.29 → 3.972.0 to
  match the rest of the @aws-sdk/* 3.972.0 family. The .29 pin was
  incidental (introduced in #119 as the version available at the time;
  no deliberate reason documented). Eliminates the dual-version split in
  the lockfile and removes @aws-sdk/nested-clients 3.996.19 (the original
  DOMParser source) from the tree entirely (-15 packages).

- Disable tsup sourcemaps. The action is consumed via `uses:
  docker/cagent-action@v1`, which clones the tagged release including
  dist/. Sourcemaps would add ~10MB to every consumer clone with no
  runtime benefit (Node doesn't load them by default).

Verified: build clean, 0 DOMParser refs in dist, 30/30 unit tests pass,
typecheck clean, no .map files in dist/.

Assisted-By: docker-agent
@derekmisler
Copy link
Copy Markdown
Contributor

/review

@derekmisler derekmisler enabled auto-merge (squash) May 4, 2026 17:49
Copy link
Copy Markdown
Contributor

@docker-agent docker-agent Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assessment: 🟢 APPROVE

The fix is correct and well-structured. The root cause (Vite resolving AWS SDK browser exports instead of Node exports) is accurately diagnosed, and the tsup configuration directly addresses it:

  • platform: 'node' ensures esbuild selects the node export condition from every package, preventing browser-only globals like DOMParser from entering the bundle
  • noExternal: [/.*/] correctly bundles all dependencies so the action works without node_modules at runtime
  • splitting: false + format: 'esm' produces self-contained per-entry-point ESM files
  • The outExtension: () => ({ js: '.js' }) preserves the .js suffix expected by the composite action's node dist/credentials.js invocation
  • Extracting Vitest config to its own vitest.config.ts is a clean separation; no test regressions
  • AWS SDK version alignment to 3.972.0 across all packages avoids Smithy runtime version-mismatch issues

No bugs found in the changed code.

@docker-agent docker-agent force-pushed the fix/tsup-bundler-aws-sdk-domparser branch from cf0ffe8 to b2596c9 Compare May 4, 2026 18:02
@derekmisler derekmisler merged commit 83bd0cd into main May 4, 2026
14 checks passed
@derekmisler derekmisler deleted the fix/tsup-bundler-aws-sdk-domparser branch May 4, 2026 18:04
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.

2 participants