dorfteich/docs/architecture/adr/0014-gitea-actions-cicd.md
Claude Fable 5 514cdf5ead
All checks were successful
CD / Build and push images (push) Successful in 3m45s
CI / Lint, typecheck, test (push) Successful in 3m39s
CI / Auth e2e pack (push) Successful in 3m43s
CI / Import/export fidelity gate (push) Successful in 43s
CI / Build container images (push) Has been skipped
CD / Deploy to Test (push) Successful in 9s
CD / Smoke tests against Test (push) Successful in 1m12s
CD / Promote to Int (push) Successful in 10s
Move stages, runner and deploy target to dedicated host ONE
Gitea itself relocated to the dedicated Hetzner server ONE
(one.101010.cloud); this commit moves the rest of the delivery chain
along: cd.yml now deploys to one.101010.cloud (DEPLOY_HOST_KEY secret
rotated to ONE's host key), the act_runner one-dorfteich replaces
vps-dorfteich, and the stage/deployment docs describe the new topology
(Test/Int migrated with volumes; Prod joins on the same host at M8).
The Int promotion gate variable RUN_INT_DEPLOY was removed — the new
host has the capacity, so promote-int deploys again by default.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EwZ4jR4KFAPvpjWevfUGX1
2026-07-11 08:05:36 +02:00

2.9 KiB

ADR 0014: CI/CD with Gitea Actions, staged promotion

  • Status: accepted
  • Date: 2026-07-04

Context

The project is hosted on a self-managed Gitea (gitea.101010.cloud). Environments (kickoff): Dev runs locally on contributors' machines; Test and Int run as separate Compose stacks on the operator's dedicated server ONE (one.101010.cloud, domains test.dorfteich.cloud / int.dorfteich.cloud), which also hosts Gitea itself; Prod (dorfteich.online) goes live on the same host at M8 — the architecture must keep any later move cheap. Contributors include AI coding sessions — gates must be automated and objective wherever possible. (Originally the stages and runner lived on a shared 4-GB VPS, 188.245.116.44; everything moved to ONE on 2026-07-11.)

Decision

  • Gitea Actions is the CI/CD system (GitHub-Actions-compatible syntax); an act_runner runs on ONE (one.101010.cloud) with Docker access.
  • Images are built once per change and promoted, never rebuilt per stage: pushed to the Gitea container registry (gitea.101010.cloud/stwaidele/dorfteich-{web,api,collab}), tagged with the git SHA plus moving tags test, int, and semver tags for releases.
  • Pipeline (details in deployment.md):
    1. PR / push: lint, typecheck, unit tests, build; PRs must be green to merge into main.
    2. Merge to main: build + push images (SHA tag) → deploy to Test automatically → run the Playwright e2e suite against Test.
    3. Promotion to Int: automatic when e2e on Test is green — Int is the stable preview environment (same images, int tag).
    4. Promotion to Prod: manual gate — creating a release tag (vX.Y.Z) triggers the Prod deploy after a required manual approval in the workflow. Database migrations run automatically on container start (ADR 0006); releases with breaking migrations must say so in the release notes.
  • Deploy mechanism: the runner executes docker compose pull && docker compose up -d in the stage's directory (/home/DOCKER/dorfteich-<stage>/) over SSH (deploy key per stage). Moving Prod to a dedicated host later changes only that SSH target.
  • Self-hosters consume the same release images via a published docker-compose.yml pinned to semver tags (update strategy in operations.md).

Consequences

  • One objective quality bar (green e2e on Test) decides Int promotion; the only human gate is the Prod release — matching the risk profile.
  • The registry, runner, and repo live on the same Gitea — no third-party CI dependency.
  • e2e stability becomes load-bearing; flaky tests block the pipeline and must be treated as defects (stated in the contributor conventions).

Alternatives considered

  • GitHub Actions with repo mirror: splits source of truth; rejected.
  • Manual deploys per stage: does not scale to many small stories and invites drift between stages.