Skip to content

chore: migrate from ncc (CJS) to rollup (ESM)#436

Merged
jdx merged 4 commits into
mainfrom
esm-migration
Apr 11, 2026
Merged

chore: migrate from ncc (CJS) to rollup (ESM)#436
jdx merged 4 commits into
mainfrom
esm-migration

Conversation

@jdx

@jdx jdx commented Apr 11, 2026

Copy link
Copy Markdown
Owner

Summary

  • Switch bundler from @vercel/ncc to rollup with @rollup/plugin-commonjs, @rollup/plugin-node-resolve, @rollup/plugin-json, and @rollup/plugin-typescript
  • Add "type": "module" to package.json for ESM support
  • Upgrade all @actions/* dependencies to their latest major versions (@actions/core v3, @actions/exec v3, @actions/cache v6, @actions/glob v0.6, @actions/io v3)
  • Remove old ncc artifacts (dist/licenses.txt, dist/sourcemap-register.js)

Why

The @actions/toolkit packages v3+ are ESM-only and can't be bundled by ncc (which uses webpack with CJS require()). This is what's blocking #435 (renovate @actions/exec v3 upgrade). The official actions/typescript-action template has already migrated to rollup.

Test plan

  • CI passes (npm run all — format, lint, package)
  • check-dist workflow passes (dist/index.js matches build output)
  • Integration tests pass on all platforms (ubuntu, macos, windows, alpine)

🤖 Generated with Claude Code


Note

Medium Risk
Moderate risk because it changes the action’s build/bundling pipeline and module format (CJS→ESM), which can break runtime execution or dependency resolution if the generated dist/ output differs across environments.

Overview
Migrates the GitHub Action build from @vercel/ncc (CommonJS) to a Rollup-based ESM bundle, adding rollup.config.ts and updating TypeScript settings to NodeNext to support ESM output.

Updates package.json to "type": "module", switches the packaging script to Rollup, and upgrades @actions/* dependencies to their latest major (ESM-only) versions. The checked-in dist/ artifacts are regenerated accordingly (including license output) and legacy ncc-specific artifacts are removed.

Reviewed by Cursor Bugbot for commit 59e728e. Bugbot is set up for automated code reviews on this repo. Configure here.

@socket-security

socket-security Bot commented Apr 11, 2026

Copy link
Copy Markdown

@greptile-apps

greptile-apps Bot commented Apr 11, 2026

Copy link
Copy Markdown

Greptile Summary

Migrates the build toolchain from @vercel/ncc (CommonJS/webpack) to Rollup with \"type\": \"module\" in package.json, enabling ESM-only @actions/* v3 packages (core, exec, io) to be bundled correctly. The dist/index.js is regenerated as a self-contained ESM bundle; Node.js picks up \"type\": \"module\" from the root package.json when the action runner loads dist/index.js, so the module format is correctly resolved.

  • The PR description says @actions/cache is upgraded to v6, but package.json specifies ^4.0.0 (v4.1.0 installed) — either the description has a typo or the v6 bump was accidentally omitted."

Confidence Score: 5/5

Safe to merge — the ESM migration is technically correct and all remaining findings are P2.

All changed files look correct: the rollup config, tsconfig NodeNext settings, and the generated ESM bundle are consistent with the official actions/typescript-action template pattern. The only finding is a P2 discrepancy between the PR description (@actions/cache v6) and package.json (^4.0.0), which does not affect runtime behavior.

No files require special attention.

Important Files Changed

Filename Overview
rollup.config.ts New rollup config replaces ncc; ESM format output with commonjs/nodeResolve/json/typescript/license plugins. esModule: true is a no-op (already flagged in prior thread) but otherwise correct.
tsconfig.json Switched module/moduleResolution to NodeNext for ESM; allowSyntheticDefaultImports redundancy was flagged in prior thread. All source imports are package-level, so NodeNext's .js-extension requirement for relative imports is not currently a problem.
package.json Added "type": "module" and exports field; switched package script to rollup; upgraded @actions/* to ESM-compatible versions. @actions/cache is at ^4.0.0 while the PR description claims v6.
dist/index.js Regenerated 121k-line ESM bundle; starts with bare import statements for Node built-ins and includes rollup CJS interop helpers. Correctly treated as ESM by Node.js via the root package.json "type":"module".
dist/licenses.txt Regenerated by rollup-plugin-license; replaces the old ncc-generated version.
dist/sourcemap-register.js Deleted — ncc-specific artifact that registered source maps at startup; no longer needed with rollup's native sourcemap support.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["src/index.ts"] -->|"rollup + plugin-typescript"| B["TypeScript transpilation"]
    B -->|"plugin-commonjs ignoreTryCatch:false"| C["CJS dependency interop"]
    C -->|"plugin-node-resolve preferBuiltins:true"| D["Node built-in resolution"]
    D -->|"plugin-json"| E["JSON imports resolved"]
    E -->|"plugin-license"| F["dist/licenses.txt"]
    E --> G["dist/index.js ESM bundle"]
    G --> H{"Root package.json type:module"}
    H -->|"Yes"| I["Node.js ESM mode"]
    I --> J["Action executes via node24"]
Loading

Fix All in Claude Code

Reviews (8): Last reviewed commit: "[autofix.ci] apply automated fixes" | Re-trigger Greptile

Comment thread rollup.config.ts
Comment thread tsconfig.json
@jdx jdx enabled auto-merge (squash) April 11, 2026 13:48

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request migrates the project's build system from @vercel/ncc to rollup to improve build configuration and dependency management. The changes include updating package.json dependencies, adding a rollup.config.ts file, and adjusting tsconfig.json settings. I have provided feedback regarding the redundancy of npx in npm scripts, the recommendation to explicitly mark Node.js built-ins as external in the Rollup configuration, and the need to restore license attribution previously handled by ncc.

Comment thread package.json Outdated
"format:write": "prettier --write **/*.ts",
"lint": "npx eslint . && npm run format:check",
"package": "ncc build -s src/index.ts --license licenses.txt",
"package": "npx rimraf ./dist && npx rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The use of npx inside npm scripts is redundant because npm run automatically adds ./node_modules/.bin to the PATH during execution. Removing it simplifies the command and slightly improves performance.

