Files
ConformalLabpp/.gitea/workflows/cpp-tests.yml
Tarik Moussa 2b456abc78 ci(test-cgal): switch to manual comment trigger (/test-cgal on PR)
Instead of triggering on every pull_request push, test-cgal now fires
only when a PR comment contains "/test-cgal".  This prevents the Pi
runner (3-4 GB RAM, swap constantly loaded) from queuing CGAL builds
faster than it can drain them on every WIP commit.

Workflow changes:
- Add `issue_comment: types: [created]` to the top-level `on:` block
- test-cgal `if:` condition:
    event is issue_comment
    AND comment is on a PR (issue.pull_request != null)
    AND comment body contains "/test-cgal"
- Checkout uses `refs/pull/N/head` so the PR branch is checked out
  correctly (issue_comment sets GITHUB_REF to the default branch, not
  the PR branch)

Usage: write "/test-cgal" as a PR comment to trigger the 277-test
CGAL suite.  The build uses CONFORMALLAB_LOW_MEMORY_BUILD=ON (-O0,
no PCH, unity batch 1) and runs in a 2000 MB container.

CLAUDE.md: CI table + status paragraph updated accordingly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 01:17:27 +02:00

199 lines
9.0 KiB
YAML
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.

name: C++ Tests
on:
push:
branches:
- main
- dev
- "claude/**"
- "feature/**"
pull_request:
# /test-cgal comment on any PR triggers the CGAL test suite manually.
issue_comment:
types: [created]
# ─────────────────────────────────────────────────────────────────────────────
# Job 1 — test-fast
# Pure-math tests (Clausen, ImLi₂, Hyper-ideal geometry).
# No CGAL, no Boost. Eigen + GTest only. Runs on ALL branches.
# ─────────────────────────────────────────────────────────────────────────────
jobs:
test-fast:
runs-on: eulernest
container:
image: git.eulernest.eu/conformallab/ci-cpp:latest
steps:
- uses: actions/checkout@v4
- name: Configure (tests-only)
run: cmake -S code -B build -DCMAKE_BUILD_TYPE=Release
- name: Build
run: nice -n 19 cmake --build build --target conformallab_tests -j$(nproc)
- name: Run tests
run: >
ctest --test-dir build
--output-on-failure
--output-junit test-results.xml
- name: Summary
if: always()
run: |
if [ -f test-results.xml ]; then
total=$(grep -o 'tests="[0-9]*"' test-results.xml | grep -o '[0-9]*' | head -1)
failed=$(grep -o 'failures="[0-9]*"' test-results.xml | grep -o '[0-9]*' | head -1)
skipped=$(grep -o 'skipped="[0-9]*"' test-results.xml | grep -o '[0-9]*' | head -1)
passed=$(( ${total:-0} - ${failed:-0} - ${skipped:-0} ))
echo "FAST ▸ TOTAL ${total:-0} | PASSED $passed | FAILED ${failed:-0} | SKIPPED ${skipped:-0}"
fi
# ─────────────────────────────────────────────────────────────────────────────
# Job 2 — test-cgal
# Full CGAL test suite (Phase 37, 158 tests).
# Runs ONLY on pull requests (not on direct pushes to dev/main).
# Starts only after test-fast succeeds.
#
# Uses -DWITH_CGAL_TESTS=ON (not -DWITH_CGAL=ON) to avoid building
# Viewer/GLFW — the CI container has no wayland-scanner.
#
# Boost (libboost-dev) is already present in the container since the image rebuild.
# ─────────────────────────────────────────────────────────────────────────────
# ─── CGAL tests: manual trigger via PR comment ───────────────────────────
#
# Trigger: write "/test-cgal" as a comment on any pull request.
#
# Why comment-triggered (not automatic on every PR push):
# The Pi runner has 3-4 GB RAM total with swap constantly loaded.
# Even with LOW_MEMORY_BUILD the CGAL build takes ~5 min and stresses
# the runner. Triggering on every push would queue builds faster than
# the Pi can drain them. A manual trigger gives full control: run the
# 277-test suite when a PR is ready for review, not on every WIP commit.
#
# How it works:
# - `issue_comment` fires on all PR + issue comments.
# - The `if:` condition checks:
# 1. Event is a comment (not a push or PR sync)
# 2. The comment is on a PR (issue.pull_request != null)
# 3. The comment body contains "/test-cgal"
# - The checkout uses refs/pull/N/head to get the PR branch, because
# `issue_comment` does not set GITHUB_REF to the PR branch by default.
#
# LOW_MEMORY_BUILD applies four RAM-saving measures so the build fits in
# 2000 MB: -O0, PCH off, unity batch 1, --no-keep-memory linker.
# See code/tests/cgal/CMakeLists.txt for the full explanation.
test-cgal:
needs: test-fast
if: |
github.event_name == 'issue_comment' &&
github.event.issue.pull_request != null &&
contains(github.event.comment.body, '/test-cgal')
runs-on: eulernest
container:
image: git.eulernest.eu/conformallab/ci-cpp:latest
# 2000 MB hard limit; 1000 MB swap headroom (memory-swap = RAM + swap).
# Uses ~half of the Pi's 3-4 GB, leaving margin for OS + runner daemon.
# With LOW_MEMORY_BUILD peak per TU is ~150-200 MB → well within limit.
options: "--memory=2000m --memory-swap=3000m"
steps:
# Check out the PR branch, not the default branch.
# issue_comment events set GITHUB_REF to the default branch; we need
# refs/pull/N/head to get the actual PR code.
- uses: actions/checkout@v4
with:
ref: refs/pull/${{ github.event.issue.number }}/head
- name: Configure (LOW_MEMORY_BUILD — -O0, no PCH, unity batch 1)
run: |
cmake -S code -B build \
-DWITH_CGAL_TESTS=ON \
-DCMAKE_BUILD_TYPE=Release \
-DCONFORMALLAB_LOW_MEMORY_BUILD=ON
- name: Build CGAL-Tests
run: nice -n 19 cmake --build build --target conformallab_cgal_tests -j1
- name: Run CGAL-Tests
run: >
ctest --test-dir build
-R "^cgal\."
--output-on-failure
--output-junit cgal-results.xml
- name: Summary
if: always()
run: |
if [ -f cgal-results.xml ]; then
total=$(grep -o 'tests="[0-9]*"' cgal-results.xml | grep -o '[0-9]*' | head -1)
failed=$(grep -o 'failures="[0-9]*"' cgal-results.xml | grep -o '[0-9]*' | head -1)
skipped=$(grep -o 'skipped="[0-9]*"' cgal-results.xml | grep -o '[0-9]*' | head -1)
passed=$(( ${total:-0} - ${failed:-0} - ${skipped:-0} ))
echo "CGAL ▸ TOTAL ${total:-0} | PASSED $passed | FAILED ${failed:-0} | SKIPPED ${skipped:-0}"
fi
# ── Structural gate: doc/api/tests.md totals match ctest reality ───
# Single source of truth for test counts (see doc/release-policy.md).
# Reuses the already-built ./build dir via BUILD_DIR env var, so this
# adds ~5 s on top of the existing CGAL job.
- name: Verify test-count consistency (doc/api/tests.md)
run: BUILD_DIR=build bash scripts/check-test-counts.sh
# ── Structural gate: end-to-end smoke (try_it.sh) ──────────────────
# The user-facing quick-start script: configure + build + run the
# full ctest + run the Euclidean example on a bundled mesh. If
# this regresses, README quick-start instructions are broken.
# try_it.sh creates its own build-try/ — accept the ~3 min cost as
# the price of guaranteeing the documented workflow stays working.
- name: End-to-end smoke test (scripts/try_it.sh)
run: bash scripts/try_it.sh
# ─────────────────────────────────────────────────────────────────────────────
# Job 3 — quality-gates (style + convention block)
#
# Cheap, deterministic checks that should never break unless a contributor
# introduces a regression. Each gate is a script under scripts/quality/
# and exits 0 only when its tree is clean. These ran for weeks locally
# at zero findings before being promoted here.
#
# Tools installed at job-start (the ci-cpp image already has python3 +
# bash; we add codespell + shellcheck on top). Total wall-time: ~30 s
# on the eulernest runner.
#
# Strictly required for merges into main/dev — a regression fails the PR.
# ─────────────────────────────────────────────────────────────────────────────
quality-gates:
needs: test-fast
runs-on: eulernest
container:
image: git.eulernest.eu/conformallab/ci-cpp:latest
steps:
- uses: actions/checkout@v4
- name: Install codespell + shellcheck (job-local)
run: |
apt-get update -qq
apt-get install -y --no-install-recommends \
codespell shellcheck
- name: License headers (every C++ source carries MIT SPDX)
run: bash scripts/quality/license-headers.sh
- name: CGAL conventions (6 rules over CGAL public headers)
run: python3 scripts/quality/cgal-conventions.py
- name: codespell (docs + source comments + script messages)
run: bash scripts/quality/codespell.sh
- name: shellcheck (scripts/**/*.sh, severity=warning, strict)
run: bash scripts/quality/shellcheck.sh --strict
- name: Summary
if: always()
run: |
echo "QUALITY ▸ all four gates passed."
echo " see scripts/quality/README.md for the full catalogue"
echo " (sanitizers, clang-tidy, coverage, etc. are local-only)"