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>
5.2 KiB
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 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, 3–4 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-allwas 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:
- Runner label
docker(Codeberg shared runners), noteulernest. - Public base image, with build tools
apt-installed at run time:- Woodpecker:
debian:bookworm - Forgejo Actions:
node:20-bookworm(Node is needed byactions/checkout@v4; cmake/g++/make are installed in the first step).
- Woodpecker:
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 — what each build mode requires.
- project-structure.md — where the test targets live.
- ../api/tests.md — per-suite test counts CI checks against.
- ../contributing.md — the git workflow that feeds CI.