Files
kandev/.github
José Almeida cfcc755702 fix(release): restore PR-and-merge pattern (#824)
* fix(release): restore PR-and-merge pattern — main is protected by a ruleset

The first real run of the new release workflow (run 25349824365) failed at
the push step with:

  remote: error: GH013: Repository rule violations found for refs/heads/main.
  remote: - Changes must be made through a pull request.
  remote: ! [remote rejected] main -> main

main is protected by a ruleset that requires PRs. Earlier I checked
/repos/kdlbs/kandev/branches/main/protection (the classic branch-protection
endpoint), which reported "not protected" — but rulesets are a separate,
newer mechanism enforced at push time, not surfaced via that API. So the
"simplify to direct push" refactor in 53c2e45 was based on a false negative.

Restoring the PR-and-merge pattern that the legacy release-pr.sh used:

  1. Bump version + regenerate CHANGELOG in working tree (separate step).
  2. Create release/<TAG> branch, commit + push it.
  3. gh pr create + gh pr merge --squash --delete-branch.
  4. Pull squashed commit into local main, tag from there, push tag.

Restored pull-requests: write on the prepare job (needed for gh pr create).

Side note: --atomic in the failed run worked correctly. The tag push was
rejected together with main, so there's no orphan tag on origin from the
failed attempt.

* fix(release): retry tag push + document --auto trade-off

Two non-blocking review suggestions on PR #824:

1. Tag push hardened against transient failures. With the PR-and-merge
   pattern, the merge and the tag push are separate operations. If the
   tag push fails after the PR merges, main has the bumped commit but
   no tag — leaving the release in a half-state where downstream jobs
   never run and the next 'bump=patch' run computes the *next* patch,
   skipping the originally-intended version.

   Now: retry once on push failure. If both attempts fail, log the
   recovery command (manual 'git push origin <TAG>') and exit non-zero
   loudly so the operator knows what to do.

2. Inline comment documenting why we use 'gh pr merge' without --auto.
   The current main ruleset only requires "PR required" — no status
   checks — so immediate merge works. If status checks are added to
   the ruleset later, this code needs to switch to --auto + polling
   before the tag steps. No behavior change today.

* fix(release): delete stale release branch before pushing

If a release run fails after `git push -u origin release/<TAG>` but
before `gh pr merge` lands, the remote branch persists. Because main's
package.json hasn't been bumped, the next workflow run computes the same
NEXT version + same branch name, then fails at the push step with a
non-fast-forward rejection (same content, different SHA from the rebuild).
Recovery currently requires manually closing the stale PR and deleting
the remote branch.

Now: delete any stale remote branch with the same name as a no-op
prologue. GitHub auto-closes the corresponding stale PR when the head
branch disappears, so the subsequent `gh pr create` opens a fresh PR
cleanly.

Caught by Claude and Greptile (P1).
2026-05-05 01:06:17 +01:00
..