A dependency floor raised only in the root manifest's [workspace.dependencies]
leaves every crate inheriting the entry with no commits of its own, so
release-version-bumps.sh defers it -- level "none", "pending_release": "true"
-- and the proposal reads as though nothing happened to it. semver-level.sh,
and now the PR-title gate, call the same change a minor.
Deferring is right: the crate's code is unchanged, the requirement its
published version states is still true of that code, and requirements are
minimums, so a consumer combining it with a freshly published sibling that
asks for the raised floor resolves the newer dependency anyway. Releasing
every inheritor of a shared entry would be churn for crates that needed
nothing. The case where a crate's code does need the raised version always
comes with a change to a file of its own, which the existing path search
already finds.
What was missing is the saying so. commits-since-release.sh now reports, per
crate, the commits that moved what a consumer of it resolves while touching
no file of its own, as `manifest_moves` beside the untouched `commits`, and
release-version-bumps.sh prints them where it defers and carries them on the
row. An operator who wants the bump now can pull the crate in by hand;
otherwise its next release is scored a minor for the same reason, since
deferring moves neither its version nor its tag.
Only commits that moved that crate's own resolved requirements are listed --
another crate's entry, a new member, a dev-dependency or a comment in the
root manifest are not its business -- as semver-level.sh --list-affected
reports them, cached per commit so the cost follows the release range and not
the range times the number of crates.
resolve_baseline takes a full commit SHA already in the clone as it stands,
which is what lets the above ask about a commit and its parent: a bare SHA is
not a ref name the remote serves and `origin/<sha>` is not a revision. A
branch or tag still resolves through the fetch, so a stale local copy cannot
stand in for the remote's.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
What does this PR do?
Stacked on #2506, which it needs for
semver-level.sh --list-affected.A dependency floor raised only in the root manifest's
[workspace.dependencies]leaves every crate inheriting the entry with no commits of its own, sorelease-version-bumps.shdefers it — levelnone,"pending_release": "true"— and the release proposal reads as though nothing happened to it.semver-level.sh, and after #2506 the PR-title gate too, call that same change aminor.Deferring is the right outcome, and this PR does not change it. The crate's code is unchanged; the requirement its published version states is still true of that code; and requirements are minimums, so a consumer combining it with a freshly published sibling that asks for the raised floor resolves the newer dependency anyway. Deferring moves neither the version nor the tag, so the raise stays in range and the crate's next release is still scored a
minorfor it — late, not wrong. The case where a crate's code genuinely needs the raised version always arrives with a change to a file of its own, which the existing path search already finds. Releasing every inheritor of a shared entry instead would mean 12 crates published for onebytesbump, none of whose code needed it, for teams that pin libdatadog versions.What was missing is the saying so:
commits-since-release.shreports, per crate, the commits that moved what a consumer of it resolves while touching no file of its own, asmanifest_movesbeside an untouchedcommits.release-version-bumps.shprints them where it defers, and carries them on the deferred row.An operator who wants the bump now can pull the crate in by hand; otherwise its next release carries it for the same reason.
Motivation
#2506 makes CI score a root-only floor raise as a
minorfor every inheriting crate. Without this, the release proposal for those same crates says levelnone, and a reviewer comparing the two has nothing to reconcile them with.Additional Notes
semver-level.sh --list-affectedbetween each root-manifest commit and its parent, so what counts as a manifest fact has one definition shared with the passes that score it.libdd-alloc, months since its last release). A commit whose parent the clone lacks is reported rather than passed over, since a silent skip is the failure this reporting exists to end.manifest_movesnever overlapscommits. A commit touching both the crate and the root manifest is listed once, among its own commits.[workspace.dependencies], so a dependency on one carries its version in the depending crate's own manifest, which the path search already sees.resolve_baselinenow takes a full commit SHA already in the clone as it stands, which is what lets the above ask about a commit and its parent: a bare SHA is not a ref name the remote serves, andorigin/<sha>is not a revision. A branch or tag still resolves through the fetch, so a stale local copy cannot stand in for the remote's.--list-affectedreports crate names; pairing old and new requirements per crate would need either a per-cratesemver-level.shrun (rustdoc passes, minutes) or a new detail mode. The commit subject carries it in practice for dependency bumps; happy to add the mode if the delta is wanted literally.Verified in a throwaway clone against a fixture tag:
commitsmanifest_movesbytesfloor raise[], still deferredbytescommitclapraise, an entry the crate does not inherit[][]libdd-alloc, real history, inherits no moved entry[]shellcheckreports nothing in any of the three scripts that was not already there.🤖 Generated with Claude Code