CI Matrix
What triggers each CI job, what it targets, and whether it executes anything
or only builds. The tables cover the jobs that gate a pull request, the
nightly sweep, the release path, and the workflows those call. Every cell is
derived from the workflow YAML in .github/workflows/, and each table cites
the files it came from. This is a hand-maintained page, not a generated
inventory: a workflow added without a row here goes unlisted, and nothing
fails when that happens.
Testing & Verification is the narrative version of the
same contract; this page is the lookup table.
Read the “executes” column first. Most of this matrix compiles and links; a smaller part of it runs code and compares results. Those are different guarantees and the difference is where defects have escaped before.
What runs on every pull request
Section titled “What runs on every pull request”All of these are workflow_call jobs invoked from .github/workflows/ci.yml,
which triggers on pull_request (any base branch), on push to main, and
on workflow_dispatch. They report through the single ci-passed job, whose
status context is CI Passed.
| Job | Workflow | Cores | Precisions | Executes | Toolchain |
|---|---|---|---|---|---|
codegen-tests |
helia-core-tester.yml |
cortex-m0, cortex-m4, cortex-m55 | integer suite (--suite int) |
yes, Corstone-300 FVP | CI container’s Arm GNU 14.3.1 |
shipped-flags-tests |
helia-core-tester.yml |
cortex-m4 (int), cortex-m55 (int, f32, f16) | integer, float32, float16 |
yes, Corstone-300 FVP | CI container’s Arm GNU 14.3.1 |
codegen-tests-mve-float |
helia-core-tester.yml |
cortex-m55 | float32, float16 |
yes, Corstone-300 FVP | CI container’s Arm GNU 14.3.1 |
codegen-tests-mve-int |
helia-core-tester.yml |
cortex-m55 | integer suite (--suite int), MVE paths without ARM_MATH_AUTOVECTORIZE |
yes, Corstone-300 FVP | CI container’s Arm GNU 14.3.1 |
codegen-tests-float-fallback |
helia-core-tester.yml |
cortex-m0 (f32), cortex-m4 (f32), cortex-m55 (f32, f16) | float32, float16 |
yes, Corstone-300 FVP | CI container’s Arm GNU 14.3.1 |
gcc |
toolchain-matrix-strict-link.yml |
cortex-m4, cortex-m55 | float32 on both, float16 on m55 |
no, build and strict link only | GCC 13.2.Rel1, 14.2.Rel1, 15.3.Rel1 |
atfe |
toolchain-matrix-strict-link.yml |
cortex-m4, cortex-m55 | float32 on both, float16 on m55 |
no, build and strict link only | ATfE 19.1.5 |
armclang |
toolchain-matrix-strict-link.yml |
cortex-m4, cortex-m55 | float32 on both, float16 on m55 |
no, build and strict link only | armclang 6.23.32 |
host-sanitizer |
host-sanitizer.yml |
x86-64 host, scalar paths | float32, float16 |
yes, on the host under ctest |
ubuntu-24.04 system GCC |
compile |
unity-m55-compile.yml |
cortex-m55, cortex-m4, cortex-m0 | float32 on all three, float16 on m55 |
no, compile and link only | Arm GNU 14.2.rel1 |
f16-exec |
unity-f16-exec-gcc-floor.yml |
cortex-m55 | float16 |
yes, QEMU mps3-an547, at -Ofast |
GCC 13.2.Rel1 |
build-staticlibs, build-pack |
pack-dryrun.yml |
cortex-m0, cortex-m4, cortex-m55 | n/a | no, packaging only | GCC 14.2.Rel1 |
check_pdsc, pdsc_contract, and the other textual gates |
pdsc.yml |
none | n/a | Python and shell gates on the host | none |
contract, find_package |
ssot-contract.yml |
none | n/a | CMake configure only | none |
wiring, install, prebuilt_real |
nsx-integration.yml |
none | n/a | CMake configure only | none |
wiring, kconfig |
zephyr-integration.yml |
none | n/a | CMake and Python only, no Zephyr SDK | none |
build |
docs.yml |
none | n/a | Doxygen API generation, Astro build, coverage/link checks and browser tests | none |
changed-files |
clang-format.yml |
none | n/a | formatting check on changed files | clang-format 18.1.8 |
all-files |
pre-commit.yml |
none | n/a | the pre-commit hook set on the whole tree | pre-commit 3.8.0 |
check |
license-headers.yml |
none | n/a | header check on the host | none pinned |
ci-tool-manifest, gen-pack-action-pin, and the other contract jobs |
release-contract.yml |
none | n/a | shell assertions over the release path’s own wiring | none pinned |
The cortex-m0 f32 fallback cell is the only pull-request-gating execution
evidence for the soft-float f32 path; legacy-tester.yml builds and runs
cortex-m0 with float32 nightly and at release. Its coverage is
intentionally not merged into the coverage gate: the merge stages the three
int legs, the m4 f32 and m55 f32 and f16 fallback legs, the m55
MVE-float legs and the m55 MVE-int leg, so adding it would move
ci/coverage-floor.json and needs
its own change.
Sources: .github/workflows/ci.yml’s on: block for the triggers and its
ci-passed job’s needs: list for the gated set; each callee’s own
strategy.matrix for its cells. The Job column names the job inside the
callee, which is not the id ci.yml gives the call. The container’s Arm GNU
14.3.1 is pinned in ci/tools/manifest.json (the arm-gnu entry), which the
CI image installs; for the helia-core-tester rows, the FVP execution and the
operator and dtype set behind each suite come from the pinned
Tests/helia-core-tester submodule rather than from anything in this
repository.
What runs nightly
Section titled “What runs nightly”.github/workflows/nightly.yml triggers on schedule (17 7 * * *) and on
workflow_dispatch.
| Job | Workflow | Cores | Executes | Notes |
|---|---|---|---|---|
helia-core-tester |
helia-core-tester.yml |
as the PR rows above | yes, Corstone-300 FVP | the same suite the PR gate runs |
legacy-unit-tests |
legacy-tester.yml |
cortex-m0, cortex-m4, cortex-m55 | yes, Corstone-300 FVP | float32 on all three, float16 on m55 |
toolchain-strict-link |
toolchain-matrix-strict-link.yml |
as the PR rows above | no | |
release-assets-audit |
nightly.yml |
none | gh against published releases |
expands ci/release-assets.json |
What runs at release
Section titled “What runs at release”.github/workflows/release.yml triggers on push to main and on
workflow_dispatch with a recover_tag input.
| Job | Workflow | Executes | Notes |
|---|---|---|---|
release-please |
release.yml |
no | creates the release PR, then publishes the tag and the Release object, and resolves the trusted commit sha every later job builds from |
resolve-release-capabilities |
release.yml |
no | decides whether an Arm user-based license is available, which is what makes the armclang assets producible |
publish-staticlibs |
release.yml |
no | GCC 14.2.Rel1 and ATfE 19.1.5, three cores each; builds the SDK tarballs |
publish-staticlibs-armclang |
release.yml |
no | armclang 6.23.32, the same three cores, run one at a time; its assets stay optional unless ARMCLANG_REQUIRED is set |
publish-staticlib-bundles |
release.yml |
no | zips the per-toolchain bundles from the other two publishers and uploads them; builds nothing itself |
publish-pack |
release.yml |
no | gen-pack, Doxygen 1.9.6 and packchk 1.4.1 over the GCC prebuilt archives; publishes the .pack and the Pages docs |
release-unit-tests |
legacy-tester.yml |
yes, Corstone-300 FVP | same three cores as nightly |
release-helia-core-tester |
helia-core-tester.yml |
yes, Corstone-300 FVP | |
release-verify |
release.yml |
no | re-reads the published release and fails on any difference from ci/release-assets.json |
Toolchain versions in this table come from release.yml’s own steps for GCC
and from ci/tools/manifest.json for the container-installed ATfE and
armclang.
What other workflows call
Section titled “What other workflows call”Neither of these has a pull_request trigger; both reach a pull request only
through a caller.
| Job | Workflow | Trigger | Executes | Notes |
|---|---|---|---|---|
resolve |
resolve-ci-image.yml |
workflow_call only |
no | resolves which ghcr.io/ambiqai/ns-cmsis-nn-ci tag a caller runs in, and reports whether it came from a release or the fallback |
build-and-push |
build_publish_docker.yml |
workflow_call, workflow_dispatch, schedule (0 16 * * 1) |
yes, a container build and push | builds the CI image from .devcontainer/Dockerfile, which installs Arm GNU 14.3.1, ATfE 19.1.5 and armclang 6.23.32 per ci/tools/manifest.json, plus clang-format 18.1.8; called from release.yml’s publish-ci-image |
What runs only on demand
Section titled “What runs only on demand”| Workflow | Trigger | Cores and toolchains |
|---|---|---|
staticlib-dryrun.yml |
workflow_dispatch |
build: cortex-m0, cortex-m4, cortex-m55 across gcc and atfe; armclang: the same three cores in a separate job, outside that matrix |
update_helia_core_tester.yml |
workflow_dispatch |
none, submodule bump only |
pack-dryrun.yml used to belong here. It now runs per PR through ci.yml
and weekly on its own schedule, and stays dispatchable.
What nothing executes
Section titled “What nothing executes”Stated plainly, because each of these is a guarantee the matrix above does not give:
- Nothing functional runs on GCC 14.2.Rel1 or 15.3.Rel1. Those two cells
of
toolchain-matrix-strict-link.ymlbuild and strict-link the archive and stop. The only GCC releases that execute a test binary are the container’s 14.3.1, through every FVP leg, and 13.2.Rel1, through the QEMUfloat16cell. Note the gap this leaves: 14.2.Rel1 is the release that builds the shipped static libraries, and no job executes anything built by it. - Nothing executes anything built by ATfE or armclang. Both are built and strict-linked on every PR and neither ever runs, on any core. Tracked in #340.
- Nothing executes the MVE or DSP paths under a sanitizer.
host-sanitizer.ymlruns on the x86-64 host, which selects the scalar implementations. Tracked in helia-core-tester#68. - The legacy Unity suites do not execute on any pull request.
legacy-tester.ymlis called only fromnightly.ymlandrelease.yml. On the PR path they are compiled but not run byunity-m55-compile.yml, except the fivefloat16suites thatunity-f16-exec-gcc-floor.ymlexecutes under QEMU. release-verifynever runs on a pull request. It lives inrelease.ymland only fires inside a release or recovery run. The nightlyrelease-assets-auditjob is what covers the gap.
Two things this page cannot tell you
Section titled “Two things this page cannot tell you”Which checks are required to merge. Branch protection and ruleset
configuration live in repository settings, not in the tree, so no file here
can state it. What the tree does show is that ci.yml funnels every gated
job into one ci-passed job whose context is named CI Passed (the
name: at the top of .github/workflows/ci.yml and the ci-passed job’s
needs: list), which is the context intended to be required.
Which dtypes the helia-core-tester suites cover. The workflow passes
--suite int or --suite float and a --float-precision; the set of
operators and quantization types inside each suite is defined by the pinned
Tests/helia-core-tester submodule release, not by anything in this
repository. Reading that pin is the only way to answer it, and the answer
moves whenever the pin does. At the pinned commit af7ac9f0, the
descriptors under Tests/helia-core-tester/assets/descriptors/ carry 39
int4 cases: 25 in ConvolutionFunctions/convolve.yaml, 10 in
ConvolutionFunctions/depthwise_conv.yaml and 4 in
FullyConnectedFunctions/fully_connected.yaml. Legacy Unity coverage of
int4 is directly visible here: Tests/UnitTest/TestCases/TestData/ carries
int4 vector directories, and those suites execute nightly and at release
only.
See also
Section titled “See also”- Testing & Verification, the narrative contract and the coverage-report instructions.
- Versioning & Releases, the release asset contract.