Skip to content

Conversation

@cemreinanc
Copy link
Contributor

@cemreinanc cemreinanc commented Jan 19, 2026

Summary

Add ephemeral preview environments for pull requests that spin up on PR open and automatically clean up on PR close.

Features

  • Docker image built and pushed to GitHub Container Registry (ghcr.io)
  • NeonDB branch for isolated PostgreSQL per PR
  • Fly Redis for isolated caching per PR
  • Fly.io deployment (app-only minimal)
  • Auto-cleanup of all resources when PR is closed

closes #4093

Summary by CodeRabbit

  • New Features

    • Automated PR preview environments: build, deploy, post preview details, and clean up ephemeral previews.
  • Bug Fixes

    • Fixed contradictory scheme header propagation to prevent proxy-related deployment errors.
  • Chores

    • Added optional Redis override env vars for isolated cache and message-queue in previews.
    • Updated proxy/nginx behavior to use upstream scheme and clear conflicting scheme headers.

✏️ Tip: You can customize this high-level summary in your review settings.

…enhance redis configuration to optionally take two different urls

- Added additional headers in the API proxy to handle scheme-related warnings on Fly.io.
- Updated Nginx configuration to use incoming X-Forwarded-Proto and clear conflicting headers.
- Modified Django settings to allow optional Redis cache and message queue URLs for better flexibility.
…nvironments

- Introduced `fly.preview.toml` for configuring Fly.io deployments specific to Metaculus preview environments.
- Created a GitHub Actions workflow (`pr_preview.yml`) to automate the setup of ephemeral preview environments for pull requests, including Docker image builds, database creation, and resource cleanup.
- Updated Django settings to allow dynamic addition of allowed hosts for preview deployments.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 19, 2026

📝 Walkthrough

Walkthrough

Adds a GitHub Actions PR preview workflow and Fly preview config to create ephemeral preview environments; provisions NeonDB branches and Fly Redis, builds/pushes Docker images, deploys to Fly.io, posts PR comments, and cleans up on close. Also adds Redis overrides, ALLOWED_HOSTS support, and scheme-related nginx/proxy/header adjustments.

Changes

Cohort / File(s) Summary
Preview workflow
.github/workflows/pr_preview.yml
New GH Actions workflow managing preview lifecycle: fork detection, deterministic resource naming, build & push Docker image to GHCR, provision NeonDB branch and Fly Redis, deploy to Fly.io, post/update PR comment, and cleanup on PR close.
Fly preview config
fly.preview.toml
New Fly.io app configuration for preview deployment (pre-built image, env vars, HTTP service, process/release commands, resource limits).
Django settings
metaculus_web/settings.py
Adds REDIS_CACHE_URL and REDIS_MQ_URL overrides, uses them for Dramatiq broker and Django cache LOCATION, and adds APP_DOMAIN appended to ALLOWED_HOSTS when provided.
Front-end proxy headers
front_end/src/app/(api)/api-proxy/[...path]/route.ts
Extends blocklistHeaders with scheme-related headers (x-forwarded-ssl, x-forwarded-scheme, x-scheme, x-url-scheme, forwarded) to avoid contradictory-scheme forwarding.
Nginx scheme mapping
scripts/nginx/etc/nginx/http.d/app_nginx.template
Adds map for $proxy_x_forwarded_proto to prefer upstream X-Forwarded-Proto, falling back to $scheme.
Nginx proxy params
scripts/nginx/etc/nginx/proxy_params
Uses $proxy_x_forwarded_proto for X-Forwarded-Proto and clears redundant scheme headers (X-Forwarded-Ssl, X-Forwarded-Scheme, X-Url-Scheme, Forwarded) to prevent conflicts.

Sequence Diagram

sequenceDiagram
    participant PR as Pull Request
    participant GHA as GitHub Actions
    participant GHCR as GitHub Container Registry
    participant Neon as NeonDB
    participant Fly as Fly.io
    participant Redis as Fly Redis
    participant App as Preview App
    participant Bot as PR Comment Bot

    PR->>GHA: PR opened/updated
    GHA->>GHA: check fork, generate preview IDs
    alt fork PR
        GHA->>Bot: post guidance comment
    else internal PR
        GHA->>GHCR: build & push Docker image
        GHCR-->>GHA: image tags
        par provision DB and cache
            GHA->>Neon: create DB branch
            Neon-->>GHA: DB connection info
        and
            GHA->>Redis: provision Redis
            Redis-->>GHA: Redis URL
        end
        GHA->>Fly: deploy app with image & env
        Fly->>App: start with DB/Redis
        App-->>Fly: ready
        Fly-->>GHA: preview URL
        GHA->>Bot: post/update PR comment with preview details
    end
    PR->>GHA: PR closed
    GHA->>Fly: delete app
    GHA->>Neon: delete DB branch
    GHA->>Redis: delete Redis
    GHA->>Bot: update comment (cleaned)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

