From 3829cb0b6893a2b25940aa3785e4d78918b54bf6 Mon Sep 17 00:00:00 2001 From: Niek Otten Date: Mon, 29 Jun 2026 12:04:44 +0200 Subject: [PATCH] ci(acl): keep the integration lane local-only; document the runner gap (refs #46) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hosted Gitea runner starts the OpenZaak stack as sibling containers via the host daemon, so a process on the runner can't reach the published ports — the seed and dotnet test get Connection refused on localhost:8000. Drop the (non-working) integration CI job; make integration stays the local / host-runner gate. Document the limitation in gitea-actions-gotchas.md §5 and the CI runbook, and track running it inside the compose network in #55. ADR-0006 updated accordingly. Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitea/workflows/ci.yaml | 23 +++----------- .../adr-0006-integration-test-provisioning.md | 13 +++++--- docs/runbooks/ci.md | 7 ++++- docs/runbooks/gitea-actions-gotchas.md | 31 +++++++++++++++++++ 4 files changed, 51 insertions(+), 23 deletions(-) diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml index 12d885e..d3b6e36 100644 --- a/.gitea/workflows/ci.yaml +++ b/.gitea/workflows/ci.yaml @@ -63,24 +63,11 @@ jobs: path: services/acl/StrykerOutput/**/reports/mutation-report.html if-no-files-found: warn - integration: - runs-on: ubuntu-latest - steps: - - uses: https://github.com/actions/checkout@v4 - - uses: https://github.com/actions/setup-dotnet@v4 - with: - dotnet-version: '10.0.x' - # `make integration` brings the OpenZaak stack up, seeds a PUBLISHED BIG - # zaaktype (OZ_PUBLISH=1) and runs the Integration-category tests, then tears - # down. Needs Docker + python3 (both on ubuntu-latest) and outbound access to - # selectielijst.openzaak.nl from the OpenZaak container (see ADR-0006). - - run: make integration - - name: dump OpenZaak logs on failure - if: failure() - run: docker compose -f infra/openzaak/docker-compose.yml logs --no-color --tail=80 oz-init openzaak 2>&1 || true - - name: tear down on failure - if: failure() - run: docker compose -f infra/openzaak/docker-compose.yml down --volumes 2>&1 || true + # NOTE: there is deliberately no `integration` job here yet. `make integration` + # runs the ACL ↔ real-OpenZaak test locally / on a host-executing runner, but on + # the hosted runner a process on the runner cannot reach the stack's published + # ports (sibling containers — see gitea-actions-gotchas.md §5). Running it inside + # the compose network is tracked in #55. compose-smoke: runs-on: ubuntu-latest diff --git a/docs/architecture/adr-0006-integration-test-provisioning.md b/docs/architecture/adr-0006-integration-test-provisioning.md index a10da6d..5494736 100644 --- a/docs/architecture/adr-0006-integration-test-provisioning.md +++ b/docs/architecture/adr-0006-integration-test-provisioning.md @@ -47,8 +47,8 @@ itself. No new test dependency is added.** - **The lane is kept out of the fast checks.** `make unit` runs with `--filter "Category!=Integration"`; Stryker is pinned to `Acl.Tests` (`test-projects`), so neither the unit nor the mutation lane needs a live stack. A new `make integration` target - brings the stack up, seeds, runs the lane, and always tears down — mirrored by a Gitea - Actions `integration` job. This matches `make` being the single source of truth (ADR-0005). + brings the stack up, seeds, runs the lane, and always tears down. This matches `make` being + the single source of truth (ADR-0005). - **Publishing is opt-in in the seed.** `infra/openzaak/seed_catalogus.py` gains an `OZ_PUBLISH=1` path that adds the relations OpenZaak's publish requires — two statustypen (begin/eind), a roltype, and a resultaattype whose Selectielijst procestype is matched onto @@ -69,8 +69,13 @@ itself. No new test dependency is added.** `selectielijst.openzaak.nl`. It is a stable public reference API (the same one OpenZaak uses in production) but it is a network touchpoint, and a CI environment without egress would need a local Selectielijst service or a recorded fixture. `OZ_SELECTIELIJST` overrides the base URL. -- **Cost:** the lane needs the stack up first; CI runs it as a dedicated job (Docker + dotnet + - python3), separate from the fast lanes. +- **Cost:** the lane needs the stack up first, so it is separate from the fast lanes. +- **Not yet a hosted-runner job.** `make integration` passes locally and on a host-executing + runner, but on Gitea's hosted runner a process *on the runner* cannot reach the stack's + published ports — Compose starts sibling containers via the host daemon, so the ports bind to + the host, not the runner (gitea-actions-gotchas.md §5, the same split as §1). Running the test + and seed *inside* the compose network (via a built image, not bind mounts) to gate it in CI is + tracked in **#55**. Until then the lane runs locally and is not a merge gate. ## Alternatives considered diff --git a/docs/runbooks/ci.md b/docs/runbooks/ci.md index 2d09172..d925115 100644 --- a/docs/runbooks/ci.md +++ b/docs/runbooks/ci.md @@ -17,9 +17,14 @@ and CI cannot drift: | `build` | `make build` → `dotnet build … -c Release` | .NET 10 SDK | | `unit` | `make unit` → `dotnet test … -c Release --filter "Category!=Integration"` | .NET 10 SDK | | `mutation` | `make mutation` → `dotnet tool restore` → `dotnet stryker` (ACL); uploads the HTML report as an artifact | .NET 10 SDK | -| `integration` | `make integration` → `openzaak-up` → seed a **published** BIG zaaktype (`OZ_PUBLISH=1`) → `dotnet test … --filter "Category=Integration"` → tear down | .NET 10 SDK + container engine + python3 + egress to `selectielijst.openzaak.nl` | | `compose-smoke` | `make smoke` → seed config volumes → `up -d` (full stack) → `up --wait` durable services → `down` | container engine + compose v2 | +> **`make integration` is not a hosted-runner job yet.** The ACL ↔ real-OpenZaak +> test (`make integration`, ADR-0006) passes locally and on a host-executing runner, +> but a process on the hosted runner can't reach the stack's published ports +> (sibling containers — see [gitea-actions-gotchas.md §5](gitea-actions-gotchas.md)). +> Run it inside the compose network to gate it in CI — tracked in **#55**. + All `uses:` references are absolute, tag-pinned URLs (`https://github.com/actions/checkout@v4`, `https://github.com/actions/setup-dotnet@v4`) per CLAUDE.md §8.7 and §15 — Gitea Actions resolves them from GitHub. diff --git a/docs/runbooks/gitea-actions-gotchas.md b/docs/runbooks/gitea-actions-gotchas.md index 0c7408b..1967454 100644 --- a/docs/runbooks/gitea-actions-gotchas.md +++ b/docs/runbooks/gitea-actions-gotchas.md @@ -124,3 +124,34 @@ needed). v3 uses the older artifact protocol that Gitea implements, and has no G guard. Inputs are the same (`name`, `path`, `if-no-files-found`), so it is a drop-in swap. Do **not** bump to `@v4` until act_runner advertises github.com-compatible artifact support. + +--- + +## 5. A runner process can't reach a service container's published port + +**Symptom** — green locally, but a CI step that runs *on the runner* and talks to a +compose service over `localhost` fails. The ACL integration test's seed died with: + +``` +OpenZaak ready (000) +urllib.error.URLError: +make: *** [Makefile:114: integration] Error 1 +``` + +OpenZaak was demonstrably up — uwsgi had been serving for ~2 minutes — yet +`curl`/`urllib` to `localhost:8000` from the runner were refused the whole time. + +**Why** — the same sibling-container split as §1. Compose starts the stack via the +host daemon, so `ports: ["8000:8000"]` publishes to the *daemon host*, not to the job +container. From the runner, `localhost:8000` has nothing listening. (`make smoke` +sidesteps this by polling readiness via `docker inspect` (§2), never a service port.) + +**Fix** — don't talk to service ports from the runner. Either check state via `docker +inspect` (health), or run the client **inside the compose network** so it reaches the +service by name (`http://openzaak:8000`). For a test/seed that needs the repo's own +code, deliver it via a **built image** (not a bind mount — §1), then +`docker run --network _cg …`. + +**Status** — `make integration` (the ACL ↔ real-OpenZaak test, ADR-0006) therefore +runs locally / on a host-executing runner only. Gating it on the hosted runner via +the compose network is tracked in **#55**.