CI Pipelines
Overview
hf-core uses 8 GitHub Actions workflows that mirror the standard CI pattern across all HardFOC repositories. Workflows use reusable workflow definitions from two shared CI tool repositories:
| Repository | Purpose |
|---|---|
hardfoc/hf-espidf-ci-tools |
ESP-IDF build, flash, release workflows |
hardfoc/hf-general-ci-tools |
C++ analysis, linting, documentation workflows |
All reusable workflows are pinned at @main.
Workflow Descriptions
1. ESP-IDF Build (esp32-examples-build-ci.yml)
Trigger: Push/PR to main, develop, feature/**, release/**
Pipeline stages:
- Validate — Checks
app_config.ymlstructure and validates APP_TYPE entries - Build Matrix —
generate_matrix.pyreadsapp_config.yml, produces a matrix of{app_type, build_type, idf_version}combinations whereci_enabled: true - Build — Each matrix entry runs
build_app.shin a Docker container with ESP-IDF - Lint — Runs clang-format/clang-tidy on modified files (excludes submodule dirs)
Only apps with ci_enabled: true in app_config.yml are included in the matrix.
Currently, canopen_utils_test and full_integration_test are disabled because they
require specific hardware or network configuration.
2. C++ Static Analysis (ci-cpp-analysis.yml)
Trigger: Push/PR modifying handlers/** or _config/**
Runs Cppcheck with --std=c++20 on the handlers/ directory. Catches common
bugs, undefined behavior, and style issues.
3. C++ Lint (ci-cpp-lint.yml)
Trigger: Push/PR modifying handlers/** or _config/**
Runs clang-format (style check) and clang-tidy (static analysis) using the
configurations in _config/. Excludes hf-core-drivers/ and hf-core-utils/
submodules from analysis.
4. Documentation Link Check (ci-docs-linkcheck.yml)
Trigger: Push/PR modifying docs/** or README.md
Uses lychee to verify all hyperlinks in documentation are reachable. Configuration
in _config/lychee.toml excludes known-flaky URLs (shields.io badges, GNU licenses).
5. Documentation Publish (ci-docs-publish.yml)
Trigger: Push to main (deploy), PR to main (build-only)
Two-stage pipeline:
- Jekyll — Builds the docs site using
_config/_config.yml(Just the Docs theme) - Doxygen — Generates API reference from handler source code, outputs to
docs/api/within the Jekyll site
Deploys to GitHub Pages on push to main.
6. Markdown Lint (ci-markdown-lint.yml)
Trigger: Push/PR modifying **/*.md
Validates Markdown files against .markdownlint.json rules. Excludes submodule
directories (hf-core-drivers/**, hf-core-utils/**).
7. YAML Lint (ci-yaml-lint.yml)
Trigger: Push/PR modifying **/*.yml or **/*.yaml
Validates YAML files against .yamllint rules. Excludes submodule directories.
8. Release (release.yml)
Trigger: Push of a tag matching v*
Creates a GitHub Release with:
- Auto-generated changelog from commits since the last tag
- Source archive attached as a release artifact
- Release notes template
Build Matrix Generation
The build matrix is generated from app_config.yml by generate_matrix.py:
1
2
3
4
5
6
7
# app_config.yml excerpt
apps:
handler_testing:
as5047u_handler_test:
source_file: "handler_tests/as5047u_handler_comprehensive_test.cpp"
ci_enabled: true
description: "AS5047U magnetic encoder handler tests"
The script produces a JSON matrix like:
1
2
3
4
[
{"app_type": "as5047u_handler_test", "build_type": "debug", "idf_version": "v5.5"},
{"app_type": "as5047u_handler_test", "build_type": "release", "idf_version": "v5.4"}
]
Running CI Locally
You can simulate the CI build locally:
1
2
3
4
5
6
7
8
9
10
cd examples/esp32/scripts
# Build a single app
./build_app.sh general_utils_test Debug
# List all available apps
./build_app.sh list
# Generate the matrix (for debugging)
python3 generate_matrix.py ../app_config.yml
Adding a New CI-Tested App
- Add the app entry to
app_config.ymlwithci_enabled: true - Create the source file under the appropriate
main/subdirectory - Add the
APP_TYPEconditional tomain/CMakeLists.txt - Push — the CI will automatically pick up the new app in the build matrix