Files
ConformalLabpp/doc/architecture/ci-cd.md
Tarik Moussa a2464af8b1 ci: add Codeberg CI (Woodpecker + Forgejo) and document CI/CD topology
Add a lightweight test-fast pipeline for the public Codeberg mirror so it
shows a build status, defined for both CI systems Codeberg offers:
- .woodpecker.yml            (Woodpecker, debian:bookworm)
- .forgejo/workflows/        (Forgejo Actions, node:20-bookworm, runner label docker)

Both run the pure-math suite only (Eigen vendored, GTest via FetchContent;
no CGAL/Boost), using public images and the docker runner label since the
private eulernest ci-cpp image and Pi runner are unreachable from Codeberg.

Docs:
- new doc/architecture/ci-cd.md: two-forge topology, runners, trigger
  keywords, mirror mechanism.
- fix stale "codeberg/main ... no CI" claim in contributing.md and bring
  the CI table up to date.
- link the new doc from the README doc index.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 23:26:46 +02:00

111 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CI / CD
Single source of truth for **how continuous integration is wired** across the
two forges this project lives on. If you add, move or rename a workflow, update
this page.
## TL;DR
| Forge | Remote | Role | CI system | Config | Runner |
|---|---|---|---|---|---|
| **eulernest Gitea** | `origin` | Authoritative gate (full test + quality suite) | Gitea Actions | `.gitea/workflows/` | self-hosted Raspberry Pi (ARM64), label `eulernest` |
| **Codeberg** | `codeberg` | Public mirror + public build badge | Woodpecker **and** Forgejo Actions | `.woodpecker.yml`, `.forgejo/workflows/` | Codeberg shared runners, label `docker` |
The two forges are connected by a one-way mirror: every push to `main` on
eulernest is force-mirrored to Codeberg (see
[Mirror](#mirror-eulernest--codeberg) below). Codeberg never pushes back.
Why two CI systems on Codeberg? They are independent and either may be enabled
per-repo; providing both means the public build status is green regardless of
which one the repo has switched on. They run the **same** `test-fast` build.
---
## eulernest Gitea (`origin`) — the real gate
Self-hosted Gitea with a single self-hosted runner: a Raspberry Pi (ARM64,
34 GB RAM). Because the runner is RAM-constrained, the heavy jobs are
**keyword-gated** (opt-in per commit) rather than run on every push.
All C++ jobs use the private image `git.eulernest.eu/conformallab/ci-cpp:latest`
(built from `.gitea/docker/Dockerfile.ci-cpp` — Ubuntu 22.04 + Node 20 + cmake +
build-essential + libboost-dev + doxygen).
### `.gitea/workflows/cpp-tests.yml`
| Job | Trigger | Memory cap | What it does |
|---|---|---|---|
| `test-fast` | every push to `main` / `claude/**` / `feature/**` / `review/**` + every PR | 800 MB | Pure-math suite (Clausen, ImLi₂, hyper-ideal). Serial build (`-j1`) to avoid OOM. Eigen vendored, GTest via FetchContent. |
| `test-cgal` | commit message contains **`/test-cgal`** | 2000 MB | Full CGAL suite via `LOW_MEMORY_BUILD` (`-O0`, no PCH, unity batch 1, `--no-keep-memory`). Then `check-test-counts.sh` + `try_it.sh` smoke test. |
| `quality-gates` | commit message contains **`/quality-gates`** | 600 MB | License headers, CGAL conventions, codespell, shellcheck, coverage (gate currently in report-only mode, `SKIP_COVERAGE_GATE=1`). |
> One keyword per commit — the Pi cannot sustain multiple Docker containers at
> once (`/ci-all` was removed for this reason). Example:
> `git commit -m "fix: correct angle formula /test-cgal"`.
### Other eulernest workflows
| File | Trigger | Purpose | Blocks merge? |
|---|---|---|---|
| `doc-build.yaml` | push to main branches + manual | Doxygen HTML + warning stats | No (`continue-on-error`) |
| `markdown-links.yml` | push + weekly cron (Mon 05:00 UTC) + manual | Link-rot check across docs | Yes on push |
| `doxygen-pages.yml` | manual only | Publish Doxygen HTML to Codeberg Pages (`tmoussa.codeberg.page/ConformalLabpp/`) | n/a |
| `perf-compile-time.yml` | manual only | Compile-time benchmark | n/a |
| `mirror-to-codeberg.yml` | push to `main` | Mirror all branches to Codeberg (see below) | n/a |
---
## Codeberg (`codeberg`) — public mirror CI
Codeberg's shared runners **cannot** pull the private `ci-cpp` image and are not
the `eulernest` Pi, so the Codeberg configs differ from Gitea in exactly two
ways:
1. **Runner label** `docker` (Codeberg shared runners), not `eulernest`.
2. **Public base image**, with build tools `apt`-installed at run time:
- Woodpecker: `debian:bookworm`
- Forgejo Actions: `node:20-bookworm` (Node is needed by
`actions/checkout@v4`; cmake/g++/make are installed in the first step).
Both run **only** `test-fast` — the pure-math suite. No CGAL/Boost/Wayland, so
they are fast (< 2 min) and headless. Eigen is vendored, GoogleTest is fetched
at configure time (Codeberg runners have network). A failing build or any
failing `ctest` turns the public CI badge red.
| File | CI system | Enable via |
|---|---|---|
| `.woodpecker.yml` | Woodpecker | https://ci.codeberg.org enable repo |
| `.forgejo/workflows/cpp-tests.yml` | Forgejo Actions | repo *Settings → Actions* (shared runner label `docker`) |
> These configs are committed in the repo and reach Codeberg through the mirror
> — they are not maintained separately on Codeberg.
---
## Mirror (eulernest → Codeberg)
`.gitea/workflows/mirror-to-codeberg.yml` runs on every push to `main` and does
a `git push --mirror` from eulernest to
`codeberg.org/TMoussa/ConformalLabpp.git`. It uses two secrets:
- `MIRROR_TOKEN` read access to the eulernest source repo.
- `CODEBERG_TOKEN` push access to the Codeberg mirror.
The mirror is **one-way and authoritative-from-eulernest**: do not commit
directly on Codeberg, it will be overwritten on the next mirror run.
---
## The one rule
> **eulernest is the gate, Codeberg is the shop window.**
> Merge decisions are made on eulernest CI (full suite). Codeberg CI exists so
> the public repo also shows a green/red build status to outside readers.
## See also
- [dependencies.md](dependencies.md) what each build mode requires.
- [project-structure.md](project-structure.md) where the test targets live.
- [../api/tests.md](../api/tests.md) per-suite test counts CI checks against.
- [../contributing.md](../contributing.md) the git workflow that feeds CI.