fix(release): wire release boundary into convergence (duplicate-bump root cause)
release_convergence() never assigned from last_release_boundary() — the production path classified ALL commits (959+) as unreleased, so the warranted bump (minor, from an ancient feat) never converged and every queued push wrote its own bump commit (5x 0.66.9 observed 2026-09-11 20:21). Now the boundary is the one source of truth: last chore(release) commit, falling back to the latest tag. Post-boundary subjects only. Also: local path was NOT reached when _boundary_subject was injected; test_cli_prints_plan_json expectation updated to boundary semantics (feat below the tag no longer warrants minor).
This commit is contained in:
1 parent
95bac995a3
commit
d01df797c1
2 files changed
+29
-9
No files matched your search
@@ -311,14 +311,30 @@ def release_convergence(
|
||||
)
|
||||
subjects = [s for s in result.stdout.splitlines() if s.strip()]
|
||||
else:
|
||||
# No release boundary: all commits are unreleased
|
||||
result = subprocess.run(
|
||||
["git", "log", "--format=%s"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
cwd=str(repo) if repo else None,
|
||||
check=True,
|
||||
)
|
||||
# Production path: converge over commits since the last release
|
||||
# boundary. T15 Part F root cause: `boundary` was initialized to
|
||||
# None and never assigned — every run classified ALL commits as
|
||||
# unreleased (959+), so the warranted bump never converged and
|
||||
# every queued push wrote its own bump commit (5× 0.66.9 observed
|
||||
# 2026-09-11 20:21). Assign the boundary from the one source of
|
||||
# truth and range the log over it.
|
||||
boundary = last_release_boundary(repo)
|
||||
if boundary:
|
||||
result = subprocess.run(
|
||||
["git", "log", "--format=%s", f"{boundary}..HEAD"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
cwd=str(repo) if repo else None,
|
||||
check=True,
|
||||
)
|
||||
else:
|
||||
result = subprocess.run(
|
||||
["git", "log", "--format=%s"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
cwd=str(repo) if repo else None,
|
||||
check=True,
|
||||
)
|
||||
subjects = [s for s in result.stdout.splitlines() if s.strip()]
|
||||
|
||||
# Exclude chore(release) commits from bump classification (they ARE releases)
|
||||
|
||||
@@ -353,4 +353,8 @@ class TestRealGitRepo:
|
||||
out = vc.main(["--repo", str(repo)])
|
||||
printed = json.loads(capsys.readouterr().out)
|
||||
assert printed == out
|
||||
assert out["warranted_bump"] == "minor" # "feat: base" is in the subjects since tag
|
||||
# Boundary semantics (T15 Part F fix): the release boundary falls
|
||||
# back to the latest tag, so only post-tag commits count —
|
||||
# "feat: base" sits below the boundary and must NOT warrant minor.
|
||||
assert out["warranted_bump"] == "patch"
|
||||
assert out["commits_since_boundary"] == 1
|
||||
Reference in new issue
Block a user