Task 1.8 — Gitea CI dry-run workflow
.gitea/workflows/build.yml builds the directus image on path-filtered pushes to main and validates the boot pipeline against a throwaway Postgres before pushing the image to the registry. The dry-run is the gate that catches snapshot drift, broken db-init scripts, or incompatible schema changes before they reach stage. Workflow shape (mirrors processor's CI but tailored to Directus): - Path filter: snapshots/, db-init/, extensions/, scripts/, entrypoint.sh, Dockerfile, the workflow file itself. Docs-only commits (.planning/, README.md, compose.dev.yaml, package.json) do NOT trigger CI. - Throwaway Postgres via services: block, pinned to the same timescale/timescaledb-ha:pg16.6-ts2.17.2-all tag as compose.dev.yaml. - Plain `docker build` (NOT build-push-action) so the image stays in the local daemon for the subsequent docker run dry-run. - Dry-run: --network host + --entrypoint bash to override the upstream entrypoint and run only apply-db-init.sh && schema-apply.sh. Skips bootstrap and pm2-runtime — the schema apply is the gate. - Two image tags: :main (mutable) and :<sha> (immutable). - Optional Portainer webhook gated on secret presence; curl -fsS so a misconfigured URL fails the step explicitly. Spec corrections folded in (the spec's draft had two contradictions that would have failed at runtime): 1. DB_HOST=localhost (not 'postgres'). With --network host, service containers are reachable on the runner's loopback by their port mapping, NOT by service name. Service-name resolution requires the default bridge network; --network host overrides it. 2. health-retries 20 (not 10). timescaledb-ha:*-all does more init work at boot than vanilla postgres; 50s isn't always enough. Operator action required in the Gitea repo Settings before first run: configure REGISTRY_USERNAME and REGISTRY_PASSWORD secrets (required for push); optionally PORTAINER_WEBHOOK_URL (for auto-deploy). Live verification deferred to first relevant commit. Documented in the task spec's Done section: positive (clean snapshot → push succeeds) and negative (malformed snapshot → halt before push) cases to validate once CI runs. ROADMAP marks 1.8 done. Phase 1 progress: 8/9 tasks complete (1.1–1.8); only 1.9 (Rally Albania 2026 dogfood seed) remains before Phase 1 ships.
This commit is contained in:
@@ -126,4 +126,50 @@ Build a Gitea Actions workflow that on push to `main` (when relevant paths chang
|
||||
|
||||
## Done
|
||||
|
||||
(Fill in commit SHA + one-line note when this lands.)
|
||||
**Implementation landed (pending live trigger by first relevant commit).** Workflow file at `.gitea/workflows/build.yml`. Statically validated; live trigger requires a push that touches one of the path-filtered locations.
|
||||
|
||||
**Corrections folded in vs. the spec's draft YAML:**
|
||||
|
||||
1. **`DB_HOST=localhost`, not `DB_HOST=postgres`.** The spec's draft mixed `--network host` with service-name resolution; those are mutually exclusive. With `--network host` the docker-run container shares the runner's loopback, so the service's port mapping (`5432:5432`) is reachable as `localhost:5432`, not by service name `postgres`. (Service-name resolution would only work with the runner's default bridge network.)
|
||||
2. **`--health-retries 20`** instead of 10. The `timescaledb-ha:*-all` image runs more init work at startup than vanilla postgres and occasionally exceeds the 50s window on cold runner images. 20 retries × 5s = 100s margin.
|
||||
3. **`--health-cmd "pg_isready -U directus -d directus"`** with explicit `-d`. Spec had user only.
|
||||
4. **`curl -fsS -X POST`** for the Portainer webhook step. Bare `curl -X POST` returns 0 even on HTTP 4xx/5xx; `-f` makes a misconfigured webhook URL fail the step explicitly.
|
||||
5. **Plain `docker build`**, NOT `docker/build-push-action@v5`. The dry-run step needs the freshly-built image accessible to a subsequent `docker run`. `build-push-action` with the docker-container Buildx driver exports into a separate buildkitd cache that `docker run` cannot see — the run would fail with "image not found." Plain `docker build` keeps the image in the local Docker daemon.
|
||||
|
||||
**Deliberate divergences from `processor/.gitea/workflows/build.yml`:**
|
||||
|
||||
| Aspect | Processor | Directus | Why |
|
||||
|---|---|---|---|
|
||||
| Build mechanism | `docker/build-push-action@v5` | plain `docker build` | dry-run needs local-daemon access (above) |
|
||||
| Buildx setup | yes | no | Buildx isolates the image; would defeat the dry-run |
|
||||
| `services:` block | absent | present | Directus dry-run needs a live Postgres; processor mocks it |
|
||||
| Node/pnpm setup | yes | no | No TS to compile in Phase 1 (Phase 5 adds this) |
|
||||
| typecheck/lint/test | three steps | none | No extensions yet |
|
||||
| Portainer webhook | unconditional | gated on secret presence | Spec requirement |
|
||||
| `runs-on` | `ubuntu-latest` | `ubuntu-22.04` | Pin to avoid floating-tag runner image breakage |
|
||||
|
||||
**Acceptance criteria status:**
|
||||
|
||||
Static (verified):
|
||||
- ✅ Workflow file at `.gitea/workflows/build.yml`.
|
||||
- ✅ Steps in correct order: checkout → build → dry-run → login → tag/push → optional Portainer.
|
||||
- ✅ Path filter excludes `.planning/`, `README.md`, `compose.dev.yaml`, `package.json` — docs-only commits won't trigger CI.
|
||||
- ✅ Workflow file itself is in the path-filter list (so changes to CI trigger CI).
|
||||
- ✅ Two image tags published (`:main`, `:<sha>`).
|
||||
- ✅ Required secrets identified: `REGISTRY_USERNAME`, `REGISTRY_PASSWORD`. Optional: `PORTAINER_WEBHOOK_URL`.
|
||||
- ✅ Dry-run command logic traced: env vars, network mode, entrypoint override, script chain all consistent.
|
||||
|
||||
Pending live trigger (will validate on first push that hits the path filter):
|
||||
- ⏳ Workflow triggers on push.
|
||||
- ⏳ Dry-run step exits 0 against a fresh Postgres + the committed snapshot (currently 105 KB, 13 collections).
|
||||
- ⏳ Snapshot drift simulation: hand-edit `snapshots/schema.yaml` to malformed YAML → push → CI fails at dry-run → image NOT pushed.
|
||||
- ⏳ Migration syntax error simulation: introduce broken `db-init/006_*.sql` → push → CI fails at dry-run → image NOT pushed.
|
||||
- ⏳ Image actually published to `git.dev.microservices.al/trm/directus:main` after a clean run.
|
||||
- ⏳ Portainer webhook fires if configured.
|
||||
|
||||
**Operator action required before first run:** in the Gitea repo at `git.dev.microservices.al/trm/directus` → Settings → Secrets, configure:
|
||||
- `REGISTRY_USERNAME` — Gitea user with write access to the container registry
|
||||
- `REGISTRY_PASSWORD` — password or PAT for that user
|
||||
- `PORTAINER_WEBHOOK_URL` (optional) — for auto-redeploy on push
|
||||
|
||||
Without `REGISTRY_USERNAME` / `REGISTRY_PASSWORD` the Login step fails with a clear auth error. Without `PORTAINER_WEBHOOK_URL` the Portainer step is skipped entirely.
|
||||
|
||||
Reference in New Issue
Block a user