Skip to content

fix(release): derive the version without lerna's dry run - #34

Merged
frantuma merged 1 commit into
mainfrom
frantuma/fix-release-version-derivation
Sep 14, 2026
Merged

frantuma merged 1 commit into
mainfrom
frantuma/fix-release-version-derivation

Conversation

@frantuma

Copy link
Copy Markdown
Member

Dispatching the Release workflow without a version currently fails. This fixes that.

The bug

scripts/release-preflight.sh derives the version by running lerna and reading the result back out of its output:

npx lerna version --conventional-commits --no-private --yes --force-publish --dry-run

lerna 10 rejects that flag: Unknown arguments: dry-run, dryRun. So preflight exits 1 with "Could not read a single stable version out of lerna's dry run", and the release stops before it starts.

The lerna 9 → 10 bump landed in #32 two days ago. The removal is not in lerna's documented breaking changes for 10.0.0, and lerna publish --dry-run still works, so it looks unintentional on their side — but it is real either way.

It has never bitten anyone, because the derive path has never been used. The 2.13.0 release passed REQUESTED_VERSION: 2.13.0 explicitly. The workflow input still tells you "Leave empty to derive it from the conventional commits", which has been advice that would fail.

The fix

Ask conventional-recommended-bump for the release type and apply it to the workspace version. That is the library lerna drives to compute this, invoked with the preset lerna.json names, so it reaches the answer lerna would have reached — verified against the tag boundary rather than assumed: the repository has 46 feat commits in its history and none since v2.13.0, and the tool reports patch, with Reason: There are 0 BREAKING CHANGES and 0 features.

Two deliberate details:

  • It becomes a direct devDependency pinned to =12.1.0, the version lerna already resolves, rather than being borrowed from lerna's tree. A release-critical script should not depend on a transitive that a future lerna could drop. No new package enters the tree; the lockfile moves by one line.
  • The binary is invoked by path, not through npx, so a missing dependency fails in preflight rather than being fetched from the network in the middle of a release.

Nothing recomputes the number afterwards. The version job receives the resolved value and passes it to lerna version explicitly, so preflight remains the single place the version is decided and the two cannot diverge.

Verification

Both modes, run against the real repository state:

mode before after
no version input exit 1 exit 0 — "Conventional commits imply a patch bump: 2.13.1"
version=2.14.0 exit 0 exit 0 — unchanged

The guards were re-tested, since this script gates a job that can write to main and publish to the registry:

input result
2.14.0-rc.1 (prerelease) rejected
^2.14.0 (range) rejected
2.13.0 (does not move forward / already published) rejected
2.12.0 (backwards) rejected
2.14.0; echo pwned (shell metacharacters) rejected
2.13.1, 2.14.0 accepted

And the new failure mode: with node_modules/.bin/conventional-recommended-bump removed, preflight aborts with a clear "No such file or directory" rather than reaching for the network.

bash -n passes; npm test is 400 passing and npm audit clean, though neither touches this script.

Not covered here

Two other things changed under the release pipeline since its last successful run on 2026-09-09, both flagged rather than fixed:

  • actions/upload-artifact went 4 → 7 in chore(deps): bump actions/upload-artifact from 4 to 7 #30 and appears only in release.yml, so no CI job exercises it. The next release is its first real run.
  • lerna 10 now throws EBEHIND in CI when the checkout is behind the remote, where that previously only happened locally. command.version.ciBehindBehavior in lerna.json is the opt-out if it becomes a problem.

Dispatching a release without a version fails. Preflight derives the
bump by running `lerna version --conventional-commits --dry-run` and
reading the version back out of the output, and lerna 10 rejects that
flag outright: "Unknown arguments: dry-run, dryRun". The bump to lerna
10 landed two days ago.

It has never bitten anyone, because it has never been used: the 2.13.0
release passed its version explicitly, so the derive path the input
description recommends has not run in a real release.

Ask conventional-recommended-bump for the release type and apply it to
the workspace version. That is the library lerna drives for this, with
the preset lerna.json names, so it reaches the answer lerna would have
reached, and it is now a direct devDependency rather than something
borrowed from lerna's own tree. The binary is invoked by path, so a
missing dependency fails in preflight instead of being fetched from
the network in the middle of a release.

Nothing recomputes the number afterwards -- the version job passes the
resolved value to `lerna version` explicitly -- so preflight stays the
single place the version is decided.
@frantuma
frantuma merged commit ef0409c into main Sep 14, 2026
9 checks passed
@frantuma
frantuma deleted the frantuma/fix-release-version-derivation branch September 14, 2026 07:45
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