feat(forgejo): make branch protection a real create-read-update converge #780

Merged
coilysiren merged 2 commits from aos/claude/qa57-branch-protection into main 2026-08-11 22:03:21 +00:00
Member

The converge only ever sent {rule_name, enable_push}, so its diff covered those two fields and nothing else. A rule hand-edited to add a push allowlist, require approvals, or block on outdated branches showed no drift and reported ok.

DESIRED_RULE now declares every field the policy owns and drives each to that value. Scope is unchanged and already covers every active repo under the four owners, including the 14 carrying no rule at all today.

Supporting fixes:

  • A field this Forgejo does not report back is skipped and named in the output, rather than diffed forever without converging.
  • List fields compare order-insensitively.
  • rule_name is sent on create only.
  • Every write is re-read and re-compared. A repo that did not converge reports fail.

Status checks are out of scope

This converge does not own enable_status_check or status_check_contexts. PR_REQUIRED_STATUS_CONTEXTS, PR_STATUS_CONTEXT_PREREQUISITES, and their accessors are removed, so whatever contexts a repo carries on the server are left exactly as they are, and setting a required PR context is a hand edit in the web UI. coilyco-flight-deck/agentic-os and coilyco-flight-deck/ward keep their existing contexts under that arrangement, now unmanaged.

New ward exec forgejo-branch-protection-test covers the engine offline, 7 cases, no live calls. It asserts drift-detection behavior rather than restating the policy values, which stay owned by DESIRED_RULE.

Docs corrected: both the skill and its reference doc claimed existing rules are "left untouched", which the code already contradicted, and the reference doc restated the rule's field values in prose. Also states plainly that this rule does not block pushes to main, verified live during the fleet sweep.

Not run against live Forgejo from this session: the apply needs the attended ward exec forgejo-admin-token shell. Run dry_run=1 first, the diff output is per-field.

refs coilyco-flight-deck/agentic-os#994

The converge only ever sent `{rule_name, enable_push}`, so its diff covered those two fields and nothing else. A rule hand-edited to add a push allowlist, require approvals, or block on outdated branches showed no drift and reported `ok`. `DESIRED_RULE` now declares every field the policy owns and drives each to that value. Scope is unchanged and already covers every active repo under the four owners, including the 14 carrying no rule at all today. Supporting fixes: * A field this Forgejo does not report back is skipped and named in the output, rather than diffed forever without converging. * List fields compare order-insensitively. * `rule_name` is sent on create only. * Every write is re-read and re-compared. A repo that did not converge reports `fail`. ## Status checks are out of scope This converge does not own `enable_status_check` or `status_check_contexts`. `PR_REQUIRED_STATUS_CONTEXTS`, `PR_STATUS_CONTEXT_PREREQUISITES`, and their accessors are removed, so whatever contexts a repo carries on the server are left exactly as they are, and setting a required PR context is a hand edit in the web UI. `coilyco-flight-deck/agentic-os` and `coilyco-flight-deck/ward` keep their existing contexts under that arrangement, now unmanaged. New `ward exec forgejo-branch-protection-test` covers the engine offline, 7 cases, no live calls. It asserts drift-detection behavior rather than restating the policy values, which stay owned by `DESIRED_RULE`. Docs corrected: both the skill and its reference doc claimed existing rules are "left untouched", which the code already contradicted, and the reference doc restated the rule's field values in prose. Also states plainly that this rule does not block pushes to `main`, verified live during the fleet sweep. Not run against live Forgejo from this session: the apply needs the attended `ward exec forgejo-admin-token` shell. Run `dry_run=1` first, the diff output is per-field. refs coilyco-flight-deck/agentic-os#994
feat(forgejo): make branch protection a real create-read-update converge
All checks were successful
TruffleHog / Scan for secrets (pull_request) Successful in 4s
CI / lint (pull_request) Successful in 1m14s
5d62acc333
The converge only ever sent {rule_name, enable_push}, so the diff it compared
against the live rule covered those two fields and nothing else. A rule
hand-edited in the web UI to add a push allowlist, require approvals, or block
on outdated branches showed no drift and reported `ok`. Status contexts had the
same gap in reverse: dropping a repo from the map left its stale contexts on
the server forever.

DESIRED_RULE now declares every field the policy owns and each is driven to
that value, so drift is corrected rather than accepted. Scope is unchanged and
already covers every active repo under the four owners, including the 14
currently carrying no rule at all.

Three supporting fixes:

* A field the running Forgejo does not report back is skipped and named in the
  output. Diffing an absent field would report drift on every run and never
  converge.
* List fields compare order-insensitively, so context ordering is not drift.
* rule_name is sent on create only. The edit endpoint takes the branch from the
  URL, and keeping it out of the desired state stops it being diffed against a
  response field that may be spelled branch_name.

Every write is now re-read and re-compared. A repo that did not converge
reports `fail` instead of a success it did not earn.

Docs corrected while here. Both the skill and its reference doc said existing
rules are "left untouched", which the code already contradicted, and the
reference doc restated the rule's field values in prose. That duplication is
gone: DESIRED_RULE is the owning source.

Also states plainly that this rule does not block pushes to main, which was
mistaken elsewhere. Verified live during the fleet sweep: ordinary pushes land
on protected factorio-mods, inbox, and scoop-bucket.

refs coilyco-flight-deck/agentic-os#994

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
refactor(forgejo): drop status checks from the branch-protection converge
All checks were successful
TruffleHog / Scan for secrets (pull_request) Successful in 5s
CI / lint (pull_request) Successful in 1m11s
631d28758a
The converge no longer owns enable_status_check or status_check_contexts.
PR_REQUIRED_STATUS_CONTEXTS, PR_STATUS_CONTEXT_PREREQUISITES, and their two
accessors are gone, so whatever contexts a repo carries on the server are left
exactly as they are and a required PR context becomes a hand edit in the web UI.

desired_protection now takes no repo, since the policy is uniform once status
checks leave. note_formatter loses its full_name argument for the same reason.

Tests drop the three status-check cases. The list-ordering case moves to
synthetic fields because every list the policy still owns is empty, which left
nothing to reverse.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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!780
No description provided.