Skip to content

Commit f60feac

Browse files
committed
perf(ci): cache smoke downloads across runs + dedup portable + narrow detect
Three independent levers to cut smoke-CI time (was: every run re-downloads xim:python/make, gcc/llvm toolchains, and every compat source archive — only ~/.mcpp/registry was cached). 1. Cross-run download cache: add actions/cache for the smoke download dir (${runner.temp}/mcpp-smoke-cache) in smoke-full-linux AND smoke-portable, keyed by MCPP_VERSION + a restore-keys prefix so a partial hit survives any pkg/test edit (only changed archives re-download). 2. Portable within-run dedup: smoke-portable never set MCPP_INDEX_SMOKE_CACHE_DIR and smoke_compat_portable.sh had only a restore half — so its 5 projects each re-downloaded the full llvm toolchain + archives within one run. Add the save_smoke_cache half (+ pbuild wrapper routing all 5 builds through it) and wire MCPP_INDEX_SMOKE_CACHE_DIR in the portable job. 3. Narrow detect: smoke-full-linux and smoke-portable run disjoint scripts on disjoint platforms, so split the single full=true into full_linux/full_portable. A change to one platform's harness no longer triggers the other's suite (a smoke_compat_portable.sh edit skips the ~12-min Linux job; a Linux smoke script edit skips win+mac). Common harness, unclassified test changes, and pkgs without an example still fall back to BOTH — no coverage is dropped. Classification verified against 9 representative changed-file sets. Diagnosis: see memory mcpp-index-ci-repeated-downloads. Python is pulled only by compat.xcb (build-dep, transitively via x11/glfw), Linux-only.
1 parent 8145abc commit f60feac

2 files changed

Lines changed: 88 additions & 16 deletions

File tree

.github/workflows/validate.yml

