The socat suite is sleep-bound and slow run serially. Drive it through
parallel-make-check.py as ~6 shards per CPU, 2 running per CPU at once: each
shard runs a round-robin slice of the tests in its own bwrap network
namespace (so parallel shards don't collide on ports) and its own build-dir
copy. The work is almost all waiting, so the oversubscription just overlaps
the waits.
Install bubblewrap so the netns isolation actually happens (without it the
runner silently shares one namespace and the shards collide). Each fresh
netns is IPv4-loopback only, so re-create IPv6 loopback (CAP_NET_ADMIN) for
the ::1 / dual-stack tests, and add non-loopback placeholders (fc00::1,
192.0.2.1) so glibc's AI_ADDRCONFIG still returns both families - without
them socat's getaddrinfo fails on numeric non-loopback addresses, e.g. the
multicast tests. Relax the AppArmor unprivileged-userns restriction so the
bwrap netns + CAP_NET_ADMIN work on ubuntu-24.04.
Support AES-XTS AVX512/VAES
Support AES-GCM AVX512/VAES
Support AES-ECB/CBC/CTR AVX512/VAES/AVX1/AES-NI.
Remove code from aes_asm.S/aes_asm.asm
Add CPU defines for AVX512 and VAES
Updated ASM files with new defines for AVX512.
Added support for printing out the new CPU Id flags in benchmark.
Added new files to Windows projects.
aes.c: Supports ECB/CBC/CTR in assembly. Supports calling AVX512/VAES assembly.
The draft guard skips the job on draft PRs, but the pull_request
trigger used the default types (no ready_for_review), so marking a
draft ready did not re-run the job and it stayed skipped. Add the
standard types, matching the other workflows, so it re-runs when the
PR becomes ready.
With the cache save restricted to master, a cold-cache PR or release
run can no longer restore in the test job what the build job just built
(the per-PR cache scope is gone), so mbedtls/nss were compiled twice.
Upload the build as an artifact on a cache miss and download it in the
test job instead of recompiling, matching the handoff hostap-vm already
uses. master still restores from the shared cache, so it never uses the
artifact.
The v6.4.3_rel version was repeated in the cache path, cache key,
download URL and extract command. Define it once as a workflow-level
env var and reference it everywhere.
GitHub Actions caches are branch-scoped: an entry written by a
pull_request run lives under refs/pull/<N>/merge and is invisible to
other PRs. The haproxy, mbedtls, nss, ntp, threadx and hostap-vm
workflows used combined actions/cache with fixed keys, so every PR
re-saved its own copy of the same dependency, yielding one duplicate
cache entry per PR.
Split each into actions/cache/restore (always) plus actions/cache/save
gated to refs/heads/master, and add a daily schedule so a master run
reseeds the single shared entry that all PRs restore. mbedtls/nss save
in their build job only; the test jobs restore-only.
Disable the setup-msys2 package cache: the action only toggles caching
on/off and cannot save on master while restoring on PRs.
A single stalled apt mirror connection hung the ubuntu-24.04-full /
ubuntu-22.04-full download for ~20 min (they normally finish in a few),
tripping the 20-min job timeout and leaving those tags stale. The per-package
retry() only re-runs on a non-zero exit, so a hang never tripped it.
- apt drops a stalled connection after 30s and retries it
(Acquire::http/https::Timeout, Acquire::Retries).
- each apt-get is wrapped in `timeout` so a wedged process is hard-killed and
retry() re-runs it from scratch.
- raise the build job timeout 20 -> 60 min as a final backstop.
arduino.yml's per-core actions/cache layer stored the installed cores and
toolchains (~/.arduino15) - several GB, dominated by the esp32 and mbed
cores - in the 10 GB Actions cache. For esp32 it was also ineffective: the
disk-cleanup step deletes the esp32 toolchain before actions/cache saves it,
so esp32 re-downloaded every run anyway.
- New arduino-cores-image workflow resolves each of the 9 distinct cores and
publishes a tar of ~/.arduino15 + ~/Arduino/libraries to
ghcr.io/<owner>/wolfssl-ci-arduino:<core>. It runs monthly: esp32, the
fastest-moving core, releases ~monthly and the rest far less often.
- New install-arduino-core composite action restores that bundle offline and
verifies the core is present, falling back to `arduino-cli core install`
when the bundle is unavailable - so nothing breaks until the image is first
published and made public.
- arduino.yml calls the action in place of the inline core install and the
actions/cache step.
This takes the flaky espressif / esp8266.com / pjrc.com downloads off the PR
critical path and frees the Actions cache of the largest binaries it held.
setup-alire@v5 caches the gnat_native+gprbuild toolchain via actions/cache
(key alr[1][2.1.0][...]), holding ~1.26 GiB - 3x the 428 MiB toolchain, one
copy per ref - against the repo's 10 GiB cache cap. On a miss the toolchain
is only a ~17s pull from github.com (alire-project releases), so the cache
saved ~20-30s on a ~6.5min Ada job (dominated by gnatprove). Not worth the
space; install it fresh each run.
Addresses PR review feedback. The kernel-tracking linuxkm bundle treated a
failed --download-only as a warning and still published, so a transient
mirror error could ship a partial bundle. Because the daily job skips
rebuilds while the kernel label matches, such a partial bundle would
persist until the kernel next changes (~monthly), forcing consumers to fall
back to apt the whole time.
The linuxkm set is small and entirely required, so resolve it as one
closure and let a failure fail the job; we push only on success, so the
last good bundle stays in place. The static -full/-minimal bundles keep
their per-package skip-and-warn - they serve many independent consumer
subsets and rebuild weekly, so maximizing coverage is the right trade-off
there.
Extends the ghcr offline-install path to every install-apt-deps consumer
that was still on plain apt, and publishes the bundles they need.
New bundles built by ci-deps-image:
- ubuntu-24.04-embedded: the membrowse ARM cross-toolchain (~0.5 GB), kept
out of -full so it does not bloat the interop workflows' pull.
- ubuntu-24.04-linuxkm: linux-headers-$(uname -r) + the kernel-module build
toolchain. linux-headers tracks the runner's running kernel, so a daily
job rebuilds it only when uname -r changed (recorded as an image label);
a mismatch during a runner-image rollout just falls back to apt.
Consumers now passing ghcr-debs-tag:
- sssd -> ubuntu-24.04-full (its deps added to that list)
- hostap-vm -> ubuntu-22.04-full (its deps added to that list)
- membrowse targets -> ubuntu-24.04-embedded; the two linuxkm targets ->
ubuntu-24.04-linuxkm (new per-target matrix.ghcr_tag)
- linuxkm.yml -> ubuntu-24.04-linuxkm (pinned to ubuntu-24.04 so the
bundle's headers match the runner kernel)
Each consumer still falls back to apt when its bundle is unavailable, so
nothing breaks until ci-deps-image first publishes the new tags.
The ci-cache-offload work added a ghcr .deb bundle path to
install-apt-deps, making the actions/cache apt-archive layer redundant.
Remove it so no apt-deps-* cache entries are produced. Apt packages now
install either offline from the ghcr bundle (when ghcr-debs-tag is set)
or via plain apt-get with the existing retry/backoff.
- Strip the Compute/Restore/Pre-seed/Collect/Save cache steps and the
cache-hit fast path; drop the now-unused 'cache' input.
- Update callers that passed 'cache': membrowse-onboard, membrowse-report
(and the apt_cache matrix key in membrowse-targets.json), and sssd.
The ghcr offline path and the ccache actions/cache usage are untouched.
Rebasing onto master (which migrated JS actions to Node.js 24 runtimes)
left a few action refs that this branch added in new steps still on the
old major versions. Bring them in line with master:
- ccache-setup read-only restore: actions/cache/restore@v4 -> @v5
- smoke-test / os-check ccache save: actions/cache/save@v4 -> @v5
- ci-deps-image checkout: actions/checkout@v4 -> @v5
- os-check.yml linux shard: add a schedule-gated CCACHE_RECACHE=1 step so
the weekday seed reseeds from clean compiles rather than only accumulating
deltas. This shard manages ccache directly (its own restore/save) and so
was not covered by the ccache-setup composite's reseed.
- install-apt-deps: hardcode the ghcr bundle owner to wolfssl. The bundle is
only published under ghcr.io/wolfssl by ci-deps-image, so fork PRs now read
the public upstream image instead of a nonexistent ghcr.io/<fork>/wolfssl-ci-debs.
- ccache-setup: document that the read-only restore key reuses the save
key shape for symmetry and is never an exact hit by design.
Skoll F3 (a packages-subset-of-bundle CI guard) is deferred to a follow-up;
F4 (release-branch ccache saves) is left as the intended seed-on-schedule /
everything-else-reads model.
Tighten three pieces of documentation to match the implementation; no
behaviour change:
- install-apt-deps (ghcr-debs-tag description): the apt mirror is avoided
only on the successful offline path. The offline install is a single
--no-download install of the whole package set, so any miss (bundle
absent/private/incomplete) falls back to the apt path.
- ci-deps-image header: each bundle is every requested package plus the
dependencies not already present on the matching runner image - tied to
that runner, not a portable/self-contained .deb closure.
- ci-deps-image schedule note: a package missing from the bundle fails the
whole offline install (it is not per-package), falling back to the full
apt path.
- ccache-setup: gate the scheduled-reseed step with
`if: github.event_name == 'schedule'` again. The github context IS
available in a composite action's step-level if: (install-apt-deps
already relies on it), so the earlier $GITHUB_EVENT_NAME workaround and
its comment were based on a wrong premise. The real load failure was the
${{ }} expression in the read-only input description, fixed separately.
- smoke-test.yml: include github.event_name in the concurrency group. The
workflow pushes to master/main and now also runs on a weekday schedule;
both share github.ref on the default branch, so under
cancel-in-progress a seed run and a master push could cancel each other.
- install-apt-deps: the ghcr offline-install path now honors the
no-install-recommends input; it was always installing recommends,
diverging from the regular apt path.
- install-apt-deps: correct the ghcr-debs-tag example to a real tag
(ubuntu-24.04-minimal) - ci-deps-image publishes -minimal/-full
variants, not a bare <ver> tag.
- os-check: fix the schedule header comment - macOS runs --build-only on
the weekday cron to seed its ccache (like the linux shards); only
Windows is skipped on schedule.
The 10 GB, LRU-evicted, PR-scoped Actions cache was being thrashed - the
docker simulator buildx layers (~6 GiB), plus per-PR ccache and apt-archive
writes whose keys never hit - which kept evicting the shared ccache, while
the apt mirror timed out often enough to break PR CI. Move the heavy caches
to ghcr (free, separate pool) and make PR runs read-only against the Actions
cache.
apt dependencies from prebuilt ghcr .deb bundles
- ci-deps-image.yml resolves each package list under .github/ci-deps/ into
its .deb closure and publishes ghcr.io/<owner>/wolfssl-ci-debs:<tag> in
two tiers: <ver>-minimal (make-check family) and <ver>-full (interop
superset), for ubuntu-22.04 and 24.04.
- install-apt-deps gains a ghcr-debs-tag input: pull the bundle and install
offline (--no-download) so the apt mirror is never on the PR critical
path. Any failure (bundle missing/not public/incomplete) falls through to
the existing apt path, so it is always safe to set.
sim-test buildx layers to a shared ghcr registry cache
- the 7 docker simulator workflows switch from cache-to: type=gha to
ghcr.io/wolfssl/wolfssl-sim-cache:<scope>. cache-from reads on every run
(anonymous); cache-to writes only on the weekend cron and manual
workflow_dispatch. Per-distinct-image tags and de-duplicated writers keep
parallel matrix jobs from racing on one ref.
ccache: PRs read, the schedule writes
- ccache-setup gains read-only: PR runs restore the shared master-scoped
cache but never upload; schedule/push runs refresh it. Wired across
os-check (linux + macOS), pq-all, smoke-test and the 12 small make-check
workflows.
- parallel-make-check.py gains --build-only (compile every config, skip the
test phase) so weekday-morning seed crons warm the cache PR runs consume.
artifact retention capped at 7 days on the failure-log/result uploads that
previously defaulted to 90.
ONE-TIME SETUP: after their first publish, make the ghcr packages
wolfssl-ci-debs and wolfssl-sim-cache PUBLIC so anonymous pulls work from PR
(including fork) runs; until then everything falls back cleanly.
GitHub Actions now emits "Node.js 20 actions are deprecated" warnings:
actions are forced to Node.js 24 by default starting 2026-06-16, and
Node.js 20 is removed from the runners on 2026-09-16. Update every
JavaScript action referenced by the workflows and the local composite
actions to the lowest release that runs on Node.js 24:
actions/checkout v4 -> v5
actions/checkout (SHA pin) v4.1.7 -> v5
actions/upload-artifact v4 -> v6 (v5 still Node.js 20)
actions/download-artifact v4 -> v7 (v5/v6 still Node.js 20)
actions/cache[/restore|/save] v4 -> v5
actions/setup-python v5 -> v6
actions/github-script v7 -> v8
docker/setup-buildx-action v3 -> v4
docker/build-push-action v5 -> v7 (v6 still Node.js 20)
docker/login-action v3 -> v4
microsoft/setup-msbuild v2 -> v3
open-watcom/setup-watcom v0 -> v1
Actions already running on Node.js 24 (jwlawson/actions-setup-cmake,
shogo82148/actions-setup-perl, msys2/setup-msys2, dorny/paths-filter)
are left unchanged. These bumps are runtime-only; no workflow uses an
input or output removed by the new majors, and v4-format artifacts
remain compatible across the upload v6 / download v7 backends.
wolfSSL's configure enables make's jobserver by default
(AX_AM_JOBSERVER([yes]) -> AM_MAKEFLAGS += -j<nproc+1> in aminclude.am),
and automake passes that explicit -j to every recursive sub-make, where
it overrides the invoking make's job limit. The script's -j therefore
only ever scheduled the outermost recursion hop: --jobs was inert.
Measured on a 4-CPU host with 10 build-only configs oversaturating the
worker pool, the jobserver default is also the better policy: capping
sub-makes via --disable-jobserver and -j2 dropped CPU utilization from
96% to 89% and lengthened the wall time, because configs' serial
phases (configure, link) stopped being backfilled by other configs'
compile jobs. So make is now invoked with no -j at all - parallelism
within a config comes from the configure-default jobserver - and the
misleading knob is gone, including the macOS job's --jobs 3.
The two jobs that manage their ccache cache manually rely on ccache's
XDG default (~/.cache/ccache) matching the actions/cache path. That
holds today, but nothing enforces it: a later change that sets
CCACHE_DIR (e.g. adopting the ccache-setup composite, which uses
~/.ccache) would silently decouple the build's cache from the
saved/restored directory. Pin CCACHE_DIR explicitly to the cached
path so the pairing is visible and cannot drift.
Address the Copilot review:
- parallel-make-check.py: validate "configure" (list of strings) and
cflags/ldflags (strings) so a malformed entry fails the load instead
of exploding a string into per-character configure arguments; print
a single line for passing configs instead of dumping their full
make-check.log into the CI log (failure dumps unchanged; the logs
remain in build-<name>/ for the failure artifacts).
- Makefile.am: use rm -rf for the certs/input/quit setup and distclean
cleanup. A --private-dir run replaces the certs symlink with a
private directory copy that rm -f cannot remove (verified: make
distclean in a build dir with a privatized certs/ now succeeds and
removes it).
- psk.yml, disable-pk-algs.yml: normalize the single-dash tokens
(-disable-rsa, -disable-ecc, -disable-aescbc, -enable-cryptonly)
carried verbatim from the old matrices to the canonical double-dash
form. No coverage change: configure honors single-dash spellings
(verified -disable-rsa sets NO_RSA with no unrecognized-option
warning), so these were always in effect; both touched configs
re-validated end-to-end.
The --cc default stays "ccache gcc": ccache resolves the compiler
through its own masquerade symlinks (verified: no recursion and normal
cache hits with /usr/lib/ccache prepended to PATH), and the explicit
CC= also covers jobs that use ccache without the PATH masquerade.
Replace the one-runner-per-configuration matrices across the
make-check workflow family with a generic pooled runner,
.github/scripts/parallel-make-check.py. Each workflow keeps its
configuration list as JSON next to the invocation; one runner (or a
small fixed set of shards, balanced by measured per-config minutes)
builds every config in its own out-of-tree (VPATH) build directory off
a single checkout/autogen, on a pool of one-per-CPU worker threads,
longest first. Concurrent checks are isolated with bubblewrap network
namespaces, compilations are cached with ccache, the first failure
aborts the rest (fail-fast, with --no-fail-fast to run everything),
and per-config timings plus pool efficiency land in the step summary.
Failure logs upload as artifacts. smoke-test.yml is likewise reworked
into a single pooled job that runs its nine configs on one runner.
Converted workflows (runner jobs per full pass):
os-check.yml 101 -> 8 (92 Ubuntu configs -> 4 shards;
the macOS matrix, the user-settings jobs and
the standalone
macos-apple-native-cert-validation.yml fold
into one macOS runner; Windows unchanged)
pq-all.yml 21 -> 2 shards
disable-pk-algs.yml 15 -> 1
wolfCrypt-Wconversion.yml 11 -> 1
trackmemory.yml 7 -> 1
cryptocb-only.yml 8 -> 1 (incl. the two new SHA512 entries)
multi-compiler.yml 6 -> 1
smallStackSize.yml 6 -> 1
multi-arch.yml 6 -> 1
async.yml 5 -> 1
psk.yml 5 -> 1
no-malloc.yml 3 -> 1
wolfsm.yml 3 -> 1
opensslcoexist.yml 2 -> 1
Measured against current upstream passing runs (job execution time,
queue excluded): ~200 runner jobs / ~374 runner-minutes per full pass
become 23 jobs / ~168 runner-minutes, with more coverage than before.
multi-arch's old matrix combined an "include" list of four
architectures with an "opts" axis; GitHub's include-merge rules made
each arch entry overwrite the previous one, so only the armel
combinations actually ran. The pooled list restores the intended
aarch64/armhf/riscv64 coverage (23 combinations; riscv64 x sp-math is
omitted as invalid - configure rejects sp-math without SP, and
--enable-riscv-asm, unlike --enable-sp-asm, does not bring SP in).
Out-of-tree build fixes this depends on:
- Makefile.am: symlink the read-only test data (certs/, tests/ config
files, sniffer captures and helpers, examples/crypto_policies,
input, quit) into the build tree via a BUILT_SOURCES stamp, removed
again in distclean-local. ChangeToWolfRoot() and the script tests
resolve everything relative to the working directory, so out-of-tree
make check and make distcheck now pass.
- scripts/multi-msg-record.py: locate the client binary from the build
tree working directory rather than the script's source directory.
- configure.ac + wolfssl/include.am: run
support/gen-debug-trace-error-codes.sh from $srcdir; it reads the
error-code headers from the source tree and generates into the build
tree.
- tests/swdev: a WOLFBUILD variable points the sub-make at the build
tree for the configure-generated headers (wolfssl/options.h,
wolfssl/version.h); the in-tree-only guards are dropped.
Portions of PR #10649 are incorporated: the cross-platform
ccache-setup composite action, repository_owner gates on check-headers
and check-source-text, the docs-only paths-ignore on os-check, and the
libspdm timeout bumps.
authorized any responder issued by an ancestor of the target's issuer;
RFC 6960 4.2.2.2 requires direct issuance by the CA identified in the
request.
- Remove CheckOcspResponderChain() and WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK.
- Drop now-unused vp parameter from CheckOcspResponder() and the
OcspRespCheck() helper; cascade through template and non-template
paths.
OCSP test blobs:
- Re-sign resp_server1_cert with intermediate1-ca (CA-direct path).
- Add resp_server1_cert_ancestor_responder for the negative test.
- Embed server1_cert_pem[] in test_ocsp_test_blobs.h so the new test
runs under NO_FILESYSTEM; matching entry added to
create_ocsp_test_blobs.py.
- Regenerate response[] in test_certman.c with intermediate1-ca as
signer; recipe switched from Wireshark export to openssl -respout
+ xxd -i for reproducibility.
- Fix self-XOR in test_wolfSSL_CertManagerCheckOCSPResponse so the
serial byte actually flips (^= 0xFF).
Live OCSP coverage:
- Add ocsp-responder-int1 (delegated responder issued directly by
intermediate1-ca, with id-kp-OCSPSigning EKU) for the
responder->intermediate->root chain.
- scripts/ocsp-stapling.test: intermediate1 responder switched to
ocsp-responder-int1 (delegated path).
- scripts/ocsp-stapling2.test, scripts/ocsp-stapling_tls13multi.test:
intermediate2 and intermediate3 sign their OCSP responses with
their own CA keys (CA-direct path); root block unchanged
(ocsp-responder-cert is still RFC-compliant for root-issued certs).
- .github/workflows/ocsp.yml: server1 OCSP responder switched to
ocsp-responder-int1 to match the cert chain.
- New test_ocsp_ancestor_responder_rejected confirms the
ancestor-issued response is rejected with OCSP_LOOKUP_FAIL.
Forks with Actions enabled would otherwise run the membrowse build matrix on push/workflow_dispatch and report fork builds to the membrowse backend. Guard the jobs in both workflows with github.repository_owner == 'wolfssl' (combined with the existing draft check in the report workflow), matching tls-anvil.yml and coverity-scan-fixes.yml.
Also default the analyze/onboard matrix to '[]' so strategy expansion does not error when load-targets is skipped on forks or draft PRs.