Skip to content

fix(release): tolerate squash-merge subject suffix in resume derivation - #43

Merged
wakemeup0 merged 1 commit into
mainfrom
fix/release-resume-squash-suffix
Sep 18, 2026
Merged

wakemeup0 merged 1 commit into
mainfrom
fix/release-resume-squash-suffix

Conversation

@wakemeup0

Copy link
Copy Markdown
Contributor

Problem

Protected-branch release pull requests are squash-merged by GitHub with a (#N) suffix appended to the commit subject, e.g. chore(release): hooray 0.7.0 (#106). DeriveResumableWithEnv then fails to recognize the release commit:

  • single-package: versions[name] != version because the parsed version is 0.7.0 (#106)
  • multi-package: the last name@version segment carries the same suffix
  • the final byte-exact CommitMessage comparison also rejects the subject

The release command then falls back to a fresh plan and attempts a forbidden direct push to the protected branch (observed stranding the openhoo/hooray 0.7.0 release).

Fix

  • Strip one trailing (#<digits>) from the HEAD subject before prefix/parsing in DeriveResumableWithEnv (covers both the single-package Cut path and the multi-package , split path).
  • New releaseMessageMatches helper compares a HEAD message against the expected release message with the same suffix tolerance; used by both the final reconstruction check in DeriveResumableWithEnv and isResumableReleaseWithEnv (without it, a suffixed HEAD falls into verifySource and fails with "Release source changed locally").
  • Suffix-free subjects keep byte-identical behavior: the fast path still compares the raw message first.

Compatibility / security impact

No behavior change for suffix-free commit subjects. Only subjects ending in a literal (#<digits>) gain tolerance; other suffixes (e.g. (alpha)) are still rejected. No public action contract changes.

Tests

  • TestResumesSquashMergedReleaseCommitWithPullRequestSuffix — single-package (#106) subject resumes and recreates the missing tag without extra commits
  • TestResumesMultiPackageReleaseCommitWithPullRequestSuffix — one@0.2.0, two@0.4.0 (#42) subject resumes both releases
  • TestRejectsReleaseCommitWithNonNumericSubjectSuffix — (alpha) suffix still derives no resumable plan
  • Existing suffix-free resume tests unchanged and passing

gofmt, go vet ./..., go build ./..., go test -race -count=1 ./... all green.

@wakemeup0
wakemeup0 merged commit 9c0eb80 into main Sep 18, 2026
11 of 12 checks passed
@wakemeup0
wakemeup0 deleted the fix/release-resume-squash-suffix branch September 18, 2026 18:18
wakemeup0 added a commit that referenced this pull request Sep 18, 2026
## 1.1.2 (2026-09-18)

### Bug Fixes

- **release:** tolerate squash-merge subject suffix in resume derivation (#43) (9c0eb80)

### Other Changes

- **ci:** adopt Hooversion v1.1.1 (d500d01)
- **ci:** adopt Hoonarqube v0.3.1 (96783b9)
wakemeup0 added a commit to openhoo/hooray that referenced this pull request Sep 18, 2026
…#114)

## Summary

Adopts Hooversion v1.1.2, which fixes the protected-branch release
finalize for GitHub squash-merged release PRs.

## Why

The v0.7.0 release finalize failed: PR #106 squash-merged as
`chore(release): hooray 0.7.0 (#106)` and Hooversion v1.1.1's
release-resume derivation rejected the trailing ` (#N)` subject suffix,
falling back to a fresh-release plan that attempted a forbidden direct
push to protected `main` (run 35275750107).

Hooversion v1.1.2 (openhoo/hooversion#43) strips a single trailing `
(#<digits>)` suffix in both `DeriveResumableWithEnv` and
`isResumableReleaseWithEnv`, with byte-identical behavior for
suffix-free subjects.

## Changes

- Pin `hooversion/actions/{lint,prepare-release,release}` to the v1.1.2
peeled commit `f0a37cca2`
- `HOOVERSION_VERSION: "1.1.2"`

## Verification

- Tag `v1.1.2` peeled commit verified against `openhoo/hooversion` refs
- `actionlint` clean on both workflows
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