Repository
Repository manages a single GitHub repository — its description, visibility, topics, labels, features, merge strategy, branch protection rules, rulesets, secrets, variables, and Actions settings.
Metadata
Section titled “Metadata”metadata: owner: babarot # GitHub owner or organization name: my-project # Repository nameThe combination of owner and name identifies the target repository (babarot/my-project).
| Field | Description |
|---|---|
description | Repository description |
homepage | URL displayed on the repo page |
visibility | public, private, or internal — see General Settings |
archived | Archive (read-only) or unarchive — see General Settings |
topics | GitHub topics for discoverability |
labels | Repository issue/PR labels — see Labels |
label_sync | Deprecated label sync mode: use reconcile.labels instead — see Labels |
features | Toggle issues, projects, wiki, discussions, pull requests — see General Settings |
merge_strategy | Merge commit, squash, rebase options — see General Settings |
branch_protection | Classic branch protection rules — see Branch Protection |
rulesets | Modern rulesets with enforcement modes and bypass actors — see Rulesets |
secrets | GitHub Actions secrets (via ${ENV_*} references) — see Secrets & Variables |
variables | Repository variables — see Secrets & Variables |
actions | GitHub Actions permissions, SHA pinning, workflow defaults, and fork PR policy — see Actions |
All fields are optional — declare only what you want to manage. Fields not present in the YAML are left unchanged on GitHub.
The one exception is spec.actions.enabled: when managing any other Actions setting, GitHub requires enabled to be sent too. See Actions.
Reconcile
Section titled “Reconcile”By default, collection fields are managed additively: gh-infra creates or updates entries declared in YAML and leaves undeclared GitHub resources untouched.
Use top-level reconcile to make selected collections match YAML exactly:
reconcile: rulesets: authoritative labels: additive branch_protection: additive
spec: rulesets: - name: protect-main target: branch rules: non_fast_forward: true| Field | Modes | Description |
|---|---|---|
reconcile.labels | additive, authoritative | Controls how spec.labels is compared with existing GitHub labels |
reconcile.rulesets | additive, authoritative | Controls how spec.rulesets is compared with existing GitHub rulesets |
reconcile.branch_protection | additive, authoritative | Controls how spec.branch_protection is compared with existing classic branch protection rules |
additive is the default. authoritative deletes remote entries that are not declared in YAML, but only when the corresponding spec collection is present. If spec.rulesets, spec.branch_protection, or spec.labels is omitted, that collection is unmanaged even when reconcile has a policy for it.
To delete all labels, rulesets, or branch protection rules, use authoritative with an empty list:
reconcile: rulesets: authoritativespec: rulesets: []labels: null, labels:, rulesets: null, rulesets:, branch_protection: null, and branch_protection: are invalid. Use an empty list when you mean an empty managed collection.
When to Use
Section titled “When to Use”Use Repository when you want to manage one repo’s settings in a dedicated YAML file. This is the simplest resource kind and the starting point for most users.
It works best when:
- Each repo has its own distinct settings — different branch protection rules, different topics, different merge strategies.
- You want per-repo change tracking — each file maps to one repo, so
git blametells you exactly who changed what and when. - You’re managing a small number of repos — for 1–5 repos, separate files are easy to maintain.
If you find yourself copying the same settings across many files, consider RepositorySet instead.
Creating Repositories
Section titled “Creating Repositories”If a YAML manifest references a repository that doesn’t exist, plan shows it as a new resource:
$ gh infra plan ./repos/
Plan: 1 to create, 0 to update, 0 to destroy
+ babarot/new-project (new) + repository: babarot/new-projectapply creates it with gh repo create, then applies all settings (features, topics, branch protection, etc.) in a single pass.
Deleting Repositories
Section titled “Deleting Repositories”gh-infra does not support repository deletion. Without a state file, there is no way to distinguish “removed from YAML” from “never managed” — and repository deletion is irreversible.
To delete a repository, use gh repo delete directly.