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.