1515concurrency :
1616 # label each workflow run; only the latest with each label will run
1717 # workflows on master get more expressive labels
18- group : ${{ github.workflow }}-${{ github.ref }}.
19- ${{ ( contains(fromJSON( '["refs/heads/master", "refs/heads/staging"]'), github.ref ) && github.run_id) || ''}}
18+ group : ${{ github.workflow }}-${{ github.ref }}-${{ (contains(fromJSON('["refs/heads/master", "refs/heads/staging"]'), github.ref) && github.run_id) || '' }}
2019 # cancel any running workflow with the same label
2120 cancel-in-progress : true
2221
@@ -132,8 +131,23 @@ jobs:
132131 - name : set LEAN_SRC_PATH
133132 shell : bash
134133 run : |
135- # Construct the LEAN_SRC_PATH using the toolchain directory
136- LEAN_SRC_PATH=".:$TOOLCHAIN_DIR/src/lean/lake:.lake/packages/Cli:.lake/packages/batteries:.lake/packages/Qq:.lake/packages/aesop:.lake/packages/proofwidgets:.lake/packages/importGraph:.lake/packages/LeanSearchClient:.lake/packages/plausible"
134+ cd pr-branch
135+
136+ # Start with the base paths
137+ LEAN_SRC_PATH=".:$TOOLCHAIN_DIR/src/lean/lake"
138+
139+ # Extract package names from lake-manifest.json and validate them
140+ # Only allow A-Z, a-z, 0-9, _, and - characters
141+ # Build the LEAN_SRC_PATH by appending each validated package
142+ PACKAGE_NAMES=$(jq -r '.packages[].name' lake-manifest.json)
143+ for pkg in $PACKAGE_NAMES; do
144+ if [[ "$pkg" =~ ^[A-Za-z0-9_-]+$ ]]; then
145+ LEAN_SRC_PATH="$LEAN_SRC_PATH:.lake/packages/$pkg"
146+ else
147+ echo "Warning: Skipping invalid package name: $pkg"
148+ fi
149+ done
150+
137151 echo "LEAN_SRC_PATH=$LEAN_SRC_PATH"
138152
139153 # Set it as an environment variable for subsequent steps
@@ -186,6 +200,33 @@ jobs:
186200 cd pr-branch
187201 lake env
188202
203+ - name : validate lake-manifest.json inputRevs
204+ # Only enforce this on the main mathlib4 repository, not on nightly-testing
205+ if : github.repository == 'leanprover-community/mathlib4'
206+ shell : bash
207+ run : |
208+ cd pr-branch
209+
210+ # Check that all inputRevs in lake-manifest.json match the required pattern
211+ echo "Validating lake-manifest.json inputRevs..."
212+
213+ # Extract all inputRevs from the manifest
214+ invalid_revs=$(jq -r '.packages[].inputRev // empty' lake-manifest.json | \
215+ grep -v -E '^(main|master|v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?)$' || true)
216+
217+ if [ -n "$invalid_revs" ]; then
218+ echo "❌ Error: Found invalid inputRevs in lake-manifest.json:"
219+ echo "$invalid_revs"
220+ echo ""
221+ echo "All inputRevs must be one of:"
222+ echo " - 'main'"
223+ echo " - 'master'"
224+ echo " - 'vX.Y.Z' (semantic version, e.g., v1.2.3 or v1.2.3-pre)"
225+ exit 1
226+ else
227+ echo "✅ All inputRevs in lake-manifest.json are valid"
228+ fi
229+
189230 - name : get cache (1/3 - setup and initial fetch)
190231 id : get_cache_part1_setup
191232 shell : bash # only runs `cache get` from `master-branch`, so doesn't need to be inside landrun
@@ -301,37 +342,6 @@ jobs:
301342 env :
302343 MATHLIB_CACHE_SAS_RAW : ${{ secrets.MATHLIB_CACHE_SAS }}
303344
304- # The cache secrets are available here, so we must not run any untrusted code.
305- - name : Upload cache to Cloudflare
306- id : cloudflare-upload-mathlib
307- if : ${{ always() && steps.get.outcome == 'success' }}
308- continue-on-error : true
309- shell : bash
310- run : |
311- cd pr-branch
312-
313- # Trim trailing whitespace from secrets to prevent issues with accidentally added spaces
314- export MATHLIB_CACHE_S3_TOKEN="${MATHLIB_CACHE_S3_TOKEN_RAW%"${MATHLIB_CACHE_S3_TOKEN_RAW##*[![:space:]]}"}"
315-
316- echo "Uploading cache to Cloudflare..."
317- USE_FRO_CACHE=1 ../master-branch/.lake/build/bin/cache --repo=${{ github.event.pull_request.head.repo.full_name || github.repository }} put-unpacked
318- env :
319- MATHLIB_CACHE_S3_TOKEN_RAW : ${{ secrets.MATHLIB_CACHE_S3_TOKEN }}
320-
321- - name : Report Cloudflare upload failure on Zulip
322- if : steps.cloudflare-upload-mathlib.outcome == 'failure'
323- uses : zulip/github-actions-zulip/send-message@e4c8f27c732ba9bd98ac6be0583096dea82feea5 # v1.0.2
324- with :
325- api-key : ${{ secrets.ZULIP_API_KEY }}
326- email : ' github-mathlib4-bot@leanprover.zulipchat.com'
327- organization-url : ' https://leanprover.zulipchat.com'
328- to : ' nightly-testing'
329- type : ' stream'
330- topic : ' Cloudflare cache upload failure'
331- content : |
332- ❌ Cloudflare cache upload (Mathlib) [failed](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for PR #${{ github.event.pull_request.number || 'push' }} on commit ${{ github.sha }}
333- continue-on-error : true
334-
335345 # Note: we should not be including `Archive` and `Counterexamples` in the cache.
336346 # We do this for now for the sake of not rebuilding them in every CI run
337347 # even when they are not touched.
@@ -382,41 +392,11 @@ jobs:
382392 export MATHLIB_CACHE_SAS="${MATHLIB_CACHE_SAS_RAW%"${MATHLIB_CACHE_SAS_RAW##*[![:space:]]}"}"
383393
384394 echo "Uploading Archive and Counterexamples cache to Azure..."
385- USE_FRO_CACHE=0 ../master-branch/.lake/build/bin/cache --repo=${{ github.event.pull_request.head.repo.full_name || github.repository }} put Archive.lean
386- USE_FRO_CACHE=0 ../master-branch/.lake/build/bin/cache --repo=${{ github.event.pull_request.head.repo.full_name || github.repository }} put Counterexamples.lean
395+ USE_FRO_CACHE=0 ../master-branch/.lake/build/bin/cache --repo=${{ github.event.pull_request.head.repo.full_name || github.repository }} put-unpacked Archive.lean
396+ USE_FRO_CACHE=0 ../master-branch/.lake/build/bin/cache --repo=${{ github.event.pull_request.head.repo.full_name || github.repository }} put-unpacked Counterexamples.lean
387397 env :
388398 MATHLIB_CACHE_SAS_RAW : ${{ secrets.MATHLIB_CACHE_SAS }}
389399
390- - name : Upload Archive and Counterexamples cache to Cloudflare
391- id : cloudflare-upload-archive
392- continue-on-error : true
393- shell : bash
394- run : |
395- cd pr-branch
396-
397- # Trim trailing whitespace from secrets to prevent issues with accidentally added spaces
398- export MATHLIB_CACHE_S3_TOKEN="${MATHLIB_CACHE_S3_TOKEN_RAW%"${MATHLIB_CACHE_S3_TOKEN_RAW##*[![:space:]]}"}"
399-
400- echo "Uploading Archive and Counterexamples cache to Cloudflare..."
401- USE_FRO_CACHE=1 ../master-branch/.lake/build/bin/cache --repo=${{ github.event.pull_request.head.repo.full_name || github.repository }} put Archive.lean
402- USE_FRO_CACHE=1 ../master-branch/.lake/build/bin/cache --repo=${{ github.event.pull_request.head.repo.full_name || github.repository }} put Counterexamples.lean
403- env :
404- MATHLIB_CACHE_S3_TOKEN_RAW : ${{ secrets.MATHLIB_CACHE_S3_TOKEN }}
405-
406- - name : Report Cloudflare Archive/Counterexamples upload failure on Zulip
407- if : steps.cloudflare-upload-archive.outcome == 'failure'
408- uses : zulip/github-actions-zulip/send-message@e4c8f27c732ba9bd98ac6be0583096dea82feea5 # v1.0.2
409- with :
410- api-key : ${{ secrets.ZULIP_API_KEY }}
411- email : ' github-mathlib4-bot@leanprover.zulipchat.com'
412- organization-url : ' https://leanprover.zulipchat.com'
413- to : ' nightly-testing'
414- type : ' stream'
415- topic : ' Cloudflare cache upload failure'
416- content : |
417- ❌ Cloudflare cache upload (Archive/Counterexamples) [failed](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for PR #${{ github.event.pull_request.number || 'push' }} on commit ${{ github.sha }}
418- continue-on-error : true
419-
420400 - name : Check {Mathlib, Tactic, Counterexamples, Archive}.lean
421401 if : always()
422402 run : |
@@ -523,29 +503,6 @@ jobs:
523503 use-mathlib-cache : false # This can be re-enabled once we are confident in the cache again.
524504 reinstall-transient-toolchain : true
525505
526- - name : retrieve and test the Cloudflare caches, but don't fail, just report to Zulip, if anything goes wrong
527- id : cloudflare-cache
528- continue-on-error : true
529- run : |
530- lake exe cache --repo=${{ github.event.pull_request.head.repo.full_name || github.repository }} get
531- lake build --no-build -v Mathlib
532- lake exe cache --repo=${{ github.event.pull_request.head.repo.full_name || github.repository }} get Archive Counterexamples
533- lake build --no-build -v Archive Counterexamples
534-
535- - name : Report Cloudflare cache failure on Zulip
536- if : steps.cloudflare-cache.outcome == 'failure'
537- uses : zulip/github-actions-zulip/send-message@e4c8f27c732ba9bd98ac6be0583096dea82feea5 # v1.0.2
538- with :
539- api-key : ${{ secrets.ZULIP_API_KEY }}
540- email : ' github-mathlib4-bot@leanprover.zulipchat.com'
541- organization-url : ' https://leanprover.zulipchat.com'
542- to : ' nightly-testing'
543- type : ' stream'
544- topic : ' Cloudflare cache failure'
545- content : |
546- ❌ Cloudflare cache retrieval/test [failed](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for PR #${{ github.event.pull_request.number || 'push' }} on commit ${{ github.sha }}
547- continue-on-error : true
548-
549506 - name : get cache for Mathlib
550507 run : |
551508 # Run once without --repo, so we can diagnose what `lake exe cache get` wants to do by itself.
@@ -563,13 +520,13 @@ jobs:
563520 - name : verify that everything was available in the cache
564521 run : |
565522 echo "::group::{verify Mathlib cache}"
566- lake build --no-build -v Mathlib
523+ lake build --no-build --rehash - v Mathlib
567524 echo "::endgroup::"
568525 echo "::group::{verify Archive cache}"
569- lake build --no-build -v Archive
526+ lake build --no-build --rehash - v Archive
570527 echo "::endgroup::"
571528 echo "::group::{verify Counterexamples cache}"
572- lake build --no-build -v Counterexamples
529+ lake build --no-build --rehash - v Counterexamples
573530 echo "::endgroup::"
574531
575532 - name : check declarations in db files
@@ -595,8 +552,15 @@ jobs:
595552
596553 - name : build everything
597554 # make sure everything is available for test/import_all.lean
555+ # and that miscellaneous executables still work
598556 run : |
599- lake build Batteries Qq Aesop ProofWidgets Plausible
557+ lake build Batteries Qq Aesop ProofWidgets Plausible pole unused
558+
559+ - name : build AesopTest (nightly-testing only)
560+ # Only run on the mathlib4-nightly-testing repository
561+ if : github.repository == 'leanprover-community/mathlib4-nightly-testing'
562+ run : |
563+ lake build AesopTest
600564
601565 # We no longer run `lean4checker` in regular CI, as it is quite expensive for little benefit.
602566 # Instead we run it in a cron job on master: see `lean4checker.yml`.
@@ -632,31 +596,19 @@ jobs:
632596 if : FORK_CONDITION
633597 runs-on : ubuntu-latest
634598 steps :
635- - uses : leanprover-community/lint-style-action@d29fb3b12c1c834450680b3c544f63fe0237a2e2 # 2025-06-20
599+ - uses : leanprover-community/lint-style-action@a7e7428fa44f9635d6eb8e01919d16fd498d387a # 2025-08-18
636600 with :
637601 mode : check
638602 lint-bib-file : true
639603 ref : ${{ PR_BRANCH_REF }}
640604
641- build_and_lint :
642- name : CI Success
643- if : FORK_CONDITION
644- needs : [style_lint, post_steps]
645- runs-on : ubuntu-latest
646- steps :
647- - name : succeed
648- run : |
649- echo "Success: Required build and lint checks completed!"
650-
651605 final :
652606 name : Post-CI jobJOB_NAME
653607 if : FORK_CONDITION
654608 needs : [style_lint, build, post_steps]
655609 runs-on : ubuntu-latest
656610 steps :
657- # This action is used to determine the PR metadata in the event of a push.
658- - if : github.event_name != 'pull_request_target'
659- id : PR_from_push
611+ - id : PR_from_push
660612 uses : 8BitJonny/gh-get-current-pr@4056877062a1f3b624d5d4c2bedefa9cf51435c9 # 4.0.0
661613 # TODO: this may not work properly if the same commit is pushed to multiple branches:
662614 # https://github.com/8BitJonny/gh-get-current-pr/issues/8
@@ -665,6 +617,7 @@ jobs:
665617 # Only return if PR is still open
666618 filterOutClosed : true
667619
620+ # TODO: delete this step and rename `PR_from_push` to `PR` if the above step seems to work properly
668621 # Combine the output from the previous action with the metadata supplied by GitHub itself.
669622 # Note that if we fall back to github.event.pull_request data, the list of labels is generated when this workflow is triggered
670623 # and not updated afterwards!
0 commit comments