From dd2f9d3ab862a225e9245ec71321b5a838887f29 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 15 Jun 2026 13:04:48 +0000 Subject: [PATCH 1/9] CI: offload ccache/apt/buildx caches off the GitHub Actions cache 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//wolfssl-ci-debs: in two tiers: -minimal (make-check family) and -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:. 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/ccache-setup/action.yml | 21 ++++ .github/actions/install-apt-deps/action.yml | 59 +++++++++- .../ci-deps/packages-ubuntu-22.04-full.txt | 80 +++++++++++++ .../ci-deps/packages-ubuntu-22.04-minimal.txt | 12 ++ .../ci-deps/packages-ubuntu-24.04-full.txt | 94 +++++++++++++++ .../ci-deps/packages-ubuntu-24.04-minimal.txt | 20 ++++ .github/scripts/parallel-make-check.py | 13 ++ .github/workflows/ada.yml | 1 + .github/workflows/async.yml | 9 ++ .github/workflows/atecc608-sim.yml | 17 ++- .github/workflows/bind.yml | 1 + .github/workflows/check-headers.yml | 1 + .github/workflows/check-source-text.yml | 1 + .github/workflows/ci-deps-image.yml | 111 ++++++++++++++++++ .github/workflows/cmake-autoconf.yml | 1 + .github/workflows/cmake.yml | 1 + .github/workflows/cryptocb-only.yml | 9 ++ .github/workflows/curl.yml | 1 + .github/workflows/cyrus-sasl.yml | 1 + .github/workflows/disable-pk-algs.yml | 9 ++ .github/workflows/docker-OpenWrt.yml | 16 ++- .github/workflows/emnet-nonblock.yml | 1 + .github/workflows/grpc.yml | 1 + .github/workflows/haproxy.yml | 1 + .github/workflows/ipmitool.yml | 1 + .github/workflows/jwt-cpp.yml | 1 + .github/workflows/memcached.yml | 1 + .github/workflows/mono.yml | 1 + .github/workflows/mosquitto.yml | 1 + .github/workflows/msmtp.yml | 1 + .github/workflows/multi-arch.yml | 9 ++ .github/workflows/multi-compiler.yml | 9 ++ .github/workflows/no-malloc.yml | 9 ++ .github/workflows/nss.yml | 2 + .github/workflows/opensslcoexist.yml | 9 ++ .github/workflows/openvpn.yml | 1 + .github/workflows/os-check.yml | 34 +++++- .github/workflows/pam-ipmi.yml | 1 + .github/workflows/pic32mz-sim.yml | 19 ++- .github/workflows/pq-all.yml | 11 ++ .github/workflows/psk.yml | 9 ++ .github/workflows/python.yml | 1 + .github/workflows/rng-tools.yml | 1 + .github/workflows/se050-sim.yml | 17 ++- .github/workflows/smallStackSize.yml | 9 ++ .github/workflows/smoke-test.yml | 23 +++- .github/workflows/socat.yml | 1 + .github/workflows/softhsm.yml | 1 + .github/workflows/stm32-sim.yml | 20 +++- .github/workflows/stsafe-a120-sim.yml | 17 ++- .github/workflows/tls-anvil.yml | 1 + .github/workflows/trackmemory.yml | 9 ++ .github/workflows/tropic01-sim.yml | 17 ++- .github/workflows/watcomc.yml | 1 + .github/workflows/wolfCrypt-Wconversion.yml | 9 ++ .github/workflows/wolfboot-integration.yml | 3 + .github/workflows/wolfsm.yml | 9 ++ .github/workflows/zephyr.yml | 1 + 58 files changed, 716 insertions(+), 24 deletions(-) create mode 100644 .github/ci-deps/packages-ubuntu-22.04-full.txt create mode 100644 .github/ci-deps/packages-ubuntu-22.04-minimal.txt create mode 100644 .github/ci-deps/packages-ubuntu-24.04-full.txt create mode 100644 .github/ci-deps/packages-ubuntu-24.04-minimal.txt create mode 100644 .github/workflows/ci-deps-image.yml diff --git a/.github/actions/ccache-setup/action.yml b/.github/actions/ccache-setup/action.yml index b15401a27c0..d4d0c1f2b06 100644 --- a/.github/actions/ccache-setup/action.yml +++ b/.github/actions/ccache-setup/action.yml @@ -21,6 +21,14 @@ inputs: description: 'Per-job ccache max size (passed to ccache -M).' required: false default: '500M' + read-only: + description: > + When 'true', restore the cache but do NOT save it (no post-job + upload). Pass `${{ github.event_name == 'pull_request' }}` so PR runs + consume the shared cache read-only - no per-PR entries, no churn - + while scheduled/push runs (read-only false) refresh it. + required: false + default: 'false' runs: using: 'composite' @@ -41,7 +49,10 @@ runs: exit 1 fi + # read-only=false (default): restore + post-job save (the run_id in the + # key never hits, so it always saves its contribution). - name: Restore + save ccache + if: inputs.read-only != 'true' uses: actions/cache@v5 with: path: ~/.ccache @@ -52,6 +63,16 @@ runs: restore-keys: | ccache-${{ inputs.workflow-id }}-${{ runner.os }}-${{ runner.arch }}-${{ inputs.config-hash }}- ccache-${{ inputs.workflow-id }}-${{ runner.os }}-${{ runner.arch }}- + # read-only=true: restore the shared cache but never upload (PR runs). + - name: Restore ccache (read-only) + if: inputs.read-only == 'true' + uses: actions/cache/restore@v4 + with: + path: ~/.ccache + key: ccache-${{ inputs.workflow-id }}-${{ runner.os }}-${{ runner.arch }}-${{ inputs.config-hash }}-${{ github.run_id }}-${{ github.run_attempt }} + restore-keys: | + ccache-${{ inputs.workflow-id }}-${{ runner.os }}-${{ runner.arch }}-${{ inputs.config-hash }}- + ccache-${{ inputs.workflow-id }}-${{ runner.os }}-${{ runner.arch }}- - name: Configure ccache and PATH shell: bash diff --git a/.github/actions/install-apt-deps/action.yml b/.github/actions/install-apt-deps/action.yml index 2a34922b8fb..0f7bce22e13 100644 --- a/.github/actions/install-apt-deps/action.yml +++ b/.github/actions/install-apt-deps/action.yml @@ -20,11 +20,56 @@ inputs: description: 'Cache apt archives (disable for dynamic package names)' required: false default: 'true' + ghcr-debs-tag: + description: > + Tag of a prebuilt .deb bundle published to + ghcr.io//wolfssl-ci-debs by the ci-deps-image workflow + (e.g. "ubuntu-24.04"). When set, the packages are installed offline + from that bundle - the apt mirror is never contacted - and the apt + cache path below is skipped entirely. Any failure (bundle missing, + not public, or missing a package) falls through to the apt path, so + this is always safe to set. Leave empty to use apt only. + required: false + default: '' runs: using: 'composite' steps: + # Preferred path: install from a prebuilt .deb bundle pulled from ghcr, + # entirely offline (--no-download), so a flaky/timing-out apt mirror + # cannot break the build. Best-effort: on any failure we leave + # "satisfied" unset and the apt steps below run unchanged. The bundle + # image must be PUBLIC so anonymous `docker pull` works (including from + # fork PRs whose GITHUB_TOKEN cannot read private packages). + - name: Install from ghcr .deb bundle (offline) + id: ghcr + if: inputs.ghcr-debs-tag != '' + shell: bash + run: | + set -u + command -v docker >/dev/null 2>&1 || { echo "::notice::docker unavailable; using apt"; exit 0; } + OWNER=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') + IMG="ghcr.io/$OWNER/wolfssl-ci-debs:${{ inputs.ghcr-debs-tag }}" + if ! docker pull -q "$IMG" >/dev/null 2>&1; then + echo "::notice::ghcr bundle $IMG unavailable; using apt" + exit 0 + fi + cid=$(docker create "$IMG" 2>/dev/null) || { echo "::notice::cannot open bundle; using apt"; exit 0; } + rm -rf "$RUNNER_TEMP/ghcr-debs"; mkdir -p "$RUNNER_TEMP/ghcr-debs" + docker cp "$cid:/debs/." "$RUNNER_TEMP/ghcr-debs/" >/dev/null 2>&1 || true + docker rm "$cid" >/dev/null 2>&1 || true + ls "$RUNNER_TEMP"/ghcr-debs/*.deb >/dev/null 2>&1 || { echo "::notice::bundle had no .debs; using apt"; exit 0; } + sudo cp "$RUNNER_TEMP"/ghcr-debs/*.deb /var/cache/apt/archives/ + # --no-download forbids any network fetch: if the bundle is missing + # a package this fails cleanly (nothing installed) and we fall back. + if sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-download ${{ inputs.packages }}; then + echo "satisfied=true" >> "$GITHUB_OUTPUT" + echo "Installed offline from $IMG: ${{ inputs.packages }}" + else + echo "::notice::offline install incomplete for $IMG; using apt" + fi + - name: Compute cache key - if: inputs.cache == 'true' + if: inputs.cache == 'true' && steps.ghcr.outputs.satisfied != 'true' id: cache-key shell: bash run: | @@ -35,7 +80,7 @@ runs: echo "restore-key=apt-deps-${{ runner.os }}-${{ runner.arch }}-${OS_VERSION}-" >> $GITHUB_OUTPUT - name: Restore apt cache - if: inputs.cache == 'true' + if: inputs.cache == 'true' && steps.ghcr.outputs.satisfied != 'true' id: apt-cache uses: actions/cache/restore@v5 with: @@ -44,7 +89,7 @@ runs: restore-keys: ${{ steps.cache-key.outputs.restore-key }} - name: Pre-seed apt archives from cache - if: inputs.cache == 'true' && steps.apt-cache.outputs.cache-hit == 'true' + if: inputs.cache == 'true' && steps.apt-cache.outputs.cache-hit == 'true' && steps.ghcr.outputs.satisfied != 'true' shell: bash run: | if [ -d ~/apt-cache ] && ls ~/apt-cache/*.deb >/dev/null 2>&1; then @@ -53,6 +98,7 @@ runs: fi - name: Install packages + if: steps.ghcr.outputs.satisfied != 'true' shell: bash env: APT_CACHE_HIT: ${{ steps.apt-cache.outputs.cache-hit }} @@ -90,8 +136,11 @@ runs: DELAY=$((DELAY * 2)) done + # PR runs never write the apt cache (no churn); only push/schedule runs + # refresh it. The make-check family does not need it anyway - it installs + # from the ghcr bundle above. - name: Collect .deb files for cache - if: inputs.cache == 'true' && steps.apt-cache.outputs.cache-hit != 'true' + if: inputs.cache == 'true' && github.event_name != 'pull_request' && steps.apt-cache.outputs.cache-hit != 'true' && steps.ghcr.outputs.satisfied != 'true' shell: bash run: | mkdir -p ~/apt-cache @@ -99,7 +148,7 @@ runs: echo "Cached $(ls ~/apt-cache/*.deb 2>/dev/null | wc -l) .deb files" - name: Save apt cache - if: inputs.cache == 'true' && steps.apt-cache.outputs.cache-hit != 'true' + if: inputs.cache == 'true' && github.event_name != 'pull_request' && steps.apt-cache.outputs.cache-hit != 'true' && steps.ghcr.outputs.satisfied != 'true' uses: actions/cache/save@v5 with: path: ~/apt-cache diff --git a/.github/ci-deps/packages-ubuntu-22.04-full.txt b/.github/ci-deps/packages-ubuntu-22.04-full.txt new file mode 100644 index 00000000000..f809efaeb4c --- /dev/null +++ b/.github/ci-deps/packages-ubuntu-22.04-full.txt @@ -0,0 +1,80 @@ +# make-check family + interop apt packages for ubuntu-22.04 (the '-full' +# bundle: ghcr.io//wolfssl-ci-debs:ubuntu-22.04-full). Superset of +# -minimal; interop workflows install their subset offline from it. +# Keep sorted; add a package when an interop workflow adds one. +autoconf +automake +bison +bridge-utils +build-essential +ca-certificates +cargo +ccache +chrpath +cmake +cpio +crossbuild-essential-arm64 +crossbuild-essential-armel +crossbuild-essential-armhf +crossbuild-essential-riscv64 +device-tree-compiler +dfu-util +diffstat +dos2unix +doxygen +file +flex +g++ +g++-multilib +gawk +gcc +gcc-multilib +gcovr +git +git-core +gnupg +gperf +gtk-sharp3 +help2man +iproute2 +lcov +libcairo2-dev +libglib2.0-dev +libgtk2.0-0 +liblocale-gettext-perl +libmagic1 +libncurses5-dev +libpcap-dev +libpopt0 +libsdl1.2-dev +libsdl2-dev +libssl-dev +libtool +libtool-bin +locales +make +net-tools +ninja-build +openssh-client +ovmf +parallel +pkg-config +python-is-python3 +python3-dev +python3-pip +python3-ply +python3-setuptools +python3-tk +python3-wheel +qemu-kvm +qemu-user +rsync +socat +srecord +sudo +texinfo +uml-utilities +unzip +wget +xz-utils +zip diff --git a/.github/ci-deps/packages-ubuntu-22.04-minimal.txt b/.github/ci-deps/packages-ubuntu-22.04-minimal.txt new file mode 100644 index 00000000000..c32e3ccb9cf --- /dev/null +++ b/.github/ci-deps/packages-ubuntu-22.04-minimal.txt @@ -0,0 +1,12 @@ +# make-check family apt packages for ubuntu-22.04 (the '-minimal' +# bundle: ghcr.io//wolfssl-ci-debs:ubuntu-22.04-minimal). UNION of +# every family workflow's list; superset is fine. Keep sorted. +autoconf +automake +build-essential +crossbuild-essential-arm64 +crossbuild-essential-armel +crossbuild-essential-armhf +crossbuild-essential-riscv64 +libtool +qemu-user diff --git a/.github/ci-deps/packages-ubuntu-24.04-full.txt b/.github/ci-deps/packages-ubuntu-24.04-full.txt new file mode 100644 index 00000000000..9872201d641 --- /dev/null +++ b/.github/ci-deps/packages-ubuntu-24.04-full.txt @@ -0,0 +1,94 @@ +# make-check family + interop apt packages for ubuntu-24.04 (the '-full' +# bundle: ghcr.io//wolfssl-ci-debs:ubuntu-24.04-full). Superset of +# -minimal; interop workflows install their subset offline from it. +# Keep sorted; add a package when an interop workflow adds one. +apache2 +apache2-dev +autoconf +autoconf-archive +automake +autopoint +bubblewrap +build-essential +ccache +clang +clang-14 +clang-19 +cmake +g++-10 +g++-11 +g++-12 +g++-9 +gcc-10 +gcc-11 +gcc-12 +gcc-9 +gcc-multilib +gettext +gyp +jq +krb5-admin-server +krb5-kdc +krb5-otp +libbz2-dev +libc++-dev +libcap-dev +libcap-ng-dev +libcmocka-dev +libcppunit-dev +libcunit1 +libcunit1-dev +libcunit1-doc +libcurl4-openssl-dev +libdb5.3-dev +libev-dev +libevent-2.1-7 +libevent-dev +libffi-dev +libgdbm-dev +libgtest-dev +libidn2-dev +libio-socket-ssl-perl +libjansson-dev +libkrb5-dev +liblz4-dev +liblzma-dev +liblzo2-dev +libncursesw5-dev +libnghttp2-dev +libnl-genl-3-200 +libnl-genl-3-dev +libnss-wrapper +libnss3-dev +libp11-dev +libpam-dev +libpam0g-dev +libpcre2-dev +libpsl-dev +libpsl5 +libreadline-dev +librtlsdr-dev +libsecret-1-dev +libsocket-wrapper +libsqlite3-dev +libssl-dev +libtool +liburcu-dev +libuv1-dev +linux-libc-dev +make +man2html +meson +mono-complete +nghttp2 +ninja-build +pkg-config +pkgconf +psmisc +python3-docutils +python3-impacket +python3-psutil +shellcheck +uuid-dev +valgrind +zlib1g-dev diff --git a/.github/ci-deps/packages-ubuntu-24.04-minimal.txt b/.github/ci-deps/packages-ubuntu-24.04-minimal.txt new file mode 100644 index 00000000000..1cd40c6fc95 --- /dev/null +++ b/.github/ci-deps/packages-ubuntu-24.04-minimal.txt @@ -0,0 +1,20 @@ +# make-check family apt packages for ubuntu-24.04 (the '-minimal' +# bundle: ghcr.io//wolfssl-ci-debs:ubuntu-24.04-minimal). UNION of +# every family workflow's list; superset is fine. Keep sorted. +autoconf +automake +bubblewrap +build-essential +ccache +clang-14 +clang-19 +g++-10 +g++-11 +g++-12 +g++-9 +gcc-10 +gcc-11 +gcc-12 +gcc-9 +gcc-multilib +libtool diff --git a/.github/scripts/parallel-make-check.py b/.github/scripts/parallel-make-check.py index 299fa464169..fc86c2be5db 100755 --- a/.github/scripts/parallel-make-check.py +++ b/.github/scripts/parallel-make-check.py @@ -468,9 +468,22 @@ def main() -> int: help="give each build dir a private copy of this " "symlinked source directory before make check, for " "tests that write into it (repeatable)") + p.add_argument("--build-only", action="store_true", + help="build every config but skip the make-check phase " + "and any post-build \"run\" commands: the compile " + "still populates ccache, which is the point when " + "seeding a shared cache on a schedule") opts = p.parse_args() all_configs = load_configs(opts, p.error) + if opts.build_only: + # Pure build: drop the check phase (and post-build "run" steps) for + # every config. The compile alone fully populates ccache, so a + # scheduled --build-only pass on the default branch warms the + # shared cache that PR runs restore, without spending time on tests. + for cfg in all_configs: + cfg.check = False + cfg.run = [] selected = all_configs if opts.configs: by_name = {cfg.name: cfg for cfg in all_configs} diff --git a/.github/workflows/ada.yml b/.github/workflows/ada.yml index 19a0fdc3cdc..ae6fc8d09c1 100644 --- a/.github/workflows/ada.yml +++ b/.github/workflows/ada.yml @@ -61,6 +61,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: valgrind + ghcr-debs-tag: ubuntu-24.04-full - name: Run Ada wrapper tests (valgrind) working-directory: ./wrapper/Ada/tests diff --git a/.github/workflows/async.yml b/.github/workflows/async.yml index 3aa3509e76f..b2c2a97e721 100644 --- a/.github/workflows/async.yml +++ b/.github/workflows/async.yml @@ -7,6 +7,11 @@ on: pull_request: types: [opened, synchronize, reopened, ready_for_review] branches: [ '*' ] + # Weekday-morning cron (10:00 UTC) seeds the master-scoped ccache that PR runs + # restore: re-runs --build-only (compile only, no tests) on the + # default branch. PR runs are read-only (see ccache-setup). + schedule: + - cron: '8 10 * * 1-5' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -35,6 +40,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: autoconf automake libtool build-essential bubblewrap + ghcr-debs-tag: ubuntu-24.04-minimal # ccache via the cross-platform composite; the script passes the # compiler to configure as CC="ccache gcc" (or a per-config "cc"). @@ -42,6 +48,7 @@ jobs: uses: ./.github/actions/ccache-setup with: workflow-id: async + read-only: ${{ github.event_name == 'pull_request' }} max-size: 250M # Ubuntu 24.04 can restrict unprivileged user namespaces via AppArmor, @@ -83,6 +90,7 @@ jobs: ] EOF .github/scripts/parallel-make-check.py \ + ${{ github.event_name == 'schedule' && '--build-only' || '' }} \ --private-dir=certs \ "$RUNNER_TEMP/async-configs.json" @@ -94,6 +102,7 @@ jobs: if: failure() uses: actions/upload-artifact@v6 with: + retention-days: 7 name: async-logs path: | build-*/make-check.log diff --git a/.github/workflows/atecc608-sim.yml b/.github/workflows/atecc608-sim.yml index 6a828c77b72..5055b15b709 100644 --- a/.github/workflows/atecc608-sim.yml +++ b/.github/workflows/atecc608-sim.yml @@ -7,12 +7,21 @@ on: pull_request: types: [opened, synchronize, reopened, ready_for_review] branches: [ '*' ] + # Weekend cron and manual workflow_dispatch refresh the shared ghcr build + # cache that PR runs read (cache-to below is gated to those two events). + schedule: + - cron: '0 6 * * 6' + workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true # END OF COMMON SECTION +permissions: + contents: read + packages: write + # Build the ATECC608 software simulator (https://github.com/wolfSSL/simulators, # ATECC608Sim/ subdirectory), build wolfSSL against cryptoauthlib + the # simulator's TCP HAL, and run the wolfCrypt ATECC608 test binary against the @@ -76,6 +85,10 @@ jobs: - uses: docker/setup-buildx-action@v4 + - name: Log in to ghcr (cache refresh on cron/manual dispatch) + if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin + - name: Build wolfCrypt-ATECC608 test image uses: docker/build-push-action@v7 with: @@ -84,8 +97,8 @@ jobs: push: false load: true tags: wolfssl-atecc608-sim:ci - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: type=registry,ref=ghcr.io/wolfssl/wolfssl-sim-cache:atecc608 + cache-to: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && 'type=registry,ref=ghcr.io/wolfssl/wolfssl-sim-cache:atecc608,mode=max' || '' }} - name: Run wolfCrypt tests against simulator run: docker run --rm wolfssl-atecc608-sim:ci diff --git a/.github/workflows/bind.yml b/.github/workflows/bind.yml index 9b6184f841f..b9cb22772ce 100644 --- a/.github/workflows/bind.yml +++ b/.github/workflows/bind.yml @@ -71,6 +71,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: libuv1-dev libnghttp2-dev libcap-dev libcmocka-dev liburcu-dev + ghcr-debs-tag: ubuntu-24.04-full - name: Checkout OSP uses: actions/checkout@v5 diff --git a/.github/workflows/check-headers.yml b/.github/workflows/check-headers.yml index 1f7bee9f365..35d35d4597f 100644 --- a/.github/workflows/check-headers.yml +++ b/.github/workflows/check-headers.yml @@ -34,6 +34,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: autoconf automake libtool build-essential + ghcr-debs-tag: ubuntu-24.04-minimal - name: autogen run: ./autogen.sh diff --git a/.github/workflows/check-source-text.yml b/.github/workflows/check-source-text.yml index 9f2b57f5510..0e10d8bd7c9 100644 --- a/.github/workflows/check-source-text.yml +++ b/.github/workflows/check-source-text.yml @@ -41,6 +41,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: shellcheck + ghcr-debs-tag: ubuntu-24.04-full - name: Collect files to check id: files diff --git a/.github/workflows/ci-deps-image.yml b/.github/workflows/ci-deps-image.yml new file mode 100644 index 00000000000..ff8ac38a562 --- /dev/null +++ b/.github/workflows/ci-deps-image.yml @@ -0,0 +1,111 @@ +name: CI deps image + +# Builds the prebuilt apt .deb bundles that the make-check family (the +# -minimal tags) and the interop workflows (the -full tags, a superset) +# install offline (see .github/actions/install-apt-deps, input +# ghcr-debs-tag). Each bundle is the .deb closure of a package list in +# .github/ci-deps/, published to ghcr.io//wolfssl-ci-debs:. +# +# Why: the apt mirror times out often enough to break PR CI. Resolving the +# closure ONCE here (on master, where a slow mirror only delays this job and +# is retried hard) and pulling it from ghcr on every PR keeps apt off the PR +# critical path entirely. ghcr storage/bandwidth is free for public images +# and is a separate pool from the 10 GB Actions cache. +# +# ONE-TIME SETUP: after the first successful run, make the package +# `wolfssl-ci-debs` PUBLIC (repo/org > Packages > Package settings > +# Change visibility). Anonymous `docker pull` then works from fork PRs too; +# until then install-apt-deps simply falls back to apt (no breakage). + +on: + schedule: + # Weekend only - refresh the bundles weekly so they track base-image + # security updates. A mid-week package-list change waits for Saturday + # (or run this manually via workflow_dispatch); until then install-apt-deps + # falls back to apt for any package not yet in the bundle. + - cron: '0 2 * * 6' + workflow_dispatch: + +concurrency: + group: ci-deps-image-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + packages: write + +jobs: + build: + name: build ${{ matrix.tag }} + if: github.repository_owner == 'wolfssl' + strategy: + fail-fast: false + matrix: + include: + # The .debs must be downloaded on the same Ubuntu version that + # consumes them, so the runner matches the tag. -minimal is the + # make-check family's packages (small, pulled on every PR); + # -full adds the interop workflows' packages (a superset). + - runner: ubuntu-24.04 + tag: ubuntu-24.04-minimal + - runner: ubuntu-24.04 + tag: ubuntu-24.04-full + - runner: ubuntu-22.04 + tag: ubuntu-22.04-minimal + - runner: ubuntu-22.04 + tag: ubuntu-22.04-full + runs-on: ${{ matrix.runner }} + timeout-minutes: 20 + steps: + - uses: actions/checkout@v4 + + - name: Resolve and download the .deb closure + shell: bash + run: | + set -euo pipefail + LIST=".github/ci-deps/packages-${{ matrix.tag }}.txt" + mapfile -t PKGS < <(grep -vE '^[[:space:]]*#|^[[:space:]]*$' "$LIST") + echo "Packages (${#PKGS[@]}): ${PKGS[*]}" + export DEBIAN_FRONTEND=noninteractive + rm -rf debs && mkdir -p debs + sudo apt-get clean + # Retry the flaky bits; this is the one place we accept apt risk. + retry() { local i; for i in 1 2 3 4 5; do "$@" && return 0; sleep $((2**i)); done; "$@"; } + retry sudo apt-get update -q + # Download each package's closure independently (requested package + + # any dependency not already installed) without installing. Per + # package, not one resolve of the whole list, so one unbundleable + # package - e.g. a conflict in the big -full union - cannot abort the + # rest; install-apt-deps falls back to apt for anything missing. + skipped=0 + for pkg in "${PKGS[@]}"; do + retry sudo apt-get install -y --download-only "$pkg" \ + || { echo "::warning::could not download $pkg"; skipped=$((skipped+1)); } + done + sudo cp /var/cache/apt/archives/*.deb debs/ 2>/dev/null || true + echo "Bundled $(ls debs/*.deb 2>/dev/null | wc -l) .deb files ($(du -sh debs | cut -f1)); ${skipped} skipped" + test -n "$(ls debs/*.deb 2>/dev/null)" # fail if nothing was bundled + + - name: Build bundle image + shell: bash + run: | + # Tiny busybox base so the consumer can `docker create`/`docker cp` + # the .debs out; the base size is negligible next to the .debs. + printf 'FROM busybox\nCOPY debs /debs\n' > Dockerfile.debs + docker build -f Dockerfile.debs -t bundle . + + - name: Log in to ghcr + shell: bash + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin + + - name: Push to ghcr + shell: bash + run: | + set -euo pipefail + OWNER=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') + IMG="ghcr.io/$OWNER/wolfssl-ci-debs" + # One mutable tag per bundle variant; each run overwrites it, so the + # package keeps exactly one version per variant (no dated duplicates). + docker tag bundle "$IMG:${{ matrix.tag }}" + docker push "$IMG:${{ matrix.tag }}" + echo "Pushed $IMG:${{ matrix.tag }}" diff --git a/.github/workflows/cmake-autoconf.yml b/.github/workflows/cmake-autoconf.yml index d52c189f9f2..9d4c076e974 100644 --- a/.github/workflows/cmake-autoconf.yml +++ b/.github/workflows/cmake-autoconf.yml @@ -20,6 +20,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: cmake autoconf automake libtool + ghcr-debs-tag: ubuntu-24.04-full # build and install wolfssl via autotools for CMake consumer test - name: Build wolfssl with autotools diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 91368047dca..354f8d9e024 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -20,6 +20,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: cmake + ghcr-debs-tag: ubuntu-24.04-full # build wolfssl - name: Build wolfssl diff --git a/.github/workflows/cryptocb-only.yml b/.github/workflows/cryptocb-only.yml index 35091fe8cd4..9b5c89591b5 100644 --- a/.github/workflows/cryptocb-only.yml +++ b/.github/workflows/cryptocb-only.yml @@ -7,6 +7,11 @@ on: pull_request: types: [opened, synchronize, reopened, ready_for_review] branches: [ '*' ] + # Weekday-morning cron (10:00 UTC) seeds the master-scoped ccache that PR runs + # restore: re-runs --build-only (compile only, no tests) on the + # default branch. PR runs are read-only (see ccache-setup). + schedule: + - cron: '12 10 * * 1-5' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -35,6 +40,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: autoconf automake libtool build-essential bubblewrap + ghcr-debs-tag: ubuntu-24.04-minimal # ccache via the cross-platform composite; the script passes the # compiler to configure as CC="ccache gcc" (or a per-config "cc"). @@ -42,6 +48,7 @@ jobs: uses: ./.github/actions/ccache-setup with: workflow-id: cryptocb-only + read-only: ${{ github.event_name == 'pull_request' }} max-size: 200M # Ubuntu 24.04 can restrict unprivileged user namespaces via AppArmor, @@ -216,6 +223,7 @@ jobs: ] EOF .github/scripts/parallel-make-check.py \ + ${{ github.event_name == 'schedule' && '--build-only' || '' }} \ --private-dir=certs \ "$RUNNER_TEMP/cryptocb-only-configs.json" @@ -227,6 +235,7 @@ jobs: if: failure() uses: actions/upload-artifact@v6 with: + retention-days: 7 name: cryptocb-only-logs path: | build-*/make-check.log diff --git a/.github/workflows/curl.yml b/.github/workflows/curl.yml index 96b50e8766e..2bae21ff5be 100644 --- a/.github/workflows/curl.yml +++ b/.github/workflows/curl.yml @@ -60,6 +60,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: nghttp2 libpsl5 libpsl-dev python3-impacket apache2 apache2-dev + ghcr-debs-tag: ubuntu-24.04-full - name: Download lib uses: actions/download-artifact@v7 diff --git a/.github/workflows/cyrus-sasl.yml b/.github/workflows/cyrus-sasl.yml index d5c631478eb..a05bab33615 100644 --- a/.github/workflows/cyrus-sasl.yml +++ b/.github/workflows/cyrus-sasl.yml @@ -64,6 +64,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: krb5-kdc krb5-otp libkrb5-dev libsocket-wrapper libnss-wrapper krb5-admin-server libdb5.3-dev + ghcr-debs-tag: ubuntu-24.04-full - name: Download lib uses: actions/download-artifact@v7 diff --git a/.github/workflows/disable-pk-algs.yml b/.github/workflows/disable-pk-algs.yml index 2e20ba47185..006f6811748 100644 --- a/.github/workflows/disable-pk-algs.yml +++ b/.github/workflows/disable-pk-algs.yml @@ -7,6 +7,11 @@ on: pull_request: types: [opened, synchronize, reopened, ready_for_review] branches: [ '*' ] + # Weekday-morning cron (10:00 UTC) seeds the master-scoped ccache that PR runs + # restore: re-runs --build-only (compile only, no tests) on the + # default branch. PR runs are read-only (see ccache-setup). + schedule: + - cron: '16 10 * * 1-5' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -35,6 +40,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: autoconf automake libtool build-essential bubblewrap + ghcr-debs-tag: ubuntu-24.04-minimal # ccache via the cross-platform composite; the script passes the # compiler to configure as CC="ccache gcc" (or a per-config "cc"). @@ -42,6 +48,7 @@ jobs: uses: ./.github/actions/ccache-setup with: workflow-id: disable-pk-algs + read-only: ${{ github.event_name == 'pull_request' }} max-size: 150M # Ubuntu 24.04 can restrict unprivileged user namespaces via AppArmor, @@ -124,6 +131,7 @@ jobs: ] EOF .github/scripts/parallel-make-check.py \ + ${{ github.event_name == 'schedule' && '--build-only' || '' }} \ --private-dir=certs \ "$RUNNER_TEMP/disable-pk-algs-configs.json" @@ -135,6 +143,7 @@ jobs: if: failure() uses: actions/upload-artifact@v6 with: + retention-days: 7 name: disable-pk-algs-logs path: | build-*/make-check.log diff --git a/.github/workflows/docker-OpenWrt.yml b/.github/workflows/docker-OpenWrt.yml index 5a0526c762c..7357b0ce392 100644 --- a/.github/workflows/docker-OpenWrt.yml +++ b/.github/workflows/docker-OpenWrt.yml @@ -9,12 +9,21 @@ on: pull_request: types: [opened, synchronize, reopened, ready_for_review] branches: [ '*' ] + # Weekend cron and manual workflow_dispatch refresh the shared ghcr build + # cache that PR runs read (cache-to below is gated to those two events). + schedule: + - cron: '30 7 * * 6' + workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true # END OF COMMON SECTION +permissions: + contents: read + packages: write + jobs: build_library: name: Compile libwolfssl.so @@ -54,6 +63,9 @@ jobs: steps: - uses: actions/checkout@v5 - uses: docker/setup-buildx-action@v4 + - name: Log in to ghcr (cache refresh on cron/manual dispatch) + if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin - uses: actions/download-artifact@v7 with: name: openwrt-libwolfssl.so @@ -68,5 +80,5 @@ jobs: push: false tags: openwrt-test:latest build-args: DOCKER_BASE_CONTAINER=openwrt/rootfs:x86-64-${{ matrix.release }} - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: type=registry,ref=ghcr.io/wolfssl/wolfssl-sim-cache:openwrt-${{ matrix.release }} + cache-to: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && format('type=registry,ref=ghcr.io/wolfssl/wolfssl-sim-cache:openwrt-{0},mode=max', matrix.release) || '' }} diff --git a/.github/workflows/emnet-nonblock.yml b/.github/workflows/emnet-nonblock.yml index a2e57cac849..893379639c6 100644 --- a/.github/workflows/emnet-nonblock.yml +++ b/.github/workflows/emnet-nonblock.yml @@ -34,6 +34,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: autoconf automake libtool build-essential + ghcr-debs-tag: ubuntu-24.04-minimal - name: Bootstrap run: ./autogen.sh diff --git a/.github/workflows/grpc.yml b/.github/workflows/grpc.yml index f950cbd3ac9..7095a2970d2 100644 --- a/.github/workflows/grpc.yml +++ b/.github/workflows/grpc.yml @@ -73,6 +73,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: build-essential autoconf libtool pkg-config cmake clang libc++-dev + ghcr-debs-tag: ubuntu-24.04-full - name: Download lib uses: actions/download-artifact@v7 diff --git a/.github/workflows/haproxy.yml b/.github/workflows/haproxy.yml index c09fdce89c1..61409b4d8ad 100644 --- a/.github/workflows/haproxy.yml +++ b/.github/workflows/haproxy.yml @@ -60,6 +60,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: libpcre2-dev + ghcr-debs-tag: ubuntu-24.04-full - name: Download lib uses: actions/download-artifact@v7 diff --git a/.github/workflows/ipmitool.yml b/.github/workflows/ipmitool.yml index db3eae670a7..4f11da7787c 100644 --- a/.github/workflows/ipmitool.yml +++ b/.github/workflows/ipmitool.yml @@ -61,6 +61,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: libreadline-dev + ghcr-debs-tag: ubuntu-24.04-full - name: Download lib uses: actions/download-artifact@v7 with: diff --git a/.github/workflows/jwt-cpp.yml b/.github/workflows/jwt-cpp.yml index 05b45e88bf3..cd4d6ffa60e 100644 --- a/.github/workflows/jwt-cpp.yml +++ b/.github/workflows/jwt-cpp.yml @@ -65,6 +65,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: libgtest-dev + ghcr-debs-tag: ubuntu-24.04-full - name: Download lib uses: actions/download-artifact@v7 diff --git a/.github/workflows/memcached.yml b/.github/workflows/memcached.yml index f2f36186f25..7bd9b5b4e30 100644 --- a/.github/workflows/memcached.yml +++ b/.github/workflows/memcached.yml @@ -77,6 +77,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: libevent-dev libevent-2.1-7 automake pkg-config make libio-socket-ssl-perl + ghcr-debs-tag: ubuntu-24.04-full - name: Checkout memcached uses: actions/checkout@v5 diff --git a/.github/workflows/mono.yml b/.github/workflows/mono.yml index ad8871fa82e..45b2c01a3a3 100644 --- a/.github/workflows/mono.yml +++ b/.github/workflows/mono.yml @@ -40,6 +40,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: mono-complete + ghcr-debs-tag: ubuntu-24.04-full - name: Copy wolfSSL.dll to C# wrapper directory run: | diff --git a/.github/workflows/mosquitto.yml b/.github/workflows/mosquitto.yml index 1cf91ba1492..c960268383c 100644 --- a/.github/workflows/mosquitto.yml +++ b/.github/workflows/mosquitto.yml @@ -76,6 +76,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: build-essential libev-dev libssl-dev automake python3-docutils libcunit1 libcunit1-doc libcunit1-dev pkg-config make python3-psutil + ghcr-debs-tag: ubuntu-24.04-full - name: Checkout mosquitto uses: actions/checkout@v5 diff --git a/.github/workflows/msmtp.yml b/.github/workflows/msmtp.yml index 1e759e443fa..ef02f75bdf0 100644 --- a/.github/workflows/msmtp.yml +++ b/.github/workflows/msmtp.yml @@ -76,6 +76,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: autoconf automake libtool pkg-config gettext libidn2-dev libsecret-1-dev autopoint + ghcr-debs-tag: ubuntu-24.04-full - name: Checkout msmtp uses: actions/checkout@v5 diff --git a/.github/workflows/multi-arch.yml b/.github/workflows/multi-arch.yml index 7ed74ab5f32..0854c430d30 100644 --- a/.github/workflows/multi-arch.yml +++ b/.github/workflows/multi-arch.yml @@ -7,6 +7,11 @@ on: pull_request: types: [opened, synchronize, reopened, ready_for_review] branches: [ '*' ] + # Weekday-morning cron (10:00 UTC) seeds the master-scoped ccache that PR runs + # restore: re-runs --build-only (compile only, no tests) on the + # default branch. PR runs are read-only (see ccache-setup). + schedule: + - cron: '20 10 * * 1-5' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -33,6 +38,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: autoconf automake libtool build-essential crossbuild-essential-arm64 crossbuild-essential-armhf crossbuild-essential-riscv64 crossbuild-essential-armel qemu-user + ghcr-debs-tag: ubuntu-22.04-minimal # ccache via the cross-platform composite; the script passes the # compiler to configure as CC="ccache gcc" (or a per-config "cc"). @@ -40,6 +46,7 @@ jobs: uses: ./.github/actions/ccache-setup with: workflow-id: multi-arch + read-only: ${{ github.event_name == 'pull_request' }} max-size: 500M # NOTE: the old runner-per-config matrix combined an "include" list @@ -246,6 +253,7 @@ jobs: ] EOF .github/scripts/parallel-make-check.py \ + ${{ github.event_name == 'schedule' && '--build-only' || '' }} \ "$RUNNER_TEMP/multi-arch-configs.json" - name: ccache stats @@ -256,6 +264,7 @@ jobs: if: failure() uses: actions/upload-artifact@v6 with: + retention-days: 7 name: multi-arch-logs path: | build-*/make-check.log diff --git a/.github/workflows/multi-compiler.yml b/.github/workflows/multi-compiler.yml index 15e2d681cd8..3dc86dd94eb 100644 --- a/.github/workflows/multi-compiler.yml +++ b/.github/workflows/multi-compiler.yml @@ -7,6 +7,11 @@ on: pull_request: types: [opened, synchronize, reopened, ready_for_review] branches: [ '*' ] + # Weekday-morning cron (10:00 UTC) seeds the master-scoped ccache that PR runs + # restore: re-runs --build-only (compile only, no tests) on the + # default branch. PR runs are read-only (see ccache-setup). + schedule: + - cron: '24 10 * * 1-5' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -33,6 +38,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: autoconf automake libtool build-essential gcc-9 g++-9 gcc-10 g++-10 gcc-11 g++-11 gcc-12 g++-12 clang-14 clang-19 + ghcr-debs-tag: ubuntu-24.04-minimal # ccache via the cross-platform composite; the script passes the # compiler to configure as CC="ccache gcc" (or a per-config "cc"). @@ -40,6 +46,7 @@ jobs: uses: ./.github/actions/ccache-setup with: workflow-id: multi-compiler + read-only: ${{ github.event_name == 'pull_request' }} max-size: 500M # One entry per compiler (the former one-runner-per-compiler matrix): @@ -89,6 +96,7 @@ jobs: ] EOF .github/scripts/parallel-make-check.py \ + ${{ github.event_name == 'schedule' && '--build-only' || '' }} \ "$RUNNER_TEMP/multi-compiler-configs.json" - name: ccache stats @@ -99,6 +107,7 @@ jobs: if: failure() uses: actions/upload-artifact@v6 with: + retention-days: 7 name: multi-compiler-logs path: | build-*/make-check.log diff --git a/.github/workflows/no-malloc.yml b/.github/workflows/no-malloc.yml index 36c67ed0e1d..d6364534c1e 100644 --- a/.github/workflows/no-malloc.yml +++ b/.github/workflows/no-malloc.yml @@ -7,6 +7,11 @@ on: pull_request: types: [opened, synchronize, reopened, ready_for_review] branches: [ '*' ] + # Weekday-morning cron (10:00 UTC) seeds the master-scoped ccache that PR runs + # restore: re-runs --build-only (compile only, no tests) on the + # default branch. PR runs are read-only (see ccache-setup). + schedule: + - cron: '28 10 * * 1-5' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -33,6 +38,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: autoconf automake libtool build-essential + ghcr-debs-tag: ubuntu-24.04-minimal # ccache via the cross-platform composite; the script passes the # compiler to configure as CC="ccache gcc" (or a per-config "cc"). @@ -40,6 +46,7 @@ jobs: uses: ./.github/actions/ccache-setup with: workflow-id: no-malloc + read-only: ${{ github.event_name == 'pull_request' }} max-size: 100M # The JSON list below is the former runner-per-config matrix. These @@ -71,6 +78,7 @@ jobs: ] EOF .github/scripts/parallel-make-check.py \ + ${{ github.event_name == 'schedule' && '--build-only' || '' }} \ "$RUNNER_TEMP/no-malloc-configs.json" - name: ccache stats @@ -81,6 +89,7 @@ jobs: if: failure() uses: actions/upload-artifact@v6 with: + retention-days: 7 name: no-malloc-logs path: | build-*/make-check.log diff --git a/.github/workflows/nss.yml b/.github/workflows/nss.yml index e96b12b7675..ef20dfd200c 100644 --- a/.github/workflows/nss.yml +++ b/.github/workflows/nss.yml @@ -45,6 +45,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: gyp ninja-build + ghcr-debs-tag: ubuntu-24.04-full - name: Checkout nss if: steps.cache.outputs.cache-hit != 'true' @@ -88,6 +89,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: gyp ninja-build + ghcr-debs-tag: ubuntu-24.04-full - name: Checkout nss (fallback on cache miss) if: steps.cache.outputs.cache-hit != 'true' diff --git a/.github/workflows/opensslcoexist.yml b/.github/workflows/opensslcoexist.yml index 9412e22970c..6b0f48f7b6b 100644 --- a/.github/workflows/opensslcoexist.yml +++ b/.github/workflows/opensslcoexist.yml @@ -7,6 +7,11 @@ on: pull_request: types: [opened, synchronize, reopened, ready_for_review] branches: [ '*' ] + # Weekday-morning cron (10:00 UTC) seeds the master-scoped ccache that PR runs + # restore: re-runs --build-only (compile only, no tests) on the + # default branch. PR runs are read-only (see ccache-setup). + schedule: + - cron: '32 10 * * 1-5' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -35,6 +40,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: autoconf automake libtool build-essential bubblewrap + ghcr-debs-tag: ubuntu-24.04-minimal # ccache via the cross-platform composite; the script passes the # compiler to configure as CC="ccache gcc" (or a per-config "cc"). @@ -42,6 +48,7 @@ jobs: uses: ./.github/actions/ccache-setup with: workflow-id: opensslcoexist + read-only: ${{ github.event_name == 'pull_request' }} max-size: 150M # Ubuntu 24.04 can restrict unprivileged user namespaces via AppArmor, @@ -72,6 +79,7 @@ jobs: ] EOF .github/scripts/parallel-make-check.py \ + ${{ github.event_name == 'schedule' && '--build-only' || '' }} \ --private-dir=certs \ "$RUNNER_TEMP/opensslcoexist-configs.json" @@ -83,6 +91,7 @@ jobs: if: failure() uses: actions/upload-artifact@v6 with: + retention-days: 7 name: opensslcoexist-logs path: | build-*/make-check.log diff --git a/.github/workflows/openvpn.yml b/.github/workflows/openvpn.yml index e914a01a0df..644909654c5 100644 --- a/.github/workflows/openvpn.yml +++ b/.github/workflows/openvpn.yml @@ -69,6 +69,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: liblzo2-dev libpam0g-dev liblz4-dev libcap-ng-dev linux-libc-dev man2html libcmocka-dev python3-docutils libtool automake autoconf libnl-genl-3-dev libnl-genl-3-200 + ghcr-debs-tag: ubuntu-24.04-full - name: workaround high-entropy ASLR # not needed after either an update to llvm or runner is done diff --git a/.github/workflows/os-check.yml b/.github/workflows/os-check.yml index f66179763cf..6da5e7af89d 100644 --- a/.github/workflows/os-check.yml +++ b/.github/workflows/os-check.yml @@ -16,6 +16,13 @@ on: paths-ignore: - '**/*.md' - 'doc/**' + # Weekday-morning cron (10:00 UTC) seeds the master-scoped ccache that PR runs restore: the + # linux job re-runs --build-only (compile only, no tests) on the default + # branch, where its ccache writes are visible to every PR. macOS and + # Windows are skipped on schedule (see their job `if`s) - seeding the + # linux shards is where the cold-cache cost lives. + schedule: + - cron: '0 10 * * 1-5' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -68,6 +75,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: autoconf automake libtool build-essential bubblewrap ccache + ghcr-debs-tag: ubuntu-24.04-minimal # Ubuntu 24.04 can restrict unprivileged user namespaces via AppArmor, # which would stop the test scripts from re-execing under @@ -81,8 +89,11 @@ jobs: - name: Pin ccache directory run: echo "CCACHE_DIR=$HOME/.cache/ccache" >> "$GITHUB_ENV" + # PRs restore the cache the weekday seed writes but never save it, so + # PR runs add no per-shard ccache entries to the Actions cache. The + # seed (schedule) saves below. - name: Restore ccache - uses: actions/cache@v5 + uses: actions/cache/restore@v5 with: path: ~/.cache/ccache # Per-shard cache lineage: each shard compiles a distinct config @@ -380,10 +391,20 @@ jobs: ] EOF .github/scripts/parallel-make-check.py \ + ${{ github.event_name == 'schedule' && '--build-only' || '' }} \ --shard "${{ matrix.shard }}/${{ strategy.job-total }}" \ --cflags='-pedantic -Wdeclaration-after-statement -Wnull-dereference -Wno-overlength-strings -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE' \ --private-dir=certs "$RUNNER_TEMP/os-check-configs.json" + # Seed runs (schedule) refresh the master-scoped ccache that PR runs + # restore above; PR/push runs never save, so PRs add nothing. + - name: Save ccache (seed only) + if: github.event_name == 'schedule' + uses: actions/cache/save@v4 + with: + path: ~/.cache/ccache + key: os-check-linux-ccache-${{ matrix.shard }}-${{ github.ref_name }}-${{ github.sha }} + - name: ccache stats if: always() run: ccache -s || true @@ -392,6 +413,7 @@ jobs: if: failure() uses: actions/upload-artifact@v6 with: + retention-days: 7 name: os-check-linux-logs-${{ matrix.shard }} path: | build-*/make-check.log @@ -413,6 +435,9 @@ jobs: # macos-apple-native-cert-validation.yml workflow. make_check_macos: name: make check macos + # Runs on PRs/pushes and on the weekday ccache-seed cron, where it + # --build-only-seeds the macOS ccache (like the linux shards). Only + # Windows is skipped on schedule (no ccache to seed). if: ${{ (github.repository_owner == 'wolfssl') && (github.event_name != 'pull_request' || github.event.pull_request.draft == false) }} runs-on: macos-latest # Serial checks: roughly the sum of the per-config minutes plus @@ -442,6 +467,8 @@ jobs: with: workflow-id: os-check-macos max-size: 500M + # PRs read the weekday-seeded macOS ccache; only the seed saves. + read-only: ${{ github.event_name == 'pull_request' }} # Same JSON config format as make_check_linux above; "minutes" only # orders the serial schedule here (longest first). @@ -478,6 +505,7 @@ jobs: ] EOF .github/scripts/parallel-make-check.py \ + ${{ github.event_name == 'schedule' && '--build-only' || '' }} \ --threads 1 --cc= \ --cflags='-pedantic -Wdeclaration-after-statement -Wnull-dereference -Wno-overlength-strings -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE' \ --private-dir=certs "$RUNNER_TEMP/os-check-macos-configs.json" @@ -490,6 +518,7 @@ jobs: if: failure() uses: actions/upload-artifact@v6 with: + retention-days: 7 name: os-check-macos-logs path: | build-*/make-check.log @@ -499,7 +528,8 @@ jobs: windows_build: name: Windows Build Test - if: ${{ (github.repository_owner == 'wolfssl') && (github.event_name != 'pull_request' || github.event.pull_request.draft == false) }} + # Skipped on the weekday ccache-seed cron: no ccache to seed here. + if: ${{ (github.repository_owner == 'wolfssl') && (github.event_name != 'schedule') && (github.event_name != 'pull_request' || github.event.pull_request.draft == false) }} runs-on: windows-latest strategy: fail-fast: false diff --git a/.github/workflows/pam-ipmi.yml b/.github/workflows/pam-ipmi.yml index 9471ae29987..02a385a359e 100644 --- a/.github/workflows/pam-ipmi.yml +++ b/.github/workflows/pam-ipmi.yml @@ -62,6 +62,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: libpam-dev ninja-build meson + ghcr-debs-tag: ubuntu-24.04-full - name: Download lib uses: actions/download-artifact@v7 diff --git a/.github/workflows/pic32mz-sim.yml b/.github/workflows/pic32mz-sim.yml index 4d63602b640..d7e3d5beb15 100644 --- a/.github/workflows/pic32mz-sim.yml +++ b/.github/workflows/pic32mz-sim.yml @@ -6,12 +6,21 @@ on: branches: [ 'master', 'main', 'release/**' ] pull_request: branches: [ '*' ] + # Weekend cron and manual workflow_dispatch refresh the shared ghcr build + # cache that PR runs read (cache-to below is gated to those two events). + schedule: + - cron: '0 7 * * 6' + workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true # END OF COMMON SECTION +permissions: + contents: read + packages: write + # Build the PIC32MZ software simulator (https://github.com/wolfSSL/simulators, # PIC32MZSim/ subdirectory) and run the wolfCrypt test suite on emulated # PIC32MZ EC (no FPU, CE ignores OUT_SWAP) and EF (FPU + OUT_SWAP) parts, @@ -67,6 +76,10 @@ jobs: - uses: docker/setup-buildx-action@v4 + - name: Log in to ghcr (cache refresh on cron/manual dispatch) + if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin + - name: Build ${{ matrix.image_tag }} image uses: docker/build-push-action@v7 with: @@ -75,8 +88,10 @@ jobs: push: false load: true tags: ${{ matrix.image_tag }} - cache-from: type=gha,scope=${{ matrix.cache_scope }} - cache-to: type=gha,mode=max,scope=${{ matrix.cache_scope }} + cache-from: type=registry,ref=ghcr.io/wolfssl/wolfssl-sim-cache:${{ matrix.cache_scope }} + # Write only on the weekend cron, and only from the EC entry of each + # image, so the two chips that share a scope do not race on the push. + cache-to: ${{ ((github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && matrix.chip_label == 'EC') && format('type=registry,ref=ghcr.io/wolfssl/wolfssl-sim-cache:{0},mode=max', matrix.cache_scope) || '' }} - name: Run wolfCrypt tests on PIC32MZ ${{ matrix.chip_label }} (${{ matrix.port_label }}) run: | diff --git a/.github/workflows/pq-all.yml b/.github/workflows/pq-all.yml index a480a93f20a..5b370e3f5f2 100644 --- a/.github/workflows/pq-all.yml +++ b/.github/workflows/pq-all.yml @@ -7,6 +7,11 @@ on: pull_request: types: [opened, synchronize, reopened, ready_for_review] branches: [ '*' ] + # Weekday-morning cron (10:00 UTC) seeds the master-scoped ccache that PR runs restore, by + # re-running --build-only (compile only, no tests) on the default branch. + # PR runs are read-only. + schedule: + - cron: '4 10 * * 1-5' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -39,6 +44,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: autoconf automake libtool build-essential bubblewrap + ghcr-debs-tag: ubuntu-24.04-minimal # ccache via the cross-platform composite; the script passes the # compiler to configure as CC="ccache gcc" (or a per-config "cc"). @@ -48,6 +54,9 @@ jobs: workflow-id: pq-all config-hash: shard-${{ matrix.shard }} max-size: 350M + # PRs read the cache the weekday seed writes; they never + # save, so PR runs add nothing to the Actions cache. + read-only: ${{ github.event_name == 'pull_request' }} # Ubuntu 24.04 can restrict unprivileged user namespaces via AppArmor, # which would stop the test scripts from re-execing under @@ -220,6 +229,7 @@ jobs: ] EOF .github/scripts/parallel-make-check.py \ + ${{ github.event_name == 'schedule' && '--build-only' || '' }} \ --shard "${{ matrix.shard }}/${{ strategy.job-total }}" \ --private-dir=certs \ "$RUNNER_TEMP/pq-all-configs.json" @@ -232,6 +242,7 @@ jobs: if: failure() uses: actions/upload-artifact@v6 with: + retention-days: 7 name: pq-all-logs-${{ matrix.shard }} path: | build-*/make-check.log diff --git a/.github/workflows/psk.yml b/.github/workflows/psk.yml index 526fee8885f..22c7de77df7 100644 --- a/.github/workflows/psk.yml +++ b/.github/workflows/psk.yml @@ -7,6 +7,11 @@ on: pull_request: types: [opened, synchronize, reopened, ready_for_review] branches: [ '*' ] + # Weekday-morning cron (10:00 UTC) seeds the master-scoped ccache that PR runs + # restore: re-runs --build-only (compile only, no tests) on the + # default branch. PR runs are read-only (see ccache-setup). + schedule: + - cron: '36 10 * * 1-5' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -35,6 +40,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: autoconf automake libtool build-essential bubblewrap + ghcr-debs-tag: ubuntu-24.04-minimal # ccache via the cross-platform composite; the script passes the # compiler to configure as CC="ccache gcc" (or a per-config "cc"). @@ -42,6 +48,7 @@ jobs: uses: ./.github/actions/ccache-setup with: workflow-id: psk + read-only: ${{ github.event_name == 'pull_request' }} max-size: 100M # Ubuntu 24.04 can restrict unprivileged user namespaces via AppArmor, @@ -95,6 +102,7 @@ jobs: ] EOF .github/scripts/parallel-make-check.py \ + ${{ github.event_name == 'schedule' && '--build-only' || '' }} \ --private-dir=certs \ "$RUNNER_TEMP/psk-configs.json" @@ -106,6 +114,7 @@ jobs: if: failure() uses: actions/upload-artifact@v6 with: + retention-days: 7 name: psk-logs path: | build-*/make-check.log diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index af388e66e53..f43b1188a23 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -109,6 +109,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: build-essential autoconf automake autoconf-archive pkgconf libffi-dev libbz2-dev libreadline-dev libsqlite3-dev zlib1g-dev libncursesw5-dev libgdbm-dev libnss3-dev liblzma-dev uuid-dev pkg-config + ghcr-debs-tag: ubuntu-24.04-full - name: Download wolfSSL uses: actions/download-artifact@v7 diff --git a/.github/workflows/rng-tools.yml b/.github/workflows/rng-tools.yml index 97a5206df3f..06fc6eb7616 100644 --- a/.github/workflows/rng-tools.yml +++ b/.github/workflows/rng-tools.yml @@ -63,6 +63,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: libcurl4-openssl-dev libjansson-dev libp11-dev librtlsdr-dev libcap-dev + ghcr-debs-tag: ubuntu-24.04-full - name: Download lib uses: actions/download-artifact@v7 diff --git a/.github/workflows/se050-sim.yml b/.github/workflows/se050-sim.yml index 8c1d8c2a2bd..7a5a7b27fb4 100644 --- a/.github/workflows/se050-sim.yml +++ b/.github/workflows/se050-sim.yml @@ -7,12 +7,21 @@ on: pull_request: types: [opened, synchronize, reopened, ready_for_review] branches: [ '*' ] + # Weekend cron and manual workflow_dispatch refresh the shared ghcr build + # cache that PR runs read (cache-to below is gated to those two events). + schedule: + - cron: '15 6 * * 6' + workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true # END OF COMMON SECTION +permissions: + contents: read + packages: write + # Build the SE050 software simulator (https://github.com/wolfSSL/simulators, # SE050Sim/ subdirectory), build wolfSSL against its NXP Plug&Trust SDK + # simulator bridge, and run the wolfCrypt SE050 test binary against the @@ -55,6 +64,10 @@ jobs: - uses: docker/setup-buildx-action@v4 + - name: Log in to ghcr (cache refresh on cron/manual dispatch) + if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin + - name: Build wolfCrypt-SE050 test image uses: docker/build-push-action@v7 with: @@ -63,8 +76,8 @@ jobs: push: false load: true tags: wolfssl-se050-sim:ci - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: type=registry,ref=ghcr.io/wolfssl/wolfssl-sim-cache:se050 + cache-to: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && 'type=registry,ref=ghcr.io/wolfssl/wolfssl-sim-cache:se050,mode=max' || '' }} - name: Run wolfCrypt tests against simulator run: docker run --rm wolfssl-se050-sim:ci diff --git a/.github/workflows/smallStackSize.yml b/.github/workflows/smallStackSize.yml index 27c604fed78..6a39e388ac8 100644 --- a/.github/workflows/smallStackSize.yml +++ b/.github/workflows/smallStackSize.yml @@ -7,6 +7,11 @@ on: pull_request: types: [opened, synchronize, reopened, ready_for_review] branches: [ '*' ] + # Weekday-morning cron (10:00 UTC) seeds the master-scoped ccache that PR runs + # restore: re-runs --build-only (compile only, no tests) on the + # default branch. PR runs are read-only (see ccache-setup). + schedule: + - cron: '40 10 * * 1-5' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -33,6 +38,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: autoconf automake libtool build-essential + ghcr-debs-tag: ubuntu-24.04-minimal # ccache via the cross-platform composite; the script passes the # compiler to configure as CC="ccache gcc" (or a per-config "cc"). @@ -40,6 +46,7 @@ jobs: uses: ./.github/actions/ccache-setup with: workflow-id: smallstacksize + read-only: ${{ github.event_name == 'pull_request' }} max-size: 150M # The JSON list below is the former runner-per-config matrix (the @@ -118,6 +125,7 @@ jobs: ] EOF .github/scripts/parallel-make-check.py \ + ${{ github.event_name == 'schedule' && '--build-only' || '' }} \ "$RUNNER_TEMP/smallstacksize-configs.json" - name: ccache stats @@ -128,6 +136,7 @@ jobs: if: failure() uses: actions/upload-artifact@v6 with: + retention-days: 7 name: smallstacksize-logs path: | build-*/make-check.log diff --git a/.github/workflows/smoke-test.yml b/.github/workflows/smoke-test.yml index 650c33d7097..61e2a03a923 100644 --- a/.github/workflows/smoke-test.yml +++ b/.github/workflows/smoke-test.yml @@ -36,6 +36,10 @@ on: pull_request: types: [opened, synchronize, reopened, ready_for_review] branches: [ master, main ] + # Weekday-morning (10:00 UTC) build-only seed of the master-scoped ccache that PR runs restore + # (in addition to the master pushes above). PR runs are read-only. + schedule: + - cron: '56 10 * * 1-5' concurrency: group: smoke-${{ github.workflow }}-${{ github.ref }} @@ -90,6 +94,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: autoconf automake libtool build-essential bubblewrap ccache + ghcr-debs-tag: ubuntu-24.04-minimal # Ubuntu 24.04 can restrict unprivileged user namespaces via AppArmor, # which would stop the test scripts from re-execing under @@ -99,15 +104,17 @@ jobs: run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 || true # ccache's default cache dir (XDG ~/.cache/ccache) is what the - # actions/cache step below saves; pin it explicitly so the two + # actions/cache steps below restore/save; pin it explicitly so the two # cannot drift apart (e.g. if a later change sets CCACHE_DIR). - name: Pin ccache directory if: steps.merge_check.outputs.skip != 'true' run: echo "CCACHE_DIR=$HOME/.cache/ccache" >> "$GITHUB_ENV" + # PRs restore the cache the master pushes / weekday seed write, but + # never save it (the save step is gated to non-PR events below). - name: Restore ccache if: steps.merge_check.outputs.skip != 'true' - uses: actions/cache@v5 + uses: actions/cache/restore@v5 with: path: ~/.cache/ccache key: smoke-ccache-${{ github.base_ref || github.ref_name }}-${{ github.sha }} @@ -153,9 +160,18 @@ jobs: {"name": "leantls-extra", "configure": ["--enable-leantls", "--enable-session-ticket", "--enable-sni", "--enable-opensslextra"]} ] EOF - .github/scripts/parallel-make-check.py --cflags=-Werror \ + .github/scripts/parallel-make-check.py ${{ github.event_name == 'schedule' && '--build-only' || '' }} --cflags=-Werror \ --private-dir=certs "$RUNNER_TEMP/smoke-configs.json" + # Seed (master pushes + the weekday cron) writes the master-scoped + # ccache that PR runs restore; PRs never save. + - name: Save ccache + if: github.event_name != 'pull_request' && steps.merge_check.outputs.skip != 'true' + uses: actions/cache/save@v4 + with: + path: ~/.cache/ccache + key: smoke-ccache-${{ github.ref_name }}-${{ github.sha }} + - name: ccache stats if: always() && steps.merge_check.outputs.skip != 'true' run: ccache -s || true @@ -164,6 +180,7 @@ jobs: if: failure() && steps.merge_check.outputs.skip != 'true' uses: actions/upload-artifact@v6 with: + retention-days: 7 name: smoke-logs path: | build-*/make-check.log diff --git a/.github/workflows/socat.yml b/.github/workflows/socat.yml index c9b102886d8..75b5431bcc3 100644 --- a/.github/workflows/socat.yml +++ b/.github/workflows/socat.yml @@ -63,6 +63,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: build-essential autoconf libtool pkg-config clang libc++-dev + ghcr-debs-tag: ubuntu-24.04-full - name: Download lib uses: actions/download-artifact@v7 diff --git a/.github/workflows/softhsm.yml b/.github/workflows/softhsm.yml index 56bacf6fc5d..9d141a2b082 100644 --- a/.github/workflows/softhsm.yml +++ b/.github/workflows/softhsm.yml @@ -63,6 +63,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: libcppunit-dev + ghcr-debs-tag: ubuntu-24.04-full - name: Download lib uses: actions/download-artifact@v7 diff --git a/.github/workflows/stm32-sim.yml b/.github/workflows/stm32-sim.yml index e46b9a6b21a..2b8da04e9ab 100644 --- a/.github/workflows/stm32-sim.yml +++ b/.github/workflows/stm32-sim.yml @@ -7,12 +7,21 @@ on: pull_request: types: [opened, synchronize, reopened, ready_for_review] branches: [ '*' ] + # Weekend cron and manual workflow_dispatch refresh the shared ghcr build + # cache that PR runs read (cache-to below is gated to those two events). + schedule: + - cron: '15 7 * * 6' + workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true # END OF COMMON SECTION +permissions: + contents: read + packages: write + # Build the STM32 software simulator (https://github.com/wolfSSL/simulators, # STM32Sim/ subdirectory) and run the wolfCrypt test suite on emulated # STM32H753 (Cortex-M7), STM32U585 (Cortex-M33), and STM32MP135 (Cortex-A7) @@ -74,6 +83,10 @@ jobs: - uses: docker/setup-buildx-action@v4 + - name: Log in to ghcr (cache refresh on cron/manual dispatch) + if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin + - name: Build stm32sim-wolfcrypt image uses: docker/build-push-action@v7 with: @@ -82,8 +95,11 @@ jobs: push: false load: true tags: stm32sim-wolfcrypt:ci - cache-from: type=gha,scope=stm32sim - cache-to: type=gha,mode=max,scope=stm32sim + # Per-chip cache tag: H753/U585 share an image but MP135's context is + # sed-patched, and a per-chip tag also keeps the weekend writers from + # racing on one ref. + cache-from: type=registry,ref=ghcr.io/wolfssl/wolfssl-sim-cache:stm32-${{ matrix.chip_label }} + cache-to: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && format('type=registry,ref=ghcr.io/wolfssl/wolfssl-sim-cache:stm32-{0},mode=max', matrix.chip_label) || '' }} - name: Run wolfCrypt tests on STM32${{ matrix.chip_label }} run: | diff --git a/.github/workflows/stsafe-a120-sim.yml b/.github/workflows/stsafe-a120-sim.yml index ba1470a490f..ee56f0d752e 100644 --- a/.github/workflows/stsafe-a120-sim.yml +++ b/.github/workflows/stsafe-a120-sim.yml @@ -7,12 +7,21 @@ on: pull_request: types: [opened, synchronize, reopened, ready_for_review] branches: [ '*' ] + # Weekend cron and manual workflow_dispatch refresh the shared ghcr build + # cache that PR runs read (cache-to below is gated to those two events). + schedule: + - cron: '30 6 * * 6' + workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true # END OF COMMON SECTION +permissions: + contents: read + packages: write + # Build the STSAFE-A120 software simulator (https://github.com/wolfSSL/simulators, # STSAFEA120Sim/ subdirectory), build wolfSSL against STMicro's STSELib + # simulator bridge, and run the wolfCrypt STSAFE-A120 test binary against the @@ -82,6 +91,10 @@ jobs: - uses: docker/setup-buildx-action@v4 + - name: Log in to ghcr (cache refresh on cron/manual dispatch) + if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin + - name: Build wolfCrypt-STSAFE-A120 test image uses: docker/build-push-action@v7 with: @@ -90,8 +103,8 @@ jobs: push: false load: true tags: wolfssl-stsafe-a120-sim:ci - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: type=registry,ref=ghcr.io/wolfssl/wolfssl-sim-cache:stsafe-a120 + cache-to: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && 'type=registry,ref=ghcr.io/wolfssl/wolfssl-sim-cache:stsafe-a120,mode=max' || '' }} - name: Run wolfCrypt tests against simulator run: docker run --rm wolfssl-stsafe-a120-sim:ci diff --git a/.github/workflows/tls-anvil.yml b/.github/workflows/tls-anvil.yml index c82e14cbf42..2319cd49a54 100644 --- a/.github/workflows/tls-anvil.yml +++ b/.github/workflows/tls-anvil.yml @@ -46,6 +46,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: build-essential autoconf automake libtool jq psmisc + ghcr-debs-tag: ubuntu-24.04-full - name: Pull TLS-Anvil Docker image run: docker pull ghcr.io/tls-attacker/tlsanvil:latest diff --git a/.github/workflows/trackmemory.yml b/.github/workflows/trackmemory.yml index a1c1e9adfab..f30d93d5e25 100644 --- a/.github/workflows/trackmemory.yml +++ b/.github/workflows/trackmemory.yml @@ -7,6 +7,11 @@ on: pull_request: types: [opened, synchronize, reopened, ready_for_review] branches: [ '*' ] + # Weekday-morning cron (10:00 UTC) seeds the master-scoped ccache that PR runs + # restore: re-runs --build-only (compile only, no tests) on the + # default branch. PR runs are read-only (see ccache-setup). + schedule: + - cron: '44 10 * * 1-5' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -37,6 +42,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: autoconf automake libtool build-essential bubblewrap + ghcr-debs-tag: ubuntu-24.04-minimal # ccache via the cross-platform composite; the script passes the # compiler to configure as CC="ccache gcc" (or a per-config "cc"). @@ -44,6 +50,7 @@ jobs: uses: ./.github/actions/ccache-setup with: workflow-id: trackmemory + read-only: ${{ github.event_name == 'pull_request' }} max-size: 250M # Ubuntu 24.04 can restrict unprivileged user namespaces via AppArmor, @@ -93,6 +100,7 @@ jobs: ] EOF .github/scripts/parallel-make-check.py \ + ${{ github.event_name == 'schedule' && '--build-only' || '' }} \ --private-dir=certs \ "$RUNNER_TEMP/trackmemory-configs.json" @@ -104,6 +112,7 @@ jobs: if: failure() uses: actions/upload-artifact@v6 with: + retention-days: 7 name: trackmemory-logs path: | build-*/make-check.log diff --git a/.github/workflows/tropic01-sim.yml b/.github/workflows/tropic01-sim.yml index ed6c2d5b393..0f00a876b17 100644 --- a/.github/workflows/tropic01-sim.yml +++ b/.github/workflows/tropic01-sim.yml @@ -7,12 +7,21 @@ on: pull_request: types: [opened, synchronize, reopened, ready_for_review] branches: [ '*' ] + # Weekend cron and manual workflow_dispatch refresh the shared ghcr build + # cache that PR runs read (cache-to below is gated to those two events). + schedule: + - cron: '45 6 * * 6' + workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true # END OF COMMON SECTION +permissions: + contents: read + packages: write + # Build the TROPIC01 software simulator (https://github.com/wolfSSL/simulators, # TROPIC01Sim/ subdirectory), build wolfSSL --with-tropic01 against libtropic # v0.1.0 + the simulator's TCP HAL, and run Tropic Square's wolfssl-test app @@ -74,6 +83,10 @@ jobs: - uses: docker/setup-buildx-action@v4 + - name: Log in to ghcr (cache refresh on cron/manual dispatch) + if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin + - name: Build wolfCrypt-TROPIC01 test image uses: docker/build-push-action@v7 with: @@ -82,8 +95,8 @@ jobs: push: false load: true tags: wolfssl-tropic01-sim:ci - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: type=registry,ref=ghcr.io/wolfssl/wolfssl-sim-cache:tropic01 + cache-to: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && 'type=registry,ref=ghcr.io/wolfssl/wolfssl-sim-cache:tropic01,mode=max' || '' }} - name: Run wolfCrypt tests against simulator run: docker run --rm wolfssl-tropic01-sim:ci diff --git a/.github/workflows/watcomc.yml b/.github/workflows/watcomc.yml index ad67feb1eeb..3fa6063239b 100644 --- a/.github/workflows/watcomc.yml +++ b/.github/workflows/watcomc.yml @@ -84,6 +84,7 @@ jobs: if: failure() uses: actions/upload-artifact@v6 with: + retention-days: 7 name: ${{ matrix.platform.id }}-${{ matrix.thread.id }}-${{ matrix.library.id }} path: | build/** diff --git a/.github/workflows/wolfCrypt-Wconversion.yml b/.github/workflows/wolfCrypt-Wconversion.yml index 070622c7d92..6e608c53688 100644 --- a/.github/workflows/wolfCrypt-Wconversion.yml +++ b/.github/workflows/wolfCrypt-Wconversion.yml @@ -7,6 +7,11 @@ on: pull_request: types: [opened, synchronize, reopened, ready_for_review] branches: [ '*' ] + # Weekday-morning cron (10:00 UTC) seeds the master-scoped ccache that PR runs + # restore: re-runs --build-only (compile only, no tests) on the + # default branch. PR runs are read-only (see ccache-setup). + schedule: + - cron: '48 10 * * 1-5' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -33,6 +38,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: autoconf automake libtool build-essential gcc-multilib + ghcr-debs-tag: ubuntu-24.04-minimal # ccache via the cross-platform composite; the script passes the # compiler to configure as CC="ccache gcc" (or a per-config "cc"). @@ -40,6 +46,7 @@ jobs: uses: ./.github/actions/ccache-setup with: workflow-id: wconversion + read-only: ${{ github.event_name == 'pull_request' }} max-size: 300M # The JSON list below is the former runner-per-config matrix. These @@ -140,6 +147,7 @@ jobs: ] EOF .github/scripts/parallel-make-check.py \ + ${{ github.event_name == 'schedule' && '--build-only' || '' }} \ "$RUNNER_TEMP/wconversion-configs.json" - name: ccache stats @@ -150,6 +158,7 @@ jobs: if: failure() uses: actions/upload-artifact@v6 with: + retention-days: 7 name: wconversion-logs path: | build-*/make-check.log diff --git a/.github/workflows/wolfboot-integration.yml b/.github/workflows/wolfboot-integration.yml index eae10b529f4..47b44fafaec 100644 --- a/.github/workflows/wolfboot-integration.yml +++ b/.github/workflows/wolfboot-integration.yml @@ -314,6 +314,7 @@ jobs: if: always() uses: actions/upload-artifact@v6 with: + retention-days: 7 name: renode-multimem-smallstack-results path: wolfboot/test_results/ @@ -422,6 +423,7 @@ jobs: if: always() uses: actions/upload-artifact@v6 with: + retention-days: 7 name: renode-multimem-smallstack-fastmath-results path: wolfboot/test_results/ @@ -530,5 +532,6 @@ jobs: if: always() uses: actions/upload-artifact@v6 with: + retention-days: 7 name: renode-multimem-smallstack-noasm-results path: wolfboot/test_results/ diff --git a/.github/workflows/wolfsm.yml b/.github/workflows/wolfsm.yml index 2a6da029d51..113e255a991 100644 --- a/.github/workflows/wolfsm.yml +++ b/.github/workflows/wolfsm.yml @@ -7,6 +7,11 @@ on: pull_request: types: [opened, synchronize, reopened, ready_for_review] branches: [ '*' ] + # Weekday-morning cron (10:00 UTC) seeds the master-scoped ccache that PR runs + # restore: re-runs --build-only (compile only, no tests) on the + # default branch. PR runs are read-only (see ccache-setup). + schedule: + - cron: '52 10 * * 1-5' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -48,6 +53,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: autoconf automake libtool build-essential bubblewrap + ghcr-debs-tag: ubuntu-24.04-minimal # ccache via the cross-platform composite; the script passes the # compiler to configure as CC="ccache gcc" (or a per-config "cc"). @@ -55,6 +61,7 @@ jobs: uses: ./.github/actions/ccache-setup with: workflow-id: wolfsm + read-only: ${{ github.event_name == 'pull_request' }} max-size: 200M # Ubuntu 24.04 can restrict unprivileged user namespaces via AppArmor, @@ -88,6 +95,7 @@ jobs: ] EOF .github/scripts/parallel-make-check.py \ + ${{ github.event_name == 'schedule' && '--build-only' || '' }} \ --private-dir=certs \ "$RUNNER_TEMP/wolfsm-configs.json" @@ -99,6 +107,7 @@ jobs: if: failure() uses: actions/upload-artifact@v6 with: + retention-days: 7 name: wolfsm-logs path: | build-*/make-check.log diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index 0639c6da449..f0bb0fc7dee 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -41,6 +41,7 @@ jobs: uses: ./.github/actions/install-apt-deps with: packages: zip bridge-utils uml-utilities git cmake ninja-build gperf ccache dfu-util device-tree-compiler wget python3-dev python3-pip python3-setuptools python3-tk python3-wheel xz-utils file make gcc gcc-multilib g++-multilib libsdl2-dev libmagic1 autoconf automake bison build-essential ca-certificates cargo ccache chrpath cmake cpio device-tree-compiler dfu-util diffstat dos2unix doxygen file flex g++ gawk gcc gcovr git git-core gnupg gperf gtk-sharp3 help2man iproute2 lcov libcairo2-dev libglib2.0-dev libgtk2.0-0 liblocale-gettext-perl libncurses5-dev libpcap-dev libpopt0 libsdl1.2-dev libsdl2-dev libssl-dev libtool libtool-bin locales make net-tools ninja-build openssh-client parallel pkg-config python3-dev python3-pip python3-ply python3-setuptools python-is-python3 qemu-kvm rsync socat srecord sudo texinfo unzip wget ovmf xz-utils + ghcr-debs-tag: ubuntu-22.04-full - name: Setup cmake version uses: jwlawson/actions-setup-cmake@v2 From 3faaf7818ccc6ad945346b9a0db139e3ff4c805f Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 15 Jun 2026 13:33:23 +0000 Subject: [PATCH 2/9] CI: address Copilot review - offline no-install-recommends, stale comments - 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 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. --- .github/actions/install-apt-deps/action.yml | 8 ++++++-- .github/workflows/os-check.yml | 8 ++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.github/actions/install-apt-deps/action.yml b/.github/actions/install-apt-deps/action.yml index 0f7bce22e13..5f692100c4d 100644 --- a/.github/actions/install-apt-deps/action.yml +++ b/.github/actions/install-apt-deps/action.yml @@ -24,7 +24,7 @@ inputs: description: > Tag of a prebuilt .deb bundle published to ghcr.io//wolfssl-ci-debs by the ci-deps-image workflow - (e.g. "ubuntu-24.04"). When set, the packages are installed offline + (e.g. "ubuntu-24.04-minimal"). When set, the packages are installed offline from that bundle - the apt mirror is never contacted - and the apt cache path below is skipped entirely. Any failure (bundle missing, not public, or missing a package) falls through to the apt path, so @@ -59,9 +59,13 @@ runs: docker rm "$cid" >/dev/null 2>&1 || true ls "$RUNNER_TEMP"/ghcr-debs/*.deb >/dev/null 2>&1 || { echo "::notice::bundle had no .debs; using apt"; exit 0; } sudo cp "$RUNNER_TEMP"/ghcr-debs/*.deb /var/cache/apt/archives/ + NO_REC="" + if [ "${{ inputs.no-install-recommends }}" = "true" ]; then + NO_REC="--no-install-recommends" + fi # --no-download forbids any network fetch: if the bundle is missing # a package this fails cleanly (nothing installed) and we fall back. - if sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-download ${{ inputs.packages }}; then + if sudo DEBIAN_FRONTEND=noninteractive apt-get install -y $NO_REC --no-download ${{ inputs.packages }}; then echo "satisfied=true" >> "$GITHUB_OUTPUT" echo "Installed offline from $IMG: ${{ inputs.packages }}" else diff --git a/.github/workflows/os-check.yml b/.github/workflows/os-check.yml index 6da5e7af89d..4e038946e3a 100644 --- a/.github/workflows/os-check.yml +++ b/.github/workflows/os-check.yml @@ -17,10 +17,10 @@ on: - '**/*.md' - 'doc/**' # Weekday-morning cron (10:00 UTC) seeds the master-scoped ccache that PR runs restore: the - # linux job re-runs --build-only (compile only, no tests) on the default - # branch, where its ccache writes are visible to every PR. macOS and - # Windows are skipped on schedule (see their job `if`s) - seeding the - # linux shards is where the cold-cache cost lives. + # linux and macOS jobs re-run --build-only (compile only, no tests) on the + # default branch, where their ccache writes are visible to every PR. Only + # Windows is skipped on schedule (see its job `if`) - seeding the linux and + # macOS shards is where the cold-cache cost lives. schedule: - cron: '0 10 * * 1-5' From 146e1c3d34085372c400dc904f8602592428c96d Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 15 Jun 2026 15:41:50 +0000 Subject: [PATCH 3/9] CI: reseed ccache from clean compiles on scheduled runs The scheduled (cron) refresh restored the prior ccache and recompiled only the translation units that changed, so unchanged objects were never rebuilt and the shared cache could drift indefinitely. Set CCACHE_RECACHE=1 on schedule events - gated inside the ccache-setup action, so none of the calling workflows change - to force fresh compiles that re-store every result. PR and push runs are unaffected and keep their warm hits; only the scheduled jobs pay the full recompile. --- .github/actions/ccache-setup/action.yml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/actions/ccache-setup/action.yml b/.github/actions/ccache-setup/action.yml index d4d0c1f2b06..b1d35e4388e 100644 --- a/.github/actions/ccache-setup/action.yml +++ b/.github/actions/ccache-setup/action.yml @@ -4,7 +4,9 @@ description: > directory from a previous run, and prepend the ccache compiler-symlink dir to PATH. Subsequent gcc/cc/g++/c++/clang invocations are transparently intercepted by ccache, so no other workflow step needs to - change. + change. On scheduled (cron) runs the cache is reseeded from clean + compiles (CCACHE_RECACHE) instead of only being updated incrementally, + so it can't drift indefinitely. inputs: workflow-id: @@ -97,6 +99,18 @@ runs: echo "$CCACHE_LIBEXEC" >> "$GITHUB_PATH" echo "CCACHE_DIR=$HOME/.ccache" >> "$GITHUB_ENV" + # On the scheduled (cron) refresh, force every compile to miss the + # cache and re-store a fresh result (CCACHE_RECACHE still writes, it + # just skips lookups). This reseeds the shared cache from clean + # compiles instead of only layering deltas onto whatever accumulated, + # so a bad/stale entry can't live forever. The cache is still saved + # (read-only is false on schedule), and PR/push runs are unaffected - + # they keep their warm hits. Cost: the scheduled jobs recompile fully. + - name: Force fresh compiles on scheduled reseed + if: github.event_name == 'schedule' + shell: bash + run: echo "CCACHE_RECACHE=1" >> "$GITHUB_ENV" + - name: Show ccache stats (initial) shell: bash run: ccache -s From 8754aee447b4039dfdcc274e75e294bd0c80ddb7 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 15 Jun 2026 16:19:48 +0000 Subject: [PATCH 4/9] CI: fix ccache-setup load failure (github context in composite if:) The scheduled-reseed step gated CCACHE_RECACHE with `if: github.event_name == 'schedule'`, but the github context is not available in a composite action's step-level if:. The action manifest therefore failed to load ("Unrecognized named-value: 'github'"), and every workflow using ccache-setup broke at the "Set up ccache" step (build library, make check, Compiler test, Multi-arch test, ...). Gate on the built-in $GITHUB_EVENT_NAME env var in the shell instead, which keeps the schedule-only reseed behaviour with no caller changes. --- .github/actions/ccache-setup/action.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/actions/ccache-setup/action.yml b/.github/actions/ccache-setup/action.yml index b1d35e4388e..675434bde39 100644 --- a/.github/actions/ccache-setup/action.yml +++ b/.github/actions/ccache-setup/action.yml @@ -106,10 +106,15 @@ runs: # so a bad/stale entry can't live forever. The cache is still saved # (read-only is false on schedule), and PR/push runs are unaffected - # they keep their warm hits. Cost: the scheduled jobs recompile fully. + # Gate in the shell via the built-in $GITHUB_EVENT_NAME, not a step-level + # `if:` - the `github` context is not available in a composite action's + # step `if:` (it loads as "Unrecognized named-value: 'github'"). - name: Force fresh compiles on scheduled reseed - if: github.event_name == 'schedule' shell: bash - run: echo "CCACHE_RECACHE=1" >> "$GITHUB_ENV" + run: | + if [ "$GITHUB_EVENT_NAME" = "schedule" ]; then + echo "CCACHE_RECACHE=1" >> "$GITHUB_ENV" + fi - name: Show ccache stats (initial) shell: bash From 86e5df754e2303c519a43ab83aaa0e9e4eec29ad Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 15 Jun 2026 17:01:42 +0000 Subject: [PATCH 5/9] CI: drop github context from ccache-setup input description The read-only input description embedded `${{ github.event_name == 'pull_request' }}` as example text. GitHub validates ${{ }} expressions in an action's input definitions at manifest-load time, where the github context is not available, so the action failed to load ("Unrecognized named-value: 'github'", action.yml line 27) and every ccache-setup consumer died at "Set up ccache" (build library, make check, Compiler test, Multi-arch test, ...). Describe the expression in prose instead of embedding it as a live ${{ }} template; the github.* references that remain are in step with:/run: blocks, where the context is available. --- .github/actions/ccache-setup/action.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/actions/ccache-setup/action.yml b/.github/actions/ccache-setup/action.yml index 675434bde39..0ba5a01f5cd 100644 --- a/.github/actions/ccache-setup/action.yml +++ b/.github/actions/ccache-setup/action.yml @@ -26,9 +26,10 @@ inputs: read-only: description: > When 'true', restore the cache but do NOT save it (no post-job - upload). Pass `${{ github.event_name == 'pull_request' }}` so PR runs - consume the shared cache read-only - no per-PR entries, no churn - - while scheduled/push runs (read-only false) refresh it. + upload). Callers should set this to the result of the expression + github.event_name == 'pull_request' so PR runs consume the shared + cache read-only - no per-PR entries, no churn - while scheduled/push + runs (read-only false) refresh it. required: false default: 'false' From 93b1e35a15dc71a5aa7d95f93a3918f4b8d0f84a Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 15 Jun 2026 17:18:52 +0000 Subject: [PATCH 6/9] CI: address Copilot review (ccache-setup if:, smoke-test concurrency) - 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. --- .github/actions/ccache-setup/action.yml | 9 ++------- .github/workflows/smoke-test.yml | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/.github/actions/ccache-setup/action.yml b/.github/actions/ccache-setup/action.yml index 0ba5a01f5cd..881e24be13f 100644 --- a/.github/actions/ccache-setup/action.yml +++ b/.github/actions/ccache-setup/action.yml @@ -107,15 +107,10 @@ runs: # so a bad/stale entry can't live forever. The cache is still saved # (read-only is false on schedule), and PR/push runs are unaffected - # they keep their warm hits. Cost: the scheduled jobs recompile fully. - # Gate in the shell via the built-in $GITHUB_EVENT_NAME, not a step-level - # `if:` - the `github` context is not available in a composite action's - # step `if:` (it loads as "Unrecognized named-value: 'github'"). - name: Force fresh compiles on scheduled reseed + if: github.event_name == 'schedule' shell: bash - run: | - if [ "$GITHUB_EVENT_NAME" = "schedule" ]; then - echo "CCACHE_RECACHE=1" >> "$GITHUB_ENV" - fi + run: echo "CCACHE_RECACHE=1" >> "$GITHUB_ENV" - name: Show ccache stats (initial) shell: bash diff --git a/.github/workflows/smoke-test.yml b/.github/workflows/smoke-test.yml index 61e2a03a923..db4466b9c01 100644 --- a/.github/workflows/smoke-test.yml +++ b/.github/workflows/smoke-test.yml @@ -42,7 +42,7 @@ on: - cron: '56 10 * * 1-5' concurrency: - group: smoke-${{ github.workflow }}-${{ github.ref }} + group: smoke-${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }} cancel-in-progress: true permissions: From 80a3e67ba3278b4cfec611f249e3f597407cb5b5 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 15 Jun 2026 18:53:00 +0000 Subject: [PATCH 7/9] CI: clarify ccache/apt-deps offload comments (Copilot review) 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. --- .github/actions/install-apt-deps/action.yml | 12 +++++++----- .github/workflows/ci-deps-image.yml | 13 +++++++++---- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/.github/actions/install-apt-deps/action.yml b/.github/actions/install-apt-deps/action.yml index 5f692100c4d..1e6222149f1 100644 --- a/.github/actions/install-apt-deps/action.yml +++ b/.github/actions/install-apt-deps/action.yml @@ -24,11 +24,13 @@ inputs: description: > Tag of a prebuilt .deb bundle published to ghcr.io//wolfssl-ci-debs by the ci-deps-image workflow - (e.g. "ubuntu-24.04-minimal"). When set, the packages are installed offline - from that bundle - the apt mirror is never contacted - and the apt - cache path below is skipped entirely. Any failure (bundle missing, - not public, or missing a package) falls through to the apt path, so - this is always safe to set. Leave empty to use apt only. + (e.g. "ubuntu-24.04-minimal"). When set, the packages are installed + offline from that bundle and the apt cache path below is skipped; on + that happy path the apt mirror is not contacted. The offline install + is all-or-nothing (a single --no-download install of the whole set), + so any failure - bundle missing, not public, or not covering every + requested package - falls back to the apt path. Always safe to set; + leave empty to use apt only. required: false default: '' runs: diff --git a/.github/workflows/ci-deps-image.yml b/.github/workflows/ci-deps-image.yml index ff8ac38a562..91cc5e63716 100644 --- a/.github/workflows/ci-deps-image.yml +++ b/.github/workflows/ci-deps-image.yml @@ -3,8 +3,11 @@ name: CI deps image # Builds the prebuilt apt .deb bundles that the make-check family (the # -minimal tags) and the interop workflows (the -full tags, a superset) # install offline (see .github/actions/install-apt-deps, input -# ghcr-debs-tag). Each bundle is the .deb closure of a package list in -# .github/ci-deps/, published to ghcr.io//wolfssl-ci-debs:. +# ghcr-debs-tag). Each bundle holds the .debs for a package list in +# .github/ci-deps/ - every package plus the dependencies not already on the +# matching runner image, so it is tied to that runner rather than being a +# portable, self-contained closure - published to +# ghcr.io//wolfssl-ci-debs:. # # Why: the apt mirror times out often enough to break PR CI. Resolving the # closure ONCE here (on master, where a slow mirror only delays this job and @@ -21,8 +24,10 @@ on: schedule: # Weekend only - refresh the bundles weekly so they track base-image # security updates. A mid-week package-list change waits for Saturday - # (or run this manually via workflow_dispatch); until then install-apt-deps - # falls back to apt for any package not yet in the bundle. + # (or run this manually via workflow_dispatch); until then the offline + # install (a single --no-download install of the whole set) fails if any + # requested package is missing from the bundle, and install-apt-deps + # falls back to the full apt path. - cron: '0 2 * * 6' workflow_dispatch: From b8c008f3ace64c66d45af7515bc393866f3f8235 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 15 Jun 2026 22:06:52 +0000 Subject: [PATCH 8/9] CI: address Skoll review (reseed coverage, ghcr owner, restore key) - 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//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. --- .github/actions/ccache-setup/action.yml | 3 +++ .github/actions/install-apt-deps/action.yml | 7 +++++-- .github/workflows/os-check.yml | 7 +++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.github/actions/ccache-setup/action.yml b/.github/actions/ccache-setup/action.yml index 881e24be13f..87c879d60e7 100644 --- a/.github/actions/ccache-setup/action.yml +++ b/.github/actions/ccache-setup/action.yml @@ -72,6 +72,9 @@ runs: uses: actions/cache/restore@v4 with: path: ~/.ccache + # Same key shape as the save branch, for symmetry. This branch never + # saves, so the run_id/run_attempt primary key is never an exact hit - + # the restore-keys below always supply the most recent seeded cache. key: ccache-${{ inputs.workflow-id }}-${{ runner.os }}-${{ runner.arch }}-${{ inputs.config-hash }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | ccache-${{ inputs.workflow-id }}-${{ runner.os }}-${{ runner.arch }}-${{ inputs.config-hash }}- diff --git a/.github/actions/install-apt-deps/action.yml b/.github/actions/install-apt-deps/action.yml index 1e6222149f1..6432392c396 100644 --- a/.github/actions/install-apt-deps/action.yml +++ b/.github/actions/install-apt-deps/action.yml @@ -49,8 +49,11 @@ runs: run: | set -u command -v docker >/dev/null 2>&1 || { echo "::notice::docker unavailable; using apt"; exit 0; } - OWNER=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') - IMG="ghcr.io/$OWNER/wolfssl-ci-debs:${{ inputs.ghcr-debs-tag }}" + # Hardcode the upstream owner: the bundle is only ever published under + # ghcr.io/wolfssl by ci-deps-image (gated to the wolfssl org), so fork + # PRs read the public upstream image too rather than a nonexistent + # ghcr.io//wolfssl-ci-debs. + IMG="ghcr.io/wolfssl/wolfssl-ci-debs:${{ inputs.ghcr-debs-tag }}" if ! docker pull -q "$IMG" >/dev/null 2>&1; then echo "::notice::ghcr bundle $IMG unavailable; using apt" exit 0 diff --git a/.github/workflows/os-check.yml b/.github/workflows/os-check.yml index 4e038946e3a..fa64195c67d 100644 --- a/.github/workflows/os-check.yml +++ b/.github/workflows/os-check.yml @@ -105,6 +105,13 @@ jobs: os-check-linux-ccache-${{ matrix.shard }}- os-check-linux-ccache- + # On the weekday seed, force clean recompiles (CCACHE_RECACHE) so the + # saved master ccache is reseeded from scratch rather than only + # accumulating deltas. PR/push runs leave it unset and keep their warm hits. + - name: Force fresh compiles on scheduled reseed + if: github.event_name == 'schedule' + run: echo "CCACHE_RECACHE=1" >> "$GITHUB_ENV" + - name: autogen run: | ccache -z From 634ac9b6da13db8a2ee5397b2aa4c51487e3d3b9 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 15 Jun 2026 22:39:56 +0000 Subject: [PATCH 9/9] CI: align branch-introduced actions with master's Node.js 24 bump 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 --- .github/actions/ccache-setup/action.yml | 2 +- .github/workflows/ci-deps-image.yml | 2 +- .github/workflows/os-check.yml | 2 +- .github/workflows/smoke-test.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/actions/ccache-setup/action.yml b/.github/actions/ccache-setup/action.yml index 87c879d60e7..775e9fd72ec 100644 --- a/.github/actions/ccache-setup/action.yml +++ b/.github/actions/ccache-setup/action.yml @@ -69,7 +69,7 @@ runs: # read-only=true: restore the shared cache but never upload (PR runs). - name: Restore ccache (read-only) if: inputs.read-only == 'true' - uses: actions/cache/restore@v4 + uses: actions/cache/restore@v5 with: path: ~/.ccache # Same key shape as the save branch, for symmetry. This branch never diff --git a/.github/workflows/ci-deps-image.yml b/.github/workflows/ci-deps-image.yml index 91cc5e63716..4bffc66f683 100644 --- a/.github/workflows/ci-deps-image.yml +++ b/.github/workflows/ci-deps-image.yml @@ -62,7 +62,7 @@ jobs: runs-on: ${{ matrix.runner }} timeout-minutes: 20 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Resolve and download the .deb closure shell: bash diff --git a/.github/workflows/os-check.yml b/.github/workflows/os-check.yml index fa64195c67d..a6b9b945940 100644 --- a/.github/workflows/os-check.yml +++ b/.github/workflows/os-check.yml @@ -407,7 +407,7 @@ jobs: # restore above; PR/push runs never save, so PRs add nothing. - name: Save ccache (seed only) if: github.event_name == 'schedule' - uses: actions/cache/save@v4 + uses: actions/cache/save@v5 with: path: ~/.cache/ccache key: os-check-linux-ccache-${{ matrix.shard }}-${{ github.ref_name }}-${{ github.sha }} diff --git a/.github/workflows/smoke-test.yml b/.github/workflows/smoke-test.yml index db4466b9c01..5cb6f198b3b 100644 --- a/.github/workflows/smoke-test.yml +++ b/.github/workflows/smoke-test.yml @@ -167,7 +167,7 @@ jobs: # ccache that PR runs restore; PRs never save. - name: Save ccache if: github.event_name != 'pull_request' && steps.merge_check.outputs.skip != 'true' - uses: actions/cache/save@v4 + uses: actions/cache/save@v5 with: path: ~/.cache/ccache key: smoke-ccache-${{ github.ref_name }}-${{ github.sha }}