Lines changed: 65 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ jobs:
103103
outputs:
104104
examples: ${{ steps.f.outputs.examples }}
105105
full: ${{ steps.f.outputs.full }}
106+
full_linux: ${{ steps.f.outputs.full_linux }}
107+
full_portable: ${{ steps.f.outputs.full_portable }}
106108
steps:
107109
- uses: actions/checkout@v4
108110
with:
@@ -111,30 +113,51 @@ jobs:
111113
run: sudo apt-get install -y --no-install-recommends jq
112114
- id: f
113115
run: |
114-
full=false
116+
# The two heavy suites run on disjoint platforms and from disjoint
117+
# scripts: smoke-full-linux runs the smoke_compat_{core,imgui,archive,
118+
# imgui_window}.sh + smoke_imgui_module.sh scripts (Linux); smoke-portable
119+
# runs ONLY smoke_compat_portable.sh (windows+macos). So a change to one
120+
# platform's harness needn't trigger the other's. We classify each changed
121+
# file into full_linux / full_portable; unclassified test changes, the
122+
# common harness, and pkgs without an example fall back to BOTH (no
123+
# coverage is ever silently dropped).
124+
full_linux=false
125+
full_portable=false
115126
examples='[]'
116127
event="${{ github.event_name }}"
117128
if [ "$event" != "pull_request" ]; then
118129
# push to main / nightly schedule / manual dispatch → full regression
119-
full=true
130+
full_linux=true; full_portable=true
120131
else
121132
git fetch -q origin "${{ github.base_ref }}"
122133
changed=$(git diff --name-only "origin/${{ github.base_ref }}...HEAD")
123134
echo "changed files:"; echo "$changed" | sed 's/^/ /'
124-
# scaffolding / CI change → full regression
125-
if echo "$changed" | grep -qE '^(tests/run_example\.sh|tests/smoke_.*\.sh|tests/check_mirror_urls\.lua|tests/list_cn_urls\.lua|\.github/workflows/validate\.yml)$'; then
126-
full=true
127-
fi
128135
sel=""
129136
while IFS= read -r file; do
137+
[ -z "$file" ] && continue
130138
case "$file" in
139+
# Common harness / the workflow itself → both platforms.
140+
tests/run_example.sh|tests/check_mirror_urls.lua|tests/list_cn_urls.lua|.github/workflows/validate.yml)
141+
full_linux=true; full_portable=true ;;
142+
# Portable suite script runs only in smoke-portable (win+mac).
143+
tests/smoke_compat_portable.sh)
144+
full_portable=true ;;
145+
# Linux-only smoke scripts run only in smoke-full-linux.
146+
tests/smoke_compat_core.sh|tests/smoke_compat_imgui.sh|tests/smoke_compat_archive.sh|tests/smoke_compat_imgui_window.sh|tests/smoke_imgui_module.sh)
147+
full_linux=true ;;
148+
# Example projects are handled by the smoke-examples fast path.
149+
tests/examples/*)
150+
: ;;
151+
# Any other tests/ change (new helper / new smoke script) → both (safe).
152+
tests/*)
153+
full_linux=true; full_portable=true ;;
131154
pkgs/*/*.lua)
132155
b=$(basename "$file" .lua); b=${b#compat.}
133156
if [ -d "tests/examples/$b" ]; then
134157
sel="$sel$b"$'\n'
135158
else
136-
# changed pkg with no example yet → cannot narrow, run full
137-
full=true
159+
# changed pkg with no example yet → cannot narrow, run both
160+
full_linux=true; full_portable=true
138161
fi
139162
;;
140163
esac
@@ -143,9 +166,13 @@ jobs:
143166
examples=$(printf '%s' "$sel" | grep -v '^$' | sort -u | jq -R . | jq -sc .)
144167
fi
145168
fi
169+
full=false
170+
{ [ "$full_linux" = true ] || [ "$full_portable" = true ]; } && full=true
146171
echo "full=$full" >> "$GITHUB_OUTPUT"
172+
echo "full_linux=$full_linux" >> "$GITHUB_OUTPUT"
173+
echo "full_portable=$full_portable" >> "$GITHUB_OUTPUT"
147174
echo "examples=$examples" >> "$GITHUB_OUTPUT"
148-
echo "=> full=$full examples=$examples"
175+
echo "=> full_linux=$full_linux full_portable=$full_portable examples=$examples"
149176
150177
# ── Fast path: per-changed-package example projects (Linux) ───────────
151178
smoke-examples:
@@ -186,7 +213,7 @@ jobs:
186213
# ── Full regression (legacy whole-suite smoke) ────────────────────────
187214
smoke-full-linux:
188215
needs: detect
189-
if: needs.detect.outputs.full == 'true'
216+
if: needs.detect.outputs.full_linux == 'true'
190217
runs-on: ubuntu-latest
191218
steps:
192219
- uses: actions/checkout@v4
@@ -197,6 +224,18 @@ jobs:
197224
key: mcpp-registry-${{ runner.os }}-${{ env.MCPP_VERSION }}-${{ hashFiles('pkgs/**/*.lua', 'tests/**', '.github/workflows/validate.yml') }}
198225
restore-keys: |
199226
mcpp-registry-${{ runner.os }}-${{ env.MCPP_VERSION }}-
227+
# Persist the smoke download cache (toolchains + compat source archives)
228+
# ACROSS runs. Without this, every run re-downloads xim:python/make, the
229+
# gcc/llvm toolchains, and every source tarball. restore-keys gives a
230+
# partial hit even when pkgs change, so only new/changed archives download;
231+
# save_smoke_cache (in the smoke scripts) repopulates the dir each run.
232+
- name: Cache smoke downloads
233+
uses: actions/cache@v4
234+
with:
235+
path: ${{ runner.temp }}/mcpp-smoke-cache
236+
key: smoke-dl-${{ runner.os }}-${{ env.MCPP_VERSION }}-${{ hashFiles('pkgs/**/*.lua') }}
237+
restore-keys: |
238+
smoke-dl-${{ runner.os }}-${{ env.MCPP_VERSION }}-
200239
- name: Download mcpp
201240
run: |
202241
curl -L -fsS -o mcpp.tar.gz \
@@ -230,7 +269,7 @@ jobs:
230269
231270
smoke-portable:
232271
needs: detect
233-
if: needs.detect.outputs.full == 'true'
272+
if: needs.detect.outputs.full_portable == 'true'
234273
name: smoke-${{ matrix.platform }}
235274
runs-on: ${{ matrix.os }}
236275
timeout-minutes: 60
@@ -259,6 +298,18 @@ jobs:
259298
key: mcpp-registry-${{ runner.os }}-${{ env.MCPP_VERSION }}-${{ hashFiles('pkgs/**/*.lua', 'tests/**', '.github/workflows/validate.yml') }}
260299
restore-keys: |
261300
mcpp-registry-${{ runner.os }}-${{ env.MCPP_VERSION }}-
301+
# Persist the smoke download cache across runs (same rationale as
302+
# smoke-full-linux). Previously the portable job never set
303+
# MCPP_INDEX_SMOKE_CACHE_DIR at all, so its 5 projects each re-downloaded
304+
# the full llvm toolchain + compat archives WITHIN one run; now they share
305+
# one dir, persisted between runs too.
306+
- name: Cache smoke downloads
307+
uses: actions/cache@v4
308+
with:
309+
path: ${{ runner.temp }}/mcpp-smoke-cache
310+
key: smoke-dl-${{ runner.os }}-${{ env.MCPP_VERSION }}-${{ hashFiles('pkgs/**/*.lua') }}
311+
restore-keys: |
312+
smoke-dl-${{ runner.os }}-${{ env.MCPP_VERSION }}-
262313
- name: Download mcpp
263314
shell: bash
264315
env:
@@ -292,6 +343,9 @@ jobs:
292343
shell: bash
293344
env:
294345
MCPP_INDEX_MIRROR: GLOBAL
346+
# Enables the within-run + cross-run download cache (copy/save_smoke_cache).
347+
MCPP_INDEX_SMOKE_CACHE_DIR: ${{ runner.temp }}/mcpp-smoke-cache
295348
run: |
349+
mkdir -p "$MCPP_INDEX_SMOKE_CACHE_DIR"
296350
"$MCPP" --version
297351
bash tests/smoke_compat_portable.sh

tests/smoke_compat_portable.sh

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,24 @@ copy_smoke_cache() {
9797
-exec cp -f {} .mcpp/.xlings/data/runtimedir/ \;
9898
}
9999

100+
# Save half (was missing): stash this project's freshly-downloaded toolchain /
101+
# source archives back into SMOKE_CACHE_DIR so the NEXT project in this run (and,
102+
# when SMOKE_CACHE_DIR is on actions/cache, the next CI run) restores them instead
103+
# of re-downloading. Mirrors tests/smoke_compat_imgui.sh. `cp -n` = no-clobber.
104+
save_smoke_cache() {
105+
[[ -n "$SMOKE_CACHE_DIR" && -d .mcpp/.xlings/data ]] || return 0
106+
mkdir -p "$SMOKE_CACHE_DIR"
107+
find .mcpp/.xlings/data -type f \
108+
\( -name '*.tar.gz' -o -name '*.tar.xz' -o -name '*.zip' \) \
109+
-exec cp -n {} "$SMOKE_CACHE_DIR"/ \; 2>/dev/null || true
110+
}
111+
112+
# Build + populate the cache, so every project's downloads are reused.
113+
pbuild() {
114+
"$MCPP_BIN_POSIX" build
115+
save_smoke_cache
116+
}
117+
100118
write_build_ldflags() {
101119
case "$platform" in
102120
Linux)
@@ -196,7 +214,7 @@ TEST(CompatPortableCore, UpstreamHeadersAndRuntime) {
196214
EXPECT_EQ(static_cast<khronos_uint32_t>(1), 1u);
197215
}
198216
EOF
199-
"$MCPP_BIN_POSIX" build
217+
pbuild
200218
"$MCPP_BIN_POSIX" run
201219

202220
make_project "compat-portable-archive-smoke"
@@ -232,7 +250,7 @@ int main() {
232250
return 0;
233251
}
234252
EOF
235-
"$MCPP_BIN_POSIX" build
253+
pbuild
236254
"$MCPP_BIN_POSIX" run
237255

238256
make_project "compat-portable-compression-smoke"
@@ -356,7 +374,7 @@ int main() {
356374
return 0;
357375
}
358376
EOF
359-
"$MCPP_BIN_POSIX" build
377+
pbuild
360378
"$MCPP_BIN_POSIX" run
361379

362380
make_project "compat-portable-imgui-glfw-smoke"
@@ -411,7 +429,7 @@ int main() {
411429
IMGUI_VERSION_NUM >= 19200 ? 0 : 1;
412430
}
413431
EOF
414-
"$MCPP_BIN_POSIX" build
432+
pbuild
415433
"$MCPP_BIN_POSIX" run
416434

417435
# compat.openblas — Windows-only build-AND-run. This is the only place that
@@ -447,7 +465,7 @@ int main() {
447465
return 0;
448466
}
449467
EOF
450-
"$MCPP_BIN_POSIX" build
468+
pbuild
451469
# `mcpp run` also prepends the source bin/ to PATH, so it alone would not
452470
# prove the DLL was deployed. Run the produced .exe DIRECTLY from a neutral
453471
# CWD: Windows searches the executable's own directory first, so a clean exit

0 commit comments

Comments
 (0)