Deployment status
GantryCD publishes every deployment’s live state back to the source-control platform, so a developer looking at a commit or pull request sees whether GantryCD deployed it — and can jump straight to the deployment.
On GitHub this surfaces in two places at once:
- A commit/build status on the deployed commit. Lane deployments use
gantrycd/<stack>; pull-request previews usegantrycd/<stack>/previewso a promoted lane deployment cannot overwrite the preview result. It appears on the commit and in the pull request’s checks area, with a link to the deployment. - A GitHub Deployment object, created on the fly, with deployment statuses. It appears in
the repository’s Environments view and the pull request timeline (“Deployed to
<stack>”).
The state tracks the deployment as it moves: queued → in progress → success / failure / cancelled. A deployment waiting on a human shows in progress, and the description says which decision is outstanding: “Awaiting approval” at the apply gate, “Awaiting approval to run the preview plan” for a pull request preview the stack holds.
A deployment that was skipped — superseded by a newer commit, aged out by a timeout, or
skipped by hand — leaves the commit’s check exactly as it was. GantryCD publishes no new
commit status for it. A lane deployment records the skip on its GitHub Deployment object,
which has a real inactive state. Read-only previews intentionally have no Deployment object.
That looks like an omission and is a decision. A deployment publishes a pending check when it is created, so a skip leaves that pending check standing. Where that lands is the whole point:
- On a pull request whose preview plan never ran, it sits on the live head — so a required check keeps the PR from merging. For a gate that means “this pull request’s plan has not run”, blocking is the right answer, not a defect.
- On a superseded preview it sits on a commit the pull request has already moved past, and branch protection only reads the head. Lane deployments use a separate context, including promoted deployments that may still reference the live PR head.
The tempting alternatives are both worse, and both were tried: reporting a skip as passing lets an unapproved preview go green the moment it times out, so the gate is defeated by ignoring it. Reporting it as failing permanently red-Xes a superseded preview SHA.
The practical consequence: make gantrycd/<stack>/preview a required check. The pull-request gate
only gates anything if you do.
This is SCM-implementation agnostic. GitHub maps to commit statuses + Deployments today; other platforms (GitLab, Bitbucket, …) are an extension point and map the same neutral states to their native mechanism (e.g. GitLab commit statuses + environments).
Configuration
There is nothing to turn on. Publishing is always on: whenever a deployment’s stack repository matches one of your SCM integrations, GantryCD publishes statuses using that integration’s existing credentials. It covers every deployment — manual, push-triggered, and pull-request — because every deployment carries a real commit SHA.
If no SCM integration matches a stack’s repository, nothing is published (and nothing breaks).
Required GitHub App permissions
Grant the GitHub App these repository permissions (in addition to what the App already needs for webhooks and clone credentials):
| Permission | Access | Used for |
|---|---|---|
| Commit statuses | Read and write | The per-commit / PR check line |
| Deployments | Read and write | The Deployment object + its statuses |
After changing permissions, accept the updated permission request on the installation. A missing permission makes a publish fail permanently (GitHub returns 403); the failure is recorded on the delivery and not retried — fix the permission and the next transition publishes normally.
Delivery guarantees
Publishing is asynchronous and durable. Each deployment has a single coalescing outbox row: rapid transitions collapse into one in-flight publish, and a stale state can never overwrite a newer one. Transient failures (rate limits, 5xx) are retried with backoff; permanent failures (missing permission, deleted repo) are dead-lettered. A reconcile sweep re-publishes any deployment whose status drifted from what was last published, so terminal states are always eventually correct.
The deep link points at the deployment in the GantryCD web UI; it is included only when the
backend’s public base URL (GANTRYCD_BACKEND_PUBLIC_BASE_URL) is configured.
For the internals — the outbox schema, the coalescing/ordering guarantees, the state mapping, and operator configuration — see the SCM status reference.