Repository navigation
Default version.preset ("conventional") can't be loaded; a bad preset crashes release/standing-pr with an unhandled rejection and no envelope #652
Description
Problem
- The default preset doesn't exist.
version.presetdefaults to"conventional"(packages/config/src/schema.ts:92,packages/version/src/types.ts:220,231). The preset loader prefixes it toconventional-changelog-conventional, which isn't on npm (404). So every config without an explicitversion.preset— including the onereleasekit initwrites, and repos with no config file — fails whenever the bump is inferred from commits (only--bumpescapes it). The repo's own config pinsangular, and every integration/e2e test pinsangularorconventionalcommits, so nothing exercises the default. - An unloadable preset crashes the CLI on tagged repos.
Bumper.loadPreset()(packages/version/src/core/versionCalculator.ts:386) starts the presetimport()without a handler; the followingawait refExists(latestTag, …)(line 393) yields, the import rejects, and Node's default--unhandled-rejections=throwkills the process before the surrounding try/catch runs.release --json [--output]andstanding-pr update --json --outputexit 1 with no envelope (stdout empty, no--outputfile) — breaking the feat(cli): uniform JSON envelope with structured errors and changed reporting #608 envelope contract. On untagged repos the&&short-circuits, the error is caught, and aGENERAL_ERRORenvelope is written — still exit 1, not a config error. - The docs disagree on the default:
"conventional"(docs/configuration.md, docs/migration.md, packages/config/README.md),"conventionalcommits"(packages/version/README.md, docs/troubleshooting.md), plus dead fallbacks'conventional-commits'(versionEngine.ts:89-91) and'angular'(versionCalculator.ts:146).
Regression note: the crash (as opposed to a clean failure) dates from 4431910 (#437, v0.33.0), which made refExists async; the default preset itself was never loadable.
Reproduction (built CLI, Node 22)
git init -q demo && cd demo && git config user.email t@e && git config user.name t
echo '{"name":"demo-pkg","version":"1.0.0"}' > package.json
echo '{"version":{}}' > releasekit.config.json # or no config, "conventional", or "nonsense"
git add -A && git commit -qm "chore: init" && git tag v1.0.0
echo x > a.txt && git add -A && git commit -qm "feat: add a"
releasekit release --json --dry-run --output out.json; echo "exit=$?"; ls out.jsonExit 1, empty stdout, no out.json; stderr ends in an uncaught Unable to load the "conventional" preset (ERR_MODULE_NOT_FOUND: conventional-changelog-conventional) with a Node crash footer. angular / conventionalcommits work. conventional-commits works in flat npm/pnpm installs (hoisted alias from @releasekit/version) but not from the bundled packages/release/dist CLI the GitHub Action runs, because the preset loader is bundled into release's dist and import() resolves from there (NODE_PATH doesn't apply to ESM).
Impact
- New users following getting-started (
releasekit init, then a release) fail on every commit-inferred release; after their first tag it's a raw crash with a bundled-code stack. - In CI,
release/standing-pr updateexit 1 with no envelope, so the standing PR is never created or updated; the Action's summary says only "Release Failed", with the cause buried in the log. - A typo'd preset fails the same way, and even the handled path reports
GENERAL_ERROR(exit 1) rather thanCONFIG_ERROR(exit 2).
Proposed fix
- Loadable default: default to
conventionalcommits; normaliseconventionalandconventional-commitsto it (nobody's behaviour changes —conventionalnever loaded); regenerate the schema; drop the dead fallbacks. - Layout-independent loading: pass a loader to
Bumper.loadPreset(preset, loader)that maps the supported names to static imports ofconventional-changelog-angular/conventional-changelog-conventionalcommits(resolve any others viacreateRequire(projectDir)if custom presets are to be supported), then drop theconventional-changelog-conventional-commitsalias dependency. - Validate at config load: an unknown preset throws
ConfigErrorlisting the supported names → exit 2 and aCONFIG_ERRORenvelope. - Close the unhandled window: load the preset (awaited) inside the try before configuring the bumper — or at minimum do the
refExistsawait beforeloadPreset— so nothing yields between starting the import andbump(). - Docs: one stated default and supported list across configuration.md, migration.md, troubleshooting.md, and the version/config READMEs.
Acceptance criteria
- Tagged repo, no preset (or
"conventional"):releasekit release --json --dry-runexits 0 with conventionalcommits rules — in npm, pnpm, and the GitHub Action (bundledrelease/dist) layouts. "preset": "nonsense", tagged and untagged:releaseandstanding-pr updateexit 2 with aCONFIG_ERRORenvelope (stdout and--output) listing supported presets; a one-line stderr message; no crash footer.- No
unhandledRejectionfor any preset value under default Node settings. - Tests: no-preset on a tagged repo (integration/e2e); unknown-preset config validation; CONFIG_ERROR envelope written to
--output; an alias resolving from the bundled release CLI. - Every doc names the same default.
Related: #544 (envelope contract), #616 (envelopes version/publish — coordinate the version path).
Activity
fix(version)!: default to conventionalcommits and reject unsupported …
fix(version)!: default to conventionalcommits and reject unsupported …