Skip to content

Release tripwire: rc.3 needs a Release-As footer on main, in the squash commit body #283

Description

@StefanSteiner

Before merging the release PR for rc.3, a Release-As: 1.0.0-rc.3 footer must be on main. Without it the release PR is wrong, and nothing downstream will catch it.

Current state

main is at v1.0.0-rc.2. The three commits since it carry no Release-As: footer, and one of them is a fix:. #282 has therefore computed 1.0.1-rc.2.

That is not a mis-parse — it is what the config asks for. release-please-config.json has no prerelease keys (prerelease, prerelease-type, versioning), so release-please applies its default strategy, which bumps major.minor.patch and carries the existing -rc.N suffix along untouched. Verified with npx release-please@17.11.2 release-pr --dry-run (17.11.2 is the version release-please-action@v5 pins), which reproduces 1.0.1-rc.2 exactly:

Highest-precedence commit since v1.0.0-rc.2 Computed version
fix: (today's actual state) 1.0.1-rc.2
feat: 1.1.0-rc.2
feat!: / fix!: / BREAKING CHANGE: 2.0.0-rc.2
any of the above + Release-As: 1.0.0-rc.3 1.0.0-rc.3

The last row is the only correct one. This is exactly the outcome a9fe1b0 was written to prevent for rc.2, and its commit message already spells out why bump-minor-pre-major does not help: it is gated on version.isPreMajor (major < 1), which has been false since 1.0.0-rc.1.

Why this is not recoverable after the fact

1.0.1-rc.2 sorts above 1.0.0. If it reaches crates.io, a later 1.0.0 final becomes a downgrade, and the 1.0.0 rc line can never be completed cleanly. cargo yank hides a version but never frees the number, so there is no undo.

Neither publish workflow would stop it. Both validate only that the tag is well-formed and matches Cargo.toml:

  • release.yml checks ^v[0-9]+\.[0-9]+\.[0-9]+(-(rc|alpha|beta)\.[0-9]+)?$, then compares against hyperdb-api-core/Cargo.toml and hyperdb-compile-check/Cargo.toml.
  • npm-build-publish.yml checks the same shape against the workspace Cargo.toml.

v1.0.1-rc.2 passes the regex, and the release PR itself wrote 1.0.1-rc.2 into every Cargo.toml, so the consistency check agrees too. The version is wrong but perfectly self-consistent. The version in the release PR title is the only gate.

Landing the footer

Recent PRs are squash-merged, so the footer must be in the squash commit body. A footer that exists only on a branch commit is discarded — this is the part that is easy to get wrong.

v1.0.0-rc.2's footer survived only because #254 landed as a real merge commit (fa35a45, two parents), preserving the empty chore: release 1.0.0-rc.2 commit that carried it. v1.0.0-rc.1 landed the same way. Every commit on main since then is single-parent.

Two working options:

  1. Squash-merge a PR and put the footer in the squash body. Edit the commit-message box in the merge dialog; the footer must survive into the commit that lands on main.

  2. Push a direct empty commitenforce_admins is false on main, so an admin can bypass the review requirement:

    git commit --allow-empty -m "chore: release 1.0.0-rc.3" -m "Release-As: 1.0.0-rc.3"
    git push upstream main

Leave #282 alone

Do not close it, retitle it, or hand-edit its version. Once the footer is on main, release-please recomputes and force-pushes its own branch, and the PR self-corrects in place to 1.0.0-rc.3. This is fa35a45's own recorded guidance from the rc.2 cut:

chore(main): release … PR computed from #253's commits alone — before this PR's Release-As: footer is on main. That PR will show the wrong version. It updates itself once this PR lands; leave it alone until then.

Confirm the title reads 1.0.0-rc.3 before merging.

Follow-up: make this unnecessary

Adding three keys to release-please-config.json removes the human step entirely. Verified by dry run, not assumed:

"prerelease": true,
"prerelease-type": "rc",
"versioning": "prerelease"

With those, fix:, feat:, and feat!: all compute 1.0.0-rc.3. Exiting the rc line stays easy: flipping "prerelease" to false makes the next release 1.0.0, and a Release-As: 1.0.0 footer still works. One caveat — the keys must be removed once 1.0.0 ships, or the next fix: computes 1.0.1-rc (also verified). That failure is visible in the release PR title, unlike the current one.

Worth doing as its own reviewed PR with the dry run attached. Rationale and the full matrix are in docs/GITHUB_OPERATIONS.mdAutomating the rc line.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions