gh-infra
Declarative GitHub infrastructure.
No state file. No HCL. Just YAML.
No state file. No HCL. Just YAML.
Get started in seconds.
$ gh extension install babarot/gh-infra
Import what you already have.
Point it at a repo. Get YAML back. No manual writing needed.
terminal
$ gh infra import babarot/my-project
# Exports current repo settings to YAML repos/my-project.yaml
apiVersion: gh-infra/v1
kind: Repository
metadata:
name: my-project
owner: babarot
spec:
description: "My awesome project"
visibility: public
features:
wiki: true
discussions: false See every change before it lands.
Edit the YAML. Run plan. Get a precise diff of what will change.
repos/my-project.yaml
apiVersion: gh-infra/v1
kind: Repository
metadata:
name: my-project
owner: babarot
spec:
description: "My awesome project"
visibility: public
features:
wiki: false
discussions: true
topics:
- go
- cli gh infra plan
# babarot/my-project will be updated
~ babarot/my-project
~ features.wiki true → false
~ features.discussions false → true
+ topics [go, cli]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Plan: 0 to create, 1 to update, 0 to destroy
To apply, run: gh infra apply Apply with confidence.
Confirm once. Changes apply in parallel. Done.
gh infra apply
$ gh infra apply ./repos/
> Do you want to apply these changes? Yes result
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✓ babarot/my-project
✓ features updated
✓ topics updated
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Apply complete! 2 changes applied. Everything you need. Nothing you don’t.
YAML, not HCL
No new language to learn. Describe your repos in plain YAML.
No state file
GitHub is the source of truth. No drift. No state to manage.
Plan & Apply
Preview every change before it happens. Apply with confidence.
Just gh + a token
No apps. No servers. No infra. Just a gh extension.
RepositorySet
Manage repos at scale. Shared defaults, per-repo overrides.
File delivery
Distribute files across repos via push or pull request.
See it in action.
Real CLI output. Real workflows.
RepositorySet
$ gh infra plan ./repos/ # babarot/my-cli will be updated ~ babarot/my-cli ~ required_reviews 1 → 2 # babarot/my-api will be updated ~ babarot/my-api ~ required_reviews 1 → 2 # babarot/my-web will be updated ~ babarot/my-web ~ required_reviews 1 → 2 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Plan: 0 to create, 3 to update
One line in defaults. Three repos updated.
Parallel apply
$ gh infra apply ./repos/ ✓ babarot/my-cli ✓ description updated ✓ merge_strategy updated ✓ babarot/my-api ✓ branch_protection updated ✓ babarot/my-web ✓ features updated ✓ topics updated ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Apply complete! 5 changes applied
Repos apply in parallel. Changes are atomic per repo.
File delivery
$ gh infra apply ./files/ # babarot/my-project — FileSet: 3 files ~ babarot/my-project ~ .github/workflows/ci.yml +18 -5 + .github/dependabot.yml +12 ~ .github/CODEOWNERS +2 -1 via: pull_request ✓ → github.com/babarot/my-project/pull/42
Distribute files across repos. Push or pull request.
Diff viewer
app-api ~ CODEOWNERS ~ ci.yml + dependabot.yml app-web ~ CODEOWNERS ~ ci.yml ⚠ dependabot.yml
- * @old-owner + * @babarot @team @@ -1,5 +1,8 @@ name: CI - on: [push] + on: [push, pull_req..
Browse every file diff. Skip what you don't want.