Rampart v0.8: Full Fleet Coverage and Better Ruleset Support

Rampart v0.8 is out. It audits your private repos, handles GitHub rulesets correctly, catches mistakes in your config file, and behaves properly in CI.

If you have not run into it before, rampart is a single Go binary that reads a rampart.yaml describing the branch protection you want, then checks every repo you own against it and optionally fixes the ones that do not match.

brew install wdm0006/tap/rampart
rampart init
rampart audit --owner myuser

Your Whole Fleet, Private Repos Included

When you audit your own account, rampart now covers your private repositories along with the public ones. On my account that took the audit from 41 repos to 88.

$ rampart audit --owner wdm0006
Fetching repos for wdm0006...
Auditing 88 repos against rampart.yaml (branch: default)

  ✗ abetaday
      require_pull_request: want true, got false
      required_approvals: want 1, got 0
      enforce_admins: want true, got false
...
Results: 0 compliant, 88 non-compliant, 0 skipped out of 88 repos

Private repos are usually where the interesting gaps are, since they tend to be the ones you spun up quickly and never went back to configure. Organizations already worked this way. Auditing another user’s account still shows their public repos only, which is all GitHub exposes.

Forks and archived repos stay excluded, so the count you get is the set of repos you can actually act on.

Rulesets Work Like You Would Expect

GitHub has two branch protection systems, classic protection and the newer rulesets API, and plenty of repos use rulesets exclusively. Three things got better there.

enforce_admins is now audited correctly for ruleset-protected repos. Rulesets do not have an enforce_admins field, so rampart reads each contributing ruleset’s bypass actors to work out whether admins are actually exempt. Repos protected purely through rulesets now report accurately instead of always failing that check.

apply finds and updates its existing ruleset reliably. Rampart manages a ruleset named rampart, and the lookup is paginated now, so on a repo with a lot of rulesets it updates the one it already made rather than adding a second one.

Rampart also fails loudly if it cannot read a repo’s ruleset state, so a partial view of GitHub never gets reported as a passing audit.

Config Mistakes Get Caught

Rampart now rejects unknown keys in rampart.yaml instead of ignoring them:

$ rampart audit --owner wdm0006
Error: failed to parse config: yaml: unmarshal errors:
  line 3: field enforce_admin not found in type config.Config

Misspell a rule name and you hear about it immediately, rather than believing a rule is enforced when it was never parsed. Malformed glob patterns in your repo overrides are caught the same way:

rules:
  require_pull_request: true
  required_approvals: 1
  enforce_admins: true

overrides:
  - repos: ["prod-*", "infra-*"]
    rules:
      required_approvals: 2
  - repos: ["docs-site"]
    rules:
      require_pull_request: false

Worth running rampart audit once right after you upgrade. If your config has anything stale in it, that is when you will find out.

Reliable in CI

rampart apply returns a nonzero exit status when repository updates fail, so a scheduled job actually goes red instead of quietly reporting success:

- name: Enforce branch protection
  run: rampart apply --owner myorg

If another ruleset or classic protection holds a repo stricter than your config, apply now tells you it cannot converge rather than reporting a successful update that changed nothing.

Report output is deterministic too. Merged required_checks used to come back in random order, so two audits of an unchanged fleet produced different text and different HTML. Now you can diff rampart audit --report output across runs and only see real drift.

Getting It

brew install wdm0006/tap/rampart
brew upgrade rampart          # if you already have it

Binaries for macOS, Linux, and Windows on amd64 and arm64 are on the releases page. Full config reference is in rampart config, and the source is on GitHub.