Skip to content

Predict the next release version without semantic-release's own orchestrator - #4

Merged
Mearman merged 4 commits into
mainfrom
feat/predict-next-version
Sep 8, 2026
Merged

Mearman merged 4 commits into
mainfrom
feat/predict-next-version

Conversation

@Mearman

@Mearman Mearman commented Sep 8, 2026

Copy link
Copy Markdown
Member

Adds predictNextVersion + loadCommitAnalyzer, and refines resolvePredictedIdentity's return type.

What this does

predictNextVersion(repoRoot, releaseRules, analyzeCommits, options?) predicts the version a repo's next release would be, from commits since its last tagged release, without running semanticRelease()'s own top-level orchestrator -- that verifies push access to the remote as part of resolving branches before analysis ever runs, on every call including dryRun, which is slow and needs credentials a prediction has no real reason to hold. It calls @semantic-release/commit-analyzer's own analyzeCommits hook directly instead.

analyzeCommits is a caller-supplied parameter, not something this package imports itself -- @semantic-release/commit-analyzer ships no types and analyzeCommits isn't part of its documented public API, so loading it safely is a toolchain-specific concern. loadCommitAnalyzer() is the tested, correct way to get a real one (declared as an optional peer dependency); predictNextVersion itself stays a pure, easily-fakeable function of its own arguments.

Breaking change

resolvePredictedIdentity now returns DisplayIdentity (kind: 'release' | 'predicted' | 'commit') instead of BuildIdentity & { predicted?: boolean }. An unreleased build with a prediction now reports kind: 'predicted' directly rather than kind: 'commit' plus a separate predicted: true flag -- three real states get three real values instead of a bolted-on boolean.

Also includes a small extraction (shared package.json version reading between resolveBuildIdentity and predictNextVersion) and a fix to vitest's per-test timeout, which was too tight for tests that spawn real git subprocesses or load the real commit-analyzer package.

…tity and predictNextVersion

Both need the same "read the semantic-release-managed version from
package.json" logic. Extract it into its own module, alongside the
default v<version> tag-name convention, so the invariant lives in one
place rather than being copied.
…ity kind

resolvePredictedIdentity used to return BuildIdentity & { predicted?:
boolean }, bolting an optional flag onto a two-value kind rather than
naming the third real state directly. A caller had to check kind ===
'commit' and then separately check predicted, when there are really
three states to switch on: a confirmed release, a predicted-but-not-
yet-tagged version, and a plain unreleased commit with no prediction
available. DisplayIdentity's kind now has all three as its own literal
values, and predicted is gone.

BREAKING CHANGE: resolvePredictedIdentity's return type is now
DisplayIdentity (kind: 'release' | 'predicted' | 'commit'), not
BuildIdentity & { predicted?: boolean }. An unreleased build with a
prediction now reports kind: 'predicted' instead of kind: 'commit' with
a separate predicted: true field.
… orchestrator

semanticRelease() verifies push access to the remote as part of
resolving branches before analysis ever runs, on every call including
dryRun -- slow, and needing credentials a prediction has no real
reason to hold. predictNextVersion calls
@semantic-release/commit-analyzer's own analyzeCommits hook directly
instead: no network, no registry lookups, no push check. It takes
analyzeCommits as a parameter rather than importing the module itself,
so it stays a pure, easily-fakeable function of its own arguments;
loadCommitAnalyzer is the tested way to obtain a real implementation,
kept as its own function since that module ships no types and
analyzeCommits isn't part of its documented public API.

@semantic-release/commit-analyzer is declared as an optional peer
dependency: not required for resolveBuildIdentity/
resolvePredictedIdentity, only for loadCommitAnalyzer/
predictNextVersion.
Most tests in this package spawn several real git subprocesses per
test (createTestRepo, tag(), commit(), the resolve/predict functions
themselves), and predict-next-version's own tests additionally load
and run the real @semantic-release/commit-analyzer package -- both
genuinely I/O- and process-bound. Vitest's 5000ms default assumes pure
in-memory JS and was already too tight for this, flaking under any
real system load.
@Mearman
Mearman marked this pull request as ready for review September 8, 2026 07:56
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 8, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
🔒 Security Review Completed 2026-09-08T08:04:49.889268Z f60d12c Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@Mearman
Mearman merged commit c664a3a into main Sep 8, 2026
4 checks passed
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown

🎉 This PR is included in version 2.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant