Command reference¶
Commands are comments on a pull request.
| Comment | Effect |
|---|---|
/plan |
Plan all changed units (re-plan). |
/plan -p <label> |
Plan one unit. |
/apply |
Apply all changed units in the PR, in dependency order. |
/apply -p <label> |
Apply one unit. |
/unlock |
Force-release the unit locks this PR holds. |
digger plan |
Alias for /plan. |
digger apply |
Alias for /apply. |
digger unlock |
Alias for /unlock. |
Selecting a unit¶
<label> after -p (or --project, or as a bare argument) matches a unit by:
- its full-path label (for example
live/landingzones/corp/corp-workload/westeurope/demo), - its name (the leaf folder), or
- its directory.
A plan with changes tells you the exact label to use in its instructions block.
The flag is spelled --project because that is the engine's word for a unit; the
two mean the same thing here.
Who can run a command¶
/plan and /apply are accepted only from a comment whose GitHub
author_association is OWNER, MEMBER, or COLLABORATOR. Any other author,
for example CONTRIBUTOR or NONE, is refused: the engine adds a 😕 reaction to
the comment and posts a reply naming the author association it saw.
This is the first of the three gates on the flow. It answers "who is asking". The approval gate below reads a property of the pull request, not of the person typing, so without this check any user who can comment on the PR could drive a real apply.
This is not a write-permission check
author_association is what GitHub reports on the comment, not the author's
permission level on the repository. MEMBER means "a member of the
organisation that owns the repository", which in an organisation with default
read access can include people with no write permission. If your organisation
grants broad membership, do not treat this gate as an apply permission on its
own. The required-review gate below is what actually decides whether an apply
may run.
The check only exists on the comment path. Runs from pull_request events,
workflow_dispatch, and workflow_call never see an author_association, so
they are not filtered by it.
Automatic runs¶
- Opening, updating, or reopening a PR runs
/planon the changed units. - Closing or merging a PR releases the unit locks it holds. See Cross-PR unit locks.
- The workflow also declares a manual
workflow_dispatchwith acommand(plan or apply) and an optionalprojectinput.
Manual dispatch needs an open pull request
A dispatch run with no pull request to resolve against fails in the resolve
job. This is a known limitation of the current engine. Drive plan and apply
from PR comments, and use manual dispatch only where a pull request exists.
The drift workflow's own dispatch is not affected, because a drift sweep
never needs a PR.
What each run posts¶
- A fresh run-report comment (so the PR keeps a history of runs).
- A per-unit check in the PR checks (a spinner while running, then a green check or red cross).
- An update to the
tf-pr-ops / merge-gatestatus. - An update to the
tf-pr-ops / approvalstatus. - Reactions on the command comment that track its lifecycle: 👀 seen, 🚀 running, 🎉 succeeded, 👎 failed.
The approval status¶
Every run sets a tf-pr-ops / approval commit status from GitHub's review
decision, so a required-approval rule is visible from the first plan rather than
only when an apply is refused. It reads:
| Review decision | State | Description |
|---|---|---|
APPROVED |
success | Required reviews met |
empty, with TF_PR_OPS_ALLOW_UNREVIEWED_APPLY set to true |
success | No reviews required; unreviewed apply allowed |
| empty, otherwise | failure | No reviews required by this repository; apply is blocked |
| anything else | failure | Required reviews not met (<decision>) |
An empty review decision means the repository requires no reviews at all. The
engine refuses that rather than treating it as consent: an empty decision cannot
be told apart from a ruleset that was removed, so allowing it would let the apply
gate disappear with no signal. A repository that requires no reviews on purpose
opts back in with the TF_PR_OPS_ALLOW_UNREVIEWED_APPLY repository variable set
to true. Leave it unset everywhere else. See
Secrets and variables.
Never make tf-pr-ops / approval a required check
It is informational. It blocks nothing on its own, and it reports failure on
every PR until someone approves. Make it required and you deadlock the
repository: the status only clears on approval, but the branch rule already
enforces approval, so the check adds nothing and can wedge merges. The gate you
do make required is tf-pr-ops / merge-gate.
/apply is gated separately, on the same review decision. If the PR does not meet
the required reviews, the engine posts a comment saying apply is blocked and does
not run.
Template repositories are skipped¶
Both workflows exit before resolve when the caller repository is a GitHub
template repository. A template holds no infrastructure and none of the
bootstrap-created variables or secrets, so plan and apply cannot work there, and
skipping keeps its own pull requests green. A repository generated from a
template is not itself a template, so a customer repo never hits this.