2727 cache_application_id :
2828 type : string
2929 required : true
30+ cache_environment :
31+ # GitHub environment for the `upload_cache` job. Its only role is to fix the
32+ # OIDC `sub` claim to `...:environment:<name>`, which the Azure cache app's
33+ # federated credential is scoped to; it must match the writer `cache_application_id`.
34+ type : string
35+ required : true
3036
3137env :
3238 # Disable Lake's automatic fetching of cloud builds.
8995
9096 # Checkout a trusted branch to build the tooling from
9197 - name : Checkout tools branch
92- uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
98+ uses : actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
9399 with :
94100 # Recall that on the `leanprover-community/mathlib4-nightly-testing` repository,
95101 # we don't maintain a `master` branch at all.
99105 path : tools-branch
100106
101107 - name : Checkout local actions
102- uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
108+ uses : actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
103109 with :
104110 ref : ${{ github.workflow_sha }}
105111 fetch-depth : 1
@@ -122,11 +128,14 @@ jobs:
122128
123129 # Checkout the PR branch into a subdirectory
124130 - name : Checkout PR branch
125- uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
131+ uses : actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
126132 with :
127133 ref : ${{ inputs.pr_branch_ref }}
128134 fetch-depth : 2 # we may fetch cache from the commit before this one (or earlier)
129135 path : pr-branch
136+ # This is an untrusted (potentially fork) checkout whose code we build.
137+ # Don't leave the GITHUB_TOKEN in pr-branch/.git/config, where that code could read it.
138+ persist-credentials : false
130139
131140 - name : Prepare DownstreamTest directory
132141 shell : bash
@@ -513,19 +522,19 @@ jobs:
513522 run : |
514523 cd pr-branch
515524 set -o pipefail
516- # Try running with --trace; if it fails due to argument parsing, the PR needs to merge master
525+ # If lint fails because the PR predates lake-lint configuration or the
526+ # old --trace argument-parsing behavior, ask the author to merge master.
517527 # We use .lake/ for the output file because landrun restricts /tmp access
518528 for attempt in 1 2; do
519- if timeout 10m env LEAN_ABORT_ON_PANIC=1 stdbuf -oL lake exe runLinter --trace Mathlib 2>&1 | tee ".lake/lint_output_attempt_${attempt}.txt"; then
529+ if timeout 10m env LEAN_ABORT_ON_PANIC=1 stdbuf -oL lake lint -- --trace 2>&1 | tee ".lake/lint_output_attempt_${attempt}.txt"; then
520530 break
521531 fi
522532 status=${PIPESTATUS[0]}
523- if grep -q "cannot parse arguments" ".lake/lint_output_attempt_${attempt}.txt"; then
533+ if grep -qE "cannot parse arguments|no lint driver configured " ".lake/lint_output_attempt_${attempt}.txt"; then
524534 echo ""
525535 echo "=============================================================================="
526- echo "ERROR: Your branch uses an older version of runLinter that doesn't support"
527- echo "the --trace flag. Please merge 'master' into your PR branch to get the"
528- echo "updated linter, then push again."
536+ echo "ERROR: Your branch predates the current 'lake lint' configuration."
537+ echo "Please merge 'master' into your PR branch and push again."
529538 echo ""
530539 echo "You can do this with:"
531540 echo " git fetch upstream"
@@ -574,7 +583,7 @@ jobs:
574583 - name : Generate lean-pr-testing app token
575584 if : ${{ always() && github.repository == 'leanprover-community/mathlib4-nightly-testing' && (startsWith(github.ref_name, 'lean-pr-testing-') || startsWith(github.ref_name, 'batteries-pr-testing-')) }}
576585 id : lean-pr-testing-token
577- uses : actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
586+ uses : actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
578587 with :
579588 # `batteries-pr-testing-*` branches need a token scoped to `leanprover-community/batteries`
580589 # for the labelling API; `lean-pr-testing-*` branches need one scoped to `leanprover/lean4`.
@@ -605,6 +614,10 @@ jobs:
605614 name : Upload to cache
606615 needs : [build]
607616 runs-on : ubuntu-latest # These steps run on a GitHub runner; no landrun sandboxing is needed.
617+ # Pins the OIDC `sub` claim to `...:environment:<cache_environment>`, which the Azure cache
618+ # app's federated credential is scoped to. A token minted by any job without this environment
619+ # (e.g. the untrusted build/post_steps/style_lint jobs) cannot satisfy that trust.
620+ environment : ${{ inputs.cache_environment }}
608621 permissions :
609622 contents : read
610623 id-token : write
@@ -614,7 +627,7 @@ jobs:
614627 if : ${{ always() && needs.build.outputs.cache-staging-has-files == 'true' }}
615628 steps :
616629 - name : Checkout tools branch
617- uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
630+ uses : actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
618631 with :
619632 ref : ${{ inputs.tools_branch_ref != '' && inputs.tools_branch_ref || (github.repository == 'leanprover-community/mathlib4-nightly-testing' && 'nightly-testing-green' || 'master') }}
620633 fetch-depth : 1
@@ -684,11 +697,17 @@ jobs:
684697 needs : [build, upload_cache]
685698 if : ${{ always() && needs.build.result == 'success' && (needs.upload_cache.result == 'success' || needs.upload_cache.result == 'skipped') }}
686699 runs-on : ubuntu-latest # Note these steps run on disposable GitHub runners, so no landrun sandboxing is needed.
700+ # This job checks out and executes (potentially fork) PR code unsandboxed,
701+ # so it must not inherit any write-capable token.
702+ permissions :
703+ contents : read
687704 steps :
688705
689- - uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
706+ - uses : actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
690707 with :
691708 ref : ${{ inputs.pr_branch_ref }}
709+ # Untrusted (potentially fork) checkout: don't persist the GITHUB_TOKEN into its .git/config.
710+ persist-credentials : false
692711
693712 - name : Configure Lean
694713 uses : leanprover/lean-action@38fbc41a8c28c4cbaec22d7f7de508ec2e7c0dd9 # v1.5.0
@@ -734,7 +753,7 @@ jobs:
734753 lake exe graph
735754
736755 - name : Checkout local actions
737- uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
756+ uses : actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
738757 with :
739758 ref : ${{ github.workflow_sha }}
740759 fetch-depth : 1
@@ -748,6 +767,21 @@ jobs:
748767 run : |
749768 lake env lean --run "${CI_SCRIPTS_DIR}/pr_summary/dumpReasonableDecls.lean" \
750769 --out decls.txt --imports-out imports.json Mathlib
770+ ## Record the PR number so the post-build `decls-diff` workflow can find
771+ ## the comment to patch without the (laggy) commit-SHA search API. Empty
772+ ## for non-PR builds (push to master / bors); the consumer then falls
773+ ## back to the commit's associated PRs.
774+ printf '%s' "${{ github.event.pull_request.number }}" > pr_number.txt
775+
776+ - name : ensure dump outputs are regular files
777+ run : |
778+ for f in decls.txt imports.json import_graph.dot pr_number.txt; do
779+ if [ -L "$f" ] || [ ! -f "$f" ]; then
780+ echo "Refusing to upload: $f is not a regular file." >&2
781+ ls -la -- "$f" >&2 || true
782+ exit 1
783+ fi
784+ done
751785
752786 - name : upload the import graph
753787 uses : actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
@@ -757,12 +791,13 @@ jobs:
757791 import_graph.dot
758792 decls.txt
759793 imports.json
794+ pr_number.txt
760795 # # Master pushes: 90 days, so later PRs forked from these commits
761796 # # can consume the dumps from the artifact. Other branches: 7 days.
762797 retention-days : ${{ github.ref == 'refs/heads/master' && '90' || '7' }}
763798
764799 - name : clean up the import graph file
765- run : rm -f import_graph.dot decls.txt imports.json
800+ run : rm -f import_graph.dot decls.txt imports.json pr_number.txt
766801
767802 - name : check all scripts build successfully
768803 run : |
@@ -788,6 +823,10 @@ jobs:
788823 style_lint :
789824 name : Lint style
790825 runs-on : ubuntu-latest
826+ # This job lints (potentially fork) PR code, so it must not inherit any write-capable token.
827+ # In `check` mode lint-style-action only reads and validates code locally (no API calls).
828+ permissions :
829+ contents : read
791830 steps :
792831 - uses : leanprover-community/lint-style-action@a7e7428fa44f9635d6eb8e01919d16fd498d387a # 2025-08-18
793832 with :
@@ -895,7 +934,7 @@ jobs:
895934 steps.get-label-actor.outputs.username != 'mathlib-update-dependencies' &&
896935 steps.get-label-actor.outputs.username != 'mathlib-splicebot'
897936 name: check team membership
898- uses: tspascoal/get-user-teams-membership@818140d631d5f29f26b151afbe4179f87d9ceb5e # v4.0.1
937+ uses: tspascoal/get-user-teams-membership@b2546c5affc730fd8e3d8483ae9ad3621938c2f9 # v4.0.2
899938 id: actorTeams
900939 with:
901940 organization: leanprover-community # optional. Default value ${{ github.repository_owner }}
@@ -914,7 +953,7 @@ jobs:
914953 contains(steps.actorTeams.outputs.teams, 'bot-users')
915954 )
916955 name: If `auto-merge-after-CI` is present, add a `bors merge` comment.
917- uses: GrantBirki/comment@608e41b19bc973020ec0e189ebfdae935d7fe0cc # v2.1.1
956+ uses: GrantBirki/comment@3439715f0cf3b8fc29bf47be0e3226679c06c41a # v3.0.0
918957 with:
919958 # This token is masked by the token minting action and will not be logged accidentally.
920959 token: ${{ steps.auto-merge-app-token.outputs.token }}
0 commit comments