feat(ws): make ruleset bypass actors configurable, move php-sdk to a deploy key - #3
Merged
Merged
Conversation
The branch-protection block built a ruleset with no bypass_actors, so no
configuration could express one. That is why ten repositories carry
releases-to-branch and have RULESET_ENABLED=false: @semantic-release/git pushes
the release commit straight to the default branch, a ruleset would reject it,
and there was no way to let exactly that push past.
RULESET_BYPASS_ACTORS takes <actor_type>:<actor_id>:<bypass_mode>, comma
separated, with actor_id empty for the types GitHub treats as a class rather
than as one actor — DeployKey requires actor_id null, because the bypass is
granted to "a deploy key of this repository", not to one key. The baseline is
empty: no bypass unless a profile asks for one.
Parsed in bash rather than in jq so a malformed entry dies with the entry
quoted. A typo that silently produced no bypass would reject the push the
bypass exists to allow; one that produced the wrong actor would hand the
bypass to someone else.
--check compares the bypass list as well, not just the ruleset's existence. An
actor added by hand in the web UI is drift of exactly the shape that makes
every other rule in the ruleset decorative, and it was invisible. The list is
fetched per ruleset because GET /rulesets returns a summary — bypass_actors
appears only on GET /rulesets/{id}.
_profile-releases-via-deploykey.conf is the one consumer: one line, identical
for every repository that moves, so no repository gets a bypass of its own in
a file nobody else reads.
The repository carried releases-to-branch, which withholds branch protection because @semantic-release/git pushes the release commit to the default branch. It does not use that plugin, so it was giving up branch protection in exchange for an exemption it never needed. Nine repositories are left to migrate, not ten.
php-sdk is the pilot for RSRMID-2994. It is the one repository in the organisation whose REQUIRED_CHECKS are filled in, so it is the only one where the end state — ruleset with real required checks, classic protection gone — is reachable now rather than after RSRMID-2991. Its release also publishes documentation, but to gh-pages, not to the default branch. The ruleset targets ~DEFAULT_BRANCH only, so unlike devcontainer-features this repository needs no second push moved to SSH. The trait switch is inert until scripts/org-settings.sh --apply php-sdk runs. Rollback is this line back to releases-to-branch and another --apply; the deploy key and the secret can stay, they do nothing without the ruleset.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
RSRMID-2994 — the engine change, the new profile, and the first repository to move.
The problem
Ten repositories carry
releases-to-branch, whose only content isRULESET_ENABLED=false.@semantic-release/gitpushes the release commit straight to the default branch, a ruleset would reject it, andscripts/repo-settings.shhad no way to express a bypass — the ruleset it built had nobypass_actorsat all. So those ten repositories came out of centralisation with weaker protection than they went in with, and the push identity isRTLDEV_MW_CI_TOKEN, a personal account's PAT.Three commits
feat(ws): make ruleset bypass actors configurable—RULESET_BYPASS_ACTORS, format<actor_type>:<actor_id>:<bypass_mode>, comma-separated. Empty in_baseline.conf: no bypass unless a profile asks.actor_idis left empty for the types GitHub treats as a class rather than as one actor —DeployKeyrequiresactor_id: null.Two details worth reviewing:
bypass_mode, non-numericactor_id, and@unmanaged.--checknow compares the bypass list, where before it only asked whether the ruleset existed. A bypass actor added by hand in the web UI is drift of exactly the shape that makes every other rule in the ruleset decorative, and it was invisible. The list is fetched per ruleset becauseGET /rulesetsreturns a summary —bypass_actorsappears only onGET /rulesets/{id}.fix(repos): semantic-release-plugins does not push release commits— it carriedreleases-to-branchand does not use@semantic-release/git, so it was giving up branch protection for an exemption it never needed. Nine left to migrate, not ten.feat(repos): move php-sdk's release push to a deploy key— php-sdk takesreleases-via-deploykey. It is the pilot because it is the one repository whoseREQUIRED_CHECKSare filled in, so it is the only one where the end state (ruleset with real required checks, classic protection removed) is reachable now rather than after RSRMID-2991. Its release also publishes docs, but togh-pages, not the default branch — so unlikedevcontainer-featuresit needs no second push moved.Verification
The
--checkrun reports the expected drift and nothing else: ruleset absent on both, plus the pre-existing "classic branch protection is ALSO present" note on php-sdk. The bypass comparison was exercised against a real ruleset (semantic-release-plugins' orphanmain,bypass_actors: []) in both directions — match and drift — and the canonical sort was checked with two actors given in reverse order with stray whitespace.This PR changes nothing on GitHub by itself
The trait switch is inert until
scripts/org-settings.sh --apply php-sdkruns, which is a manual step;repo-settings-drift.ymlonly checks. Until that apply, the weekly drift job will report php-sdk's ruleset as absent.Order
Merge last, after:
RTLDEV_MW_CI_SSH_KEYis set on php-sdk (a deploy key titledsemantic-release, id161381923, is already registered)repositoryUrlat SSHThen
scripts/org-settings.sh --apply php-sdkcreates the ruleset, and--apply semantic-release-pluginspicks up rung 0.Still to do, not in this PR
semantic-release-plugins(id18311775, namedmain,conditions.ref_name.include: []so it matches no branch) has to be deleted by hand — the engine only knows the ruleset it is configured to own.DEBUG: semantic-release:get-git-auth-urlset for the pilot run._profile-releases-to-branch.confis deleted, and the register's trait comment trimmed, once no repository carries it.🤖 Generated with Claude Code