fix(staging): robust env write + stop double-binding prod ports
CI / backend (pull_request) Successful in 1m2s
CI / frontend (pull_request) Successful in 21s
Security / secrets (pull_request) Successful in 6s
Security / dependencies (pull_request) Successful in 1m4s

Two fixes to the auto-deploy path found on the first host-mode run:
- Write deploy/.env.staging line-by-line instead of a here-string, so the step
  can't be broken by how act_runner indents/wraps the PowerShell script (the
  here-string terminator must be col 0; the runner's wrapping broke it, leaving
  POSTGRES_PASSWORD blank so postgres/api failed while frontend came up).
- Tag the staging 'ports' lists with !override so the overlay REPLACES the base
  ports instead of merging — staging no longer also binds prod's 8080/8081.
Verified locally: compose config shows only 18080/18081/15432.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
cesnimda
2026-07-01 12:44:14 +02:00
parent 8727be9e94
commit 3f8b5c6ea4
2 changed files with 16 additions and 15 deletions
+10 -11
View File
@@ -22,18 +22,17 @@ jobs:
- name: Write staging env from secrets
shell: powershell
# Single-quoted here-string: Gitea substitutes the ${{ secrets.* }} tokens
# before the shell runs, and PowerShell then treats the values literally
# (no $ interpolation). ascii = no BOM, which docker compose's env parser needs.
# Per-line writes (not a here-string) so the step can't be broken by how the
# runner indents/wraps the script. Gitea substitutes ${{ secrets.* }} first;
# ascii = no BOM, which docker compose's env parser needs.
run: |
@'
POSTGRES_PASSWORD=${{ secrets.STAGING_POSTGRES_PASSWORD }}
GOOGLE_CLIENT_ID=${{ secrets.STAGING_GOOGLE_CLIENT_ID }}
GOOGLE_CLIENT_SECRET=${{ secrets.STAGING_GOOGLE_CLIENT_SECRET }}
AI_MODE=Disabled
FRONTEND_ORIGIN=http://localhost:18081
MAX_MESSAGES=2000
'@ | Out-File -FilePath deploy/.env.staging -Encoding ascii
Set-Content deploy/.env.staging "POSTGRES_PASSWORD=${{ secrets.STAGING_POSTGRES_PASSWORD }}" -Encoding ascii
Add-Content deploy/.env.staging "GOOGLE_CLIENT_ID=${{ secrets.STAGING_GOOGLE_CLIENT_ID }}" -Encoding ascii
Add-Content deploy/.env.staging "GOOGLE_CLIENT_SECRET=${{ secrets.STAGING_GOOGLE_CLIENT_SECRET }}" -Encoding ascii
Add-Content deploy/.env.staging "AI_MODE=Disabled" -Encoding ascii
Add-Content deploy/.env.staging "FRONTEND_ORIGIN=http://localhost:18081" -Encoding ascii
Add-Content deploy/.env.staging "MAX_MESSAGES=2000" -Encoding ascii
Write-Host "wrote $((Get-Content deploy/.env.staging).Count) env lines"
- name: Redeploy staging stack
shell: powershell
+6 -4
View File
@@ -21,7 +21,9 @@
services:
postgres:
ports:
# !override replaces the base port list instead of merging with it, so staging
# binds ONLY its shifted 18xxx/15432 ports and never squats on prod's 8080/8081.
ports: !override
- "127.0.0.1:15432:5432"
api:
@@ -32,13 +34,13 @@ services:
App__DevMode: "true"
GmailSync__MaxMessages: ${MAX_MESSAGES:-2000}
Cors__Origins__0: ${FRONTEND_ORIGIN:-http://localhost:18081}
ports:
ports: !override
- "127.0.0.1:18080:8080"
frontend:
ports:
ports: !override
- "18081:80"
nginx:
ports:
ports: !override
- "18000:80"