name: libakstdlib CI Build run-name: ${{ gitea.actor }} libakstdlib test on: [push] jobs: cmake_build: runs-on: ubuntu-latest steps: - run: echo "Triggered by ${{ gitea.event_name }} from ${{ gitea.repository }}@${{ gitea.ref }}. Building on ${{ runner.os }}." - name: Check out repository code uses: actions/checkout@v4 with: # A top-level build uses deps/libakerror via add_subdirectory, so the # submodule has to be present or the configure step fails outright. submodules: recursive - name: dependencies run: | sudo apt-get update -y sudo apt-get install -y cmake gcc moreutils # Depends on libakerror@main git clone https://source.starfort.tech/andrew/libakerror.git cd libakerror cmake -S . -B build cmake --build build cmake --install build - name: build and test run: | cmake -S . -B build cmake --build build sudo cmake --install build ctest --test-dir build --output-on-failure - run: echo "🍏 This job's status is ${{ job.status }}." coverage: runs-on: ubuntu-latest steps: - name: Check out repository code uses: actions/checkout@v4 with: submodules: recursive - name: dependencies run: | sudo apt-get update -y sudo apt-get install -y cmake gcc python3 # scripts/coverage.py needs nothing but python3 and gcc's own gcov, so # there is no lcov/gcovr to install here. # # The gate is a ratchet, not a target: src/stdlib.c is at 99.0% of lines # and 51.0% of branches, so 90/45 fails on a real regression (a test # deleted, or new untested code added) without tripping over rounding. # The report is printed either way -- the uncovered lines it lists are the # missing tests. - name: coverage run: | cmake -S . -B build-coverage -DAKSL_COVERAGE=ON \ -DAKSL_COVERAGE_THRESHOLD=90 \ -DAKSL_COVERAGE_BRANCH_THRESHOLD=45 cmake --build build-coverage ctest --test-dir build-coverage --output-on-failure cat build-coverage/coverage-summary.txt - run: echo "🍏 This job's status is ${{ job.status }}." mutation_test: runs-on: ubuntu-latest steps: - name: Check out repository code uses: actions/checkout@v4 with: # The harness copies the repo and builds the copy top-level, so it # needs deps/libakerror present just like the main job does. submodules: recursive - name: dependencies run: | sudo apt-get update -y sudo apt-get install -y cmake gcc moreutils python3 # Verify the tests actually catch bugs: break the library many ways and # confirm the suite fails. Gated on src/stdlib.c (fast, deterministic); # run the full default target locally for the macro header as well. # # The threshold is a ratchet, not a quality bar. The score is 89.6% # (155/173 killed) now that TODO.md sections 1.2-1.6 have tests; it was # 46.8% when only the list and tree functions were covered. 80 leaves # headroom for the runner while still failing on a real regression (tests # deleted, or new untested code added). The 18 survivors are listed in the # published report -- each one is a missing assertion. - name: mutation testing run: | python3 scripts/mutation_test.py \ --target src/stdlib.c \ --junit mutation-junit.xml \ --threshold 80 # Publish even when the threshold gate fails, so survivors are visible -- # each one is a missing test. Display-only (fail_on_failure: false); the # --threshold above is the gate. annotate_only avoids the Checks API 404 # on Gitea (mikepenz/action-junit-report#23). - 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' - run: echo "🍏 This job's status is ${{ job.status }}."