Add a Gitea workflow
Fills the gap TODO.md recorded last commit: the sibling libraries all carry .gitea/workflows/ci.yaml and this one did not, so every gate was run by hand. Four jobs, in the shape libakerror and libakstdlib use, down to the JUnit reporting and the annotate_only note about Gitea 404ing on the Checks API. cmake_build configures, builds and runs the 61-case suite with JUnit output. docs runs `doxygen Doxyfile` -- a real gate, since WARN_AS_ERROR is set -- and uploads build/docs/html as the api-documentation artifact. sanitizers runs the whole suite under ASan and UBSan, which libakstdlib's TODO.md calls its own highest-value missing item and which matters here because this library is all fixed pools and manual buffer arithmetic. coverage gates at 90% of lines against an actual 92.3% and uploads the html report. Two things worth knowing, both checked rather than assumed. The checkout is submodules: true, not recursive. The build needs libakerror, libakstdlib and basicinterpret; it does not need libakgl, which is guarded behind AKBASIC_WITH_AKGL and defaults OFF, and recursing would clone SDL, SDL_image, SDL_mixer, SDL_ttf and jansson for a target that is never configured. The nested submodules are uninitialized in this working tree today and the build is green, which is the proof. The docs job takes no submodules at all -- verified by running doxygen against a tree with deps/ absent. There is no branch-coverage gate. Branch coverage reads 17.3% and is not a meaningful number here, for the reason libakgl's and libakstdlib's TODO.md both record: the akerror control-flow macros expand into large branch trees at every call site, most unreachable in normal operation. Gating on it would mean writing tests for libakerror's macros. All four jobs were executed locally end to end before committing, not just eyeballed: 61/61 plain, 61/61 under ASan+UBSan, doxygen exit 0 producing 441 files, and gcovr exit 0 at the 90 gate. The gate was also confirmed to bite by raising it to 99. Not added: a mutation-testing job, which all three siblings have. There is no scripts/mutation_test.py in this repository to run, and porting libakerror's is its own piece of work -- filed in TODO.md, where it matters more than usual because the akerror macros expand at their call sites and coverage cannot see them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
161
.gitea/workflows/ci.yaml
Normal file
161
.gitea/workflows/ci.yaml
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
name: akbasic CI Build
|
||||||
|
run-name: ${{ gitea.actor }} akbasic 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:
|
||||||
|
# Not recursive, deliberately. The top-level build needs
|
||||||
|
# deps/libakerror and deps/libakstdlib (via add_subdirectory) and
|
||||||
|
# deps/basicinterpret (the golden corpus is driven in place from it).
|
||||||
|
# It does *not* need deps/libakgl, which is guarded behind
|
||||||
|
# AKBASIC_WITH_AKGL and defaults OFF -- and recursing into it would
|
||||||
|
# clone SDL, SDL_image, SDL_mixer, SDL_ttf and jansson for a target
|
||||||
|
# that is never configured. libakstdlib's own nested deps/libakerror is
|
||||||
|
# skipped for the same reason: our CMakeLists declares akerror::akerror
|
||||||
|
# first and libakstdlib guards on if(NOT TARGET ...).
|
||||||
|
submodules: true
|
||||||
|
- name: dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update -y
|
||||||
|
sudo apt-get install -y cmake gcc
|
||||||
|
- name: build
|
||||||
|
run: |
|
||||||
|
cmake -S . -B build
|
||||||
|
cmake --build build --parallel
|
||||||
|
# The suite is 61 cases: 41 golden files byte-compared against the Go
|
||||||
|
# reference's own corpus, 17 unit tests, 2 embedding examples, and 1
|
||||||
|
# known-failing test that asserts the *correct* contract for defects
|
||||||
|
# carried over from the reference (TODO.md section 6). A green run
|
||||||
|
# therefore does not mean defect-free -- see AKBASIC_KNOWN_FAILING_TESTS.
|
||||||
|
#
|
||||||
|
# --output-junit resolves relative to the test dir, so give an absolute
|
||||||
|
# path to land the report in the workspace root for the reporter below.
|
||||||
|
- name: test (JUnit)
|
||||||
|
run: ctest --test-dir build --output-on-failure --output-junit "$(pwd)/ctest-junit.xml"
|
||||||
|
# annotate_only: true skips creating a check run via the Checks API, which
|
||||||
|
# Gitea does not support and 404s on (mikepenz/action-junit-report#23).
|
||||||
|
# Results surface via the job summary instead.
|
||||||
|
- 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'
|
||||||
|
- run: echo "🍏 This job's status is ${{ job.status }}."
|
||||||
|
|
||||||
|
docs:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Check out repository code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
# No submodules at all. Doxyfile's INPUT is include/akbasic, src and
|
||||||
|
# examples, none of which live under deps/, and doxygen does not need to
|
||||||
|
# resolve <akerror.h> to parse a declaration. Verified by running it
|
||||||
|
# against a tree with no deps/ present.
|
||||||
|
- name: dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update -y
|
||||||
|
sudo apt-get install -y doxygen graphviz
|
||||||
|
# This is a gate, not a convenience. The Doxyfile sets
|
||||||
|
# WARN_AS_ERROR = FAIL_ON_WARNINGS, so a doc block that documents some of a
|
||||||
|
# function's parameters but not all of them fails the build. All 114 public
|
||||||
|
# declarations under include/akbasic carry a @brief, a @param per
|
||||||
|
# parameter, a @return and their @throws; keep it that way.
|
||||||
|
#
|
||||||
|
# OUTPUT_DIRECTORY is build/docs and doxygen will not create a missing
|
||||||
|
# parent, so make it first -- there is no cmake step in this job to do it.
|
||||||
|
- name: build API documentation
|
||||||
|
run: |
|
||||||
|
mkdir -p build
|
||||||
|
doxygen Doxyfile
|
||||||
|
- name: upload API documentation
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: api-documentation
|
||||||
|
path: build/docs/html/
|
||||||
|
if-no-files-found: error
|
||||||
|
- run: echo "🍏 This job's status is ${{ job.status }}."
|
||||||
|
|
||||||
|
sanitizers:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Check out repository code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
- name: dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update -y
|
||||||
|
sudo apt-get install -y cmake gcc
|
||||||
|
# The whole suite under ASan and UBSan, golden files included. This is the
|
||||||
|
# gate libakstdlib's TODO.md section 1 calls its highest-value missing item
|
||||||
|
# -- worth having here from the start, because this library is all fixed
|
||||||
|
# pools and manual buffer arithmetic, which is exactly what it catches.
|
||||||
|
- name: build and test under ASan + UBSan
|
||||||
|
run: |
|
||||||
|
cmake -S . -B build-asan \
|
||||||
|
-DAKBASIC_SANITIZE=ON \
|
||||||
|
-DCMAKE_BUILD_TYPE=Debug
|
||||||
|
cmake --build build-asan --parallel
|
||||||
|
ctest --test-dir build-asan --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: true
|
||||||
|
- name: dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update -y
|
||||||
|
sudo apt-get install -y cmake gcc gcovr
|
||||||
|
# The gate is a ratchet, not a target: src/ sits at 92.3% of lines and
|
||||||
|
# 96.9% of functions, so 90 fails on a real regression (a test deleted, or
|
||||||
|
# new untested code added) without tripping over rounding.
|
||||||
|
#
|
||||||
|
# There is deliberately no branch gate. Branch coverage reads about 17%
|
||||||
|
# and is not a meaningful number here, for the reason libakgl's and
|
||||||
|
# libakstdlib's TODO.md both record: the akerror control-flow macros expand
|
||||||
|
# into large branch trees at every call site, most of them unreachable in
|
||||||
|
# normal operation. Gating on it would mean writing tests for libakerror's
|
||||||
|
# macros, which is libakerror's mutation suite's job.
|
||||||
|
#
|
||||||
|
# --root . with a src/ filter keeps the dependency trees out of the report.
|
||||||
|
# Note gcovr searches for .gcda under --root, so a stale instrumented build
|
||||||
|
# left in the source directory would be folded in -- that is libakgl defect
|
||||||
|
# #13, and the reason build*/ is gitignored rather than kept around.
|
||||||
|
- name: coverage
|
||||||
|
run: |
|
||||||
|
cmake -S . -B build-coverage \
|
||||||
|
-DAKBASIC_COVERAGE=ON \
|
||||||
|
-DCMAKE_BUILD_TYPE=Debug
|
||||||
|
cmake --build build-coverage --parallel
|
||||||
|
ctest --test-dir build-coverage --output-on-failure
|
||||||
|
mkdir -p build-coverage/coverage
|
||||||
|
gcovr --root . --filter 'src/.*' \
|
||||||
|
--print-summary \
|
||||||
|
--html-details build-coverage/coverage/index.html \
|
||||||
|
--xml build-coverage/coverage/coverage.xml \
|
||||||
|
--fail-under-line 90
|
||||||
|
# Publish even when the threshold gate fails, so the uncovered lines are
|
||||||
|
# visible -- each one is a missing test.
|
||||||
|
- name: upload coverage reports
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: code-coverage
|
||||||
|
path: build-coverage/coverage/
|
||||||
|
if-no-files-found: warn
|
||||||
|
- run: echo "🍏 This job's status is ${{ job.status }}."
|
||||||
@@ -18,6 +18,10 @@ ctest --test-dir build --output-on-failure
|
|||||||
doxygen Doxyfile
|
doxygen Doxyfile
|
||||||
```
|
```
|
||||||
|
|
||||||
|
CI is `.gitea/workflows/ci.yaml` and runs all four of those: the suite, the doxygen gate,
|
||||||
|
ASan+UBSan, and coverage gated at 90% of lines. The generated API documentation and the
|
||||||
|
coverage report are uploaded as build artifacts (`api-documentation` and `code-coverage`).
|
||||||
|
|
||||||
The `Doxyfile` is configured the way `libakgl`'s is, including
|
The `Doxyfile` is configured the way `libakgl`'s is, including
|
||||||
`WARN_AS_ERROR = FAIL_ON_WARNINGS` — a doc block that documents some of a function's
|
`WARN_AS_ERROR = FAIL_ON_WARNINGS` — a doc block that documents some of a function's
|
||||||
parameters but not all of them fails the run, so `doxygen Doxyfile` is a gate rather than a
|
parameters but not all of them fails the run, so `doxygen Doxyfile` is a gate rather than a
|
||||||
|
|||||||
23
TODO.md
23
TODO.md
@@ -635,10 +635,17 @@ Dependency baseline:
|
|||||||
| `deps/libakstdlib` | 0.1.0 | soname `libakstdlib.so.0.1`. `AKSL_VERSION_CHECK()` asserted in `tests/version_check.c`. Its `aksl_ato*` family is banned here — see §1.9. |
|
| `deps/libakstdlib` | 0.1.0 | soname `libakstdlib.so.0.1`. `AKSL_VERSION_CHECK()` asserted in `tests/version_check.c`. Its `aksl_ato*` family is banned here — see §1.9. |
|
||||||
| `deps/libakgl` | 0.1.0 | Migrated to the 1.0.0 registry and owns 256–260. Not yet linked: `AKBASIC_WITH_AKGL` defaults OFF and `src/sink_akgl.c` does not exist. |
|
| `deps/libakgl` | 0.1.0 | Migrated to the 1.0.0 registry and owns 256–260. Not yet linked: `AKBASIC_WITH_AKGL` defaults OFF and `src/sink_akgl.c` does not exist. |
|
||||||
|
|
||||||
**This repository has no CI.** `libakgl` and `libakstdlib` both carry
|
CI is `.gitea/workflows/ci.yaml`, in the shape the sibling libraries use: four jobs covering
|
||||||
`.gitea/workflows/ci.yaml`; akbasic does not, so every gate here — ctest, the sanitizer build,
|
the suite, the doxygen gate, ASan+UBSan and coverage. The generated API documentation and the
|
||||||
coverage, and `doxygen Doxyfile` with `WARN_AS_ERROR` — is currently run by hand. Copying
|
coverage report are both uploaded as artifacts. Two notes on it worth keeping:
|
||||||
`deps/libakgl/.gitea/workflows/ci.yaml` and adjusting the option prefixes is the whole job.
|
|
||||||
|
- The checkout is `submodules: true`, **not** `recursive`. The build needs `libakerror`,
|
||||||
|
`libakstdlib` and `basicinterpret`; it does not need `libakgl`, which is guarded behind
|
||||||
|
`AKBASIC_WITH_AKGL` and defaults OFF — and recursing into it would clone SDL, SDL_image,
|
||||||
|
SDL_mixer, SDL_ttf and jansson for a target that is never configured. The `docs` job needs
|
||||||
|
no submodules at all.
|
||||||
|
- There is no mutation-testing job, unlike `libakerror`, `libakstdlib` and `libakgl`. This
|
||||||
|
repository has no `scripts/mutation_test.py`; see the item below.
|
||||||
|
|
||||||
What remains, in priority order:
|
What remains, in priority order:
|
||||||
|
|
||||||
@@ -647,5 +654,11 @@ What remains, in priority order:
|
|||||||
2. **§4 — the language completion work queue.** Groups A, B, D, F and J need nothing from
|
2. **§4 — the language completion work queue.** Groups A, B, D, F and J need nothing from
|
||||||
`libakgl` and can start immediately. Multiple statements per line (the `COLON` token exists
|
`libakgl` and can start immediately. Multiple statements per line (the `COLON` token exists
|
||||||
and nothing consumes it) should come first, because `DO`/`LOOP` reads badly without it.
|
and nothing consumes it) should come first, because `DO`/`LOOP` reads badly without it.
|
||||||
3. **§6 items 12–16** — the defects the port uncovered. Item 12 is the one that produces a
|
3. **§6 items 12–17** — the defects the port uncovered. Item 12 is the one that produces a
|
||||||
*wrong answer* rather than a refused one, and should be fixed first.
|
*wrong answer* rather than a refused one, and should be fixed first.
|
||||||
|
4. **Mutation testing.** All three sibling libraries gate on it and this one does not, because
|
||||||
|
there is no `scripts/mutation_test.py` here to run. It matters more than usual for this
|
||||||
|
codebase: the akerror macros expand at their call sites, so line coverage cannot see them
|
||||||
|
and mutation testing is the only thing that checks the `ATTEMPT`/`CATCH`/`PASS` control
|
||||||
|
flow at all. `deps/libakerror/scripts/mutation_test.py` is the one to port; `src/value.c`
|
||||||
|
or `src/scanner.c` would be the right first target.
|
||||||
|
|||||||
Reference in New Issue
Block a user