Skip to content

Add branch protection ruleset as code#1992

Closed
nicolasnoble wants to merge 1 commit intogrumpycoders:mainfrom
nicolasnoble:add-ruleset
Closed

Add branch protection ruleset as code#1992
nicolasnoble wants to merge 1 commit intogrumpycoders:mainfrom
nicolasnoble:add-ruleset

Conversation

@nicolasnoble
Copy link
Member

Store the main branch required status checks and protection rules in a JSON file
that can be imported via the GitHub API, replacing manual UI configuration.

To apply: gh api --method POST -H "Accept: application/vnd.github+json" /repos/grumpycoders/pcsx-redux/rulesets --input .github/rulesets/main.json

Changes from current UI config:

  • Drops stale macos-intel-build-and-test check
  • Includes full protection rules (deletion, non-fast-forward, PR reviews)

Store the main branch required status checks and protection rules
in a JSON file that can be imported via the GitHub API, replacing
manual UI configuration. Drops the stale macos-intel-build-and-test
check.

Signed-off-by: Nicolas 'Pixel' Noble <nicolas@nobis-crew.org>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 24, 2026

📝 Walkthrough

Walkthrough

A new GitHub branch ruleset configuration file is added at .github/rulesets/main.json to enforce protection rules on the main branch, including deletion restrictions, non-fast-forward prevention, pull request approval requirements, and mandatory status checks across nine build contexts.

Changes

Cohort / File(s) Summary
GitHub Ruleset Configuration
.github/rulesets/main.json
New branch protection ruleset for the main branch with enforcement rules for deletion prevention, non-fast-forward pushes, PR approval requirements (1 review), and nine required status checks.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~5 minutes

Poem

🐰 Branch protection rules now in place,
The main branch safe from reckless pace,
Reviews required, fast-forwards banned,
Deletions thwarted by rules so grand,
A ruleset strong to guard our ways,
Keeping code safe through all our days! 🛡️

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add branch protection ruleset as code' clearly and concisely summarizes the main change: adding a JSON configuration file for branch protection rules that replaces manual UI configuration.
Description check ✅ Passed The description is directly related to the changeset, explaining the purpose of the new JSON file, providing implementation instructions, and detailing specific changes from the current UI configuration.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
.github/rulesets/main.json (1)

1-74: Test the ruleset import before applying to main.

After correcting the status check contexts, test the import command safely before enforcing on the main branch:

  1. First, validate the JSON syntax: jq empty .github/rulesets/main.json
  2. Consider testing with a temporary branch pattern first by modifying line 7 to "include": ["test-*"] and verifying with a test branch
  3. Or use a dry-run approach by checking existing rulesets first: gh api repos/grumpycoders/pcsx-redux/rulesets
  4. Only after verification, import the actual ruleset for the main branch

This prevents accidentally blocking all PRs due to misconfigured status checks.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/rulesets/main.json around lines 1 - 74, Validate and test the
ruleset JSON and import process before applying to the default branch: run a
JSON syntax check on the document and confirm the "ref_name" include value
(currently "~DEFAULT_BRANCH") is correct; temporarily change
"ref_name"."include" to "test-*" and apply to a test branch to verify the
"required_status_checks" array and contexts behave as expected; alternatively
list existing rulesets via the API (e.g., using gh api) to perform a dry-run
validation before importing; only restore "ref_name"."include" back to
"~DEFAULT_BRANCH" and import the ruleset to enforce on main once verified.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/rulesets/main.json:
- Around line 44-63: Update the status check context strings to match GitHub
Actions' reported names so the required checks map to actual workflow job names:
replace "build-openbios" with "macOS CI / build-openbios", "build" with "Linux
CI / build", "coverage" with "Linux CI coverage / coverage", "cross-arm64" with
"Linux CI cross / cross-arm64", "asan" with "Linux CI asan / asan", and
"toolchain" with "Linux CI toolchain / toolchain" for the entries that share
integration_id 15368 so the contexts match the workflow "workflow-name / job-id"
format and allow the checks to pass.

---

Nitpick comments:
In @.github/rulesets/main.json:
- Around line 1-74: Validate and test the ruleset JSON and import process before
applying to the default branch: run a JSON syntax check on the document and
confirm the "ref_name" include value (currently "~DEFAULT_BRANCH") is correct;
temporarily change "ref_name"."include" to "test-*" and apply to a test branch
to verify the "required_status_checks" array and contexts behave as expected;
alternatively list existing rulesets via the API (e.g., using gh api) to perform
a dry-run validation before importing; only restore "ref_name"."include" back to
"~DEFAULT_BRANCH" and import the ruleset to enforce on main once verified.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 71adcb2d-090f-4935-b7bd-eeef844284f1

