have a workflow that automatically merges PRs that got approved and check all boxes. this workflow should be added to all repos #5

Closed
opened 2026-09-07 16:13:08 +00:00 by bit · 4 comments
Owner
No description provided.
bit added the
Kind
Enhancement
Type
Chore
Priority
Low
4
labels 2026-09-07 16:13:08 +00:00
Member

Gitea already does this. I do not think we should write the workflow.

Measured on this instance rather than read from docs.

The finding

merge_when_checks_succeed is a documented field on MergePullRequestOption
in this server's own swagger, and it works:

POST /repos/weblib/weblib-ci/pulls/6/merge
     {"Do":"merge","merge_when_checks_succeed":true}

on a PR that was unapproved, targeting protected main. It did not
refuse for lack of approvals and it did not merge — it scheduled. Proved by
cancelling twice:

DELETE .../pulls/6/merge   ->  204 No Content     (something was scheduled)
DELETE .../pulls/6/merge   ->  404 Not Found      (nothing left to cancel)

So the whole feature is one extra field when I open a PR. Nothing to install,
nothing to maintain, and it is armed at the moment the PR is created rather
than discovered later by a poller.

Why I would not add the workflow

A workflow would have to live in five repos and be kept in step, and it
walks into three traps this project has already paid for:

  • scheduled workflows only run from the default branch, so a polling
    version would be inert on development until promoted
  • the Actions token's permissions are not the same as mine — it cannot even
    delete an issue label
    , measured; whether it can merge is another thing to
    find out
  • it would race the native mechanism if both existed

Against that, the native path is a single JSON field.

What is not yet proven

That the scheduled merge fires on approval, rather than only on status
checks. The name says checks; Gitea evaluates full mergeability, which should
include approvals, but I have not seen it happen.

PR #6 is armed and waiting for exactly that. It is a real change — the
README describing what the reconciler now does — and it needs your approval
anyway. Approve it and one of two things happens:

  • it merges by itself → confirmed, and I will start passing the flag on every
    PR and close this issue
  • it sits there → the flag waits on checks only, and this issue becomes worth
    doing properly, at which point I would still put the logic in a script here
    and call it from a thin per-repo workflow

Either way we learn it from one approval rather than from building something.

One thing I need you to disambiguate

PRs that got approved and check all boxes

Two readings, and they need different work:

  1. CI checks pass — covered by the native flag, nothing more to do.
  2. The markdown task list in the PR body is fully ticked (- [ ]- [x]).
    Not covered. The PR API exposes no task-list state at all — I listed every
    field on the object to check — so this would mean fetching .body and
    parsing it, and that genuinely needs a script.

I read you as meaning (1), which is why I tested that first. If you meant (2),
say so and I will build it — it is a reasonable thing to want, and it is the
only part of this issue that native auto-merge cannot do.

**Gitea already does this. I do not think we should write the workflow.** Measured on this instance rather than read from docs. ## The finding `merge_when_checks_succeed` is a documented field on `MergePullRequestOption` in this server's own swagger, and it works: ``` POST /repos/weblib/weblib-ci/pulls/6/merge {"Do":"merge","merge_when_checks_succeed":true} ``` on a PR that was **unapproved**, targeting **protected `main`**. It did not refuse for lack of approvals and it did not merge — it *scheduled*. Proved by cancelling twice: ``` DELETE .../pulls/6/merge -> 204 No Content (something was scheduled) DELETE .../pulls/6/merge -> 404 Not Found (nothing left to cancel) ``` So the whole feature is one extra field when I open a PR. Nothing to install, nothing to maintain, and it is armed at the moment the PR is created rather than discovered later by a poller. ## Why I would not add the workflow A workflow would have to live in **five** repos and be kept in step, and it walks into three traps this project has already paid for: - **scheduled workflows only run from the default branch**, so a polling version would be inert on `development` until promoted - the Actions token's permissions are not the same as mine — it **cannot even delete an issue label**, measured; whether it can merge is another thing to find out - it would race the native mechanism if both existed Against that, the native path is a single JSON field. ## What is *not* yet proven That the scheduled merge fires on **approval**, rather than only on status checks. The name says checks; Gitea evaluates full mergeability, which should include approvals, but I have not seen it happen. **PR #6 is armed and waiting for exactly that.** It is a real change — the README describing what the reconciler now does — and it needs your approval anyway. Approve it and one of two things happens: - it merges by itself → confirmed, and I will start passing the flag on every PR and close this issue - it sits there → the flag waits on checks only, and this issue becomes worth doing properly, at which point I would still put the logic in a script here and call it from a thin per-repo workflow Either way we learn it from one approval rather than from building something. ## One thing I need you to disambiguate > PRs that got approved **and check all boxes** Two readings, and they need different work: 1. **CI checks pass** — covered by the native flag, nothing more to do. 2. **The markdown task list in the PR body is fully ticked** (`- [ ]` → `- [x]`). Not covered. The PR API exposes no task-list state at all — I listed every field on the object to check — so this would mean fetching `.body` and parsing it, and *that* genuinely needs a script. I read you as meaning (1), which is why I tested that first. If you meant (2), say so and I will build it — it is a reasonable thing to want, and it is the only part of this issue that native auto-merge cannot do.
Member

Confirmed: native auto-merge fires on approval. No workflow needed.

Your approval of #6 settled it:

APPROVED by bit   16:42:25
merged            16:42:27      <- two seconds later
merged_by         claude        <- the user who *scheduled* it, not the approver
cancel probe      404           <- the scheduled merge was consumed

I never touched it after arming it. So merge_when_checks_succeed waits for
the PR to become mergeable — which includes required approvals — not merely
for CI. That is exactly what this issue asked for, and Gitea has had it all
along.

What I will do instead of building it

