PR Preview Deployments

Each pull request gets an isolated Fly.io preview app with its own ephemeral database.

How It Works

  1. PR opened/updated (non-draft only)
  2. pr-preview.yml detects app code changes
  3. Builds PR-specific Docker image (tag: pr-<number>)
  4. Creates Fly.io app: renewa-app-pr-{number}
  5. Provisions isolated PostgreSQL instance
  6. Deploys and posts preview URL as PR comment

Workflow Files

WorkflowTriggerPurpose
.github/workflows/pr-preview.ymlPR open/syncBuild + deploy preview
.github/workflows/pr-cleanup.ymlPR closeDestroy preview app + database
.github/workflows/cleanup-orphaned-previews.ymlScheduledRemove stale preview apps

Database Behavior

  • Created on first deploy for the PR
  • Recreated only when schema/migration files change
  • Data persists across non-schema commits (faster deploys)
  • Uses minimal seed (3 Users, 3 Buildings, 5 Projects) for fast startup (<30s)

Fly.io Configuration

Preview apps use a dedicated config: renewa-one/fly.pr-preview.toml

Key differences from production:

  • Smaller VM size (cost optimization)
  • Single region (Frankfurt)
  • Ephemeral storage only

Required Status Check

The ci-gate job in pr-preview.yml is the single required check for merging. It validates all upstream jobs (build, test, deploy) passed or were correctly skipped. See CI-CD Workflows for the full workflow list.

Skip Logic

The workflow detects whether app code changed (vs. docs-only or config-only changes) and skips unnecessary builds. This keeps docs branches fast.

Promotion Path

Preview deployments are independent from the promotion pipeline:

PR Preview (pr-<number>)     -- ephemeral, per-PR
Development (main-<sha>)     -- auto-deploy on merge
Staging                      -- manual promotion
Production                   -- manual promotion

Key Files

  • .github/workflows/pr-preview.yml
  • .github/workflows/pr-cleanup.yml
  • .github/workflows/cleanup-orphaned-previews.yml
  • renewa-one/fly.pr-preview.toml

See Also