Some checks failed
CD / Build and push images (push) Successful in 1m9s
CI / Lint, typecheck, test (push) Failing after 1m11s
CI / Auth e2e pack (push) Has been skipped
CI / Import/export fidelity gate (push) Has been skipped
CI / Build container images (push) Has been skipped
CD / Deploy to Test (push) Successful in 9s
CD / Smoke tests against Test (push) Successful in 1m13s
CD / Promote to Int (push) Successful in 11s
ONE consolidated every Docker stack under /srv/DOCKER (BASEL convention, tracked in stwaidele/infrastructure-one); the three Dorfteich stages follow. Deploy targets in cd.yml (test/int) and prod-deploy.yml plus the docs now point at /srv/DOCKER/dorfteich-<stage>. Data lives in named volumes keyed by the unchanged compose project name, so the directory move carries no data migration. The go-live checklist's uptime-kuma path already lives under /srv/DOCKER — the doc just catches up. Deliberately committed together with the host-side move: this commit must not deploy before the directories exist at the new path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
61 lines
2.9 KiB
Markdown
61 lines
2.9 KiB
Markdown
# 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 (`/srv/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.
|