a8e808e71c
Initial commit. Establishes the .planning/ tree mirroring processor's shape (ROADMAP.md as nav hub + per-phase folders with READMEs and granular task files). Six phases: 1. Slice 1 schema + deploy pipeline — what Rally Albania 2026 needs. Org catalog (orgs, users, vehicles, devices) + event participation (events, classes, entries, entry_crew, entry_devices). db-init/ for the positions hypertable + faulty column. snapshot/apply tooling. Gitea CI dry-run. Dogfood seed of Rally Albania 2026. Nine task files with full Goal / Deliverables / Specification / Acceptance criteria / Risks / Done sections. 2. Course definition — stages, segments, geofences, waypoints, SLZs. PostGIS extension introduced here. 3. Timing & penalty tables — co-developed with processor Phase 2. entry_segment_starts, entry_crossings, entry_penalties, stage_results, penalty_formulas. 4. Permissions & policies — Directus 11 dynamic-filter Policies per logical role. Deployment-time work, deferred to keep early phases focused on the data model. 5. Custom extensions — TypeScript hooks/endpoints implementing the cross-plane workflows the schema implies (faulty-flag → Redis stream emit, stage-open materializer, etc.). 6. Future / optional — retroactivity preview UI, command-routing Flows, audit trails, federation rule import. Not committed. Non-negotiable design rules captured in ROADMAP.md: schema authority in Directus + snapshot-as-code + db-init for non-Directus DDL + sequential idempotent migrations + entrypoint apply order + no application logic in Flows + permissions deferred to Phase 4. Architectural anchors point at the wiki at ../docs/wiki/ — the schema draft, the Rally Albania 2025 source page, plus the existing processor/postgres-timescaledb/live-channel pages. Each task file calls out the wiki refs an implementing agent should read first. README.md mirrors the processor service README structure: quick start, local Docker test, prod/stage deployment notes, env vars, CI behavior.
130 lines
6.3 KiB
Markdown
130 lines
6.3 KiB
Markdown
# Task 1.8 — Gitea CI dry-run workflow
|
|
|
|
**Phase:** 1 — Slice 1 schema + deploy pipeline
|
|
**Status:** ⬜ Not started
|
|
**Depends on:** 1.7
|
|
**Wiki refs:** `docs/wiki/entities/directus.md` (Schema management section)
|
|
|
|
## Goal
|
|
|
|
Build a Gitea Actions workflow that on push to `main` (when relevant paths change): builds the image, spins up a throwaway Postgres + TimescaleDB in CI, runs the entrypoint flow as a **dry-run** to catch snapshot/migration breakage, and only publishes the image to the registry if the dry-run succeeds. Mirrors the `processor` and `tcp-ingestion` workflow shape.
|
|
|
|
## Deliverables
|
|
|
|
- `.gitea/workflows/build.yml`:
|
|
```yaml
|
|
name: Build directus image
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
paths:
|
|
- 'snapshots/**'
|
|
- 'db-init/**'
|
|
- 'extensions/**'
|
|
- 'scripts/**'
|
|
- 'entrypoint.sh'
|
|
- 'Dockerfile'
|
|
- '.gitea/workflows/build.yml'
|
|
workflow_dispatch:
|
|
|
|
jobs:
|
|
build-and-publish:
|
|
runs-on: ubuntu-22.04
|
|
services:
|
|
postgres:
|
|
image: timescale/timescaledb-ha:pg16-latest
|
|
env:
|
|
POSTGRES_USER: directus
|
|
POSTGRES_PASSWORD: directus
|
|
POSTGRES_DB: directus
|
|
ports: ['5432:5432']
|
|
options: >-
|
|
--health-cmd "pg_isready -U directus"
|
|
--health-interval 5s
|
|
--health-timeout 5s
|
|
--health-retries 10
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Build image
|
|
run: docker build -t trm-directus:ci .
|
|
|
|
- name: Dry-run boot against throwaway Postgres
|
|
env:
|
|
DB_HOST: postgres
|
|
DB_PORT: 5432
|
|
DB_USER: directus
|
|
DB_PASSWORD: directus
|
|
DB_DATABASE: directus
|
|
KEY: ci-key-not-secret
|
|
SECRET: ci-secret-not-secret
|
|
ADMIN_EMAIL: ci@example.com
|
|
ADMIN_PASSWORD: ci-password-not-secret
|
|
PUBLIC_URL: http://localhost:8055
|
|
run: |
|
|
docker run --rm \
|
|
-e DB_CLIENT=pg \
|
|
-e DB_HOST=$DB_HOST -e DB_PORT=$DB_PORT \
|
|
-e DB_USER=$DB_USER -e DB_PASSWORD=$DB_PASSWORD -e DB_DATABASE=$DB_DATABASE \
|
|
-e KEY=$KEY -e SECRET=$SECRET \
|
|
-e ADMIN_EMAIL=$ADMIN_EMAIL -e ADMIN_PASSWORD=$ADMIN_PASSWORD \
|
|
-e PUBLIC_URL=$PUBLIC_URL \
|
|
--network host \
|
|
--entrypoint bash \
|
|
trm-directus:ci \
|
|
-c '/directus/scripts/apply-db-init.sh && /directus/scripts/schema-apply.sh && echo "dry-run ok"'
|
|
|
|
- name: Login to Gitea registry
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: git.dev.microservices.al
|
|
username: ${{ secrets.REGISTRY_USERNAME }}
|
|
password: ${{ secrets.REGISTRY_PASSWORD }}
|
|
|
|
- name: Tag and push
|
|
run: |
|
|
docker tag trm-directus:ci git.dev.microservices.al/trm/directus:main
|
|
docker tag trm-directus:ci git.dev.microservices.al/trm/directus:${{ github.sha }}
|
|
docker push git.dev.microservices.al/trm/directus:main
|
|
docker push git.dev.microservices.al/trm/directus:${{ github.sha }}
|
|
|
|
- name: Trigger Portainer redeploy (optional)
|
|
if: secrets.PORTAINER_WEBHOOK_URL != ''
|
|
run: curl -X POST "${{ secrets.PORTAINER_WEBHOOK_URL }}"
|
|
```
|
|
|
|
## Specification
|
|
|
|
- **Dry-run runs the entrypoint scripts only**, not `directus start`. Starting the server and waiting for it to serve is slow and unnecessary — the goal is to catch DDL / snapshot apply errors. Override the `ENTRYPOINT` and run the two scripts directly.
|
|
- **Service container is the throwaway Postgres.** `services:` block in Gitea Actions (compatible syntax with GitHub Actions). Use the pinned TimescaleDB image; mismatch with prod hides bugs.
|
|
- **Path filter on `on.push.paths`** keeps CI quiet for unrelated repo changes (docs-only commits, etc.). Mirrors the processor workflow.
|
|
- **Two image tags published:** `:main` (always points at latest main) and `:<sha>` (specific commit, immutable). The deploy stack can pin to either.
|
|
- **Portainer webhook is optional** (gated by secret presence). If unset, no auto-deploy.
|
|
- **No integration tests in CI for Phase 1.** The dry-run boot *is* the integration test — it proves the snapshot+db-init combination works against a fresh Postgres. Phase 5+ adds extension-specific tests as those land.
|
|
- **Required Gitea secrets:**
|
|
- `REGISTRY_USERNAME`, `REGISTRY_PASSWORD` — for the image push.
|
|
- `PORTAINER_WEBHOOK_URL` — optional, for auto-deploy.
|
|
|
|
## Acceptance criteria
|
|
|
|
- [ ] Workflow file is committed at `.gitea/workflows/build.yml`.
|
|
- [ ] First push to `main` after this lands triggers the workflow.
|
|
- [ ] Workflow steps in order: checkout → build → dry-run boot → registry login → tag/push → optional Portainer ping.
|
|
- [ ] Dry-run step exits 0 with logs showing "db-init complete" and "schema apply: no changes" (after the snapshot has been applied once, subsequent runs against fresh Postgres still apply from scratch — verify the apply step works in both cases).
|
|
- [ ] Intentionally break the snapshot (manually edit `snapshots/schema.yaml` to a malformed YAML) → workflow fails at the dry-run step → image is NOT pushed.
|
|
- [ ] Intentionally break a migration (introduce SQL syntax error in `db-init/`) → workflow fails at the dry-run step → image is NOT pushed.
|
|
- [ ] Push a docs-only change → workflow does NOT trigger.
|
|
- [ ] Image pushed to registry under `git.dev.microservices.al/trm/directus:main` and `:<sha>`.
|
|
- [ ] Portainer webhook fires if configured.
|
|
|
|
## Risks / open questions
|
|
|
|
- **Gitea Actions `services:` syntax compatibility.** Gitea's runner is mostly GitHub-Actions-compatible but has historically had quirks with the `services:` block (especially around image pulls from private registries). If the throwaway Postgres can't be brought up via `services:`, fall back to a `docker run` step that backgrounds the container and a wait-loop on `pg_isready`. Document the chosen approach.
|
|
- **Network access between job container and service container.** `--network host` is the simplest solution if Gitea's runner allows it. If not, use the Docker network created by the runner and reference the service by name (`postgres:5432`).
|
|
|
|
## Done
|
|
|
|
(Fill in commit SHA + one-line note when this lands.)
|