A pull request gets its own environment

What a review environment is, why it is a dev tier rather than a copy of staging, what it costs, and what happens to it when the pull request closes.

Open a pull request against a repository this platform builds and it gets a whole environment: its own namespace, its own database, its own hostname. It exists while the pull request is open and it is collected when it closes.

Each one with its environment, or the reason it does not have one.

Open pull requests →

The pull requests page, with each environment or the reason there is none

What gets created

One pull request: its review environment, what was built from the branch, and the components bound around it

  1. 1

    An Environment named review-pr-N

    Not in any DeploymentPipeline, deliberately. A pull request is not something you promote into — adding it to the pipeline once made the portal draw every open pull request as a promotion target of staging, which is the relationship backwards.

  2. 2

    A project cell

    A ProjectReleaseBinding copying the root environment's, which is what creates the namespace and its quota.

  3. 3

    A copy of every backing service

    A real Postgres, a real object store — one per pull request, sized from the root environment's binding so a review database is small. retainPolicy is Delete: a review environment's data should not outlive the pull request.

    This is what makes review environments expensive, and why there is a cap.

  4. 4

    A forked component per changed repository

    Named <component>-pr-N, pinned to the pull request's branch. Components from other repositories in the same project are not forked — the original is bound in at whatever the root environment is running, so the environment is "this change against the rest of the project as it stands" rather than a snapshot of everything.

Where it sits in the promotion order

A review environment ranks below staging — it is the dev tier. Every list in this console puts pull-request environments first, before the standing environments, because a change moves from a pull request towards production and never the other way.

Standing environments first, then review environments under their own heading.

The estate by environment →

The estate by environment, with review environments kept separate

note

On a project page a review column is drawn as transient, with a link to the pull request it exists for. The estate is staging and production; everything else is somebody's work in progress and should not make the board churn every time a branch opens.

The one binding that looks like it is in staging

This is worth understanding, because it looks like a bug and is not.

A forked component must carry autoDeploy — without it no ComponentRelease is ever cut and the review environment has nothing to bind. And autoDeploy always writes a ReleaseBinding into the pipeline's root environment, whichever that is.

So project-flow claims that binding first, itself, in the Undeploy state, before the Component exists. That is what stops pull-request code deploying into the root environment's cell against its real database. It reads the release name off it and deletes it, usually within thirty seconds.

warning

One of those once survived for fourteen hours: deleted on time, caught by a finalizer, and then invisible to every cleanup path because it carried no labels and lived outside any review-pr-* environment. It showed on the project page as though a pull request were deployed into staging.

A sweep collects them by shape now — a *-pr-<n> subject whose Component does not exist is garbage wherever it lives — and the console keeps them out of the estate views. /deploys still shows them, under their own heading, because a binding that exists has to be visible somewhere or the next stuck one is invisible too.

Why there might not be one

OC_MAX_REVIEW_ENVS is 1 on this host. A second open pull request gets a comment on the pull request saying so, and no environment.

That is a capacity limit, not an absence, and the pull-requests page says which it is. The three states it distinguishes:

what you see what it means
an environment, Ready the ordinary case
an environment, not Ready the reviewer's build is broken
no environment, with a reason the cap, or a build that never cut a release

A page that simply omitted the third would be reporting a capacity limit as nothing at all.

Teardown

Closing or merging the pull request tears down everything labelled for it, in order: project binding, resource bindings, release bindings, components, environment — each finalizer waits on the layer below.

caution

RenderedRelease objects go first. Their cleanup resolves its plane client through the Environment, so collecting the Environment first strands renderings that can then never finalize. Thirteen of them once hot-looped for twenty-one hours and took three controller restarts.