4476cbb518b9286b315e44d1ae058f4613d38cc7
6 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
fc9b63f24a |
feat(infra): add dev.sh wrapper for the local-dev compose stack (#68)
## Summary Two recurring frictions on the local-dev stack: 1. **Compose-profile asymmetry** — `docker compose down` only operates on services whose profile is currently active. Anything brought up with `--profile X` keeps running unless the same flag is passed on `down`. pgweb and Jaeger silently survived several `down -v` invocations before we noticed (#67 documented the gotcha; this PR makes it impossible to hit if you use the wrapper). 2. **Verbose invocations** — typing `docker compose -f infra/local/dev.compose.yml --profile … <verb>` for routine ops gets old fast. Add [`infra/local/dev.sh`](infra/local/dev.sh) as a thin wrapper. Always passes every profile in scope on teardown / status / log commands, exposes ergonomic verbs: | Command | Effect | | --------------------------------------------- | --------------------------------------------------------------- | | `./infra/local/dev.sh up` | Core only (postgres + redis + otel-collector) | | `./infra/local/dev.sh up all` | Core + every profile | | `./infra/local/dev.sh up dbtools` | Core + pgweb | | `./infra/local/dev.sh up observability` | Core + Jaeger | | `./infra/local/dev.sh down [-v]` | Tear down (every profile in scope, no orphaned services) | | `./infra/local/dev.sh stop <service>` | Stop one service (containers stay around) | | `./infra/local/dev.sh restart <service>` | Restart one service | | `./infra/local/dev.sh status` | `ps` with every profile visible | | `./infra/local/dev.sh logs [service]` | Follow logs | | `./infra/local/dev.sh exec <service> <cmd>` | Run a command inside a container | Anything not matching one of the named verbs is passed through to `docker compose -f dev.compose.yml ...` (with every profile flagged in), so the full Compose surface remains available. ## Doc updates - **`infra/README.md`** — new "Convenience script" subsection with the cheat-sheet table; "First-time setup" rewritten to use the script; the standalone "Profile symmetry" tip from #67 is collapsed into a one-liner since the script now handles it (the note remains as a fallback for direct `docker compose` users). - **`docs/development.md` §3** — points at the script for the typical setup flow. The compose file itself is unchanged. ## Test plan - [ ] `./infra/local/dev.sh help` prints the usage block. - [ ] `./infra/local/dev.sh up` brings up the 3 core services (no pgweb / no jaeger). - [ ] `./infra/local/dev.sh up all` adds pgweb and Jaeger. - [ ] `./infra/local/dev.sh down -v` stops and removes all 5 containers (incl. pgweb and Jaeger), wipes the postgres-data and redis-data volumes. - [ ] `./infra/local/dev.sh stop pgweb` stops just pgweb. - [ ] `./infra/local/dev.sh logs otel-collector` follows that service's logs. - [ ] `./infra/local/dev.sh exec postgres psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "\du"` lists the audit roles. - [ ] `./infra/local/dev.sh stop` (no arg) errors with a clear message. --------- Co-authored-by: Julien Gautier <julien.gautier@apf.asso.fr> Reviewed-on: #68 |
||
|
|
4d2d4d652a |
docs(infra): document Compose profile + down/up symmetry gotcha (#67)
## Summary `docker compose -f infra/local/dev.compose.yml down -v` left pgweb and Jaeger running, with no error and no obvious diagnostic — they kept eating memory until the next reboot. Reason: Compose only operates on services whose profile is currently active. Bringing them up with `--profile dbtools` / `--profile observability` requires the same flag(s) on `down`, otherwise they're invisible to that command. Document the gotcha in `infra/README.md` "Local-dev stack" → "Operational tips", with the two pragmatic resolutions: 1. Pass the same flags on each command (most explicit). 2. Set `COMPOSE_PROFILES=dbtools,observability` once in the shell or `infra/local/.env`, and let it propagate to every `up` / `down` / `ps` invocation. ## Test plan - [ ] Bring up the full stack: `docker compose -f infra/local/dev.compose.yml --profile dbtools --profile observability up -d`. - [ ] `docker compose -f infra/local/dev.compose.yml down -v` (no flags) — confirms pgweb + jaeger keep running. - [ ] Run the documented "complete" command — confirms everything is gone. - [ ] Repeat with `COMPOSE_PROFILES` set; same outcome. --------- Co-authored-by: Julien Gautier <julien.gautier@apf.asso.fr> Reviewed-on: #67 |
||
|
|
0f00d6d93f |
feat(infra): add local-dev Docker Compose stack (#57)
## Summary Bring up Postgres + Redis + OTel Collector in one command so contributors can run the BFF end-to-end without manually wiring each service. Replaces the throwaway `docker run postgres:17-alpine` one-liner that was in `docs/development.md` §3. ### What lands - **`infra/local/dev.compose.yml`** — three core services (`postgres:17.2-alpine`, `redis:7.4-alpine`, `otel/opentelemetry-collector-contrib:0.115.0`) plus two viewers gated behind Compose profiles: - `--profile dbtools` → `sosedoff/pgweb:0.16.2` (Postgres GUI on port 8081) - `--profile observability` → `jaegertracing/all-in-one:1.62` (Jaeger UI on 16686) - All ports overridable via `.env`. State in named volumes. Healthchecks on data services. - **`infra/local/.env.example`** — credentials + ports template. `POSTGRES_PASSWORD` and `REDIS_PASSWORD` are mandatory (compose refuses to boot without them); other keys default sensibly. - **`infra/local/init/postgres/01-init.sql`** — bootstrap SQL per **ADR-0013**: `audit_owner` / `audit_writer` / `audit_reader` / `audit_archiver` roles + `audit` schema. Default privileges encode the append-only contract (INSERT to writer, SELECT to reader, DELETE to archiver, no UPDATE/TRUNCATE to anyone). Applied on first Postgres boot only; documented re-run procedure. - **`infra/local/otel-collector.yaml`** — pipeline: OTLP gRPC/HTTP → batch → debug exporter (always) + forward to `jaeger:4317`. When the observability profile is off, the Jaeger export logs warn-level retries but doesn't block the debug pipeline. ### Surrounding doc updates - **`infra/README.md`** — new "Local-dev stack" section: service inventory, port table, first-time setup walkthrough, persistence/bootstrap-replay tips. The previous `local/` placeholder line is removed. - **`docs/development.md`** §3 — rewritten to walk through the compose-based setup; cross-links to `infra/README.md` for the full reference. Roadmap entry for "Local infra recipe" removed from §8 (now implemented); "Observability dev-loop" line adjusted to point at the new Jaeger profile. ### Out of scope - **Production parity** — HA Postgres, Redis Sentinel, real OTel backend (Tempo / Loki / etc.) — defer to the on-prem infrastructure ADR (phase 3b). The dev-only nature of this stack is called out explicitly in `infra/README.md`. - **Wiring the BFF** to actually use these endpoints (NestJS config, Prisma datasource URL, OTel SDK init) — that's the **B — Observability foundations** chantier, next up. ## Test plan - [ ] `cd infra/local && cp .env.example .env && docker compose -f dev.compose.yml up -d` → all three core services come up healthy; verify with `docker compose ps`. - [ ] `psql postgres://portal:<pwd>@localhost:5432/portal_dev -c "\dn"` shows the `audit` schema; `\dg` shows the four audit roles. - [ ] `redis-cli -a <pwd> PING` → `PONG`. - [ ] Send a fake OTLP trace via grpcurl → see it printed by `docker compose logs otel-collector`. - [ ] `--profile dbtools up -d` → http://localhost:8081 shows pgweb UI, can navigate to the audit schema. - [ ] `--profile observability up -d` → http://localhost:16686 shows Jaeger UI; collector logs no longer report Jaeger export retries. - [ ] `docker compose down -v` cleanly removes everything; next `up -d` re-runs the bootstrap SQL. --------- Co-authored-by: Julien Gautier <julien.gautier@apf.asso.fr> Reviewed-on: #57 |
||
|
|
efa660abab |
chore(infra): pin act_runner image pull policy (#10)
## Summary `act_runner`'s default `container.force_pull: true` re-issues a `docker pull` at the start of every job, adding 10–30 s of registry round-trip even when every layer is already locally cached. With job images pinned to specific tags (`catthehacker/ubuntu:act-22.04` and `:full-22.04`), the implicit pull is pure overhead and contradicts the deliberate-upgrade policy ADR-0015 spells out for the runner image. - Add `infra/runner-config.yaml` with `container.force_pull: false`. - Mount it read-only into all three runners and point each at it via `CONFIG_FILE=/etc/runner/config.yaml`. - Document the pre-pull procedure and image-upgrade playbook in `infra/README.md` → "Job image pinning and pre-pull". - Fold the pre-pull into the "First-time registration" walkthrough so a fresh setup is correct end-to-end. The trade-off: the runner host must hold the images locally before the runner is asked to use them. Documented. ## Roll-out (manual, on the runner host) ```bash cd infra/ # 1. Pre-pull the job images (one-shot — pays the cold cost once). docker pull catthehacker/ubuntu:act-22.04 docker pull catthehacker/ubuntu:full-22.04 # 2. Recreate the runners so the new mount + env var take effect. docker compose -f ci-runners.compose.yml up -d --force-recreate --------- Co-authored-by: Julien Gautier <julien.gautier@apf.asso.fr> Reviewed-on: #10 |
||
|
|
f2440fbf24 |
fix(ci): disable broken pnpm cache on actions/setup-node (#8)
## Summary `act_runner`'s built-in GitHub-Actions-cache server binds inside the runner container on the compose-defined `apf-portal-act-runners` bridge. Jobs spawned via the mounted Docker socket land on Docker's default `bridge` network and can't reach it. Every job opting into `cache: 'pnpm'` ate ~2 min `ETIMEDOUT` on restore + another ~2 min on save — across the 5 jobs, ~20 min wasted per CI run for zero cache hits. Drop `cache: 'pnpm'` everywhere. `pnpm install --frozen-lockfile` is fast on the warm store inside the job container, so removing the cache layer is a net gain today. The proper fix (cross-container networking / fixed-port cache binding) is documented in `infra/README.md` → "Cache server (deferred)" so it can be picked up as an isolated infra spike later. ## Test plan - [ ] CI run on this PR: every job's `Set up Node.js` step finishes in seconds (no ETIMEDOUT warning). - [ ] `Complete job` step also finishes promptly (no `reserveCache failed` warning). - [ ] Total wall-clock time for the run should drop by ~15-20 min vs. previous runs. --------- Co-authored-by: Julien Gautier <julien.gautier@apf.asso.fr> Reviewed-on: #8 |
||
|
|
644d3603d2 |
chore: add docker compose for self-hosted Gitea act_runners
Set up the infrastructure-as-code recipe to bring up the three
self-hosted Gitea Actions runners required by ADR-0015. The compose
file launches three act_runner instances pinned to 0.2.13, registered
with the project's Gitea organisation, labelled self-hosted + on-prem
to match the runs-on selector in every job under .gitea/workflows/*.
Layout:
- infra/ new top-level folder for IaC
- infra/README.md explains the folder, registration
flow, security implications, future
placeholders (local/, prod/, runbooks/)
- infra/ci-runners.compose.yml three act_runner services, networked
together, persisting credentials to
./data/runner-N
- infra/.env.example GITEA_INSTANCE_URL +
GITEA_RUNNER_REGISTRATION_TOKEN; .env
itself stays git-ignored (root rule)
- infra/data/.gitignore tracks the dir, ignores runtime state
Security posture (documented in infra/README.md): mounting
/var/run/docker.sock gives the runner root-equivalent access to the
host Docker daemon. Mitigations rely on (a) repo-scope of the runner
in Gitea, (b) running the runner host outside the production trust
boundary, (c) no extra host filesystem mounts. Future hardening
(rootless Docker, DinD sidecar) is flagged as deferred.
The compose pins the runner image (0.2.13). Bumps go through a
dedicated chore(deps) PR per the convention; image upgrades roll one
runner at a time so CI is never starved (procedure documented in the
README).
Doc indexing (docs/README.md) deliberately not touched here to avoid
a conflict with the pending docs/architecture-diagrams branch which
also modifies that file. A small follow-up PR will add an index entry
once that branch is merged.
|