@@ -266,17 +266,50 @@ jobs:
266266 mirror-cn-reachable :
267267 # Closed-loop guard for the CN mirror: every CN url referenced by a
268268 # descriptor must be a live, downloadable gitcode release asset.
269+ #
270+ # ── Scoped to the CHANGED descriptors ─────────────────────────────────
271+ # This used to walk all 87 descriptors on every run — 105 unique urls,
272+ # each fetched in full (`curl -o /dev/null` downloads the body; that is
273+ # the point, a gitcode release page can 200 while the asset behind it is
274+ # gone) — while a PR mirrors one package's assets at a time. Everything
275+ # else it re-downloaded was mirrored by an earlier PR that already
276+ # checked it, and a url that was live then can only have gone dark
277+ # SINCE, which is decay over time rather than something this PR did.
278+ #
279+ # Decay is real, and it is what the weekly cron below is for: `select`
280+ # answers `__ALL__` for schedule/dispatch, so the full 105-url sweep
281+ # still happens — once a week, and on demand — instead of on every push.
282+ # It also still happens on any PR that touches this workflow file or a
283+ # shared test script (including tests/list_cn_urls.lua, the extractor
284+ # this job reads the urls with), because those widen `select` to a full
285+ # run for the same reason they widen the workspace matrix.
286+ #
287+ # `needs: select` rather than a second diff here: the "can I trust this
288+ # diff" question is already answered there, in one place.
289+ needs : select
290+ # Empty when the diff names no descriptor at all — a docs-only or
291+ # tools-only PR mirrors nothing.
292+ if : needs.select.outputs.pkgs != ''
269293 runs-on : ubuntu-latest
270294 steps :
271295 - uses : actions/checkout@v4
272296 - name : Install lua
273297 run : sudo apt-get install -y --no-install-recommends lua5.4
274298 - name : Check CN mirror assets are reachable
299+ env :
300+ PKGS : ${{ needs.select.outputs.pkgs }}
275301 run : |
276302 fail=0
277- # collect unique CN urls across all descriptors
303+ if [ "$PKGS" = "__ALL__" ]; then
304+ files=$(printf '%s\n' pkgs/*/*.lua)
305+ echo "full sweep: every descriptor"
306+ else
307+ files=$PKGS
308+ echo "changed descriptor(s): $files"
309+ fi
310+ # collect unique CN urls across the selected descriptors
278311 : > /tmp/cn.tsv
279- for f in pkgs/*/*.lua ; do
312+ for f in $files ; do
280313 lua5.4 tests/list_cn_urls.lua "$f" >> /tmp/cn.tsv || true
281314 done
282315 sort -u /tmp/cn.tsv -o /tmp/cn.tsv
@@ -324,6 +357,9 @@ jobs:
324357 members : ${{ steps.fanout.outputs.members }}
325358 matrix : ${{ steps.fanout.outputs.matrix }}
326359 plan : ${{ steps.plan_shards.outputs.plan }}
360+ # The descriptors this change actually touches, for `mirror-cn-reachable`.
361+ # `__ALL__` on a full run, empty when the diff names no descriptor at all.
362+ pkgs : ${{ steps.plan.outputs.pkgs }}
327363 steps :
328364 - uses : actions/checkout@v4
329365 with :
@@ -344,11 +380,22 @@ jobs:
344380 # package), a non-member edit to the workspace manifest, or shared test
345381 # scripts. Docs-only and tools/-only changes select nothing.
346382 # Note: bash 3.2 on macOS runners — no associative arrays here.
383+ #
384+ # The same walk also collects the CHANGED DESCRIPTORS (`pkgs` output) for
385+ # `mirror-cn-reachable`. Two selections, one classification: every reason
386+ # to distrust the diff — this workflow file, a shared test script, an
387+ # unclassified path, a push with no predecessor, cron/dispatch — has to
388+ # widen both, and writing that decision twice is how the two drift.
347389 - name : Select affected workspace members
348390 id : plan
349391 shell : bash
350392 run : |
351- full() { echo "MEMBERS=__ALL__" >> "$GITHUB_ENV"; echo "full run: $1"; exit 0; }
393+ full() {
394+ echo "MEMBERS=__ALL__" >> "$GITHUB_ENV"
395+ echo "pkgs=__ALL__" >> "$GITHUB_OUTPUT"
396+ echo "full run: $1"
397+ exit 0
398+ }
352399
353400 # A push to main has a diff too — it was just never asked for.
354401 #
@@ -388,7 +435,7 @@ jobs:
388435 esac
389436 changed=$(git diff --name-only $range)
390437 printf 'changed files vs %s:\n%s\n' "$base" "$changed"
391- sel=""
438+ sel=""; pkgsel=""
392439 add() { case " $sel " in *" $1 "*) ;; *) sel="$sel $1" ;; esac; }
393440 while IFS= read -r f; do
394441 [ -n "$f" ] || continue
@@ -413,6 +460,9 @@ jobs:
413460 # which already forces a full run above.
414461 [ -d "tests/examples/$m" ] && add "$m" ;;
415462 pkgs/*.lua|pkgs/*/*.lua)
463+ # A DELETED descriptor is in the diff but not on disk, and its
464+ # CN urls are gone with it — nothing left to reach.
465+ if [ -f "$f" ]; then pkgsel="$pkgsel $f"; fi
416466 lib=$(basename "$f" .lua); lib=${lib#compat.}
417467 hit=0
418468 for mt in tests/examples/*/mcpp.toml; do
@@ -447,6 +497,9 @@ jobs:
447497 sel=${sel# }
448498 echo "MEMBERS=$sel" >> "$GITHUB_ENV"
449499 echo "selected members: ${sel:-<none>}"
500+ pkgsel=${pkgsel# }
501+ echo "pkgs=$pkgsel" >> "$GITHUB_OUTPUT"
502+ echo "changed descriptors: ${pkgsel:-<none>}"
450503 # Sharding is for the FULL run only, and the shard count per platform is
451504 # that platform's RUNNER CONCURRENCY — not a round number.
452505 #
0 commit comments