wolfCert's CI runs on GitHub Actions. Every job builds (or restores from cache)
a wolfSSL configuration, builds wolfCert to match, and runs the tests. wolfSSL
is tracked at master and built from source, except in cmake-full-floor,
which builds the oldest supported release (v5.9.4-stable). The install
prefix is cached so a run with an unchanged wolfSSL commit + configure-flag
set skips the wolfSSL build entirely.
| Workflow | Trigger | What it does |
|---|---|---|
pr.yml |
PR + push | Merge gate: CMake (-Werror) + autoconf + ASan/UBSan on the canonical config, the same config against the minimum wolfSSL release (cmake-full-floor), plus per-PR feature/config gating — EST-only, SCEP-only, server-off, the key-alg variants (NO_RSA, ECC-only, RSA-only, no-3DES), TLS 1.3-only, the three ML-DSA per-level builds, the static-memory and no-malloc constrained builds, the platform-pieces-off build (cmake-no-builtin-transport), the freestanding ARM compile and config-resolution check (no-posix-arm), the header-only (WOLFCERT_USER_SETTINGS) build, a macOS build, and the two cheapest configure-must-fail assertions. |
lint.yml |
PR + push | GPL license-header check and CMake↔autoconf parity of both the library and test source lists, plus the Zephyr module's library list (scripts/ci/check-buildsystem-parity.sh). No wolfSSL build — fails in seconds. |
nightly.yml |
schedule + dispatch | Re-runs the wolfSSL-variant build matrix against fresh wolfSSL master, the macOS extras, and the full negative-config set. Also reseeds the wolfSSL prefix caches so the next day's PRs restore instead of build. The feature/config gating itself now runs per-PR (see pr.yml). |
sanitizers.yml |
schedule + dispatch | ASan+UBSan over the full test suite, ThreadSanitizer over the threaded integration roundtrips (against a TSAN-instrumented wolfSSL), and valgrind over a representative subset. |
interop.yml |
schedule + dispatch | Third-party EST/SCEP interop (openssl, micromdm/scep, globalsign/est, cisco/libest, smallstep/step-ca). Best-effort: a dependency that fails to install makes its script exit 77, which is treated as a neutral skip; a real interop regression fails. |
zephyr.yml |
PR + push, schedule + dispatch | Two jobs sharing the west workspace setup (.github/actions/zephyr-workspace). The qemu_x86 job runs the Zephyr module on qemu_x86: the unit suites, build-only rows for off-default Kconfig combinations, and an EST enrollment gate plus the sample against a host wolfcert-server, including a build of the sample with a custom trust anchor. The mcxn job builds the EST sample for frdm_mcxn947/mcxn947/cpu0 with the SDK's arm-zephyr-eabi toolchain; zephyr/README.md lists what CI covers per board. scripts/ci/twister-assert-ran.py checks that each step's suites actually ran. The slow scep_msg suite runs only on the nightly and on manual dispatch. |
scripts/ci/build-wolfssl.sh is the single source of truth mapping a short
config name to the exact wolfSSL ./configure flags. CI hashes
--print-flags <name> into the cache key, so a cached prefix and a local build
can never disagree.
scripts/ci/build-wolfssl.sh --list # every known config name
scripts/ci/build-wolfssl.sh --print-flags full # the flags for a config
scripts/ci/build-wolfssl.sh full --prefix /tmp/ws # build + install to /tmp/wsConfig names include full (all algorithms), full-tsan, full-opensslextra
(the old canonical line with --enable-opensslextra, kept verbatim so existing
setups stay covered), full-all (full plus --enable-all, which brings
OPENSSL_ALL and its compatible defaults), est-only-nonrsa (NO_RSA),
rsa-min, ecc-only-est, no-des3, tls13-only, mldsa-{44,65,87}off,
static-mem, no-malloc, and the neg-* configs used by the negative-config
gate.
# 1. Build the wolfSSL config the job uses.
scripts/ci/build-wolfssl.sh full --prefix /tmp/wolfssl
# 2. Build wolfCert against it and run the tests (CMake).
cmake -S . -B build -DWITH_WOLFSSL=/tmp/wolfssl -DWOLFCERT_ENABLE_TESTS=ON
cmake --build build -j
ctest --test-dir build --output-on-failure
# autoconf equivalent
./autogen.sh
PKG_CONFIG_PATH=/tmp/wolfssl/lib/pkgconfig ./configure \
--with-wolfssl=/tmp/wolfssl --enable-tests
make -j && make checkThe negative-config gate asserts wolfCert's configure hard-fails on an
unsupportable wolfSSL. It covers the cases a buildable wolfSSL can express
(no-rsa-scep, no-pkcs7, no-public-asn, no-aes128-scep); wolfSSL
itself refuses to drop AES / SHA-256 / all TLS / all key algorithms, so
wolfCert's compile-time #error guards for those (wolfcert/check_config.h)
are validated at compile time, not by this gate.
scripts/ci/assert-configure-fails.sh # all cases, both build systems
scripts/ci/assert-configure-fails.sh no-rsa-scep # a single caseThe no-posix-arm gate compiles every portable src/*.c for a Cortex-M4
against wolfSSL's headers only, keeping wolfCert runnable on a non-BSD-sockets
stack. Nothing is built or linked, so it needs a wolfSSL checkout rather than a
prefix. Its feature set is scripts/ci/freestanding-user_settings.h; the
script's own header documents the rest.
git clone --depth 1 https://github.com/wolfSSL/wolfssl /tmp/wolfssl-src
scripts/ci/compile-freestanding.sh --wolfssl-src /tmp/wolfssl-srcIts companion is the cmake-no-builtin-transport row: the ARM job proves the
code is header-clean, that row proves the gated build links and passes tests.
The same job then runs scripts/ci/check-config-resolution.sh, which preprocesses
one <wolfcert/est.h> translation unit and one <wolfcert/wolfcert.h> one and
requires the two to resolve the same wolfSSL feature set, since memory.h and
check_config.h reach that config separately. Each case stages an
<wolfssl/options.h> that disagrees with user_settings.h; an absent or
forwarding one would let the two agree for the wrong reason. The cases cover
both provenances - user_settings.h winning under WOLFSSL_USER_SETTINGS, and
options.h winning without it. It uses the host cc and takes seconds.
scripts/ci/check-config-resolution.sh --wolfssl-src /tmp/wolfssl-src
scripts/ci/check-config-resolution.sh --wolfssl-src /tmp/wolfssl-src optionsh-decoy