It was reporting and shrugging. A definite leak, a read past the end of an allocation or a branch on uninitialised memory now fails the build on the push that introduces it, which is the only point at which it is cheap to fix. The six findings the job had on its first run were fixed rather than excused, so the gate closes on a clean tree instead of on a backlog. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
211 lines
8.4 KiB
YAML
211 lines
8.4 KiB
YAML
name: libakgl CI Build
|
|
run-name: ${{ gitea.actor }} libakgl test
|
|
on: [push]
|
|
|
|
jobs:
|
|
cmake_build:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Check out repository code
|
|
uses: actions/checkout@v4
|
|
with:
|
|
submodules: recursive
|
|
- name: Install build dependencies
|
|
run: |
|
|
sudo apt-get update -y
|
|
sudo apt-get install -y \
|
|
cmake doxygen gcc gcovr pkg-config \
|
|
libasound2-dev libfreetype-dev libharfbuzz-dev \
|
|
libpng-dev libtiff-dev libwebp-dev \
|
|
libudev-dev libx11-dev libxcursor-dev libxext-dev \
|
|
libxfixes-dev libxi-dev libxrandr-dev libxrender-dev \
|
|
libxss-dev libxtst-dev
|
|
- name: Configure and build
|
|
run: |
|
|
cmake -S . -B build \
|
|
-DCMAKE_BUILD_TYPE=Debug \
|
|
-DAKGL_COVERAGE=ON
|
|
cmake --build build --parallel
|
|
- name: Build API documentation
|
|
run: doxygen Doxyfile
|
|
# The perf suites run here too -- they are ordinary CTest tests -- but this
|
|
# is a Debug build with coverage instrumentation, where a timing is a
|
|
# measurement of gcov. AKGL_BENCH_SCALE cuts their iteration counts so
|
|
# they contribute path coverage without spending ten minutes proving
|
|
# nothing; benchutil.h already refuses to enforce budgets in an
|
|
# unoptimized build. The performance job below is where the timings are
|
|
# taken and the budgets are checked.
|
|
- name: Test (JUnit)
|
|
env:
|
|
AKGL_BENCH_SCALE: '0.02'
|
|
run: |
|
|
export LD_LIBRARY_PATH="$PWD/build:$PWD/build/deps/SDL:$PWD/build/deps/SDL_image:$PWD/build/deps/SDL_mixer:$PWD/build/deps/SDL_ttf"
|
|
ctest \
|
|
--test-dir build \
|
|
-E '^character$' \
|
|
--output-on-failure \
|
|
--output-junit "$(pwd)/ctest-junit.xml"
|
|
- name: Publish test results
|
|
if: always()
|
|
uses: mikepenz/action-junit-report@v4
|
|
with:
|
|
report_paths: 'ctest-junit.xml'
|
|
annotate_only: true
|
|
detailed_summary: true
|
|
include_passed: true
|
|
fail_on_failure: 'true'
|
|
- name: Upload coverage reports
|
|
if: always()
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: code-coverage
|
|
path: build/coverage/
|
|
if-no-files-found: warn
|
|
|
|
# The benchmarks, in the only build where their numbers mean anything.
|
|
# tests/benchutil.h enforces a budget per measurement only when it is compiled
|
|
# optimized and running at full scale, which is exactly this job and no other:
|
|
# the coverage job above is Debug, and the memory job below is under valgrind.
|
|
# A budget is roughly ten times the baseline recorded in PERFORMANCE.md, which
|
|
# is what makes a shared, slower runner viable -- it catches an algorithmic
|
|
# regression and ignores a busy machine. If a budget still proves flaky here,
|
|
# raise that one budget with a measurement behind it and re-record the
|
|
# baseline; do not drop the gate.
|
|
performance:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Check out repository code
|
|
uses: actions/checkout@v4
|
|
with:
|
|
submodules: recursive
|
|
- name: Install build dependencies
|
|
run: |
|
|
sudo apt-get update -y
|
|
sudo apt-get install -y \
|
|
cmake gcc pkg-config \
|
|
libasound2-dev libfreetype-dev libharfbuzz-dev \
|
|
libpng-dev libtiff-dev libwebp-dev \
|
|
libudev-dev libx11-dev libxcursor-dev libxext-dev \
|
|
libxfixes-dev libxi-dev libxrandr-dev libxrender-dev \
|
|
libxss-dev libxtst-dev
|
|
- name: Configure and build
|
|
run: |
|
|
cmake -S . -B build \
|
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
|
cmake --build build --parallel
|
|
# --verbose rather than --output-on-failure: a passing benchmark's output
|
|
# is the entire point of running it, and --output-on-failure prints
|
|
# nothing at all for a green run. pipefail because the step ends in a
|
|
# pipe, whose status would otherwise be tee's -- always 0 -- and a blown
|
|
# budget would be reported as a passing step.
|
|
- name: Benchmarks (JUnit)
|
|
run: |
|
|
set -o pipefail
|
|
export LD_LIBRARY_PATH="$PWD/build:$PWD/build/deps/SDL:$PWD/build/deps/SDL_image:$PWD/build/deps/SDL_mixer:$PWD/build/deps/SDL_ttf"
|
|
ctest \
|
|
--test-dir build \
|
|
-L perf \
|
|
--verbose \
|
|
--output-junit "$(pwd)/perf-junit.xml" \
|
|
2>&1 | tee "$(pwd)/perf-baseline.txt"
|
|
- name: Publish benchmark results
|
|
if: always()
|
|
uses: mikepenz/action-junit-report@v4
|
|
with:
|
|
report_paths: 'perf-junit.xml'
|
|
annotate_only: true
|
|
detailed_summary: true
|
|
include_passed: true
|
|
fail_on_failure: 'true'
|
|
# Kept whether the job passed or failed: the tables are the point. A run
|
|
# that went red says which measurement moved, and a run that went green is
|
|
# the next baseline if somebody re-records PERFORMANCE.md.
|
|
- name: Upload benchmark tables
|
|
if: always()
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: performance-baseline
|
|
path: perf-baseline.txt
|
|
if-no-files-found: warn
|
|
|
|
# Every suite under valgrind. No memory-check programs of their own: the perf
|
|
# suites scale themselves down when they detect valgrind, which turns them
|
|
# into the broadest path coverage in the tree at a cost this job can afford.
|
|
#
|
|
# This job gates. A definite leak, a read past the end of an allocation, or a
|
|
# branch on uninitialised memory fails the build on the push that introduced
|
|
# it -- not on the day somebody gets around to caring. The six findings this
|
|
# job had on its first run were fixed to make that possible rather than
|
|
# excused into a warning.
|
|
memory_check:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Check out repository code
|
|
uses: actions/checkout@v4
|
|
with:
|
|
submodules: recursive
|
|
- name: Install memory-check dependencies
|
|
run: |
|
|
sudo apt-get update -y
|
|
sudo apt-get install -y \
|
|
cmake gcc pkg-config valgrind \
|
|
libasound2-dev libfreetype-dev libharfbuzz-dev \
|
|
libpng-dev libtiff-dev libwebp-dev \
|
|
libudev-dev libx11-dev libxcursor-dev libxext-dev \
|
|
libxfixes-dev libxi-dev libxrandr-dev libxrender-dev \
|
|
libxss-dev libxtst-dev
|
|
# RelWithDebInfo rather than Debug: valgrind needs the symbols, and -O0
|
|
# would leave every inlined frame in the stacks it prints.
|
|
- name: Configure and build
|
|
run: |
|
|
cmake -S . -B build \
|
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
|
cmake --build build --parallel
|
|
# The character suite is excluded here for the same reason as in the
|
|
# coverage job: it fails deliberately, and a failing suite would be
|
|
# reported as "valgrind found nothing but ctest exited non-zero".
|
|
- name: Memory check
|
|
run: scripts/memcheck.sh -E '^character$'
|
|
- name: Upload valgrind logs
|
|
if: always()
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: valgrind-logs
|
|
path: build/Testing/Temporary/MemoryChecker.*.log
|
|
if-no-files-found: warn
|
|
|
|
mutation_test:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Check out repository code
|
|
uses: actions/checkout@v4
|
|
with:
|
|
submodules: recursive
|
|
- name: Install mutation-test dependencies
|
|
run: |
|
|
sudo apt-get update -y
|
|
sudo apt-get install -y \
|
|
cmake gcc pkg-config python3 \
|
|
libasound2-dev libfreetype-dev libharfbuzz-dev \
|
|
libpng-dev libtiff-dev libwebp-dev \
|
|
libudev-dev libx11-dev libxcursor-dev libxext-dev \
|
|
libxfixes-dev libxi-dev libxrandr-dev libxrender-dev \
|
|
libxss-dev libxtst-dev
|
|
# Keep CI bounded to a focused source file. Run the default target locally
|
|
# for the complete libakgl-owned src/ tree.
|
|
- name: Mutation testing
|
|
run: |
|
|
python3 scripts/mutation_test.py \
|
|
--target src/staticstring.c \
|
|
--junit mutation-junit.xml \
|
|
--threshold 50
|
|
- name: Publish mutation results
|
|
if: always()
|
|
uses: mikepenz/action-junit-report@v4
|
|
with:
|
|
report_paths: 'mutation-junit.xml'
|
|
annotate_only: true
|
|
detailed_summary: true
|
|
include_passed: true
|
|
fail_on_failure: 'false'
|