Pull requests
When a repository is connected via an SCM integration, GantryCD turns pull request activity into preview plans — so reviewers see the infrastructure impact of a change before it merges, right alongside the code review.
Preview plans
When a PR is opened, reopened, or gets new commits, GantryCD creates a plan (unlocked) deployment against the PR’s head commit. “Unlocked” means it:
- never takes the stack lock, so it runs alongside your normal deployments and doesn’t block them;
- never applies — it’s read-only, a plan and nothing more.
Preview plans wait for approval by default
A preview plan is read-only, but it is not harmless. To plan a pull request,
GantryCD downloads the modules and provider binaries that the PR’s code names,
then runs them — with this stack’s credentials. Your tracked branch has been
reviewed and merged; a pull request has not. So by default, GantryCD asks first:
the preview appears immediately, marked waiting for approval, and someone with the
preview permission clicks Run preview plan to start it. The built-in Stack
Approver role carries that permission. Stack Triggerer deliberately does not:
triggering reviewed branch code must not silently confer authority to execute an
unreviewed pull request’s providers with stack credentials.
A waiting preview holds nothing up inside GantryCD — no stack lock, no runner. That is also why there is no “discard” button: leaving a preview alone and throwing it away amount to the same thing.
But it does hold up the pull request, and that is the point. GantryCD publishes a
gantrycd/<stack>/preview check on the PR, and while the preview waits, that check stays pending. If
you have made it a required check
in your branch protection — and you should, or none of this gates anything — the PR cannot
merge until someone answers. A plan that never ran never reports success, so the gate cannot
be defeated by waiting it out.
The next commit on the PR replaces a waiting preview with a fresh one, so you are never stuck: push, and you get another chance to answer. Closing the PR retires the preview outright.
Change this per stack under Pull request preview plans:
| Setting | Behaviour |
|---|---|
| Manual — confirm before planning (default) | The preview waits for someone to approve it. |
| Automatic — plan every pull request | The preview runs as soon as the PR syncs. |
Choose Automatic when only people you trust can open pull requests on the
repository, or when the stack’s credentials are narrow enough that planning
unreviewed code can’t do harm. Switching a stack to Automatic itself requires the
preview permission — it turns every future pull request into a standing yes.
Previews appear in the stack’s pull requests view, not in the main deployments timeline. Each PR shows its latest preview and that plan’s outcome.
A PR is matched to a stack by repository, branch, and working directory: a PR that doesn’t touch a stack’s working directory won’t generate a preview for it (root-directory stacks match everything). Once matched, a PR stays attached until it closes.
Promoting a pull request
A preview plan can’t apply — so to actually act on a PR, you promote it.
Promotion creates a brand-new, standard plan-mode deployment at the PR’s head
commit that follows the normal plan → confirm → apply flow and takes the stack
lock like any other deployment.
You can only promote a PR whose latest preview plan succeeded — so on a stack
that asks before planning, run the preview first. The Promote
button is hidden otherwise. Promotion requires the deploy permission.
The promoted deployment shows in the normal deployments timeline with a “Promoted from PR #N” banner linking back to the PR. That banner survives even after the PR closes, because GantryCD snapshots the PR’s title, URL, and description onto the deployment.
Promotion requirements (required checks)
By default neither action is gated by SCM status: any open PR gets a preview plan
(subject to the approval above), and anyone with deploy can promote a successful
one. A stack can instead require
pull-request conditions — approvals and named CI checks — before either
action is allowed. Conditions are evaluated against live SCM status at the
moment the action runs, so they always reflect the PR’s current state.
There are two independent gates:
- Plan — holds a PR’s read-only preview plan until the conditions are met. The gate is two-way: if a PR that was meeting its conditions later stops (an approval is dismissed, a required check regresses), its preview is retracted until the conditions are met again at the same commit.
- Promote — blocks promoting a PR into an apply-capable deployment until the
conditions are met. An unmet Promote gate disables the Promote button (with the
reason shown) and rejects a promote attempt with
409 Conflict.
Configuring a stack’s requirements
Open a stack’s Create or Edit dialog and use the Promotion requirements editor. Each gate offers two condition types:
- Approvals — require at least N approving reviews on the PR.
- Required checks — list specific check names. Each named check (a CI check-run name or a commit-status context) must report success on the PR’s head commit. A check that is missing or still running holds the gate — it isn’t “passing yet” — mirroring GitHub branch-protection’s required status checks. Checks that finish as skipped or neutral count as success. List exactly the checks you depend on; an unrelated or newly-added check never silently starts gating, because only the checks you name are consulted.
Leave both gates empty to keep the stack ungated (the default). Each gate allows at most one of each condition type.
Operator setup for live re-evaluation. Because status is read on demand, the plan gate must be re-triggered when a review or CI run changes a PR without a new push. GantryCD re-evaluates automatically on
pull_request_reviewevents and when acheck_suiteis requested, rerequested, or completed — but for the latter, the GitHub App must be subscribed to thecheck_suiteevent and hold thechecks: readpermission. Two caveats: PRs from forks arrive without PR linkage and aren’t auto-re-triggered, and CI that reports only via the legacy commit-status API (no Checks API) carries no PR linkage either. Both still re-evaluate on the next push or review. Seedocs/reference/promotion_requirements.mdfor the full model and how to add new condition types.
Apply/confirm is intentionally not gated by these conditions — by that point the deployment has already been promoted and user-authorized.
What triggers what
| Event | Result |
|---|---|
| Push to a stack’s tracked branch | A normal plan deployment (deployments view). |
| PR opened / updated | A preview plan (pull requests view), read-only. Waits for approval unless the stack plans pull requests automatically — and unless a Plan gate holds it entirely. |
| PR review submitted / dismissed | Re-evaluates the Plan gate (may create or retract the preview). |
check_suite is requested, rerequested, or completes | Re-evaluates the Plan gate for each linked PR (needs the GitHub App checks: read + event subscription). |
| You click Promote on a PR | A new standard deployment at the PR head — blocked if a Promote gate is unmet. |
This keeps the two flows cleanly separated: branch pushes drive your delivery timeline, PR activity stays scoped to the PR until someone decides to act on it.