Skip to content

plan

Show diff between YAML and current GitHub state. No mutations are made.

Terminal window
gh infra plan [path...]

One or more paths can be given. When multiple paths are provided, manifests from all paths are collected and planned together.

Argument Example Behavior
(none) or . gh infra plan All *.yaml / *.yml in the current directory
File gh infra plan repos/my-cli.yaml That file only
Directory gh infra plan repos/ All *.yaml / *.yml directly under it (subdirectories are ignored)
Multiple gh infra plan repos/ files/ Manifests from all listed paths combined

Overlapping paths (e.g., . and ./repos/) are rejected to prevent duplicate processing.

YAML files that are not gh-infra manifests are silently skipped. Use --fail-on-unknown to treat them as errors.

Flag Description
-r, --repo <owner/repo> Target a specific repository
--detailed-exitcode Exit with 2 if changes are detected, 1 on error, 0 otherwise (see Exit status)
--ci Deprecated: use --detailed-exitcode. Exits with 1 if changes are detected, and disables colors
--changed-since <ref> Only the manifests changed since a git ref, and those that read a changed local file. See Only what changed
--fail-on-unknown Error on YAML files with unknown Kind (default: silently skip)
--concurrency <n> Maximum number of gh processes (GitHub API calls) at once, across the whole command. Default 8, or GH_INFRA_CONCURRENCY. Lower it if you hit GitHub’s secondary rate limit or network timeouts
--diff Show a unified diff for each FileSet file change, capped at 500 lines per file. Deleted files show no diff
-o, --output <format> text (default), json, or markdown. See JSON output and Markdown output
Code Meaning
0 Plan computed for every repository (with --detailed-exitcode: and no changes)
1 An error, or the current state of one or more repositories could not be fetched. With --detailed-exitcode, also an interrupted plan and paths with no manifests
2 Changes detected (--detailed-exitcode only)

An error wins over changes: a plan with changes that also skipped a repository exits with 1. Without --detailed-exitcode, changes alone exit with 0.

--ci is deprecated and will be removed in a future release. It exits with 1 for changes as well as errors, so a job cannot tell them apart; switch to --detailed-exitcode. --ci also disabled colors; set NO_COLOR=1 for that.

plan reads only the settings each manifest sets, so the token needs only their permissions (see Authentication). When fetching fails for a repository (for example, the token cannot read a setting the manifest manages), its error is shown and the repository is left out of the plan; an unreadable setting is never compared as if it were absent or at its default. A plan with skipped repositories is incomplete, so plan exits with 1 even if the other repositories have no changes. A file that cannot be fetched is never treated as missing, so no create is planned for it. A repository that is already archived is reported and left out the same way when the manifest changes it without archived: false, since gh-infra does not change an archived repository except to unarchive it.

Terminal window
# Plan all YAML files in a directory
gh infra plan ./repos/
# Plan multiple directories at once
gh infra plan ./repos/ ./files/
# Plan a single file
gh infra plan ./repos/my-cli.yaml
# Plan a specific repository
gh infra plan ./repos/ --repo babarot/my-cli
# CI drift detection (exit 2 when changes are detected)
gh infra plan ./repos/ --detailed-exitcode
# Plan only what changed on this branch
gh infra plan ./repos/ --changed-since origin/main
# Show the content changes of FileSet files
gh infra plan ./files/ --diff