From b164c4ca70265db752784291ef3d6f17b45ba4fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hartmut=20N=C3=B6renberg?= Date: Mon, 13 Apr 2026 00:04:32 +0200 Subject: [PATCH] ci: fix e2e hostname collision and docker-deploy admin seed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit E2E: rename service hosts postgres/redis to e2epg/e2eredis — the gitea_gitea network has multiple containers answering to 'postgres' (Gitea core + concurrent job services), causing split-brain where prisma db push and db:seed connected to different databases and audit_logs ended up missing. docker-compose.ci.yml: stop attaching postgres/redis to gitea_gitea for the docker-deploy-test job — only the app needs cross-network reachability; the compose services talk to each other on the internal default network. Docker Deploy: setup-admin.mjs imports @prisma/client and @node-rs/argon2 which only live in packages/db/node_modules. Node resolves bare specifiers from the script's directory (/app/scripts), not cwd, so pnpm --filter wrappers did not help. Set NODE_PATH to packages/db/node_modules as a fallback resolution root. --- .claude/worktrees/agent-a0063a64 | 1 + .claude/worktrees/agent-a06ee6f2 | 1 + .claude/worktrees/agent-a2939317 | 1 + .claude/worktrees/agent-a74dc5bc | 1 + .claude/worktrees/agent-a7de1005 | 1 + .claude/worktrees/agent-a8de1898 | 1 + .claude/worktrees/agent-a90e1bc2 | 1 + .claude/worktrees/agent-acdb74a3 | 1 + .claude/worktrees/agent-aed43cff | 1 + .github/workflows/ci.yml | 36 ++++++++++++++++++-------------- docker-compose.ci.yml | 20 +++++++----------- 11 files changed, 37 insertions(+), 28 deletions(-) create mode 160000 .claude/worktrees/agent-a0063a64 create mode 160000 .claude/worktrees/agent-a06ee6f2 create mode 160000 .claude/worktrees/agent-a2939317 create mode 160000 .claude/worktrees/agent-a74dc5bc create mode 160000 .claude/worktrees/agent-a7de1005 create mode 160000 .claude/worktrees/agent-a8de1898 create mode 160000 .claude/worktrees/agent-a90e1bc2 create mode 160000 .claude/worktrees/agent-acdb74a3 create mode 160000 .claude/worktrees/agent-aed43cff diff --git a/.claude/worktrees/agent-a0063a64 b/.claude/worktrees/agent-a0063a64 new file mode 160000 index 0000000..b9fd7fd --- /dev/null +++ b/.claude/worktrees/agent-a0063a64 @@ -0,0 +1 @@ +Subproject commit b9fd7fdb035847ebe23cd6fb63364c51737a0841 diff --git a/.claude/worktrees/agent-a06ee6f2 b/.claude/worktrees/agent-a06ee6f2 new file mode 160000 index 0000000..dda0490 --- /dev/null +++ b/.claude/worktrees/agent-a06ee6f2 @@ -0,0 +1 @@ +Subproject commit dda049075fff72dc578c0215c660fc51f733be1b diff --git a/.claude/worktrees/agent-a2939317 b/.claude/worktrees/agent-a2939317 new file mode 160000 index 0000000..b2c8d98 --- /dev/null +++ b/.claude/worktrees/agent-a2939317 @@ -0,0 +1 @@ +Subproject commit b2c8d98b25fbd916eda60ea038e8fede86dd18d6 diff --git a/.claude/worktrees/agent-a74dc5bc b/.claude/worktrees/agent-a74dc5bc new file mode 160000 index 0000000..fbca017 --- /dev/null +++ b/.claude/worktrees/agent-a74dc5bc @@ -0,0 +1 @@ +Subproject commit fbca017eaa8e8da509d03d02c1abc56c27e10294 diff --git a/.claude/worktrees/agent-a7de1005 b/.claude/worktrees/agent-a7de1005 new file mode 160000 index 0000000..d7a35b2 --- /dev/null +++ b/.claude/worktrees/agent-a7de1005 @@ -0,0 +1 @@ +Subproject commit d7a35b2d7adeb7cdd53c33a05b51ddf6be9f9710 diff --git a/.claude/worktrees/agent-a8de1898 b/.claude/worktrees/agent-a8de1898 new file mode 160000 index 0000000..999626c --- /dev/null +++ b/.claude/worktrees/agent-a8de1898 @@ -0,0 +1 @@ +Subproject commit 999626cf70351fcd4772383a817fbbbde8bb5192 diff --git a/.claude/worktrees/agent-a90e1bc2 b/.claude/worktrees/agent-a90e1bc2 new file mode 160000 index 0000000..9a42615 --- /dev/null +++ b/.claude/worktrees/agent-a90e1bc2 @@ -0,0 +1 @@ +Subproject commit 9a42615a21847d4e0d06f6858e15cbbb4241b891 diff --git a/.claude/worktrees/agent-acdb74a3 b/.claude/worktrees/agent-acdb74a3 new file mode 160000 index 0000000..aebe5bc --- /dev/null +++ b/.claude/worktrees/agent-acdb74a3 @@ -0,0 +1 @@ +Subproject commit aebe5bc57db5a27c30240b89be9890110929fc0b diff --git a/.claude/worktrees/agent-aed43cff b/.claude/worktrees/agent-aed43cff new file mode 160000 index 0000000..6f3bdd8 --- /dev/null +++ b/.claude/worktrees/agent-aed43cff @@ -0,0 +1 @@ +Subproject commit 6f3bdd81e877ee4c0b85b531f86c518ce6053753 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index df4c402..f64ca84 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -284,7 +284,11 @@ jobs: needs: [build] runs-on: ubuntu-latest services: - postgres: + # Unique hostnames — "postgres"/"redis" collide with Gitea's own core + # containers and concurrent job service containers on the shared + # gitea_gitea network, producing split-brain where push hits one DB and + # seed hits another. See audit_logs-missing bug from commit f856dd26. + e2epg: image: postgres:16 env: POSTGRES_DB: capakraken_test @@ -295,7 +299,7 @@ jobs: --health-interval=10s --health-timeout=5s --health-retries=5 - redis: + e2eredis: image: redis:7 options: >- --health-cmd="redis-cli ping" @@ -303,15 +307,15 @@ jobs: --health-timeout=5s --health-retries=5 env: - DATABASE_URL: postgresql://capakraken:capakraken_test@postgres:5432/capakraken_test + DATABASE_URL: postgresql://capakraken:capakraken_test@e2epg:5432/capakraken_test # Playwright test-server.mjs requires an explicit test DB URL. - PLAYWRIGHT_DATABASE_URL: postgresql://capakraken:capakraken_test@postgres:5432/capakraken_test + PLAYWRIGHT_DATABASE_URL: postgresql://capakraken:capakraken_test@e2epg:5432/capakraken_test # prisma-with-env.mjs refuses to run unless DATABASE_URL's db name matches # the expected target; default is "capakraken", CI uses capakraken_test. CAPAKRAKEN_EXPECTED_DB_NAME: capakraken_test ALLOW_DESTRUCTIVE_DB_TOOLS: "true" CONFIRM_DESTRUCTIVE_DB_NAME: capakraken_test - REDIS_URL: redis://redis:6379 + REDIS_URL: redis://e2eredis:6379 PORT: 3100 NEXTAUTH_URL: ${{ env.CI_AUTH_URL }} AUTH_URL: ${{ env.CI_AUTH_URL }} @@ -364,15 +368,15 @@ jobs: # postgres hosts reachable as "postgres" on gitea_gitea (the Gitea # core DB plus the service container) and push/seed hit different # ones. Verify via direct psql. - echo "--- hosts resolving to 'postgres' ---" - getent hosts postgres || true + echo "--- hosts resolving to 'e2epg' ---" + getent hosts e2epg || true echo "--- DROP SCHEMA ---" - psql -h postgres -U capakraken -d capakraken_test -v ON_ERROR_STOP=1 \ + psql -h e2epg -U capakraken -d capakraken_test -v ON_ERROR_STOP=1 \ -c "DROP SCHEMA IF EXISTS public CASCADE; CREATE SCHEMA public; GRANT ALL ON SCHEMA public TO capakraken; GRANT ALL ON SCHEMA public TO public;" echo "--- prisma db push ---" pnpm --filter @capakraken/db exec prisma db push --schema ./prisma/schema.prisma --accept-data-loss --skip-generate echo "--- tables in public after push ---" - psql -h postgres -U capakraken -d capakraken_test -v ON_ERROR_STOP=1 \ + psql -h e2epg -U capakraken -d capakraken_test -v ON_ERROR_STOP=1 \ -c "\dt public.*" | tee /tmp/tables.txt if ! grep -q 'audit_logs' /tmp/tables.txt; then echo "ERROR: audit_logs table missing after push!" @@ -457,15 +461,15 @@ jobs: echo "$BODY" | grep '"status":"ok"' - name: Seed admin user - # setup-admin.mjs imports @prisma/client, which only lives in - # packages/db/node_modules in pnpm workspaces. Run via pnpm so Node - # resolution finds it. + # setup-admin.mjs imports @prisma/client and @node-rs/argon2, both of + # which live only in packages/db/node_modules under pnpm workspaces. + # Node's bare-specifier resolution walks up from the *script's* + # directory (/app/scripts), not cwd, and the root /app/node_modules + # has neither. NODE_PATH adds packages/db/node_modules as a fallback + # resolution root so the imports succeed. run: | docker compose -f docker-compose.yml -f docker-compose.ci.yml exec -T app \ - pnpm --filter @capakraken/db exec node /app/scripts/setup-admin.mjs \ - --email admin@capakraken.dev \ - --name "Admin" \ - --password admin123 + sh -c 'NODE_PATH=/app/packages/db/node_modules node /app/scripts/setup-admin.mjs --email admin@capakraken.dev --name Admin --password admin123' - name: Set up Node.js 20 uses: actions/setup-node@v4.0.4 diff --git a/docker-compose.ci.yml b/docker-compose.ci.yml index 5833083..5062498 100644 --- a/docker-compose.ci.yml +++ b/docker-compose.ci.yml @@ -13,18 +13,14 @@ services: app: volumes: !reset [] - # Attach to the gitea_gitea network too so the act_runner job container - # (which lives on gitea_gitea) can reach the compose services by name. - # Otherwise "localhost:3100" from inside the job container resolves to - # the job container itself, not the compose-network app. - networks: - - default - - gitea_gitea - postgres: - networks: - - default - - gitea_gitea - redis: + # Attach only the app to gitea_gitea so the act_runner job container + # (which lives on gitea_gitea) can reach the compose app by service name. + # Do NOT attach postgres/redis here — doing so causes hostname collisions + # with other containers already on gitea_gitea (Gitea core + concurrent + # job service containers all answer to "postgres"), producing split-brain + # where different clients hit different DBs. The app talks to postgres/ + # redis by service name on the internal compose network, which works + # regardless of gitea_gitea. networks: - default - gitea_gitea