📥 Commits

Reviewing files that changed from the base of the PR and between a7d01bb and 33e7fe8.

📒 Files selected for processing (1)
  • .github/rulesets/main.json

Comment on lines +44 to +63
{
"context": "build-openbios",
"integration_id": 15368
},
{
"context": "build",
"integration_id": 15368
},
{
"context": "coverage",
"integration_id": 15368
},
{
"context": "cross-arm64",
"integration_id": 15368
},
{
"context": "asan",
"integration_id": 15368
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Extract workflow names and job IDs to determine correct status check contexts

echo "=== GitHub Actions Workflows and Jobs ==="
echo

for workflow in .github/workflows/*.yml .github/workflows/*.yaml; do
  if [ -f "$workflow" ]; then
    echo "File: $workflow"
    echo -n "  Workflow name: "
    gawk '/^name:/ {gsub(/^name: */, ""); gsub(/"/, ""); print; exit}' "$workflow"
    echo "  Job IDs:"
    gawk '/^jobs:/,/^[^ ]/ {if ($0 ~ /^  [a-zA-Z0-9_-]+:$/) {gsub(/:/, ""); gsub(/^  /, ""); print "    - " $0}}' "$workflow"
    echo
  fi
done

Repository: grumpycoders/pcsx-redux

Length of output: 1043


🏁 Script executed:

#!/bin/bash
# Extract job definitions from workflow files more reliably

echo "=== Job Extraction from Workflows ==="
echo

for workflow in .github/workflows/macos-build.yml .github/workflows/linux-build.yml .github/workflows/linux-coverage.yml .github/workflows/linux-asan.yml .github/workflows/linux-cross.yml .github/workflows/linux-toolchain.yml; do
  if [ -f "$workflow" ]; then
    echo "File: $(basename $workflow)"
    echo -n "  Workflow name: "
    grep "^name:" "$workflow" | head -1 | sed 's/^name: *//; s/"//g'
    echo "  Jobs:"
    # Use a more robust approach: find job IDs and check for explicit 'name:' fields
    python3 << 'PYSCRIPT'
import sys
import re

workflow = sys.argv[1]
with open(workflow) as f:
    content = f.read()

# Parse YAML-like structure
lines = content.split('\n')
in_jobs = False
current_job = None

for i, line in enumerate(lines):
    if line.startswith('jobs:'):
        in_jobs = True
        continue
    
    if in_jobs and line and not line[0].isspace():
        break
    
    if in_jobs and re.match(r'^  [a-zA-Z0-9_-]+:', line):
        current_job = line.strip().rstrip(':')
        job_name = None
        # Look ahead for explicit 'name:' field
        for j in range(i+1, min(i+10, len(lines))):
            if re.match(r'^    name:', lines[j]):
                job_name = lines[j].split('name:')[1].strip().strip("'\"")
                break
            if re.match(r'^  [a-zA-Z0-9_-]+:', lines[j]):
                break
        
        if job_name:
            print(f"    - {current_job} (name: {job_name})")
        else:
            print(f"    - {current_job}")

PYSCRIPT
  fi
done

Repository: grumpycoders/pcsx-redux

Length of output: 1148


🏁 Script executed:

cat -n .github/rulesets/main.json | grep -A 2 -B 2 '"context"'

Repository: grumpycoders/pcsx-redux

Length of output: 1273


🏁 Script executed:

echo "=== macos-build.yml jobs ===" && sed -n '/^jobs:/,/^[^ ]/p' .github/workflows/macos-build.yml | head -20
echo ""
echo "=== linux-build.yml jobs ===" && sed -n '/^jobs:/,/^[^ ]/p' .github/workflows/linux-build.yml | head -20
echo ""
echo "=== linux-coverage.yml jobs ===" && sed -n '/^jobs:/,/^[^ ]/p' .github/workflows/linux-coverage.yml | head -20
echo ""
echo "=== linux-asan.yml jobs ===" && sed -n '/^jobs:/,/^[^ ]/p' .github/workflows/linux-asan.yml | head -20
echo ""
echo "=== linux-cross.yml jobs ===" && sed -n '/^jobs:/,/^[^ ]/p' .github/workflows/linux-cross.yml | head -20
echo ""
echo "=== linux-toolchain.yml jobs ===" && sed -n '/^jobs:/,/^[^ ]/p' .github/workflows/linux-toolchain.yml | head -20

Repository: grumpycoders/pcsx-redux

Length of output: 4057


🏁 Script executed:

for workflow in .github/workflows/macos-build.yml .github/workflows/linux-build.yml .github/workflows/linux-coverage.yml .github/workflows/linux-asan.yml .github/workflows/linux-cross.yml .github/workflows/linux-toolchain.yml; do
  echo "=== $(basename $workflow) ===" 
  # Extract job section and check for 'name:' fields at job level (4 spaces indent)
  sed -n '/^jobs:/,/^[^ ]/p' "$workflow" | grep -E "^  [a-zA-Z0-9_-]+:|^    name:" | head -10
  echo ""
done

Repository: grumpycoders/pcsx-redux

Length of output: 395


🏁 Script executed:

# Check if there's any Windows build workflow in GitHub Actions
ls -la .github/workflows/ | grep -i windows
echo ""
echo "Windows build checks in ruleset:"
grep -B 1 -A 1 '"integration_id": 9426' .github/rulesets/main.json

Repository: grumpycoders/pcsx-redux

Length of output: 404


🏁 Script executed:

# Verify the exact behavior by checking GitHub Actions documentation
# Also double-check if any of the jobs have name: fields deeper in their definitions
for job_section in "build-openbios" "build" "coverage" "asan" "cross-arm64" "toolchain"; do
  echo "=== Checking for 'name:' in job definitions ==="
  grep -n "name:" .github/workflows/*.yml | grep -i "$job_section" | head -5
done

Repository: grumpycoders/pcsx-redux

Length of output: 1474


🏁 Script executed:

# Check macos-build.yml for build-openbios job definition
echo "=== macos-build.yml: build-openbios job ===" 
sed -n '/^  build-openbios:/,/^  [a-z]/p' .github/workflows/macos-build.yml | head -20

echo ""
echo "=== linux-build.yml: build job ===" 
sed -n '/^  build:/,/^  [a-z]/p' .github/workflows/linux-build.yml | head -20

echo ""
echo "=== linux-coverage.yml: coverage job ===" 
sed -n '/^  coverage:/,/^  [a-z]/p' .github/workflows/linux-coverage.yml | head -20

Repository: grumpycoders/pcsx-redux

Length of output: 2126


Critical: Status check names won't match GitHub Actions reporting.

The status check context names for GitHub Actions jobs (integration_id 15368) don't match how GitHub actually reports them. When a workflow job has no explicit name: field, GitHub reports the check as "workflow-name / job-id", not just "job-id".

Based on the workflow configurations:

  • Line 45: "build-openbios" should be "macOS CI / build-openbios"
  • Line 49: "build" should be "Linux CI / build"
  • Line 53: "coverage" should be "Linux CI coverage / coverage"
  • Line 57: "cross-arm64" should be "Linux CI cross / cross-arm64"
  • Line 61: "asan" should be "Linux CI asan / asan"
  • Line 65: "toolchain" should be "Linux CI toolchain / toolchain"

Without correction, these required checks will never pass and PRs will be permanently blocked from merging.

🔧 Proposed fix
         {
-          "context": "build-openbios",
+          "context": "macOS CI / build-openbios",
           "integration_id": 15368
         },
         {
-          "context": "build",
+          "context": "Linux CI / build",
           "integration_id": 15368
         },
         {
-          "context": "coverage",
+          "context": "Linux CI coverage / coverage",
           "integration_id": 15368
         },
         {
-          "context": "cross-arm64",
+          "context": "Linux CI cross / cross-arm64",
           "integration_id": 15368
         },
         {
-          "context": "asan",
+          "context": "Linux CI asan / asan",
           "integration_id": 15368
         },
         {
-          "context": "toolchain",
+          "context": "Linux CI toolchain / toolchain",
           "integration_id": 15368
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/rulesets/main.json around lines 44 - 63, Update the status check
context strings to match GitHub Actions' reported names so the required checks
map to actual workflow job names: replace "build-openbios" with "macOS CI /
build-openbios", "build" with "Linux CI / build", "coverage" with "Linux CI
coverage / coverage", "cross-arm64" with "Linux CI cross / cross-arm64", "asan"
with "Linux CI asan / asan", and "toolchain" with "Linux CI toolchain /
toolchain" for the entries that share integration_id 15368 so the contexts match
the workflow "workflow-name / job-id" format and allow the checks to pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant