# Preview and staging environments per Git branch (deploy on push) (/docs/compute/deploy-on-push) > For the complete Prisma documentation index, see [llms.txt](https://www.prisma.io/docs/llms.txt). A markdown version of any docs page is available by appending `.md` to its URL. Test a new version of your app, such as a feature a coding assistant is building, on its own URL without replacing production. With deploy on push, every branch you push other than the default one gets its own preview environment, and the default branch deploys to production. Location: Compute > Preview and staging environments per Git branch (deploy on push) To test a new version of your app without replacing the one your users have, push it to a Git branch other than the default one. Once deploy on push is set up, Prisma Compute deploys that branch as a preview environment with its own URL, its own services and its own databases, and the workflow deploys production only when you push to the default branch. A branch you keep, such as `staging`, works as a long-lived staging environment, and deleting a branch removes its preview. The same works when a coding assistant does the pushing; see [If a coding assistant is building the feature](#if-a-coding-assistant-is-building-the-feature). This guide sets that up for a [Prisma Composer](https://www.prisma.io/docs/composer) app that you deploy today by running `deploy module.ts` in a terminal. Composer is in [Early Access](https://www.prisma.io/docs/console/more/feature-maturity#early-access), so its commands can change between releases. You connect the app's GitHub repository and add a deploy workflow, and from then on a push replaces that manual step. ## Host a test version without replacing production [#host-a-test-version-without-replacing-production] When the workflow from this guide runs, each Git branch you push, other than the default one, becomes its own environment next to production. The preview gets the following, separate from production: * **Its own deployment and URL.** The deploy action deploys the branch as a preview named after it, and the workflow run prints the preview's URL in its deploy report. Custom domains attach to production only, so a preview is reached at its generated URL. * **The whole app, not only the frontend.** Every service your module declares, such as a frontend and an API, runs in the preview as its own service. The code is the only thing a preview shares with production. * **Preview environment variables.** Every preview reads the preview-scoped values, and a branch override changes a value for one branch; production values are used only by production. See [Environment variables](https://www.prisma.io/docs/compute/environment-variables). * **Its own databases.** Each Prisma Postgres database your module declares is created for the branch, so what you write in the preview stays out of the production database. Don't assume production data is copied into it. If the app reads its connection string from a variable such as `DATABASE_URL` instead, the preview is only as separate as that value, so set a preview-scoped `DATABASE_URL` that points at a non-production database. * **Production stays on the default branch.** The workflow deploys production only from the default branch, so a push to any other branch never touches production. If a production deploy goes wrong, `npx prisma service version rollback ` puts the previous version back without a rebuild; see [Deployments](https://www.prisma.io/docs/compute/deployments#promote-and-roll-back). * **Teardown with the branch.** Deleting the Git branch removes the preview's services, databases and buckets. Automated cleanup never touches production or the default branch. ### A long-lived staging environment [#a-long-lived-staging-environment] A Git branch you keep, such as `staging`, works as a staging environment. Every push to it updates the same preview in place, and branch overrides give it staging values for the variables that differ. Variables are read at deploy time, so an override applies from the next push: #### bun ```bash bunx prisma project env add API_BASE_URL=https://staging-api.example.com --branch staging ``` #### pnpm ```bash pnpm prisma project env add API_BASE_URL=https://staging-api.example.com --branch staging ``` #### yarn ```bash yarn prisma project env add API_BASE_URL=https://staging-api.example.com --branch staging ``` #### npm ```bash npx prisma project env add API_BASE_URL=https://staging-api.example.com --branch staging ``` When a release is ready, merge `staging` into the default branch, and that push updates production. On Compute, the staging services cost money only while they do work, such as serving traffic, because creating a preview branch is free and an idle app scales to zero; see [Compute pricing](https://www.prisma.io/docs/compute/pricing#what-is-not-billed-separately). Without GitHub, `npx prisma deploy module.ts --stage staging` deploys the same kind of persistent staging environment from your terminal or another CI system, as [Deploying](https://www.prisma.io/docs/composer/deploying#production-and-stages) shows. ## If a coding assistant is building the feature [#if-a-coding-assistant-is-building-the-feature] Have the assistant (Claude Code, Codex, Cursor or another coding agent) work on a feature branch and push that branch, not the default one. With the workflow from this guide in the repository, every pushed branch other than the default one gets a preview with its own services and, for databases declared in the Composer module, its own new database; production data is not copied. If the app reads `DATABASE_URL`, the preview is only as separate as that value, so give previews a preview-scoped `DATABASE_URL`. * **Keep the assistant off the default branch.** A push to the default branch deploys production through the workflow without asking anyone. [Protect the default branch](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches) in GitHub and tell the assistant to open a pull request instead, for example in `AGENTS.md`: `Never push to main. Open a pull request for every change.` * **Give it its own Prisma credential.** An [enrolled agent](https://www.prisma.io/docs/prisma-compute/agent-enrollment) works on preview branches by default and asks you before it changes production through the Prisma API. The policy covers those API requests, not the deploy workflow, which is why branch protection matters. * **Check the preview, then merge.** The workflow run prints the preview's URL in its deploy report. When the feature works there, merge the pull request: the push to the default branch updates production, and deleting the feature branch removes the preview's services, databases and buckets. ## How it works [#how-it-works] Push-to-deploy needs a repository connection and a deploy workflow, and you set up both: 1. **The repository connection.** [`git connect`](https://www.prisma.io/docs/cli/git) installs the Prisma GitHub App and registers the repository with your project. This lets workflow runs authenticate: a job exchanges its GitHub OIDC token for a Prisma workspace token that expires after 30 minutes, so the workflow needs no repository secrets. The connection also subscribes the project to branch events, which is what tears a preview down when its Git branch is deleted. 2. **The deploy workflow.** [prisma/cloud-deploy-action](https://github.com/prisma/cloud-deploy-action) runs in your repository's GitHub Actions. On each push it installs dependencies, runs your build, and runs the [`deploy` command](https://www.prisma.io/docs/cli/deploy) against production or a stage named after the branch. Connecting a repository does not deploy it; deploys come from the workflow. Without the connection, the workflow has no credential: the action prints a notice, sets its `outcome` output to `skipped-no-credential`, and exits successfully, so the run stays green. You can connect in the [Console](https://pris.ly/pdp) or from the CLI. The Console opens a pull request that adds the workflow file at the same time. The CLI registers the connection only, and you add the workflow file yourself. This guide uses the CLI. ## Prerequisites [#prerequisites] * A Composer app that builds and deploys from your machine. The [full-stack tutorial](https://www.prisma.io/docs/full-stack-tutorial) ends with one. * Admin access to the GitHub repository, so you can install the Prisma GitHub App on it. ## 1. Push the project to GitHub [#1-push-the-project-to-github] If the app is not on GitHub yet, create a repository from the project directory and push it. With the [GitHub CLI](https://cli.github.com/): ```bash gh repo create my-app --private --source . --push ``` ## 2. Link the directory to the project [#2-link-the-directory-to-the-project] The `git` commands operate on the project this directory is linked to. `deploy` creates and updates the project but does not link the directory, so link it to the project your deploys created, unless you already ran `project link` or `project create` here: #### bun ```bash bunx prisma project link my-app ``` #### pnpm ```bash pnpm prisma project link my-app ``` #### yarn ```bash yarn prisma project link my-app ``` #### npm ```bash npx prisma project link my-app ``` Run the command in the project root, next to `module.ts`. Linking records the current directory, and it accepts a parent directory without a warning. If later commands fail with `PROJECT.SETUP_REQUIRED`, re-run `project link` from the project root. See the [`project` command reference](https://www.prisma.io/docs/cli/project) for how the link is stored and resolved. ## 3. Connect the repository [#3-connect-the-repository] Connect the project to the repository from step 1: #### bun ```bash bunx prisma git connect https://github.com/you/my-app ``` #### pnpm ```bash pnpm prisma git connect https://github.com/you/my-app ``` #### yarn ```bash yarn prisma git connect https://github.com/you/my-app ``` #### npm ```bash npx prisma git connect https://github.com/you/my-app ``` The command opens your browser to install the Prisma GitHub App if it is not installed yet, then registers the connection. It needs an interactive terminal. With `--no-interactive` it fails with `CLI.INTERACTION_REQUIRED`; if you cannot run it interactively, connect through the [Console](https://pris.ly/pdp) instead. ## 4. Add the deploy workflow [#4-add-the-deploy-workflow] Commit a workflow that runs the deploy action on every push: ```yaml title=".github/workflows/prisma-deploy.yml" name: prisma-deploy on: push: concurrency: group: prisma-deploy-${{ github.ref }} cancel-in-progress: false permissions: contents: read id-token: write jobs: deploy: if: github.ref_type == 'branch' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 22 - uses: oven-sh/setup-bun@v2 - uses: prisma/cloud-deploy-action@v1 with: build-command: npm run build ``` A few settings to be aware of: * `id-token: write` lets the job request the OIDC token that the action exchanges for a workspace token. Without this permission the exchange cannot happen and the run skips. * `build-command` runs verbatim. The action does not detect your framework or build for you. If the app runs its source directly, set `build-command: none`. * The action requires Bun on the runner PATH, which `oven-sh/setup-bun@v2` provides. When the repository has a `prisma` devDependency, the action deploys with that installed version, so keep it current. The action's [README](https://github.com/prisma/cloud-deploy-action) documents the remaining inputs, including `module` for an entry file that is not `module.ts` and `working-directory` for monorepos. ## 5. Push to deploy production [#5-push-to-deploy-production] Commit the workflow and push to your default branch. In the repository's **Actions** tab, the `prisma-deploy` run installs, builds, and deploys, and ends with the same deploy report you know from your terminal: ```text no-copy my-app ├─ db postgres-database db_def456 └─ api compute-service cps_abc123 https://xyz.ewr.prisma.build ``` Every later push to the default branch updates production the same way, as if you had run `deploy module.ts` yourself. If the deploy step fails with `CLI.UNKNOWN_COMMAND`, the action release predates the unified CLI: releases up to v1.5.0 call the removed `prisma composer` commands. Use a release that runs the top-level `deploy` command; the action's [releases page](https://github.com/prisma/cloud-deploy-action/releases) lists what changed in each. If the run is green but its log shows `skipped-no-credential`, the repository is not connected; repeat step 3. Runs triggered from forks skip the same way, because GitHub does not issue OIDC tokens to them, so contributors' pushes keep a green CI without reaching your workspace. ## 6. Preview a branch [#6-preview-a-branch] Push a branch to try the preview flow: ```bash git switch -c feature/search git push -u origin feature/search ``` The action deploys the branch as a [stage](https://www.prisma.io/docs/composer/deploying#production-and-stages) named after it, which is a [preview branch](https://www.prisma.io/docs/compute/branching) of the same project. The preview has its own services, its own databases assigned to that branch, its own buckets, and its own URL. The only thing it shares with production is the code. Confirm it from your terminal: #### bun ```bash bunx prisma service list --branch feature/search ``` #### pnpm ```bash pnpm prisma service list --branch feature/search ``` #### yarn ```bash yarn prisma service list --branch feature/search ``` #### npm ```bash npx prisma service list --branch feature/search ``` Further pushes to the branch update the same preview. Its configuration comes from the branch's [environment variables](https://www.prisma.io/docs/compute/environment-variables), so a preview reads preview-scoped values rather than production ones. ## 7. Delete the branch to clean up [#7-delete-the-branch-to-clean-up] When the branch has served its purpose, delete it: ```bash git push origin --delete feature/search ``` The platform tears down the matching preview: its services, databases, and buckets are removed. This automation comes from the connection you set up in step 3, so it runs whether or not a workflow fires for the deletion. Automated cleanup skips your production and default branches. ## Next steps [#next-steps] * [GitHub integration](https://www.prisma.io/docs/compute/github): what the repository connection is and does. * [Environments: production, staging and preview branches](https://www.prisma.io/docs/compute/branching): how preview branches relate to Git branches. * [Deploying](https://www.prisma.io/docs/composer/deploying): stages, deploy state, and per-stage secrets, which apply to CI deploys too. ## Related pages - [`Alchemy`](https://www.prisma.io/docs/compute/alchemy): Provision Prisma Postgres and deploy applications to Prisma Compute in one TypeScript stack. - [`Deploy Button`](https://www.prisma.io/docs/compute/deploy-button): Add a Deploy with Prisma button that copies a public Composer repository and starts a Composer-managed deployment. - [`Deployments`](https://www.prisma.io/docs/compute/deployments): How deploys create service versions on Prisma Compute, and how to inspect, promote, roll back, start, and stop them. - [`Domains`](https://www.prisma.io/docs/compute/domains): Point a custom domain at a production app and the platform verifies DNS and provisions TLS for you. - [`Environment variables`](https://www.prisma.io/docs/compute/environment-variables): Project configuration that gets injected into your deployments, scoped to production, preview, or a single branch.