Skip to content

fix(changelog): report a public-dependency change once, and only claim a break when proven - #13

Merged
upbqdn merged 1 commit into
mainfrom
fix/one-bullet-per-dep
Jul 31, 2026
Merged

fix(changelog): report a public-dependency change once, and only claim a break when proven#13
upbqdn merged 1 commit into
mainfrom
fix/one-bullet-per-dep

Conversation

@upbqdn

@upbqdn upbqdn commented Jul 31, 2026

Copy link
Copy Markdown
Member

Motivation

Two problems in the public-dependency reporting path, both visible in the draft a curator
has to hand-edit.

One change produced two bullets. A dependency whose types are reachable in a crate's
public API got both the Migrated to ... line that every requirement change emits and a
second Public dependency ... line from the reachability join:

### Changed
- Migrated to `ext_dep 0.30.0`.
- Public dependency `ext_dep` upgraded to `0.30.0` (major); it appears in this crate's public API, so this is a breaking change.

A changelog entry is per change and written for the user adapting to it, so this left the
curator merging the two by hand every time.

An undecidable change was counted as a break. #11 added the unknown classification
for a requirement that changed without moving the version it starts at, and routed it into
the reachability join so it would be surfaced. But the join's output feeds
totals.public_dep_breaking and the verdict, so widening a version ceiling
(>=0.1, <0.3 -> >=0.1, <0.4) produced verdict: breaking and a nonzero exit — failing
a consumer's CI over a change nothing shows to be incompatible.

Solution

Fold the note into the Migrated to line:

### Changed
- Migrated to `ext_dep 0.30.0`; its types appear in this crate's public API, so downstream users must upgrade `ext_dep` in lockstep.

And separate the two classes throughout:

provably incompatible undecidable
changelog wording must upgrade in lockstep check whether downstream users are affected
totals.public_dep_breaking counted not counted
verdict / exit code breaking, exit 1 unchanged
JSON class breaking review
summary section red, "incompatible" yellow, "compatibility unclear"

So an undecidable change is still surfaced — the point of routing it through the join —
without asserting a break or demanding a major version bump.

The new class field is documented in both the README's --json reference and the inline
schema zc --help prints, so neither describes a shape the tool no longer emits.

Tests

  • The reachable incompatible case asserts the folded line and guards against a second
    bullet appearing beside it.
  • A new case covers the undecidable arm end to end: exit 0, verdict: ok,
    public_dep_breaking: 0, a class: review entry, the review wording in the folded
    line, and the absence of any break assertion.
  • Branch coverage for the external Migrated to line itself, which the fold rewrites in
    place.

Rebased onto main now that #11 has landed; supersedes #12, which GitHub auto-closed when
its stacked base branch was deleted.

Ran locally: shellcheck -S warning zc tests/run.sh, bash -n zc, bash -n tests/run.sh, tests/run.sh (137 tests, 0 failures).

@upbqdn
upbqdn force-pushed the fix/one-bullet-per-dep branch from a60d043 to f6ff952 Compare July 31, 2026 16:57
@upbqdn upbqdn changed the title fix(changelog): emit one bullet per dependency change fix(changelog): report a public-dependency change once, and only claim a break when proven Jul 31, 2026
…m a break when proven

A dependency whose types are reachable in a crate's public API produced two
`### Changed` bullets naming it: the `Migrated to ...` line every requirement
change emits, and a second `Public dependency ...` line from the reachability
join. A changelog entry is per change and written for the user adapting to it, so
the curator had to merge the two by hand on every such dependency. Fold the note
into the `Migrated to` line, keeping a standalone bullet only where no such line
exists.

The reachability join also reports requirement changes that classification cannot
prove incompatible, and those were being counted as breaks: a widened version
ceiling produced a `breaking` verdict and a nonzero exit, failing a consumer's CI
on a change nothing shows to be incompatible. Split the two. A provably
incompatible change counts toward the verdict and states the lockstep upgrade; an
undecidable one is reported as a review item, excluded from the count, and asks
for review instead of asserting a break.

The JSON entries carry a `class` of `breaking` or `review` so a consumer can tell
them apart, and `totals.public_dep_breaking` counts only the former. The
human-readable section reports both counts and labels each row.
@upbqdn
upbqdn force-pushed the fix/one-bullet-per-dep branch from f6ff952 to f778486 Compare July 31, 2026 16:59
@upbqdn
upbqdn merged commit a29b3c6 into main Jul 31, 2026
2 checks passed
@upbqdn
upbqdn deleted the fix/one-bullet-per-dep branch July 31, 2026 17:02
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