Pass the flag when opening every PR:

$TEA api -X POST repos/weblib/<repo>/pulls/<n>/merge \
  -d '{"Do":"merge","merge_when_checks_succeed":true}'

For a PR into development that changes nothing in practice — I can merge those
myself after the cold re-read, and I would rather keep that read than have it
merge out from under me. For a PR into main, or anything in weblib-ci, it
closes a real gap
: those need your approval, and until now the PR sat until I
next looked. Now your approval is the merge.

One caveat worth stating: an armed PR merges without a cold re-read from me
if you approve after I have moved on. For weblib-ci and promotions that is
fine, since your approval is the review. I will not arm a development PR for
that reason.

Still open — the half native auto-merge cannot do

PRs that got approved and check all boxes

If "boxes" meant the markdown task list in the PR body, that is not covered and
not exposed by the API at all. Say the word and I will build it; otherwise I
will close this as done by the native feature.

Recorded in docs/WORKFLOW.md.

## Confirmed: native auto-merge fires on **approval**. No workflow needed. Your approval of #6 settled it: ``` APPROVED by bit 16:42:25 merged 16:42:27 <- two seconds later merged_by claude <- the user who *scheduled* it, not the approver cancel probe 404 <- the scheduled merge was consumed ``` I never touched it after arming it. So `merge_when_checks_succeed` waits for the PR to become **mergeable** — which includes required approvals — not merely for CI. That is exactly what this issue asked for, and Gitea has had it all along. ## What I will do instead of building it Pass the flag when opening every PR: ```bash $TEA api -X POST repos/weblib/<repo>/pulls/<n>/merge \ -d '{"Do":"merge","merge_when_checks_succeed":true}' ``` For a PR into `development` that changes nothing in practice — I can merge those myself after the cold re-read, and I would rather keep that read than have it merge out from under me. **For a PR into `main`, or anything in weblib-ci, it closes a real gap**: those need your approval, and until now the PR sat until I next looked. Now your approval *is* the merge. One caveat worth stating: an armed PR merges **without a cold re-read from me** if you approve after I have moved on. For weblib-ci and promotions that is fine, since your approval is the review. I will not arm a `development` PR for that reason. ## Still open — the half native auto-merge cannot do > PRs that got approved **and check all boxes** If "boxes" meant the markdown task list in the PR body, that is not covered and not exposed by the API at all. Say the word and I will build it; otherwise I will close this as done by the native feature. Recorded in `docs/WORKFLOW.md`.
Author
Owner

in that case, auto-merge should become the default option for PRs

in that case, auto-merge should become the default option for PRs
Member

Agreed and done — auto-merge is now the default for every PR.

I had said I would not arm development PRs, because there no approval is
required, so armed means "merges the moment CI goes green" with no review at
all — and the cold re-read is the only review those get. You have that in front
of you and said default it on, so it is on.

The fix turned out to be ordering, not an exception:

old:  push -> wait for CI -> re-read -> merge
new:  push -> re-read -> arm -> (CI green) -> it merges itself

The review still happens, on the same diff, before anything can merge — and it
is faster, because the old order meant coming back to a PR after CI finished,
which is the waiting you are trying to remove. So the rule is arm last:
after the re-read, after the final push.

One thing I have not verified and am treating as dangerous until I do:
whether pushing to an already-armed PR cancels the scheduled merge. A scheduled
merge attaches to the PR, not to a commit, so it may merge code nobody re-read.
Until measured, the rule is cancel → push → re-read → re-arm:

$TEA api -X DELETE repos/weblib/<repo>/pulls/<n>/merge   # 204 = was armed, 404 = not

That DELETE doubles as the way to ask whether a PR is armed.

Recorded in docs/WORKFLOW.md, loop step 6 of docs/UNSUPERVISED.md, and the
subagent briefing in docs/DELEGATION.md — subagents open PRs but do not
arm them, since arming before the parent's re-read is exactly the failure this
ordering avoids.

Closing: no workflow needed, native auto-merge does it, and it is now the
default. If you did mean the markdown task-list checkboxes by "check all
boxes", reopen and say so — that part is genuinely not covered and would need
parsing the PR body.

Agreed and done — auto-merge is now the default for every PR. I had said I would *not* arm `development` PRs, because there no approval is required, so armed means "merges the moment CI goes green" with no review at all — and the cold re-read is the only review those get. You have that in front of you and said default it on, so it is on. **The fix turned out to be ordering, not an exception:** ``` old: push -> wait for CI -> re-read -> merge new: push -> re-read -> arm -> (CI green) -> it merges itself ``` The review still happens, on the same diff, before anything can merge — and it is *faster*, because the old order meant coming back to a PR after CI finished, which is the waiting you are trying to remove. So the rule is **arm last**: after the re-read, after the final push. One thing I have **not** verified and am treating as dangerous until I do: whether pushing to an already-armed PR cancels the scheduled merge. A scheduled merge attaches to the PR, not to a commit, so it may merge code nobody re-read. Until measured, the rule is cancel → push → re-read → re-arm: ```bash $TEA api -X DELETE repos/weblib/<repo>/pulls/<n>/merge # 204 = was armed, 404 = not ``` That `DELETE` doubles as the way to ask whether a PR is armed. Recorded in `docs/WORKFLOW.md`, loop step 6 of `docs/UNSUPERVISED.md`, and the subagent briefing in `docs/DELEGATION.md` — subagents open PRs but do **not** arm them, since arming before the parent's re-read is exactly the failure this ordering avoids. Closing: no workflow needed, native auto-merge does it, and it is now the default. If you did mean the markdown task-list checkboxes by "check all boxes", reopen and say so — that part is genuinely not covered and would need parsing the PR body.
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Reference: weblib/weblib-ci#5