Suggested change
"package": "npx rimraf ./dist && npx rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript",
"package": "rimraf dist && rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript",

Comment thread rollup.config.ts
import nodeResolve from '@rollup/plugin-node-resolve'
import typescript from '@rollup/plugin-typescript'

const config = {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

For a Node.js bundle, it is recommended to explicitly mark Node.js built-in modules (like node:crypto, node:fs, etc.) as external. This prevents Rollup from attempting to resolve them or producing warnings about unresolved dependencies during the build process.

const config = {
  external: [/node:/],
  input: 'src/index.ts',

Comment thread rollup.config.ts
Comment on lines +14 to +19
plugins: [
typescript(),
nodeResolve({ preferBuiltins: true }),
commonjs(),
json()
]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The migration from @vercel/ncc to rollup removes the automatic generation of a licenses.txt file (which was previously included via the --license flag). For GitHub Actions that bundle third-party dependencies, it is a best practice (and often a legal requirement for MIT/Apache licenses) to include attribution for those dependencies. Consider adding a plugin like rollup-plugin-license to regenerate this artifact.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit f2de96e. Configure here.

Comment thread .github/workflows/test.yml Outdated
Comment thread .github/workflows/test.yml Outdated
jdx and others added 2 commits April 11, 2026 17:35
Switch bundler from @vercel/ncc to rollup to support ESM-only
@actions/toolkit v3 packages. This upgrades all @actions/* dependencies
to their latest major versions and adds "type": "module" to package.json.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
minimatch 3.x uses `try { return require('path') } catch (e) {}` to
get the path module, falling back to `{ sep: '/' }`. With rollup's
commonjs plugin, `ignoreTryCatch: true` (the default) leaves
require('path') unconverted inside try blocks. At runtime in the ESM
bundle, require() is unavailable, so the catch fires and minimatch
uses '/' as the path separator — breaking all glob matching on Windows
where paths use backslashes.

Setting ignoreTryCatch: false ensures require('path') is converted to
an ESM import, giving minimatch the correct path.sep ('\\' on Windows).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add rollup-plugin-license to generate dist/licenses.txt for bundled
  third-party dependencies (replaces ncc's --license flag)
- Remove redundant npx from npm scripts since npm run already adds
  node_modules/.bin to PATH

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@jdx jdx merged commit 2a3eb97 into main Apr 11, 2026
18 checks passed
@jdx jdx deleted the esm-migration branch April 11, 2026 17:55
@jdx jdx mentioned this pull request Apr 18, 2026
@jdx jdx mentioned this pull request May 22, 2026
@jdx jdx mentioned this pull request Jun 4, 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