feat(pulls/merge): add --delete-branch flag #1

Closed
jmz wants to merge 3 commits from maximus/feat/delete-branch-flag into main
Owner

Summary

Surfaces the existing DeleteBranchAfterMerge field from the Gitea SDK's MergePullRequestOption on tea pr merge, so callers can opt into deleting the head branch after a successful merge. Mirrors the web UI's "Delete branch after merge" checkbox.

Behaviour

Invocation Result
tea pr merge 42 Field unset → server applies its repo-level default_delete_branch_after_merge setting (status quo).
tea pr merge 42 --delete-branch Force-deletes the head branch on success.
tea pr merge --delete-branch (interactive) Same, in the interactive picker.

Pointer-to-bool semantics keep "omitted" distinct from "explicitly false". If a future caller needs to override the repo default to-false explicitly, switch to IsSet()-aware threading then; not needed today.

Why

Surfaced on srv-mirus on 2026-05-06: the Optimacro/tf-sgm-mirustech-data-generation-ip-temporary repo has default_delete_branch_after_merge=true, but tea pr merge doesn't pass the field, so merged feature branches were surviving and accumulating. Manual DELETE /branches calls were the workaround. Once this lands, tea pr merge --delete-branch (or a repo where the server-side default fires server-side) cleans up automatically.

Test plan

  • Reviewer to confirm: make test passes (no Go toolchain on the host this was authored on; build deferred to CI).
  • Reviewer to spot-check the interactive path still works (tea pr merge with no args from a branch that has an open PR).
## Summary Surfaces the existing `DeleteBranchAfterMerge` field from the Gitea SDK's `MergePullRequestOption` on `tea pr merge`, so callers can opt into deleting the head branch after a successful merge. Mirrors the web UI's "Delete branch after merge" checkbox. ## Behaviour | Invocation | Result | |---|---| | `tea pr merge 42` | Field unset → server applies its repo-level `default_delete_branch_after_merge` setting (status quo). | | `tea pr merge 42 --delete-branch` | Force-deletes the head branch on success. | | `tea pr merge --delete-branch` (interactive) | Same, in the interactive picker. | Pointer-to-bool semantics keep "omitted" distinct from "explicitly false". If a future caller needs to override the repo default to-false explicitly, switch to IsSet()-aware threading then; not needed today. ## Why Surfaced on srv-mirus on 2026-05-06: the `Optimacro/tf-sgm-mirustech-data-generation-ip-temporary` repo has `default_delete_branch_after_merge=true`, but `tea pr merge` doesn't pass the field, so merged feature branches were surviving and accumulating. Manual `DELETE /branches` calls were the workaround. Once this lands, `tea pr merge --delete-branch` (or a repo where the server-side default fires server-side) cleans up automatically. ## Test plan - [ ] Reviewer to confirm: `make test` passes (no Go toolchain on the host this was authored on; build deferred to CI). - [ ] Reviewer to spot-check the interactive path still works (`tea pr merge` with no args from a branch that has an open PR).
Two related changes that make `tea pulls merge` more usable on Forgejo
deployments with branch protection:

1. cmd/pulls/merge.go + docs/CLI.md: extend the --style flag's usage
   text to include `fast-forward-only` as a documented option. The
   underlying gitea SDK already forwards arbitrary strings to the API,
   and Forgejo accepts `fast-forward-only` as a valid merge style; the
   patch just documents that you can pass it.

2. modules/task/pull_merge.go: when MergePullRequest returns
   `success=false` with a non-nil response, read the HTTP response
   body and include the actual API status code + message in the
   returned Go error. Replaces the misleading default
   "failed to merge PR, is it still open?" with concrete diagnostics
   like "failed to merge PR (HTTP 405): rebase is not an allowed
   merge style for this repository". Lets callers distinguish
   policy-style rejections (405) from PR-state issues (404/409)
   without guessing.

Local build identifier: 0.14.0+ff-5103496-local.
feat(pulls/merge): add --delete-branch flag
Some checks failed
check-and-test / check-and-test (pull_request) Failing after 21s
fc1758c638
Surfaces the existing ``DeleteBranchAfterMerge`` field on the Gitea
SDK's ``MergePullRequestOption`` so callers can opt into deleting the
head branch after a successful merge. Mirrors the web UI checkbox.

Default behaviour unchanged: when the flag is omitted, the field stays
nil and the server applies its repo-level
``default_delete_branch_after_merge`` setting. So repos that already
have auto-delete configured will start deleting branches once their
contributors run ``tea pr merge`` from this build.

Pointer-to-bool semantics: setting --delete-branch=false would
currently mean "don't pass the field" rather than "explicitly false".
If a future caller needs to override the repo default to-false
explicitly, switch to IsSet()-aware threading then; not needed today.

Both call sites updated:
- cmd/pulls/merge.go (non-interactive)
- modules/interact/pull_merge.go (huh-driven interactive selection)

Closes the gap surfaced on srv-mirus on 2026-05-06: dg repo had
``default_delete_branch_after_merge=True`` but tea pr merge wasn't
sending the field, so merged stage-1/2/3 branches survived. Manual
DELETE /branches cleanup was the workaround.
ci: add Forgejo-compatible CI workflow
All checks were successful
check / check (pull_request) Successful in 3m5s
16ae6d8b1d
The inherited upstream `.gitea/workflows/test-pr.yml` doesn't run on
our local Forgejo infra:

- `runs-on: ubuntu-latest` doesn't match the rpi5 runner labels
  (`self-hosted, arm64, rpi5`).
- The `services: gitea: image: ...` block needs Docker-in-Docker;
  our host-mode runner doesn't provide Docker for jobs.
- `actions/checkout@v6` / `setup-go@v6` aren't pinned in our network;
  every other repo on this Forgejo uses `@v4` / `@v5`.

This file at `.forgejo/workflows/check.yml` shadows the upstream one
(Forgejo prefers `.forgejo/workflows/` when both directories exist)
without modifying it on disk, so an upstream sync stays clean.

The check is minimal: clean → vet → build. No Docker-based test
fixture; that lives upstream and runs in upstream CI. Job name is
``check`` to match the ensure-repo-policy contract.
jmz closed this pull request 2026-05-06 23:29:13 +00:00
Author
Owner

Closing in favour of model A architecture — main stays a clean upstream mirror, local patches accumulate on a long-lived release/mirus branch, releases are tagged there. The replacement PR will target release/mirus.

Closing in favour of **model A** architecture — `main` stays a clean upstream mirror, local patches accumulate on a long-lived `release/mirus` branch, releases are tagged there. The replacement PR will target `release/mirus`.
All checks were successful
check / check (pull_request) Successful in 3m5s

Pull request closed

Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
public/tea!1
No description provided.