Testing and CI¶
What runs on a pull request, what each check means, and how to run it on your machine first. All workflows are in
.github/workflows; most call reusable workflows in
hf-general-ci-tools or
hf-espidf-ci-tools.
Workflows¶
| Workflow | File | Runs on | Checks |
|---|---|---|---|
| ESP32 Examples Build CI | esp32-examples-build-ci.yml |
push, pull request | Builds every app with ci_enabled: true in app_config.yml, Debug and Release, with ESP-IDF release/v5.5 |
| C++ Lint CI | ci-cpp-lint.yml |
push, pull request | clang-format and clang-tidy with _config/.clang-format and _config/.clang-tidy |
| C++ Analysis CI | ci-cpp-analysis.yml |
push, pull request | cppcheck on lib/managers and lib/api (C++20) |
| Docs Publish CI | ci-docs-publish.yml |
push to main, v* tags, pull request |
hardfoc-docs check (figures and generated tables current), strict MkDocs build, Doxygen under api/, offline link check of the built site, Lighthouse budget, phone and desktop screenshots (artifact docs-screenshots); publishes on main and tags |
| Docs Link Check CI | ci-docs-linkcheck.yml |
push, pull request | lychee over the Markdown files, config _config/lychee.toml |
| Markdown Lint CI | ci-markdown-lint.yml |
push, pull request | markdownlint, config _config/.markdownlint.json |
| YAML Lint CI | ci-yaml-lint.yml |
push, pull request | yamllint, config _config/.yamllint |
| HAL Boundary CI | ci-hal-boundary.yml |
push, pull request | tools/lint/lint_hal_boundary.sh (no ESP-IDF, FreeRTOS or Esp* code outside lib/managers/bsp_bind/<family>/; shrink-only allowlist checked against the PR base); tools/lint/lint_hal_alloc.sh (no heap or heap-backed type in the HAL library); host build of the managers against bsp_bind/host and the manager tests in tests/host (GCC, Clang, Clang with UBSan) |
| Release | release.yml |
v* tags |
Builds the release artifacts |
The examples are integration tests: they run on a board, not in CI. CI proves they compile; a person flashes them. The manager logic is unit-tested on a host, below.
Host tests¶
tests/host builds the facade and the managers against the host family of the platform binding
(bsp_bind/host, over hf-core's hf_core_host_mocks) and runs one executable per
manager. The chips are register-level SPI models in FluxChipModels.h, so the real
hf-core handlers and chip drivers run their unmodified bring-up and channel code:
| Model | What it answers |
|---|---|
Max22200Model |
Two-phase protocol (command byte with CMD high, then 8- or 32-bit data), STATUS / CFG / FAULT registers, fault flags on SDO, the CFG_CHx fields as the chip reads them (VDR duty in percent), an absent part (MISO high) |
Tle92466Model |
32-bit frames with the SAE J1850 CRC, the one-frame reply pipeline, 16- and 22-bit reply widths, write-1-to-clear diagnosis registers, ICVID, critical-fault replies (reply mode 10B, no CRC), an absent part |
Ads7952Model |
16-bit frames, manual channel select, channel id in the reply, an absent part |
| Test | Proves |
|---|---|
test_valve_manager |
kValveChannelMap is a bijection onto MAX22200 OUT0-7 and TLE92466ED OUT0-5; each channel switches only its own output on the wire; currents land on the mapped TLE channel; the bank mask splits; the board's SPI modes and clocks; fault pins are inputs and enables start low before any valve code runs; the enable path drops both banks without SPI, latches, refuses energising and re-arms; shutdown ends in SafeHold; fail-closed bring-up with either chip absent, the bus down or TLE92466ED critical-fault replies, retry; MAX22200 VDR duty in percent and CDR / VDR reconfiguration of one channel; MAX22200 and TLE92466ED fault reporting; shutdown turns every channel off |
test_adc_manager |
Every pin-map channel registers; each ADS7952 channel reads its own input; the VBUS divider; name and enum lookups agree; failed reads are recorded; fail-closed with the ADS7952 absent, the pressure bus down or the MCU ADC down |
test_temperature_manager |
All three sensors; the NTC through its pin-map channel; the MCP9700 through the ADS7952; degraded mode without the ADC or the die sensor; failure with no sensor |
test_nvs_manager |
The three namespaces and their binding slots; isolation; the 15-character key limit; fail-closed opening |
test_flux_hal |
Init order and the required set; CollectDiagnostics() for a healthy board, a missing valve driver, a missing valve bus and a degraded temperature manager; system calls through the binding |
cmake -S tests/host -B build/host -G Ninja
cmake --build build/host
ctest --test-dir build/host --output-on-failure
# with UndefinedBehaviorSanitizer:
cmake -S tests/host -B build/host-ubsan -G Ninja -DHF_HAL_SANITIZERS=undefined
AddressSanitizer is not used yet: hf-core's MAX22200 SPI adapter copies buffers with aligned word accesses that touch
the bytes around them (see hf-core's docs/host-build.md).
Run the checks locally¶
# Build one example (needs ESP-IDF, see Get started)
cd examples/esp32 && ./scripts/build_app.sh flux_api_test Release && cd ../..
# HAL boundary lint and the host build of the managers (no ESP-IDF needed)
tools/lint/lint_hal_boundary.sh
tools/lint/lint_hal_alloc.sh
cmake -S tests/host -B build/host -G Ninja && cmake --build build/host
# Format check
clang-format --style=file:_config/.clang-format --dry-run --Werror lib/managers/*.cpp lib/managers/*.h
# Docs: drift checks, then the strict site build (the pin map needs lib/core and hf-pincfg)
python3 -m pip install "git+https://github.com/hardfoc/hf-general-ci-tools@v1#subdirectory=packages/hardfoc-mkdocs-theme"
hardfoc-docs gen --check
hardfoc-docs figures --check
mkdocs build --strict
# Markdown and YAML lint
npx markdownlint-cli2 --config _config/.markdownlint.json "docs/**/*.md" README.md
yamllint -c _config/.yamllint .github/workflows mkdocs.yml
When the docs checks fail¶
| Message | Fix |
|---|---|
generated region is stale |
The pin map, app_config.yml or a manager's #includes changed. Run hardfoc-docs gen and commit |
... is stale (run hardfoc-docs figures) |
A figure's source data changed. Run hardfoc-docs figures, look at the SVGs, commit |
contains a link ... not found |
A page links to a file that does not exist. Fix the link |
image(s) have no alt text |
Every image needs alt text |