feat(forgejo): require branches to be up to date before merge #816

Merged
coilysiren merged 1 commit from outdated-branch-815 into main 2026-08-13 10:08:43 +00:00
Member

DESIRED_RULE already owned block_on_outdated_branch and actively drove it to False on every protected repo, so this is a one-value flip rather than a new claim on server state.

A pull request that went green against a base which has since moved proves the branch was good, not the merge result. Blocking an outdated head makes the tree CI tested the tree that lands.

Blast radius

Gates merges only. enable_push stays True and required_approvals stays 0, so this adds no review gate and does not stop anyone pushing a protected branch directly.

That matters because the fleet's automated writers push rather than open pull requests: the dispatch implementer lands on main, and tap and scoop bumps land on their protected default branches. A grep across the CI of agentic-os, deploy, and infrastructure found no automated pull request merges, so nothing that merges unattended today starts failing.

The cost is real but bounded: on a fast-moving repo a pull request needs its branch updated when main advances underneath it. Every affected repo already allows update-by-rebase, so the web UI update button covers it.

Docs

The rule's own documentation described it as a force-push and deletion boundary only, which stops being the whole truth. The module docstring, the skill reference, and SKILL.md all pick up the merge-side half, and each is careful to keep the still-true part: nothing compels work to arrive as a pull request, so the pull-request-and-merge lane stays ungated server-side. What is now gated is how a pull request may merge once one exists.

The reference doc sat one line under its 80-line cap, so the redundant direct-invocation line comes out. SKILL.md already documents those flags, pointing at the script as the owning source.

scripts/forgejo_branch_protection_test.py covers the engine rather than the policy values, so it needed no change.

Verification

ward exec forgejo-branch-protection-test passes (7 tests). pre-commit run --files passes on all three changed files.

Not verified: the live effect. Applying this needs the attended admin-token shell, which this session cannot hold. After merge, run ward exec forgejo-branch-protection -- --dry-run in a real terminal to preview the fleet diff, then apply. Expect one block_on_outdated_branch: False -> True line per protected repo.

If this Forgejo does not report the field back, the converge will name it as skipped rather than rewrite it, and the dry-run output will say so.

closes #815

`DESIRED_RULE` already owned `block_on_outdated_branch` and actively drove it to `False` on every protected repo, so this is a one-value flip rather than a new claim on server state. A pull request that went green against a base which has since moved proves the branch was good, not the merge result. Blocking an outdated head makes the tree CI tested the tree that lands. ## Blast radius Gates merges only. `enable_push` stays `True` and `required_approvals` stays `0`, so this adds no review gate and does not stop anyone pushing a protected branch directly. That matters because the fleet's automated writers push rather than open pull requests: the dispatch implementer lands on `main`, and tap and scoop bumps land on their protected default branches. A grep across the CI of agentic-os, deploy, and infrastructure found no automated pull request merges, so nothing that merges unattended today starts failing. The cost is real but bounded: on a fast-moving repo a pull request needs its branch updated when `main` advances underneath it. Every affected repo already allows update-by-rebase, so the web UI update button covers it. ## Docs The rule's own documentation described it as a force-push and deletion boundary only, which stops being the whole truth. The module docstring, the skill reference, and `SKILL.md` all pick up the merge-side half, and each is careful to keep the still-true part: nothing compels work to arrive as a pull request, so the `pull-request-and-merge` lane stays ungated server-side. What is now gated is how a pull request may merge once one exists. The reference doc sat one line under its 80-line cap, so the redundant direct-invocation line comes out. `SKILL.md` already documents those flags, pointing at the script as the owning source. `scripts/forgejo_branch_protection_test.py` covers the engine rather than the policy values, so it needed no change. ## Verification `ward exec forgejo-branch-protection-test` passes (7 tests). `pre-commit run --files` passes on all three changed files. Not verified: the live effect. Applying this needs the attended admin-token shell, which this session cannot hold. After merge, run `ward exec forgejo-branch-protection -- --dry-run` in a real terminal to preview the fleet diff, then apply. Expect one `block_on_outdated_branch: False -> True` line per protected repo. If this Forgejo does not report the field back, the converge will name it as skipped rather than rewrite it, and the dry-run output will say so. closes #815
feat(forgejo): require branches to be up to date before merge
All checks were successful
TruffleHog / Scan for secrets (pull_request) Successful in 5s
CI / lint (pull_request) Successful in 47s
2dcc553d33
DESIRED_RULE already owned block_on_outdated_branch and drove it to
False on every protected repo. Flip it to True so a pull request whose
base moved cannot merge until its head is updated, making the tree CI
tested the tree that lands.

Gates merges only. enable_push stays True, so the fleet's automated
writers keep landing directly on protected branches: the dispatch
implementer, tap bumps, and scoop bumps all push rather than open a
pull request, and no CI in agentic-os, deploy, or infrastructure merges
a pull request unattended.

The rule's docs described it as a force-push and deletion boundary only,
which stops being the whole truth, so the docstring, the skill reference,
and SKILL.md all pick up the merge-side half. The reference doc was one
line under its cap, so the redundant direct-invocation line comes out;
SKILL.md already documents those flags.

The converge is the rollout and needs the attended admin-token shell.

closes #815

Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
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
coilyco-flight-deck/infrastructure!816
No description provided.