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 b15401a27c..d4d0c1f2b0 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 2a34922b8f..0f7bce22e1 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 0000000000..f809efaeb4 --- /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 0000000000..c32e3ccb9c --- /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 0000000000..9872201d64 --- /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 0000000000..1cd40c6fc9 --- /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 299fa46416..fc86c2be5d 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 19a0fdc3cd..ae6fc8d09c 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 3aa3509e76..b2c2a97e72 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 6a828c77b7..5055b15b70 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 9b6184f841..b9cb22772c 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 1f7bee9f36..35d35d4597 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 9f2b57f551..0e10d8bd7c 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 0000000000..ff8ac38a56 --- /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 d52c189f9f..9d4c076e97 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 91368047dc..354f8d9e02 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 35091fe8cd..9b5c89591b 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 96b50e8766..2bae21ff5b 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 d5c631478e..a05bab3361 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 2e20ba4718..006f681174 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 5a0526c762..7357b0ce39 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 a2e57cac84..893379639c 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 f950cbd3ac..7095a2970d 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 c09fdce89c..61409b4d8a 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 db3eae670a..4f11da7787 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 05b45e88bf..cd4d6ffa60 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 f2f36186f2..7bd9b5b4e3 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 ad8871fa82..45b2c01a3a 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 1cf91ba149..c960268383 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 1e759e443f..ef02f75bdf 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 7ed74ab5f3..0854c430d3 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 15e2d681cd..3dc86dd94e 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 36c67ed0e1..d6364534c1 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 e96b12b767..ef20dfd200 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 9412e22970..6b0f48f7b6 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 e914a01a0d..644909654c 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 f66179763c..6da5e7af89 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 9471ae2998..02a385a359 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 4d63602b64..d7e3d5beb1 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 a480a93f20..5b370e3f5f 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 526fee8885..22c7de77df 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 af388e66e5..f43b1188a2 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 97a5206df3..06fc6eb761 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 8c1d8c2a2b..7a5a7b27fb 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 27c604fed7..6a39e388ac 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 650c33d709..61e2a03a92 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 c9b102886d..75b5431bcc 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 56bacf6fc5..9d141a2b08 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 e46b9a6b21..2b8da04e9a 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 ba1470a490..ee56f0d752 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 c82e14cbf4..2319cd49a5 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 a1c1e9adfa..f30d93d5e2 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 ed6c2d5b39..0f00a876b1 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 ad67feb1ee..3fa6063239 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 070622c7d9..6e608c5368 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 eae10b529f..47b44fafae 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 2a6da029d5..113e255a99 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 0639c6da44..f0bb0fc7de 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 0f7bce22e1..5f692100c4 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 6da5e7af89..4e038946e3 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 d4d0c1f2b0..b1d35e4388 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 b1d35e4388..675434bde3 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 675434bde3..0ba5a01f5c 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 0ba5a01f5c..881e24be13 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 61e2a03a92..db4466b9c0 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 5f692100c4..1e6222149f 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 ff8ac38a56..91cc5e6371 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 881e24be13..87c879d60e 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 1e6222149f..6432392c39 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 4e038946e3..fa64195c67 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 87c879d60e..775e9fd72e 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 91cc5e6371..4bffc66f68 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 fa64195c67..a6b9b94594 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 db4466b9c0..5cb6f198b3 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 }}