Templating
File content can include Go template expressions that are expanded per target repository. This lets you customize values like project names, module paths, and binary names.
Quick Example
Section titled “Quick Example”files: - path: Makefile source: ./templates/Makefile
- path: go.mod content: | module github.com/<% .Repo.FullName %> go 1.24.0When applied to babarot/my-cli, the go.mod becomes:
module github.com/babarot/my-cligo 1.24.0Built-in Variables
Section titled “Built-in Variables”Every template has access to the target repository’s metadata:
| Variable | Value | Example (babarot/my-cli) |
|---|---|---|
<% .Repo.Name %> | Repository name | my-cli |
<% .Repo.Owner %> | Owner name | babarot |
<% .Repo.FullName %> | owner/name | babarot/my-cli |
Custom Variables
Section titled “Custom Variables”Use vars to define additional variables. Values can themselves reference built-in variables:
files: - path: .github/workflows/release.yml source: ./templates/release.yml vars: binary_name: "<% .Repo.Name %>" docker_image: "ghcr.io/<% .Repo.FullName %>"In the template file:
- run: docker build -t <% .Vars.docker_image %> .- run: ./<% .Vars.binary_name %> --versionVariables are resolved in two passes:
varsvalues are expanded (can reference.Repoonly)- File content is expanded (can reference both
.Repoand.Vars)
Compatibility with Other Template Systems
Section titled “Compatibility with Other Template Systems”gh-infra uses <% %> delimiters, which do not conflict with:
- GitHub Actions
${{ }}— preserved as-is - GoReleaser
{{ .Version }}— preserved as-is - Helm
{{ .Release.Name }}— preserved as-is - Any
{{ }}syntax — untouched by gh-infra
files: - path: .github/workflows/ci.yml content: | runs-on: ${{ matrix.os }} # ← GitHub Actions (no conflict) env: TOKEN: ${{ secrets.GITHUB_TOKEN }} # ← GitHub Actions (no conflict) steps: - run: echo "Building <% .Repo.Name %>" # ← gh-infra (expanded)No escaping needed.
When Templates Are Applied
Section titled “When Templates Are Applied”Templates are expanded during plan, before the diff comparison. This means:
planoutput shows the expanded contentapplycommits the expanded content- Each target repository gets its own expansion with the correct
.Repovalues
Files without <% %> syntax are not processed by the template engine — they pass through unchanged.
Error Handling
Section titled “Error Handling”If a template references an undefined variable, plan and apply stop with an error:
files: - path: Makefile content: | BINARY = <% .Vars.typo %> # ← error: undefined key "typo"Error: template Makefile for babarot/my-cli: template: :1:12: executing "" at <.Vars.typo>: map has no entry for key "typo"This prevents accidentally committing files with missing values.