From 3f8b5c6ea4d51967581f646de24aabebbc55006a Mon Sep 17 00:00:00 2001 From: cesnimda Date: Wed, 1 Jul 2026 12:44:14 +0200 Subject: [PATCH] fix(staging): robust env write + stop double-binding prod ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .gitea/workflows/deploy-staging.yml | 21 ++++++++++----------- docker-compose.staging.yml | 10 ++++++---- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/.gitea/workflows/deploy-staging.yml b/.gitea/workflows/deploy-staging.yml index a0f7112..5d07023 100644 --- a/.gitea/workflows/deploy-staging.yml +++ b/.gitea/workflows/deploy-staging.yml @@ -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 diff --git a/docker-compose.staging.yml b/docker-compose.staging.yml index be62449..9482043 100644 --- a/docker-compose.staging.yml +++ b/docker-compose.staging.yml @@ -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" -- 2.52.0