Introducing Rampart: Branch Protection Rules Across All Your Repos

I have too many GitHub repos with no branch protection at all. Most of them are personal projects where it doesn’t matter much, but a few have collaborators, are depended on by other projects, or are public-facing enough that I’d really prefer nobody (including me) force-pushes to main by accident.

The GitHub UI makes it easy to set branch protection for one repo. But doing it consistently across thirty repos is tedious. And keeping them consistent over time - when new repos get created, when you decide to change a rule, when you want to check that nothing has drifted - is the kind of thing that only works if it’s automated.

So I built rampart.

What It Does

Rampart is a CLI tool that audits and enforces GitHub branch protection rules across all repos for a user or organization. You define your desired rules in a YAML config file, and rampart tells you which repos are compliant and which aren’t. If you want, it’ll fix the non-compliant ones too.

The workflow is simple:

# Generate a config with sensible defaults
rampart init

# Check all your repos
rampart audit --owner wdm0006

# Fix the ones that don't match
rampart apply --owner wdm0006

The audit command exits non-zero when any repos are non-compliant, so you can run it in CI as a drift detector.

The Config

rampart.yaml defines the branch you want to protect and the rules to enforce:

branch: main
rules:
  require_pull_request: true
  required_approvals: 1
  dismiss_stale_reviews: true
  require_code_owner_reviews: false
  require_status_checks: false
  strict_status_checks: true
  required_checks: []
  enforce_admins: true
  allow_force_pushes: false
  allow_deletions: false
  required_linear_history: false
  required_conversation_resolution: false

The defaults are opinionated toward “protect main from accidents without being annoying”: require a PR with one approval, enforce rules for admins too, don’t allow force pushes or deletions. Status checks are off by default because not every repo has CI configured.

How Audit Works

When you run rampart audit, it:

  1. Lists all non-fork, non-archived repos for the owner
  2. Fetches the current branch protection rules for each
  3. Compares each rule against your config
  4. Shows pass/fail per repo with details on what’s different
Auditing 24 repos against rampart.yaml (branch: main)

  ✓ pygeohash
  ✓ elote
  ✗ keeks
      enforce_admins: want true, got false
      allow_force_pushes: want false, got true
  ✓ vanity
  - old-project (skipped: insufficient permissions)

Results: 21 compliant, 2 non-compliant, 1 skipped out of 24 repos

Repos where you don’t have admin access get skipped with a note rather than failing the whole run. Repos with no protection configured at all show up as non-compliant with every rule diffed against the zero state.

Apply and Dry Run

Once you know what’s out of compliance, rampart apply fixes it:

# Preview what would change
rampart apply --owner wdm0006 --dry-run

# Actually apply
rampart apply --owner wdm0006

You can also target a single repo or exclude specific ones:

rampart apply --owner wdm0006 --repo keeks
rampart audit --owner wdm0006 --exclude legacy-thing --exclude experiment

Implementation

Rampart follows the same pattern as vanity: a Go CLI that wraps the gh CLI for all GitHub API calls. No SDK, no OAuth setup, no token management. If gh auth login works, rampart works.

It’s installable via Homebrew:

brew install wdm0006/tap/rampart

Or grab a binary from the releases page, or go install:

go install github.com/wdm0006/rampart/cmd/rampart@latest

Why Not Terraform?

If you manage GitHub repos at scale, you might already use Terraform with the GitHub provider. That works well for organizations with dedicated infrastructure teams. Rampart is for the rest of us - individual maintainers and small teams who want a quick way to check and enforce a baseline without setting up state files and plan/apply cycles.

The YAML config is the entire state. There’s no drift to reconcile. You run audit, see the diff, and decide whether to apply.

Check out the repo: github.com/wdm0006/rampart