Preview environments
This guide gives every pull request its own environment with its own URLs, then removes it when the pull request closes. Previews are ordinary environments marked as ephemeral, so they use the same networks, volumes, health checks, and proxy as every other environment.
The GitHub App receives the pull request events and deploys the preview from the control node. No GitHub Actions runner is used.
Prerequisites
Previews need four things before the first pull request:
- A deploy node, registered with the deploy role. See Setting up nodes.
- A wildcard DNS record for the preview base domain that points at that node,
for example
*.preview.example.com. Preview URLs are subdomains of the base domain, so one wildcard record covers every pull request. - The proxy obtains a certificate for each preview host through ACME, so no wildcard certificate is needed. The hosts must resolve and ports 80 and 443 must reach the node for the challenge to succeed. Keep in mind the certificate authority’s limit on new certificates per domain per week.
- A GitHub App installed on the repository, with the control node reachable from GitHub. See GitHub App deployments.
Declare the base domain
Add a previews block to up.yaml and name the base domain:
project: acme
previews:
base_domain: preview.example.com
environments:
- branch: main
name: production
previews: true
services:
- name: web
domains:
- example.com
source:
type: git
url: https://github.com/acme/web
The base domain is inert until a preview deploys, so normal applies keep using
the domains you declared. An environment can override the shared base domain
with its own previews.base_domain. See the
previews configuration reference for the field.
Enable previews for the base branch
A pull request deploys a preview only when the environment for its base branch
declares previews. In the example above, the production environment maps
main and enables previews, so every pull request that targets main deploys
the environment pr-<number>.
A pull request that targets an undeclared branch, or a branch whose environment
omits previews, does not deploy. See
Environments for the catalog fields.
How preview URLs are derived
A preview deploy replaces each service’s first declared domain with
<environment>-<service>.<base_domain>. Pull request 42 of the config above
serves web at pr-42-web.preview.example.com, while production keeps
example.com. Services without a declared domain stay private: they are
reachable inside the environment network and have no public URL.
Environment names used for previews must be lowercase alphanumeric with dashes,
because the name becomes part of a hostname. pr-42 and release-1-2 are
valid; PR_42 and release/1.2 are not.
What GitHub shows
For each preview deploy, the App:
- creates a check run for the pull request head commit, and updates it as the apply runs;
- records a GitHub deployment named
pr-<number>that links to the preview URL, and marks it inactive when the pull request closes; - writes one comment on the pull request with a table of service name, URL, status, and short commit. The App updates that same comment while the apply runs, so each service shows as in progress and then carries its deployment outcome as soon as it finishes.
When the pull request closes, the App removes the environment, marks the deployment inactive, and replaces the comment with a note that says the preview environment was removed. The removal works whether the pull request merged or was abandoned.
Run a preview by hand
The App composes ordinary commands, so you can do the same locally:
up environment create --if-not-exists --preview pr-42
up apply --pr 42 --preview --git-ref <commit-sha>
up service list --env pr-42
up environment create --preview marks the environment as ephemeral and
auto-selects a deploy node; --if-not-exists makes a repeat call succeed
without creating a second environment. up apply
rewrites the domains, overrides the git ref on every git source, and converges
the environment. up service list with
--env shows only that environment’s services.
Remove the preview when you are done:
up environment remove pr-42 --force
Notes and limits
- A preview apply adds its target environment to the catalog for the run only.
--env(or--pr) names the target, and placement comes from the environment record. The GitHub App instead resolves the target from the declared catalog, so a pull request deploys only when the base environment enables previews. - Image sources are not rewritten. Previews build git sources at the pull request commit; bring your own per-pull-request image tags if you deploy pre-built images.
- A pull request from a fork does not deploy. The App cannot read the fork.
- A GitHub environment approval rule does not apply, because no workflow job runs. To approve production changes, protect the default branch.
- The App deploys one preview at a time per repository and environment. A second push waits for the first to finish.