Three related fixes from PR #493 deploy incident (deploy/1156 failed at bootstrap; tradein-backend USER MAPPING never created): 1. deploy-tradein.yml — restart tradein-backend AFTER SQL migrations apply. Root cause: `compose up -d` runs at line 157 before migrations at line 163, so tradein-backend lifespan hook (ensure_fdw_user_mapping) tries to CREATE USER MAPPING against FOREIGN SERVER gendesign_remote that doesn't exist yet (created by 060_postgres_fdw_extension.sql later). Hook fails permanently with `psycopg.errors.UndefinedObject: server "gendesign_remote" does not exist`; never retried. Restart after migrations triggers retry. 2. deploy.yml — extract inline psql DO block into ops/db-bootstrap/ set_tradein_fdw_password.sql, run via `psql -v pw=$ENV -f <file>`. Original block used multi-line backslash continuations inside double-quoted bash string with $$-dollar-quoting + psql var substitution — fragile escaping likely caused deploy/1156 failure between migration apply (09:01:03) and compose up -d. Clean .sql file with `-v pw=` substitution is safe and psql-native. 3. deploy.yml — verify postgres in gendesign_shared after `compose up -d`, force-recreate if not. Compose sometimes skips recreate on network membership change (PR #493 introduced `networks: shared (alias gendesign-postgres)` to postgres service). Without postgres in shared, tradein-postgres can't resolve DNS `gendesign-postgres` -> FDW queries fail with "could not translate host name". Manual fix on prod: `docker network connect --alias gendesign-postgres gendesign_shared gendesign-postgres-1`. No code changes — only deploy workflow and one new SQL file.
27 lines
1.4 KiB
SQL
27 lines
1.4 KiB
SQL
-- Set tradein_fdw_reader password from env.
|
|
-- Applied by .forgejo/workflows/deploy.yml after main DB migrations:
|
|
-- psql -v pw="$GENDESIGN_FDW_PASSWORD" -f ops/db-bootstrap/set_tradein_fdw_password.sql
|
|
--
|
|
-- Idempotent: ALTER if role exists, NOTICE and continue if missing
|
|
-- (migration 100_tradein_fdw_role.sql might not have applied yet on first deploy).
|
|
-- Password is NEVER stored in this file or in git — only the variable name.
|
|
--
|
|
-- Format %L escapes the password as a SQL string literal — safe even with quotes.
|
|
-- Combined with the regex whitelist on the backend side (fdw.py _PASSWORD_RE)
|
|
-- this gives defense-in-depth.
|
|
--
|
|
-- Extracted from deploy.yml inline DO block (PR #493 deploy/1156 incident).
|
|
-- The original block used multi-line backslash continuations inside a double-quoted
|
|
-- bash string with $$-dollar-quoting + psql variable substitution — fragile escaping
|
|
-- that likely caused the bootstrap step to fail before `compose up -d` ran.
|
|
-- Using `-f <file>` with psql-native variable substitution via `-v pw=` is safe.
|
|
|
|
DO $$
|
|
BEGIN
|
|
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'tradein_fdw_reader') THEN
|
|
EXECUTE format('ALTER ROLE tradein_fdw_reader WITH PASSWORD %L', :'pw');
|
|
RAISE NOTICE 'tradein_fdw_reader password set';
|
|
ELSE
|
|
RAISE NOTICE 'tradein_fdw_reader role missing — migration 100_tradein_fdw_role.sql not applied yet';
|
|
END IF;
|
|
END $$;
|