Skip to content

Update an existing ruleset instead of failing to create a second one - #39

Merged
oetiker merged 1 commit into
mainfrom
fix/ruleset-update
Aug 24, 2026
Merged

Update an existing ruleset instead of failing to create a second one#39
oetiker merged 1 commit into
mainfrom
fix/ruleset-update

Conversation

@oetiker

@oetiker oetiker commented Aug 24, 2026

Copy link
Copy Markdown
Member

Found finishing the oposs/mkp-builder conversion — the second defect that only using apply on a real repository could surface.

$ repo_infra apply --item required-checks
gh: Validation Failed (HTTP 422)

The repository already had a ruleset named main. POST creates; it cannot adopt.

This is not an edge case

It is every repository that was protected before it was converted — and check says so on the line directly above:

  branch-protection     ok
  required-checks       missing    the ruleset does not require changelog-updated or ci-passed

Both facts are read from the same ruleset. The one that reads ok is the one the POST collides with. mkp-builder’s existing ruleset was the standard’s payload minus the required_status_checks rule, which is exactly why required-checks was the item still outstanding.

Fix

Gh.ruleset_id looks for a Repository-source ruleset of that name. PUT to it when there is one, POST when there is not.

An organisation ruleset is deliberately not adopted: it cannot be written through the repository endpoint, and its name does not collide with a repository one.

Every guard on the POST path is on the PUT path — they are the same code after the call — so a ruleset that comes back disabled, bypassed, not covering the default branch, or missing a required context is still refused. A test pins that for the PUT path specifically, because "the write did not error" was never the evidence here.

Evidence

Injected Result
always POST (the original bug) 1 failed
always PUT to whatever is listed first 3 failed
adopt an organisation ruleset too 1 failed
read-back stripped of required_status_checks on the PUT path refused, as designed

290 passed, 5 deselected, uvx ruff check . clean.

🤖 Generated with Claude Code

Found finishing the `oposs/mkp-builder` conversion. `apply --item
required-checks` died with `gh: Validation Failed (HTTP 422)`: the repository
already had a ruleset named `main`, and POST creates rather than adopts.

This is not an edge case. It is every repository that was protected before it
was converted, and `check` says so on the line above -- `branch-protection ok`
is read from exactly the ruleset the POST then collides with. mkp-builder's
existing ruleset was the standard's payload minus the required_status_checks
rule, which is the whole reason `required-checks` was the item still missing.

`Gh.ruleset_id` looks for a Repository-source ruleset of that name; PUT to it
when there is one, POST when there is not. An organisation ruleset is not
adopted: it cannot be written through this endpoint and its name does not
collide with a repository one.

Every guard on the POST path is on the PUT path, because they are the same
code after the call -- the read-back that rejects a ruleset which comes back
disabled, bypassed, not covering the default branch, or missing the required
contexts. A test pins that for the PUT path specifically.

Four fault injections, each confirmed red: always POST, always PUT, adopt an
organisation ruleset, and the read-back on the PUT path.

290 tests, ruff clean.
@oetiker
oetiker merged commit cb87cc6 into main Aug 24, 2026
7 checks passed
@oetiker
oetiker deleted the fix/ruleset-update branch August 24, 2026 13:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant