repo-policy
Lightweight, declarative repository governance for GitHub. Define expected branch protection and ruleset configuration in YAML; audit, preview, and apply it locally or in CI.
Not a Terraform replacement — no state file, no backend. repo-policy is safe to adopt
incrementally on a live repository: by default it only ever touches branches you declare, and
never deletes anything you didn't ask it to manage.
Install
pip install repo-policy
Quick start
# policy.yml
version: 1
branches:
main:
pull_requests:
required: true
approvals: 2
code_owner_review: true
status_checks:
required: [build, test]
signed_commits: true
linear_history: true
allow_force_push: false
allow_deletion: false
repo-policy validate
repo-policy audit --repo acme/widgets
repo-policy plan --repo acme/widgets
repo-policy apply --repo acme/widgets
CLI Reference
| Command | Flags | Behavior | Exit codes |
|---|---|---|---|
validate |
--config (default policy.yml) |
Parses and schema-validates the policy file only; no network calls | 0 valid, 2 invalid |
audit |
--config, --repo, --token |
Read-only compliance check | 0 compliant, 1 drift found, 2 invalid config, 3 API/auth error |
plan |
--config, --repo, --token |
Same diff engine as audit, renders a human-readable +/-/~/✓ preview |
same as audit |
apply |
--config, --repo, --token |
Executes only the changes plan would show |
0 success (incl. no-op), 2 invalid config, 3 API/auth error |
Token resolution order: --token → GITHUB_TOKEN → GH_TOKEN. Repo resolution order:
--repo owner/name → $GITHUB_REPOSITORY → the local git origin remote.
GitHub Action
- uses: shipsolid/repo-policy@v0
env:
GITHUB_TOKEN: ${{ secrets.REPO_POLICY_TOKEN }}
with:
config: .github/repository-policy.yml
mode: audit
secrets.GITHUB_TOKEN will not work here, in any workflow, no matter what permissions: you
grant it — confirmed against a real repo. GitHub Actions' automatically-generated token has no
permission scope covering branch protection or ruleset administration; that's a platform
constraint, not something a workflow can opt into. Create a PAT with repo scope (classic) or
Administration: Read and write (fine-grained), store it as a repository secret — REPO_POLICY_TOKEN
above is just an example name — and reference that secret instead.
The floating tag tracks the current major version (v0 until a 1.0.0 release ships), the same
convention actions/checkout and similar Actions use.
How it works
Every declared branch is diffed against live GitHub state and reconciled through one of two
backends, selected per branch with enforcement: branch_protection | ruleset (default
branch_protection). See ARCHITECTURE.md for the full data flow, safety model,
and known v1 limitations, and docs/adrs/ for why it's built this way.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Success / compliant / no-op |
| 1 | Drift detected (audit/plan) |
| 2 | Invalid policy.yml |
| 3 | GitHub API or auth error |
More docs
- ARCHITECTURE.md — design, data flow, safety model
- docs/adrs/ — why the key decisions were made
- docs/ci-cd.md — release pipeline, PyPI publishing, the
v0tag - docs/test-strategy.md — what's tested, and what mocking alone can't catch
- docs/troubleshooting.md · FAQ.md · SUPPORT.md
- SECURITY.md — token permissions and threat model
- CONTRIBUTING.md · ROADMAP.md · CHANGELOG.md
License
MIT
Release files for repo-policy 0.4.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| repo_policy-0.4.2.tar.gz | 112.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| repo_policy-0.4.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 136.0 kB
Release files / repo_policy-0.4.2.tar.gz
| Download URL | repo_policy-0.4.2.tar.gz |
|---|---|
| Size | 112.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
736ae3257e2723f0e18a7966e763eef394ba859dc3ba4ef3472852a01fda20f1
|
|
BLAKE2b-256 checksum How to use checksums |
b197c8aef9994953f5b5e75097c1f9480d79c53dd1dd7eb9b1b541a01dc31522
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.
Transparency logRelease files / repo_policy-0.4.2-py3-none-any.whl
| Download URL | repo_policy-0.4.2-py3-none-any.whl |
|---|---|
| Size | 23.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
98ed675e84e167e34a5ccfcc147f7985c87bd3746b96ea52094675da4e696847
|
|
BLAKE2b-256 checksum How to use checksums |
3e87c47b8a18c47462a15d02c89536a1cbd93bbdfcbd7c8de993259ea8895532
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.
Transparency log