Skip to content

gh-infra

Declarative GitHub infrastructure.
No state file. No HCL. Just YAML.
~/repos
 

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.

Y
YAML, not HCL
No new language to learn. Describe your repos in plain YAML.
S
No state file
GitHub is the source of truth. No drift. No state to manage.
P
Plan & Apply
Preview every change before it happens. Apply with confidence.
G
Just gh + a token
No apps. No servers. No infra. Just a gh extension.
R
RepositorySet
Manage repos at scale. Shared defaults, per-repo overrides.
F
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.