forgejo-repo-settings can never report a repo as ok, because allow_manual_merge is write-only #907

Open
opened 2026-08-23 23:41:33 +00:00 by coilyco-ops · 0 comments
Owner

scripts/forgejo-repo-settings.py declares allow_manual_merge: False in DESIRED_REPO_SETTINGS, but Forgejo's GET /api/v1/repos/{owner}/{repo} does not return that field at all.

repo_settings_diff compares current.get("allow_manual_merge") against False, gets None, and records a difference. So the field is permanently drifted from the converge's point of view.

Observed right after a successful apply. coilyco-gaming/sirens-echo was converged, every other field verified on the server, and allow_manual_merge still reads back as None:

allow_merge_commits                    False
allow_rebase                           False
allow_rebase_explicit                  False
allow_squash_merge                     True
allow_fast_forward_only_merge          True
allow_manual_merge                     None      <- written, never returned
default_merge_style                    'squash'
allow_rebase_update                    True
default_update_style                   'merge'
default_delete_branch_after_merge      True
ignore_whitespace_conflicts            True

Why it matters

The converge is also the audit surface. --dry-run is how drift gets checked, and today every repo reports would-update forever, so a genuine drift is indistinguishable from this artifact. The ok branch in converge_repo is unreachable in practice.

It also makes each run write all 11 fields to all 32 repos regardless of need.

Options

  1. Drop allow_manual_merge from DESIRED_REPO_SETTINGS. It is already covered by allow_merge_commits: False plus branch protection, and the policy loses nothing readable.
  2. Keep writing it but exclude it from the diff, with a comment saying the field is write-only on this API.

Option 1 is simpler and I would take it, but it narrows the declared policy by one field, so it wants a decision rather than a drive-by edit.

Found while converging sirens-echo for coilysiren/inbox#398.

`scripts/forgejo-repo-settings.py` declares `allow_manual_merge: False` in `DESIRED_REPO_SETTINGS`, but Forgejo's `GET /api/v1/repos/{owner}/{repo}` does not return that field at all. `repo_settings_diff` compares `current.get("allow_manual_merge")` against `False`, gets `None`, and records a difference. So the field is permanently drifted from the converge's point of view. Observed right after a successful apply. `coilyco-gaming/sirens-echo` was converged, every other field verified on the server, and `allow_manual_merge` still reads back as `None`: ``` allow_merge_commits False allow_rebase False allow_rebase_explicit False allow_squash_merge True allow_fast_forward_only_merge True allow_manual_merge None <- written, never returned default_merge_style 'squash' allow_rebase_update True default_update_style 'merge' default_delete_branch_after_merge True ignore_whitespace_conflicts True ``` ## Why it matters The converge is also the audit surface. `--dry-run` is how drift gets checked, and today every repo reports `would-update` forever, so a genuine drift is indistinguishable from this artifact. The `ok` branch in `converge_repo` is unreachable in practice. It also makes each run write all 11 fields to all 32 repos regardless of need. ## Options 1. Drop `allow_manual_merge` from `DESIRED_REPO_SETTINGS`. It is already covered by `allow_merge_commits: False` plus branch protection, and the policy loses nothing readable. 2. Keep writing it but exclude it from the diff, with a comment saying the field is write-only on this API. Option 1 is simpler and I would take it, but it narrows the declared policy by one field, so it wants a decision rather than a drive-by edit. Found while converging sirens-echo for `coilysiren/inbox#398`.
Sign in to join this conversation.
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#907
No description provided.