@@ -20,11 +20,65 @@ inputs:
2020 description : ' Cache apt archives (disable for dynamic package names)'
2121 required : false
2222 default : ' true'
23+ ghcr-debs-tag :
24+ description : >
25+ Tag of a prebuilt .deb bundle published to
26+ ghcr.io/<owner>/wolfssl-ci-debs by the ci-deps-image workflow
27+ (e.g. "ubuntu-24.04-minimal"). When set, the packages are installed
28+ offline from that bundle and the apt cache path below is skipped; on
29+ that happy path the apt mirror is not contacted. The offline install
30+ is all-or-nothing (a single --no-download install of the whole set),
31+ so any failure - bundle missing, not public, or not covering every
32+ requested package - falls back to the apt path. Always safe to set;
33+ leave empty to use apt only.
34+ required : false
35+ default : ' '
2336runs :
2437 using : ' composite'
2538 steps :
39+ # Preferred path: install from a prebuilt .deb bundle pulled from ghcr,
40+ # entirely offline (--no-download), so a flaky/timing-out apt mirror
41+ # cannot break the build. Best-effort: on any failure we leave
42+ # "satisfied" unset and the apt steps below run unchanged. The bundle
43+ # image must be PUBLIC so anonymous `docker pull` works (including from
44+ # fork PRs whose GITHUB_TOKEN cannot read private packages).
45+ - name : Install from ghcr .deb bundle (offline)
46+ id : ghcr
47+ if : inputs.ghcr-debs-tag != ''
48+ shell : bash
49+ run : |
50+ set -u
51+ command -v docker >/dev/null 2>&1 || { echo "::notice::docker unavailable; using apt"; exit 0; }
52+ # Hardcode the upstream owner: the bundle is only ever published under
53+ # ghcr.io/wolfssl by ci-deps-image (gated to the wolfssl org), so fork
54+ # PRs read the public upstream image too rather than a nonexistent
55+ # ghcr.io/<fork>/wolfssl-ci-debs.
56+ IMG="ghcr.io/wolfssl/wolfssl-ci-debs:${{ inputs.ghcr-debs-tag }}"
57+ if ! docker pull -q "$IMG" >/dev/null 2>&1; then
58+ echo "::notice::ghcr bundle $IMG unavailable; using apt"
59+ exit 0
60+ fi
61+ cid=$(docker create "$IMG" 2>/dev/null) || { echo "::notice::cannot open bundle; using apt"; exit 0; }
62+ rm -rf "$RUNNER_TEMP/ghcr-debs"; mkdir -p "$RUNNER_TEMP/ghcr-debs"
63+ docker cp "$cid:/debs/." "$RUNNER_TEMP/ghcr-debs/" >/dev/null 2>&1 || true
64+ docker rm "$cid" >/dev/null 2>&1 || true
65+ ls "$RUNNER_TEMP"/ghcr-debs/*.deb >/dev/null 2>&1 || { echo "::notice::bundle had no .debs; using apt"; exit 0; }
66+ sudo cp "$RUNNER_TEMP"/ghcr-debs/*.deb /var/cache/apt/archives/
67+ NO_REC=""
68+ if [ "${{ inputs.no-install-recommends }}" = "true" ]; then
69+ NO_REC="--no-install-recommends"
70+ fi
71+ # --no-download forbids any network fetch: if the bundle is missing
72+ # a package this fails cleanly (nothing installed) and we fall back.
73+ if sudo DEBIAN_FRONTEND=noninteractive apt-get install -y $NO_REC --no-download ${{ inputs.packages }}; then
74+ echo "satisfied=true" >> "$GITHUB_OUTPUT"
75+ echo "Installed offline from $IMG: ${{ inputs.packages }}"
76+ else
77+ echo "::notice::offline install incomplete for $IMG; using apt"
78+ fi
79+
2680 - name : Compute cache key
27- if : inputs.cache == 'true'
81+ if : inputs.cache == 'true' && steps.ghcr.outputs.satisfied != 'true'
2882 id : cache-key
2983 shell : bash
3084 run : |
3589 echo "restore-key=apt-deps-${{ runner.os }}-${{ runner.arch }}-${OS_VERSION}-" >> $GITHUB_OUTPUT
3690
3791 - name : Restore apt cache
38- if : inputs.cache == 'true'
92+ if : inputs.cache == 'true' && steps.ghcr.outputs.satisfied != 'true'
3993 id : apt-cache
4094 uses : actions/cache/restore@v5
4195 with :
4498 restore-keys : ${{ steps.cache-key.outputs.restore-key }}
4599
46100 - name : Pre-seed apt archives from cache
47- if : inputs.cache == 'true' && steps.apt-cache.outputs.cache-hit == 'true'
101+ if : inputs.cache == 'true' && steps.apt-cache.outputs.cache-hit == 'true' && steps.ghcr.outputs.satisfied != 'true'
48102 shell : bash
49103 run : |
50104 if [ -d ~/apt-cache ] && ls ~/apt-cache/*.deb >/dev/null 2>&1; then
53107 fi
54108
55109 - name : Install packages
110+ if : steps.ghcr.outputs.satisfied != 'true'
56111 shell : bash
57112 env :
58113 APT_CACHE_HIT : ${{ steps.apt-cache.outputs.cache-hit }}
@@ -90,16 +145,19 @@ runs:
90145 DELAY=$((DELAY * 2))
91146 done
92147
148+ # PR runs never write the apt cache (no churn); only push/schedule runs
149+ # refresh it. The make-check family does not need it anyway - it installs
150+ # from the ghcr bundle above.
93151 - name : Collect .deb files for cache
94- if : inputs.cache == 'true' && steps.apt-cache.outputs.cache-hit != 'true'
152+ if : inputs.cache == 'true' && github.event_name != 'pull_request' && steps.apt-cache.outputs.cache-hit != 'true' && steps.ghcr.outputs.satisfied != 'true'
95153 shell : bash
96154 run : |
97155 mkdir -p ~/apt-cache
98156 cp /var/cache/apt/archives/*.deb ~/apt-cache/ 2>/dev/null || true
99157 echo "Cached $(ls ~/apt-cache/*.deb 2>/dev/null | wc -l) .deb files"
100158
101159 - name : Save apt cache
102- if : inputs.cache == 'true' && steps.apt-cache.outputs.cache-hit != 'true'
160+ if : inputs.cache == 'true' && github.event_name != 'pull_request' && steps.apt-cache.outputs.cache-hit != 'true' && steps.ghcr.outputs.satisfied != 'true'
103161 uses : actions/cache/save@v5
104162 with :
105163 path : ~/apt-cache
0 commit comments