agentsclimarketplace

Branch ruleset setup

Skill emaarco/hogwarts/plugins/felix-felicis/skills/branch-ruleset-setup

A magical place where my skills, rules, and plugins for AI agents are defined, which magically boost productivity 🏰πŸͺ„

Install
npx -y skills add emaarco/hogwarts --skill branch-ruleset-setup

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Sets up a GitHub branch ruleset protecting the default branch via the gh CLI: no deletion, no force-push, linear history, signed commits, PR-only changes, and a required CI status check with a dynamically resolved integration_id. Idempotent β€” creates the ruleset or updates an existing one. Use when asked to protect the default branch, set up branch protection or rulesets, or require status checks before merge.

SKILL.md

6.6 KB, as published. Nobody here has run it

Skill: branch-ruleset-setup

Configures a repository ruleset (not classic branch protection) named main targeting the default branch (~DEFAULT_BRANCH). Everything runs through the gh CLI with the ruleset passed as inline JSON via heredoc β€” never create a ruleset JSON file in the repo.

Run this when asked to "protect main", set up branch protection / a branch ruleset, or as the branch-protection slice of a release/supply-chain audit (see the sibling skill release-audit).

Precondition: gh auth status must be authenticated with admin rights on the target repo.

Phase 0 β€” Ensure a referenceable CI check exists

A required status check only makes sense if the CI job actually exists. Never hardcode the check name β€” detect it:

ls .github/workflows/ 2>/dev/null
grep -rl "pull_request" .github/workflows/ 2>/dev/null
  • A pull_request-triggered workflow exists β†’ note its job name (= the status-check context). If the job is called ci or test instead of build, use that name below.

  • No workflow exists β†’ create a minimal one first, commit it to the default branch, and let it run at least once so the check context exists. Example (.github/workflows/build.yml β€” adapt steps to the repo's actual stack):

    name: Build
    on:
      pull_request:
        branches: [main]
    jobs:
      build:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v6
          - uses: actions/setup-node@v6
            with:
              node-version: '24'
          - run: npm ci
          - run: npm test
          - run: npm run build
    

Phase 1 β€” Resolve the integration_id dynamically

The check is reported by GitHub Actions, whose app ID can vary by context β€” never hardcode a number like 15368:

ACTIONS_APP_ID=$(gh api /apps/github-actions --jq .id)
echo "GitHub Actions integration_id = ${ACTIONS_APP_ID}"

If the check is reported by a different CI provider, resolve its app ID from a commit where the check already ran:

gh api repos/{owner}/{repo}/commits/<sha>/check-runs --jq '.check_runs[] | {name, app: .app.id}'

Phase 2 β€” Check for an existing ruleset (idempotency)

RULESET_ID=$(gh api repos/{owner}/{repo}/rulesets --jq '.[] | select(.name=="main") | .id')
  • Empty β†’ create with POST (Phase 3).
  • Present β†’ update with PUT on .../rulesets/${RULESET_ID} β€” same body, different method/URL β€” so no duplicate is created.

Phase 3 β€” Create or update the ruleset

The integration_id is injected via an unquoted heredoc (<<JSON without quotes is intentional β€” only then does ${ACTIONS_APP_ID} expand; the body contains no other $):

gh api --method POST repos/{owner}/{repo}/rulesets \
  -H "Accept: application/vnd.github+json" --input - <<JSON
{
  "name": "main",
  "target": "branch",
  "enforcement": "active",
  "conditions": {
    "ref_name": { "include": ["~DEFAULT_BRANCH"], "exclude": [] }
  },
  "rules": [
    { "type": "deletion" },
    { "type": "non_fast_forward" },
    { "type": "required_linear_history" },
    { "type": "required_signatures" },
    {
      "type": "pull_request",
      "parameters": {
        "required_approving_review_count": 0,
        "dismiss_stale_reviews_on_push": false,
        "require_code_owner_review": false,
        "require_last_push_approval": false,
        "required_review_thread_resolution": false,
        "allowed_merge_methods": ["merge", "squash", "rebase"]
      }
    },
    {
      "type": "required_status_checks",
      "parameters": {
        "strict_required_status_checks_policy": false,
        "do_not_enforce_on_create": false,
        "required_status_checks": [
          { "context": "build", "integration_id": ${ACTIONS_APP_ID} }
        ]
      }
    }
  ],
  "bypass_actors": []
}
JSON

Replace "build" with the actual job name from Phase 0.

Phase 4 β€” Verify

RULESET_ID=$(gh api repos/{owner}/{repo}/rulesets --jq '.[] | select(.name=="main") | .id')
gh api repos/{owner}/{repo}/rulesets/${RULESET_ID} --jq '{enforcement, target}'
gh api repos/{owner}/{repo}/rulesets/${RULESET_ID} --jq '.rules[].type'
gh api repos/{owner}/{repo}/rulesets/${RULESET_ID} \
  --jq '.rules[] | select(.type=="required_status_checks") | .parameters.required_status_checks'

Success criteria:

  • Exactly one ruleset main, enforcement: active, target: branch, targeting ~DEFAULT_BRANCH.
  • .rules[].type contains: deletion, non_fast_forward, required_linear_history, required_signatures, pull_request, required_status_checks.
  • The required status check has the correct context (job name from Phase 0) and a resolved integration_id (not empty, not hardcoded).

What the rules do & how to adapt them

RuleEffectAdapt when
deletionDefault branch cannot be deletedβ€”
non_fast_forwardNo force-pushesβ€”
required_linear_historyLinear history enforcedDrop if the team uses merge commits from long-lived branches
required_signaturesCommits must be signed (GPG/SSH/S-MIME)Requires signing to be set up for all committers β€” otherwise pushes/merges are rejected; drop if not. Note: commits made via the API by GitHub Apps (e.g. release-please with an app token β€” see release-please-setup) are signed by GitHub automatically
pull_requestChanges only via PR; 0 approvals by defaultRaise required_approving_review_count to 1+ for teams
required_status_checksCI check must be green before mergeOmit integration_id to match any provider reporting that context (less strict); remove the whole block if there is no CI
bypass_actors: []Nobody can bypass, not even adminsAdd e.g. { "actor_id": <id>, "actor_type": "Team", "bypass_mode": "always" } for a deliberate bypass

Sources

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.