You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Turn on pull-request previews for an application on a Fabric cluster, and every PR's build is served at its own subdomain, <branch-slug>.<app>.<cluster-domain>, with a valid certificate. Each push updates the preview, and closing the PR removes it. Customer setup should be one toggle in Studio plus one workflow file, with no stored secrets, DNS records or certificates to manage.
Example: a PR from branch david/1778-custom-regions is served at https://david-1778-custom-regions.<app>.<cluster-domain>.
This is the next step after staged component deploys (#2315), and the "preview deployments" item of the Ephemeral Instances roadmap lane, beside #641 and #642. Studio is the first consumer.
Fabric routing: host-manager routes a host one label under a claimed *.domain to an isolated application's worker sockets, and serves a wildcard certificate for it (HarperFast/host-manager#224).
CI deploys it straight to the cluster, authenticated by OIDC, as an identity that can only deploy and drop that application's previews.
Central Manager acts once per application, when previews are enabled. It adds a wildcard DNS record, puts the wildcard on the instances' certificates, sends the claim host-manager routes on, and creates the trust policy and scoped role on the cluster.
Closing the PR drops the preview. An expiry and a per-application cap catch anything the close event missed.
The branch slug is one lowercase DNS label:
Anything outside [a-z0-9] becomes -, and runs collapse.
It is cut to 40 characters, with a hash suffix when cut.
Reserved names fall back to pr-<n>.
For example, david/1778-custom-regions becomes david-1778-custom-regions. The documented recipe uses pr-<n>.<suffix>, which needs no slug at all.
The workflow is trusted, not the PR. The job runs on pull_request_target from the default branch and never checks out PR code. The trust policy pins workflow_ref to that branch's workflow file, event_name: pull_request_target, and an environment, so a PR can't change the privileged workflow. Fork PRs are skipped by the workflow's same-repository condition.
The PR's code still runs on Harper, with the preview role's rights. Until Scope deploy permissions to component names #3046, that role can deploy and drop any component. So previews belong on a separate preview cluster, or behind required reviewers when they share a production cluster.
Data is shared until branches work. A preview's writes, schema changes and roles apply to the cluster's databases.
Public repositories: GitHub's default execution protection blocks pull_request_target for affected public repositories from 2026-11-02. The repository's Actions policy has to allow it for the preview workflow.
Turn on pull-request previews for an application on a Fabric cluster, and every PR's build is served at its own subdomain,
<branch-slug>.<app>.<cluster-domain>, with a valid certificate. Each push updates the preview, and closing the PR removes it. Customer setup should be one toggle in Studio plus one workflow file, with no stored secrets, DNS records or certificates to manage.Example: a PR from branch
david/1778-custom-regionsis served athttps://david-1778-custom-regions.<app>.<cluster-domain>.This is the next step after staged component deploys (#2315), and the "preview deployments" item of the Ephemeral Instances roadmap lane, beside #641 and #642. Studio is the first consumer.
Where things stand
Previews already work by hand on 5.3.0. HarperFast/documentation#715 (stacked on HarperFast/documentation#713) documents a recipe, "Per-PR previews with shared databases":
pull_request_targetworkflow runs from the default branch and never checks out PR code.by_ref, as an isolated applicationmy-app-pr-<n>atpr-<n>.<suffix>.packagedeploy'sbranchedDatabasesis ignored at load, so the application runs on its base databases #3071,deploy_componentacceptsbranchedDatabaseson a payload deploy and silently ignores it #3044).It works, but it takes a lot of setup. This epic removes that cost one mechanism at a time:
What already exists
host(feat(threads): run an isolated application in a dedicated worker thread #2524).threads.maxIsolatedcaps them at 8 per node by default; a deploy past the cap answers 409.restart_servicewithscope: '<app>'restarts one isolated application's worker and nothing else (5.3.0).packagedeploy'sbranchedDatabasesis ignored at load, so the application runs on its base databases #3071,deploy_componentacceptsbranchedDatabaseson a payload deploy and silently ignores it #3044).workflow_refto the default branch's workflow andevent_name: pull_request_target.deployment_id(Staged component deploys: land build-aside-then-swap as a sequence of small PRs #2315).*.domainto an isolated application's worker sockets, and serves a wildcard certificate for it (HarperFast/host-manager#224).Shape
<component>-pr-<n>, withhost: <branch-slug>.<label>.<cluster-domain>. Applications with tables addbranchedDatabasesonce Apackagedeploy'sbranchedDatabasesis ignored at load, so the application runs on its base databases #3071 anddeploy_componentacceptsbranchedDatabaseson a payload deploy and silently ignores it #3044 are fixed. Until then, previews share the cluster's databases, as the documented recipe does.The branch slug is one lowercase DNS label:
[a-z0-9]becomes-, and runs collapse.pr-<n>.For example,
david/1778-custom-regionsbecomesdavid-1778-custom-regions. The documented recipe usespr-<n>.<suffix>, which needs no slug at all.Sub-issues
Harper core
host,urlPath,isolatedandbranchedDatabases#3043deploy_componentacceptsbranchedDatabaseson a payload deploy and silently ignores it #3044deploy_componentdeploysproject=shop.pr-12ontoshop#3047corsAccessList#3050fastifyRoutes#3051databases/tablesglobals to an isolated application's branches #3053drop_component, and make dropping an absent component a no-op #3091packagedeploy'sbranchedDatabasesis ignored at load, so the application runs on its base databases #3071CI tooling
harper preview: deploy, drop and list PR previews from any CI #3054Central Manager
Studio as the first consumer
Host Manager
Security model
pull_request_targetfrom the default branch and never checks out PR code. The trust policy pinsworkflow_refto that branch's workflow file,event_name: pull_request_target, and an environment, so a PR can't change the privileged workflow. Fork PRs are skipped by the workflow's same-repository condition.pull_request_targetfor affected public repositories from 2026-11-02. The repository's Actions policy has to allow it for the preview workflow.Related, tracked elsewhere
Not in this epic
_acme-challengeCNAME delegation.deployment_id. Builds are bound to their component today.