Macros
Overview
The cikit.macros package provides reusable building blocks for project-specific
CI commands. Macros cover common tasks such as linting, testing, coverage generation,
build execution, report generation, packaging, and documentation builds.
Run-bound macros operate on a CiRunEnvironment so generated metrics and artifacts
belong to an explicit logical run. Project-specific command modules should primarily
handle command-line arguments and orchestration while reusable tool integration remains
inside the macros.
Dependency Model
cikit intentionally keeps its own runtime dependency set small. Tool-specific dependencies are not installed automatically just because a corresponding macro exists.
Projects must provide the tools required by the macros they use. Depending on the tool, this may mean adding a Python package to the project environment, installing a system executable, or providing a project-specific toolchain.
The current macro dependencies are:
Macro |
Dependency |
Notes |
|---|---|---|
|
|
Required only by |
|
|
Required for linting and GitLab Code Quality output. |
|
|
Required for normal Pylint execution. |
|
|
Required only for GitLab Code Quality output. |
|
|
Required for normal test execution. |
|
|
Required only when |
|
|
Required by |
|
|
Required by |
|
|
Required for CMake builds, File API compiler metadata, and CTest execution. |
|
Selected generator |
For example, |
|
|
Provided by PlatformIO Core. |
|
|
Provided by Sphinx. |
|
None |
Uses cikit functionality and the Python standard library. |
|
None |
ZIP and TAR creation use the Python standard library. |
Python-based tools can normally be kept in a project dependency group, for example:
[dependency-groups]
dev = [
"ruff>=0.15",
"pylint~=4.0",
"pylint-gitlab~=2.1",
"pytest>=9",
"coverage>=7.14",
"gcovr",
"sphinx",
"platformio",
]
System tools such as CMake, Ninja, or rsync should be installed by the development environment or CI image when the corresponding functionality is used.
Common Helpers
The common module contains shared helpers used by project commands and other macros.
Typical responsibilities include:
environment initialization
cikit data preparation
timeline creation
standard project badges
directory comparison
name and label resolution
A run-bound environment can be created with:
from cikit.macros.common import init_env
env = init_env(run_name="ruff")
Without run_name, init_env() returns a generic CiEnvironment.
data_prepare() initializes the configured cikit data backend for the current
pipeline. chart_timeline() retrieves historical run data and returns a configurable
TimelineChart before rendering.
Directory comparison is available through compare_dirs(). This helper executes
rsync in dry-run mode and therefore requires the rsync executable.
Ruff
The ruff macro executes Ruff checks and integrates their results with cikit.
Dependencies
The ruff executable is required.
Features
JSON lint report generation
GitLab Code Quality output
cikit data updates
lint artifact registration
badge generation
RST report generation
timeline integration
Typical usage
from cikit.macros import ruff
ruff.ruff(env, ["src", "tests"])
ruff.badge(env)
ruff.write_rst(env)
GitLab Code Quality output can be generated separately with
ruff.gitlab_code_quality(). Ruff provides the GitLab output format directly, so no
additional reporter package is required.
Pylint
The pylint macro executes Pylint checks and converts the resulting diagnostics into
cikit reports.
Dependencies
Normal operation requires pylint.
GitLab Code Quality output additionally requires pylint-gitlab because the macro
uses its GitlabCodeClimateReporter reporter.
Features
JSON lint report generation
GitLab Code Quality output
cikit data updates
lint artifact registration
badge generation
RST report generation
timeline integration
rule-specific filtered reports
Typical usage
from pathlib import Path
from cikit.macros import pylint
pylint.pylint(env, ["src", "tests"], rcfile=Path(".pylintrc"))
pylint.badge(env)
pylint.write_rst(env)
Pytest
The pytest macro executes Python test suites and stores their JUnit results.
Dependencies
Normal test execution requires pytest.
When coverage_dir is provided, the test suite is executed through coverage run.
This mode additionally requires coverage.
Features
pytest execution
JUnit XML generation
optional parallel coverage data collection
cikit data updates
XUnit artifact registration
Typical usage
from pathlib import Path
from cikit.macros import pytest
pytest.pytest(
env,
Path("tests/unittests"),
test_alias="unittests",
)
To collect coverage data for later processing:
pytest.pytest(
env,
Path("tests/unittests"),
test_alias="unittests",
coverage_dir=Path("build/coverage"),
)
Coverage
The coverage macro generates coverage reports from previously collected coverage
data.
Dependencies
The required tool depends on the coverage workflow:
pycoverage()requirescoverage.ccoverage()requiresgcovrand a compatiblegcovtool.
For GCC builds, gcovr uses gcov by default. The gcov version should
match the GCC version used to compile the instrumented code. Clang-based builds
can use the compatible llvm-cov gcov mode instead.
Features
Python coverage processing
C/C++ coverage processing with gcovr
Cobertura XML generation
HTML coverage reports
cikit data updates
artifact registration
coverage badges
RST report generation
timeline integration
Python coverage
Parallel coverage data generated by the pytest macro can be combined and rendered
with:
from pathlib import Path
from cikit.macros import coverage
coverage.pycoverage(env, Path("build/coverage"))
coverage.badge(env)
coverage.write_rst(env)
C/C++ coverage
For C or C++ projects, gcovr can process coverage data from a build directory:
from pathlib import Path
from cikit.macros import coverage
coverage.ccoverage(env, Path("build"))
Generated HTML coverage output is registered as a folder artifact. Generated RST pages refer to registered artifacts rather than depending on the physical public output layout.
CMake
The cmake macro supports CMake configuration, builds, and CTest execution.
Dependencies
CMake 3.20 or newer providing cmake and ctest is required.
The selected CMake generator and project toolchain must also be available. For example,
using generator="Ninja" requires the ninja executable. Compilers and linkers are
project toolchain requirements rather than cikit dependencies.
Features
CMake configuration
optional clean configuration
CMake build execution
CMake version metadata
compiler metadata collection through the CMake File API
optional
compile_commands.jsongeneration and registrationoptimization and LTO metadata from the compilation database
CTest execution
parallel execution
configure, build, and total build time metrics
compiled file counts
compiler warning and error counts
linker memory usage metrics
configure and build command logs
JUnit XML output
cikit data updates
artifact registration
RST build reports
Typical build usage
from pathlib import Path
from cikit.macros import cmake
build_dir = cmake.get_build_dir(env)
cmake.gather_cmake_meta(env)
cmake.cmake_configure(
env,
source_dir=Path("."),
build_dir=build_dir,
generator="Ninja",
clean=True,
compile_commands=True,
)
cmake.gather_compiler_meta(env, build_dir, "CXX")
cmake.cmake_build(env, build_dir)
cmake.write_rst(env)
CTest can also be executed independently on an already configured build directory:
cmake.ctest(
env,
build_dir,
test_alias="ctest",
)
Build reports include the metrics and artifacts available for the current run. See Builds for the wider build and report workflow.
CMake and Compiler Metadata
CMake metadata can be collected independently from project configuration:
cmake.gather_cmake_meta(env)
This stores the version of the CMake executable as cmake_version.
After configuration, compiler metadata can be collected for a CMake language:
cmake.gather_compiler_meta(env, build_dir, "CXX")
The language must match a language enabled by the configured CMake project, for
example C or CXX.
cikit uses the CMake File API toolchains-v1 reply generated during
cmake_configure() and stores:
compilercompiler_versioncompiler_type
compiler_type contains the compiler ID reported by CMake, for example
GNU or Clang.
When compile_commands=True is used and CMake generates the compilation
database, it is registered as a METADATA artifact. During cmake_build(),
recognized optimization and LTO options are exposed as optimization and
lto metrics.
Missing, invalid, or unavailable toolchain metadata is reported as a
CiToolsError. Compilation-database-derived metrics are optional when the
database or recognized options are unavailable.
PlatformIO
The platformio macro builds PlatformIO projects and collects build and compiler
metadata.
Dependencies
PlatformIO Core and its pio executable are required.
Platforms, frameworks, libraries, and toolchains configured through platformio.ini
are managed by PlatformIO and are project requirements rather than direct cikit
dependencies.
Features
compiler metadata collection
PlatformIO build execution
optional clean builds
build time metrics
compiled file counts
compiler warning and error counts
memory usage metrics
build command logs
cikit data updates
artifact registration
RST build reports
Typical usage
from pathlib import Path
from cikit.macros import platformio
platformio.gather_compiler_meta(env, project_dir=Path("."))
platformio.build(env, project_dir=Path("."), clean=True)
platformio.write_rst(env)
When project_dir is omitted, the project root from the environment is used.
gather_compiler_meta() asks PlatformIO for the resolved build environment and, when
exactly one environment can be determined, stores available compiler information in the
current run data:
compilercompiler_versioncompiler_type
The compiler executable is taken from PlatformIO metadata and queried for its version.
Reports
The reports module provides common report handling shared by test and build macros.
Dependencies
No additional tool dependency is required.
Features
shared JUnit result processing for pytest and CTest
XUnit artifact registration and result persistence
test result badges
test summary reports
build summary reports with available tool, compiler, build, and timing metadata
timeline integration
memory usage tables
build artifact and bundle tables with download links, file sizes, and SHA-256 hashes
collapsible command log integration
RST artifact registration
Typical test report usage:
from cikit.macros import reports
reports.badge(env)
reports.write_test_report(env)
Typical build report usage:
from cikit.macros import reports
reports.write_build_report(env, report_title="Build Report")
Build-specific macros such as cmake and platformio expose their own
write_rst() wrappers and use the generic build report internally.
Bundle
The bundle macro creates distributable archives from a file or directory and
registers the generated archive as a bundle artifact.
Dependencies
No additional dependency is required. ZIP, TAR, and TAR.GZ archives are created with the Python standard library.
Typical usage
from pathlib import Path
from cikit.macros import bundle
bundle.create(
env,
"firmware-package.zip",
Path("build/release"),
)
Supported target formats are:
.zip.tar.tar.gz
Directory contents are placed directly in the archive root.
Sphinx
The sphinx macro prepares registered cikit artifacts for documentation and builds
the final HTML documentation.
Dependencies
Sphinx and its sphinx-build executable are required.
Themes and additional Sphinx extensions used by the target documentation must be installed by the consuming project. They are not dependencies of the cikit Sphinx macro itself.
Features
generated RST report integration
badge integration
static artifact integration
folder artifact integration
HTML documentation builds
HTML folder artifact registration
cikit Sphinx extension integration
Typical usage
from pathlib import Path
from cikit.macros import sphinx
docs_dir = Path("docs")
sphinx.prepare(env, docs_dir)
html_artifact = sphinx.sphinx(env, docs_dir)
prepare() rebuilds the generated portions of the Sphinx source tree from registered
cikit artifacts. RST artifacts are copied to docs/_generated while other artifact
types are placed below docs/_static according to the common Sphinx artifact layout.
The documentation itself is built in a temporary directory. The completed HTML tree is then registered as a folder artifact.
See Sphinx Documentation Build for the complete documentation build workflow and Sphinx Extensions for the cikit-specific roles and directives.
Artifacts and Cikit Data
Most run-bound macros update the current run data and register generated artifacts. This allows independent pipeline steps to exchange reports and generated outputs without depending on fixed filesystem paths.
Typical artifact types produced by macros include:
badges
timeline charts
JUnit and Cobertura XML reports
lint reports
generated RST pages
HTML report folders
command logs
direct build outputs
bundles
Artifacts can later be consumed by reporting and Sphinx macros. Run-specific report helpers only include artifacts associated with the current logical run.
For the complete artifact model, see Artifacts. For persistent run data and timeline history, see Cikit Data.
Using Macros from Project Commands
Macros are intended to be orchestrated from project-local command modules loaded by
cikit.ci. Command modules define project policy; macros provide reusable
implementation.
A lint command can remain small:
from cikit.macros import common, pylint
env = common.init_env(run_name="pylint")
pylint.pylint(env, ["src", "tests"])
pylint.badge(env)
pylint.write_rst(env)
A CMake build command can compose several build helpers:
from pathlib import Path
from cikit.macros import cmake, common
env = common.init_env(run_name="build")
build_dir = cmake.get_build_dir(env)
cmake.gather_cmake_meta(env)
cmake.cmake_configure(
env,
source_dir=Path("."),
build_dir=build_dir,
generator="Ninja",
clean=True,
)
cmake.gather_compiler_meta(env, build_dir, "CXX")
cmake.cmake_build(env, build_dir)
cmake.write_rst(env)
This separation keeps command-line handling and workflow policy inside the project while
the reusable implementation remains in cikit.macros.