"I nibble at commits and hop with delight,
building tiny worlds for each PR in sight.
Neon and Redis, a Fly app to share,
ephemeral gardens spun up with care.
When PRs close, I tidy the lair. 🐇✨"

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Implement Preview Deployments' directly and concisely describes the main objective of the changeset: implementing preview deployment infrastructure.
Linked Issues check ✅ Passed All coding requirements from issue #4093 are met: Docker image build/push to GHCR, NeonDB branch creation, Fly Redis provisioning, Fly.io deployment, and auto-cleanup on PR close.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing preview deployments; no unrelated modifications were introduced outside the stated objectives.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 19, 2026

🧹 Preview Environment Cleaned Up

The preview environment for this PR has been destroyed.

Resource Status
🌐 Preview App ✅ Deleted
🗄️ PostgreSQL Branch ✅ Deleted
⚡ Redis Database ✅ Deleted
🔧 GitHub Deployments ✅ Removed
📦 Docker Image ⚠️ Retained (auto-cleanup via GHCR policies)

Cleanup triggered by PR close at 2026-01-20T11:38:02Z

Copy link
Contributor

@elisescu elisescu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

…od builds.

- Changed the method of generating the Docker image tag and tag SHA to use the slug URL output from the slugify step.
- Updated the image name output to include the new slug URL format for better traceability.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @.github/workflows/pr_preview.yml:
- Around line 305-319: The backend settings are reading the typo'd environment
variable SENTRY_DNS—update metaculus_web/settings.py to read SENTRY_DSN (e.g.,
change any os.environ.get("SENTRY_DNS") / config lookup to
os.environ.get("SENTRY_DSN") or equivalent) and then update the workflow snippet
to export SENTRY_DSN instead of SENTRY_DNS so the backend and workflow use the
standard Sentry DSN name; leave PUBLIC_FRONTEND_SENTRY_DSN unchanged.
- Around line 138-159: The generated Fly resource names (PREVIEW_ID used for
fly_app and redis_name) may exceed Fly's 63-char limit or contain trailing
hyphens; sanitize and shorten PREVIEW_ID derived from
steps.slugify.outputs.slug-url by enforcing lowercase, removing/normalizing
invalid chars (allow only a-z0-9 and hyphen), trimming the overall name to
ensure fly_app and redis_name <=63 chars (accounting for their prefixes
"metaculus-" and "mtc-redis-"), and ensure redis_name ends with an alphanumeric
character (trim trailing hyphens or append a digit if needed); update the
name-generation block around PREVIEW_ID, fly_app, and redis_name to perform
these checks/truncation before writing to GITHUB_OUTPUT.
🧹 Nitpick comments (1)
.github/workflows/pr_preview.yml (1)

245-278: Use flyctl redis status --json for stable URL parsing.

The current grep/awk parsing of "Private URL" is brittle and will break if the CLI output format changes. Instead, use flyctl redis status <name> --json which outputs GraphQL API response as JSON, then parse the private URL field with jq. This is more maintainable and resilient to CLI updates.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b023a34 and f278d2d.

📒 Files selected for processing (1)
  • .github/workflows/pr_preview.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Build Docker Image
  • GitHub Check: Backend Checks
  • GitHub Check: Frontend Checks
  • GitHub Check: integration-tests
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (4)
.github/workflows/pr_preview.yml (4)

71-113: Fork PR guardrails look good.

Clear skip path + user-facing guidance keeps secrets safe for forked PRs.


167-212: Docker build/push flow is solid.

Tags, metadata, and cache usage look well-structured for PR previews.


339-395: PR comment content is clear and helpful.

Nice summary + details section for discoverability.


399-475: Cleanup flow is thorough.

Resource teardown + PR comment update covers the full lifecycle well.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@cemreinanc cemreinanc merged commit 42cfb5b into main Jan 20, 2026
14 checks passed
@cemreinanc cemreinanc deleted the chore/init-preview-deployments branch January 20, 2026 11:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement PR Preview Environments

4 participants