Getting Started with Previewops
Previewops automatically deploys pull-request previews to your cloud account. Comment /deploy-previewops on any PR and the bot builds your Docker image, deploys it, and replies with the live URL — all within minutes.
How it works
- You (or a teammate) comment
/deploy-previewopson a pull request. - Previewops builds a Docker image from the PR branch (via Cloud Build, SSH, or your provider's native build, depending on configuration).
- The image is deployed to your chosen cloud provider (Cloud Run, Fly.io, AWS Lightsail, etc.).
- Previewops posts a comment on the PR with the preview URL.
- When the PR is merged or closed, Previewops deletes the preview automatically.
- Previews also expire automatically after their TTL (default: 24 hours).
Prerequisites
GitHub App installed on your organisation or repository. Install Previewops →
Cloud credentials stored (required for Free and Premium BYOC plans). See credentials.md.
Free BYOC: only public repositories are supported. Private repo support requires Premium BYOC.
A Dockerfile in your repository root (or configured via
.previewops.yaml). If your Dockerfile is not in the repo root, you will need to set the path in.previewops.yamlbefore your first deploy.Previewops builds and runs your container as-is. A few requirements:
- The container must listen on a port (Previewops detects it automatically, or you can pin it via
port:in.previewops.yaml). - The container must start quickly — Previewops polls for readiness after deploy; a slow cold start will delay the preview URL appearing on the PR.
- Run as a non-root user where possible. This is a security best practice that reduces the container's attack surface.
A minimal multi-stage Dockerfile example looks like this:
# ── Build stage ────────────────────────────────────────────────────────── FROM node:22-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build # ── Runtime stage ──────────────────────────────────────────────────────── FROM node:22-alpine AS runtime # Non-root user (recommended as a security best practice) RUN addgroup -S app && adduser -S app -G app WORKDIR /app COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules COPY package.json ./ USER app ENV NODE_ENV=production ENV PORT=8080 EXPOSE 8080 CMD ["node", "dist/index.js"]Adjust the build commands, copied paths, dependencies, and base image for your language or framework. For non-Node stacks (Python, Go, Ruby, etc.), the same multi-stage pattern applies: compile or install in a builder stage, then copy only the required artefacts into a slim runtime image.
- The container must listen on a port (Previewops detects it automatically, or you can pin it via
Your first deploy
Step 1 — Install the GitHub App
Go to the Previewops GitHub App page and install it on your organisation or the specific repositories you want to enable.
After installation, sign in to the dashboard with GitHub. If you belong to multiple organisations that have Previewops installed, you'll be prompted to choose which org's dashboard to access.
Step 2 — Store your cloud credentials (BYOC plans)
If you are on the Free or Premium BYOC plan, you need to add your cloud provider credentials before your first deploy. Click Credentials in the left sidebar, or see credentials.md for a step-by-step walkthrough.
Pro, Enterprise, and Custom plan users can skip this step — Previewops handles the cloud account for you.
Step 3 — Open a pull request and deploy
Comment on any open PR in an enabled repository:
/deploy-previewops
Previewops will reply with a "Building Previewops environment…" comment on the PR, then update it with the live preview URL once the deploy completes (typically 2–5 minutes depending on build time).
Deploy status guide:
- ✅ Live — Previewops confirmed the app is answering requests before showing this status. If the URL stops responding afterward, see the "Troubleshooting readiness and availability" section further down this page.
- ❌ Failed — either the build or deployment failed, or the deployed service did not respond to a readiness check within the startup window. A preview resource may not exist after a build or deployment failure. After a readiness failure, the resource exists and remains recorded so Previewops can clean it up. Expand Show build logs in the PR comment for the specific error, or run
/validate-previewopsto check your credentials and configuration.- ⌛ Expired — the preview's TTL has passed but the periodic cleanup job hasn't reaped it yet. The URL may still work for a short while. Run
/delete-previewopsto remove it immediately, or wait for the next cleanup pass.
Privacy note for AI debugging links: The optional Ask Claude, Ask ChatGPT, and Open in Cursor links send a generated prompt to the selected third-party service. The prompt contains the repository name, PR number, provider, branch name, and a sanitized excerpt of the deployment error. Review that information and your organisation's data-handling policy before opening one of these links. Do not use them when the remaining error text contains credentials, customer data, or other sensitive information.
Step 4 — Configure per-repo settings (required if Dockerfile is not in root)
Add a .previewops.yaml file to the root of your repository to customise TTL, concurrency, the Dockerfile path, and more. See configuration.md for all available options.
Troubleshooting readiness and availability
A deploy shows ✅ Live only after Previewops receives an HTTP response from the application. Diagnose a preview that never becomes Live differently from one that was Live and later became unavailable.
The preview never becomes Live
Common causes of an initial readiness failure include:
- The app is listening on
127.0.0.1orlocalhostinstead of0.0.0.0. The provider's ingress layer connects through the container's network interface. A loopback-only binding refuses that connection even whencurl localhost:PORTworks inside the container. Most frameworks default to0.0.0.0, but an explicit binding such asapp.listen(port, '127.0.0.1')will prevent external readiness checks from succeeding. - The app ignores the injected
PORTenvironment variable. Previewops setsPORTto the configured service port, and the provider routes traffic to that port. Hardcoding a different port makes the application unreachable. - The start command blocks on a migration or another dependency. For example,
npx prisma db push && node server.jsnever starts the server if the migration cannot reach the database. Run migrations as a separate, visible step when possible so failures surface independently instead of preventing the application from starting.
The preview was Live but later stopped responding
Because the application already passed its readiness check, its host and port configuration were valid at deployment time. Check the runtime and provider logs for an application crash, an out-of-memory termination, or an unavailable dependency such as a database or external API. Confirm that the preview has not expired, inspect the provider's service status, and redeploy after correcting the underlying issue.
Next steps
- Welcome — Overview, plans, and full table of contents
- Commands — Full command reference (
/deploy-previewops,/delete-previewops,/list-previewops,/validate-previewops,/qa-previewops,/perf-previewops) - QA Testing — AI code review, test coverage mapping, and HTTP smoke tests with
/qa-previewops - QA Hub — Dashboard-based Playwright test library and runs against preview URLs (Pro / Enterprise / Custom)
- Performance Testing — Run k6 load tests against your preview with
/perf-previewops - Add-ons — Optional add-ons: Advanced Perf (longer tests and baselines) and Custom LLM (your own LLM key)
- Configuration —
.previewops.yamlschema and runtime options - Databases — Connecting a database to your preview container, credential safety, and migrations
- Authentication — JWT, OAuth, session cookies, and HTTPS in preview environments
- Credentials — How to add and manage cloud credentials
- Plans & Billing — Plan comparison, caps, AI QA features, and how to upgrade
- Provider guides — Per-provider setup guides
- Self-hosting — Run your own Previewops instance