Single-file bind mounts (./foo.yml:/etc/foo.yml) pin to the host file's
inode at container-create time. The CD pipeline scp's a replacement file
(new inode), so the running container keeps reading the OLD inode —
`docker compose up -d` won't recreate on a content-only change, and
neither restart/SIGHUP/`caddy reload` re-reads the new file. Net effect:
config-only infra PRs deployed "successfully" but never took effect
(confirmed with PR #500's prometheus.yml; the WAL retention work only
applied because #498 also changed docker-compose.yml, forcing a
recreate). Caddyfile changes had the same latent gap.
Switch the four single-file config mounts to DIRECTORY mounts, which
resolve children live so a reload/restart picks up the new file:
- prometheus, loki, promtail: mount ./<svc> dir (loki/promtail
--config.file paths updated to the real filenames).
- caddy: move Caddyfile into caddy/ and mount the dir; ./sites overlays
/etc/caddy/sites (caddy/sites/.gitkeep keeps the mountpoint). Container
path /etc/caddy/Caddyfile is unchanged, so every `caddy reload --config
/etc/caddy/Caddyfile` ref still works. scp source paths in cd-infra and
cd-apps updated to ship the caddy/ dir.
cd-infra now applies config-only changes after `up -d`: SIGHUP prometheus
(zero downtime), restart loki+promtail (no SIGHUP reload), caddy reload
(graceful). Mirrored prometheus/loki mounts in docker-compose.dev.yml.
Validated: docker compose config (both files), caddy validate from the
new path, read-only-parent + sites-overlay mount mechanics, workflow YAML.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The routing probe healthcheck was too strict — BRouter is up but may
not have the segment loaded yet, causing all probes to fail. Use a
simple liveness check (curl exit 0 when server responds on any code)
so --wait unblocks as soon as the server is up. Add an explicit
routing readiness wait step in CI that actually confirms a route can
be computed before running E2E tests.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Percent-encoding the | may confuse older curl; use a literal | inside
single quotes instead. Also bump retries from 12 to 18 (total window
30s start + 180s probing) to cover slow first-run segment downloads.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Without a healthcheck, --wait considers BRouter healthy as soon as the
container starts, before it has loaded segments and opened its port.
The healthcheck probes the routing endpoint directly, matching the old
manual curl loop in CI.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Mounting the full production provisioning dir pulled in the alerting
config which requires Pushover secrets. Mount only the two subdirs
that make sense locally.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Extend docker-compose.dev.yml with optional monitoring profile
(Prometheus, Grafana, Loki) via --profile monitoring
- Align dev PostgreSQL with production: pg_stat_statements + init scripts
- Add scripts/seed.ts with idempotent Berlin test data (user, route, activity)
- Add pnpm db:seed and pnpm dev:reset scripts
- Simplify CI e2e job: replace manual docker run + BRouter setup with
docker compose up --wait; add db:seed step
- Improve scripts/dev.sh: Docker check, --wait health checks, --monitoring
flag, seed step
- Add scripts/reset-dev.sh to wipe and restart the local stack
- Add .env.development.example with documented local defaults
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>