@@ -271,6 +271,7 @@ jobs:
271271 timeout-minutes : 30
272272 outputs :
273273 carryover : ${{ steps.carryover.outputs.summary }}
274+ new_content : ${{ steps.carryover.outputs.new_content }}
274275 env :
275276 LAKE_CACHE_ARTIFACT_ENDPOINT : ${{ vars.LAKE_CACHE_ARTIFACT_ENDPOINT }}
276277 LAKE_CACHE_REVISION_ENDPOINT : ${{ vars.LAKE_CACHE_REVISION_ENDPOINT }}
@@ -292,7 +293,7 @@ jobs:
292293 echo "$HOME/.elan/bin" >> "${GITHUB_PATH}"
293294
294295 - name : Download staging artifact
295- uses : actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v6 .0.0
296+ uses : actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 .0.1
296297 with :
297298 name : lake-cache-staging-${{ github.run_id }}
298299 path : lake-cache-staging
@@ -322,11 +323,15 @@ jobs:
322323 # Here:
323324 # carryover = artifacts also present last run;
324325 # new = this run's churn (≈ how much Mathlib changed since the last build).
326+ # We also size the new artifacts (bytes of fresh content pushed to the
327+ # bucket this run) by mapping each new content-hash back to its staged file.
325328 - name : Cache carryover analysis
326329 id : carryover
327330 continue-on-error : true
328331 env :
329332 AUTH : ${{ vars.LAKE_CACHE_ARTIFACT_ENDPOINT }}
333+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
334+ REPO : ${{ github.repository }}
330335 run : |
331336 base="${AUTH%/artifacts}/analysis"
332337 sha="${{ needs.build_and_stage.outputs.sha }}"
@@ -336,20 +341,51 @@ jobs:
336341 if [ "$total" -eq 0 ]; then
337342 echo "::warning::no uploaded artifacts parsed from put.log — skipping carryover (manifest/pointer left unchanged)"
338343 echo "summary=n/a (no artifacts uploaded)" >> "$GITHUB_OUTPUT"
344+ echo "new_content=n/a (no artifacts uploaded)" >> "$GITHUB_OUTPUT"
339345 exit 0
340346 fi
347+ # Map staged artifact content-hash -> file size in bytes. Staging files
348+ # are flat `<hash>.<ext>` (see Lake's `artifactPath`); the lone
349+ # `outputs.jsonl` keys to "outputs" and never matches a hash.
350+ declare -A SZ
351+ while read -r fname fsize; do
352+ SZ[${fname%%.*}]=$fsize
353+ done < <(find lake-cache-staging -maxdepth 1 -type f -printf '%f %s\n')
354+ sum_bytes() { # sum staged sizes for the artifact hashes read from a file
355+ local h tot=0
356+ while read -r h; do tot=$((tot + ${SZ[$h]:-0})); done < "$1"
357+ echo "$tot"
358+ }
341359 summary="n/a (baseline — no prior manifest)"
360+ # Baseline: with no prior manifest, every uploaded artifact is "new".
361+ new_bytes=$(sum_bytes /tmp/today.txt)
362+ new_content="$(numfmt --to=iec-i --suffix=B "$new_bytes") across ${total} new artifact(s) (baseline — all new)"
342363 prev="$(curl -fsS "${sig[@]}" "$base/_latest.txt" 2>/dev/null || true)"
343364 if [ -n "$prev" ] && curl -fsS "${sig[@]}" "$base/$prev.txt" 2>/dev/null | sort -u > /tmp/prev.txt && [ -s /tmp/prev.txt ]; then
344365 carry=$(comm -12 /tmp/today.txt /tmp/prev.txt | wc -l)
345- new=$(comm -23 /tmp/today.txt /tmp/prev.txt | wc -l)
366+ comm -23 /tmp/today.txt /tmp/prev.txt > /tmp/new.txt
367+ new=$(wc -l < /tmp/new.txt)
368+ new_bytes=$(sum_bytes /tmp/new.txt)
369+ # Commit distance prev..sha on master, via the GitHub compare API
370+ # (`.ahead_by`) — avoids deepening the shallow checkout across what
371+ # can be hundreds of commits between daily runs.
372+ dist=$(curl -fsS \
373+ -H "Authorization: Bearer ${GH_TOKEN}" \
374+ -H "Accept: application/vnd.github+json" \
375+ "https://api.github.com/repos/${REPO}/compare/${prev}...${sha}" \
376+ 2>/dev/null | jq -r '.ahead_by // empty' || true)
377+ distnote=""
378+ [ -n "$dist" ] && distnote=" (distance: ${dist} commits)"
379+ new_content="$(numfmt --to=iec-i --suffix=B "$new_bytes") across ${new} new artifact(s) vs rev ${prev:0:12}${distnote}"
346380 pct=$(awk "BEGIN{printf \"%.1f\", ($total>0)?100*$carry/$total:0}")
347381 note=""
348382 [ "$total" -gt 0 ] && [ "$new" -eq "$total" ] && note=" — full turnover, likely a toolchain/generation change, not source churn"
349383 summary="${carry}/${total} (${pct}%) carried over, ${new} new vs rev ${prev:0:12}${note}"
350384 fi
351385 echo "::notice::cache carryover: ${summary}"
386+ echo "::notice::new content uploaded: ${new_content}"
352387 echo "summary=${summary}" >> "$GITHUB_OUTPUT"
388+ echo "new_content=${new_content}" >> "$GITHUB_OUTPUT"
353389 # Persist this run's manifest + advance the pointer (best-effort).
354390 printf %s "$sha" > /tmp/latest.txt
355391 curl -fsS "${sig[@]}" -X PUT -T /tmp/today.txt "$base/${sha}.txt" >/dev/null || echo "::warning::failed to store analysis manifest"
@@ -484,6 +520,7 @@ jobs:
484520 UPLOAD : ${{ needs.upload.result }}
485521 CONSUME : ${{ needs.consume.result }}
486522 CARRYOVER : ${{ needs.upload.outputs.carryover }}
523+ NEW_CONTENT : ${{ needs.upload.outputs.new_content }}
487524 CACHE_HEALTH : ${{ needs.consume.outputs.cache_health }}
488525 SHA : ${{ needs.build_and_stage.outputs.sha }}
489526 RUN_URL : ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
@@ -505,16 +542,17 @@ jobs:
505542 echo "- $(emoji "$CONSUME") consume: \`$CONSUME\`"
506543 echo "- ${CACHE_HEALTH:-❓ cache hits: n/a (consume skipped)}"
507544 echo "- 🔁 cache carryover: ${CARRYOVER:-n/a}"
545+ echo "- 📦 new content uploaded: ${NEW_CONTENT:-n/a}"
508546 echo "MSG_EOF"
509547 } >> "$GITHUB_OUTPUT"
510548
511549 - name : Send to Zulip
512- uses : zulip/github-actions-zulip/send-message@e4c8f27c732ba9bd98ac6be0583096dea82feea5 # v1 .0.2
550+ uses : zulip/github-actions-zulip/send-message@bd8ec52de371d139ae8313661b7d8318c19266aa # v2 .0.1
513551 with :
514552 api-key : ${{ secrets.ZULIP_API_KEY }}
515553 email : ' github-mathlib4-bot@leanprover.zulipchat.com'
516554 organization-url : ' https://leanprover.zulipchat.com'
517- to : ' nightly-testing'
555+ to : ' nightly-testing-mathlib '
518556 type : ' stream'
519557 topic : ' mathlib + lake cache shadow workflow'
520558 content : ${{ steps.compose.outputs.msg }}
0 commit comments