From 92a1ea1db152aa7d28cbf4764adfd9396a77203f Mon Sep 17 00:00:00 2001 From: Jesse_Chen Date: Mon, 20 Jul 2026 15:55:59 +0800 Subject: [PATCH] feat: parameterize staging compose configuration --- deploy/Caddyfile.staging | 4 ++++ deploy/docker-compose.server.yml | 8 +++++--- frontend/tests/health-deployment.test.ts | 22 ++++++++++++++++++++-- 3 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 deploy/Caddyfile.staging diff --git a/deploy/Caddyfile.staging b/deploy/Caddyfile.staging new file mode 100644 index 00000000..66bbb59c --- /dev/null +++ b/deploy/Caddyfile.staging @@ -0,0 +1,4 @@ +{$SITE_ADDRESS:https://staging.jyotisha.chat} { + encode zstd gzip + reverse_proxy web:3000 +} diff --git a/deploy/docker-compose.server.yml b/deploy/docker-compose.server.yml index caa615f6..42998526 100644 --- a/deploy/docker-compose.server.yml +++ b/deploy/docker-compose.server.yml @@ -4,7 +4,8 @@ services: context: .. dockerfile: deploy/railway-api.Dockerfile restart: unless-stopped - env_file: ../.env.production + env_file: + - ${APP_ENV_FILE:-../.env.production} environment: PORT: 5200 JYOTISH_ALLOWED_HOSTS: localhost,127.0.0.1,::1,api @@ -24,7 +25,8 @@ services: NEXT_PUBLIC_SUPABASE_URL: ${NEXT_PUBLIC_SUPABASE_URL} NEXT_PUBLIC_SUPABASE_ANON_KEY: ${NEXT_PUBLIC_SUPABASE_ANON_KEY} restart: unless-stopped - env_file: ../.env.production + env_file: + - ${APP_ENV_FILE:-../.env.production} environment: GITHUB_SHA: ${GITHUB_SHA} PORT: 3000 @@ -45,7 +47,7 @@ services: - "443:443" - "443:443/udp" volumes: - - ./Caddyfile:/etc/caddy/Caddyfile:ro + - ${CADDYFILE_PATH:-./Caddyfile}:/etc/caddy/Caddyfile:ro - caddy_data:/data - caddy_config:/config depends_on: diff --git a/frontend/tests/health-deployment.test.ts b/frontend/tests/health-deployment.test.ts index 4888e47b..81473c35 100644 --- a/frontend/tests/health-deployment.test.ts +++ b/frontend/tests/health-deployment.test.ts @@ -11,12 +11,14 @@ test("health endpoint exposes deployment identity for production verification", assert.match(source, /gitCommit/); }); -test("production deployment passes the tested revision into the web runtime", () => { +test("manual production deployment passes the selected revision into the web runtime", () => { const compose = readFileSync(new URL("../../deploy/docker-compose.server.yml", import.meta.url), "utf8"); const workflow = readFileSync(new URL("../../.github/workflows/deploy-production.yml", import.meta.url), "utf8"); assert.match(compose, /GITHUB_SHA: \$\{GITHUB_SHA\}/); - assert.match(workflow, /DEPLOY_GIT_SHA: \$\{\{ github\.event\.workflow_run\.head_sha \|\| github\.sha \}\}/); + assert.match(workflow, /workflow_dispatch:/); + assert.doesNotMatch(workflow, /workflow_run:/); + assert.match(workflow, /DEPLOY_GIT_SHA: \$\{\{ github\.sha \}\}/); assert.match(workflow, /GITHUB_SHA='\$DEPLOY_GIT_SHA'/); assert.match(workflow, /get\("deployment", \{\}\)\.get\("gitCommit"/); assert.match(workflow, /DEPLOY_GIT_SHA/); @@ -24,3 +26,19 @@ test("production deployment passes the tested revision into the web runtime", () assert.match(workflow, /git ls-remote origin refs\/heads\/main/); assert.match(workflow, /steps\.revision\.outputs\.deploy == 'true'/); }); + +test("server compose accepts staging paths while preserving production defaults", () => { + const compose = readFileSync(new URL("../../deploy/docker-compose.server.yml", import.meta.url), "utf8"); + + assert.match(compose, /env_file:\s*\n\s*- \$\{APP_ENV_FILE:-\.\.\/\.env\.production\}/); + assert.match(compose, /\$\{CADDYFILE_PATH:-\.\/Caddyfile\}:\/etc\/caddy\/Caddyfile:ro/); + assert.match(compose, /SITE_ADDRESS: \$\{SITE_ADDRESS:-https:\/\/jyotisha\.chat\}/); +}); + +test("staging Caddy configuration serves only the configured staging address", () => { + const caddy = readFileSync(new URL("../../deploy/Caddyfile.staging", import.meta.url), "utf8"); + + assert.match(caddy, /\{\$SITE_ADDRESS:https:\/\/staging\.jyotisha\.chat\}/); + assert.match(caddy, /reverse_proxy web:3000/); + assert.doesNotMatch(caddy, /www\.jyotisha\.chat/); +});