Add staging + PR-preview environments on the flagship
Implements the staging-environments OpenSpec change. Persistent staging at staging.trails.cool / planner.staging.trails.cool deploys from main; PR opens get a journal-only preview at pr-<N>.staging.trails.cool that shares the persistent planner. cd-staging.yml builds tagged images, manages per-PR Postgres databases and Caddyfile snippets, evicts the oldest preview at the cap of 3, and tears everything down on PR close. staging-cleanup.yml runs weekly to sweep orphaned previews. DNS records (staging + *.staging A/AAAA) already applied to production via tofu. Caddy approach: per-PR Caddyfile snippets imported from /etc/caddy/sites/ and reloaded on each PR event — no wildcard / on-demand TLS, no router service. Production compose gains a trails-shared network for the staging project to reach Postgres, and host.docker.internal on Caddy so it can reverse-proxy staging containers published on the host loopback. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
795ec2215c
commit
c8a7a0b253
11 changed files with 818 additions and 29 deletions
|
|
@ -6,10 +6,19 @@ services:
|
|||
- "80:80"
|
||||
- "443:443"
|
||||
- "443:443/udp"
|
||||
# host.docker.internal lets Caddy reverse-proxy to staging / PR-preview
|
||||
# containers, which publish on the host's loopback (e.g. 127.0.0.1:3100).
|
||||
# Linux requires `host-gateway` to make this name resolve.
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
environment:
|
||||
DOMAIN: ${DOMAIN:-trails.cool}
|
||||
volumes:
|
||||
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
||||
# Per-PR staging snippets dropped in by cd-staging.yml. Bind mount
|
||||
# auto-creates the host directory if it doesn't exist, so a fresh
|
||||
# server doesn't need pre-provisioning.
|
||||
- ./sites:/etc/caddy/sites:ro
|
||||
- caddy_data:/data
|
||||
- caddy_config:/config
|
||||
depends_on:
|
||||
|
|
@ -90,6 +99,12 @@ services:
|
|||
postgres:
|
||||
image: postgis/postgis:16-3.4
|
||||
restart: unless-stopped
|
||||
# Joined to the shared network so the staging compose project can reach
|
||||
# this instance by hostname `postgres`. Production services keep using
|
||||
# the default network as before.
|
||||
networks:
|
||||
- default
|
||||
- trails-shared
|
||||
environment:
|
||||
POSTGRES_USER: trails
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-trails}
|
||||
|
|
@ -226,6 +241,16 @@ services:
|
|||
# - garage_data:/var/lib/garage
|
||||
# - ./garage.toml:/etc/garage.toml:ro
|
||||
|
||||
networks:
|
||||
# Default project network — kept implicit for production services.
|
||||
default:
|
||||
# Created by this compose project with a fixed (un-namespaced) name so the
|
||||
# staging compose project can attach to it via `external: true`. Only
|
||||
# postgres is joined here on the production side; staging containers join
|
||||
# to reach postgres by hostname.
|
||||
trails-shared:
|
||||
name: trails-shared
|
||||
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue