Skip to content

Commit ba5cc46

Browse files
committed
merge
2 parents 5740d37 + 8f845ad commit ba5cc46

4,944 files changed

Lines changed: 82717 additions & 35192 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.git-blame-ignore-revs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# 2024-05-20 replace `refine'` with one underscore by `refine` (#13059)
2+
7493b5f81b4c031b87877c5c124bea1ddc4e567d
3+
# 2024-05-24 replace many `refine'` with `refine` (#13166)
4+
fc48848e4374f13c796a7399bfccd2e228f776df
5+
# 2025-11-19 move Mathlib to the module system (#31786)
6+
6a54a80825b060ab20dc31751ebdce78b3a3b518
7+
# 2025-12-01 fix spelling in doc-strings (#32286)
8+
b728e1450a53133aa4171eeadc0bc8d3ee58415c

.github/actions/cache-trust-dispatch/action.yml

Lines changed: 71 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Single source of truth mapping (repo, branch) → (upload container,
1+
# Single source of truth mapping (repo, ref) → (upload container,
22
# read fallback chain) for Mathlib's multi-container cache.
33
#
44
# Called by build, upload_cache, and post_steps in build_template.yml so
@@ -14,7 +14,10 @@ inputs:
1414
description: GitHub repo full name (`owner/name`).
1515
required: true
1616
branch:
17-
description: Branch name (`github.head_ref || github.ref_name`).
17+
description: |
18+
Branch name (`github.head_ref || github.ref_name`); on tag-triggered
19+
runs this is the tag name, distinguished via `github.ref_type` inside
20+
the dispatch step.
1821
required: true
1922
head-sha:
2023
description: |
@@ -55,6 +58,10 @@ runs:
5558
REPO="${{ inputs.repo }}"
5659
BRANCH="${{ inputs.branch }}"
5760
HEAD_SHA="${{ inputs.head-sha }}"
61+
# Whether `branch` names a branch or a tag. Read from the run context
62+
# rather than an input: unlike `repo`/`branch`, the value does not
63+
# depend on which event shape (PR vs push) the caller handles.
64+
REF_TYPE="${{ github.ref_type }}"
5865
PRIMARY=""
5966
READ_CHAIN=""
6067
REPO_SCOPE=""
@@ -66,32 +73,69 @@ runs:
6673
# be 403'd by Azure regardless. The dispatch exists so the workflow
6774
# does the right thing in the honest case; defence in depth is RBAC.
6875
76+
# Privileged containers (master, nightly-testing, pr-toolchain-tests) are
77+
# writable only by a repo's own native CI, whose OIDC token is RBAC-scoped
78+
# to match. A cross-repo pull request is built by build_fork.yml with
79+
# fork-trust credentials whatever repo the PR head lives on (e.g. a `bump/*`
80+
# branch on the mathlib4-nightly-testing fork), so it can only write
81+
# `forks`. `GITHUB_REPOSITORY` is the repo the workflow runs as (the base
82+
# repo for `pull_request_target`), i.e. the one whose credentials this job
83+
# holds; when it differs from `$REPO`, the build is a fork and targets
84+
# `forks` regardless of the head repo's own trust class.
85+
if [ "$REPO" != "$GITHUB_REPOSITORY" ]; then
86+
PRIMARY="forks"
87+
else
6988
case "$REPO" in
7089
"leanprover-community/mathlib4")
71-
case "$BRANCH" in
72-
"master"|"staging")
73-
# Master / staging are the only writers that feed `master`
74-
# (`staging` is bors's merge candidate, which fast-forwards to
75-
# `master`). Read `master` only, not the default [master,
76-
# legacy]: files the read chain serves are skipped at stage
77-
# time, so keeping `legacy` would leave legacy-only files out of
78-
# `master` for good. Reading `master` alone turns them into
79-
# misses that get rebuilt and uploaded, so `master` fills itself
80-
# into a standalone cache. (Only PRIMARY=master does this; other
81-
# runs write to `forks` and keep the wider chain.)
82-
PRIMARY="master"
83-
READ_CHAIN="master"
84-
;;
85-
*)
86-
# `bors trying`, `ci-dev/*`, maintainer dev branches on the
87-
# canonical repo: trust level is fork-equivalent (the OIDC
88-
# token's RBAC scopes them to `forks`). Reads must widen
89-
# past the default [master, legacy] so the post-build
90-
# verification finds the just-uploaded fork-trust artifacts.
91-
PRIMARY="forks"
92-
READ_CHAIN="master,forks,legacy"
93-
;;
94-
esac
90+
if [ "$REF_TYPE" = "tag" ]; then
91+
case "$BRANCH" in
92+
v4.*)
93+
# `v4.*` release tags: release_cache.yml rebuilds off-master
94+
# release commits (patch releases, patched release
95+
# candidates) and publishes them into `master`, the container
96+
# canonical checkouts read. Tag creation is restricted to
97+
# release managers by a tag ruleset, and the
98+
# `cache-upload-master` environment admits `v4.*` tag refs,
99+
# so these builds carry master trust. Reads are `master`-only
100+
# for the same fill-in reason as the master/staging arm
101+
# below.
102+
PRIMARY="master"
103+
READ_CHAIN="master"
104+
;;
105+
*)
106+
# Other tags have no trust class of their own:
107+
# fork-equivalent, like the dev-branch arm below.
108+
PRIMARY="forks"
109+
READ_CHAIN="master,forks,legacy"
110+
;;
111+
esac
112+
else
113+
case "$BRANCH" in
114+
"master"|"staging")
115+
# Master, staging, and `v4.*` release tags (above) are the
116+
# only writers that feed `master` (`staging` is bors's merge
117+
# candidate, which fast-forwards to `master`). Read `master`
118+
# only, not the default [master, legacy]: files the read
119+
# chain serves are skipped at stage time, so keeping `legacy`
120+
# would leave legacy-only files out of `master` for good.
121+
# Reading `master` alone turns them into misses that get
122+
# rebuilt and uploaded, so `master` fills itself into a
123+
# standalone cache. (Only PRIMARY=master does this; other
124+
# runs write to `forks` and keep the wider chain.)
125+
PRIMARY="master"
126+
READ_CHAIN="master"
127+
;;
128+
*)
129+
# `bors trying`, `ci-dev/*`, maintainer dev branches on the
130+
# canonical repo: trust level is fork-equivalent (the OIDC
131+
# token's RBAC scopes them to `forks`). Reads must widen
132+
# past the default [master, legacy] so the post-build
133+
# verification finds the just-uploaded fork-trust artifacts.
134+
PRIMARY="forks"
135+
READ_CHAIN="master,forks,legacy"
136+
;;
137+
esac
138+
fi
95139
;;
96140
"leanprover-community/mathlib4-nightly-testing")
97141
case "$BRANCH" in
@@ -121,6 +165,7 @@ runs:
121165
PRIMARY="forks"
122166
;;
123167
esac
168+
fi
124169
125170
# Per-commit cache namespace, only for fork-trust uploads. Closes the
126171
# within-fork temporal replay attack: each commit's CI run gets its
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# Get this commit's oleans, in two phases:
2+
# 1. Warm the cache from the `cache-snapshot` GitHub artifact (canonical repo only).
3+
# 2. Fetch this commit's oleans from the remote cache with the trusted master-built binary.
4+
# The fetch is HEAD-scoped (reads only this commit's own cache scope). The warm is fail-safe
5+
# (any failure → just the remote fetch) and its source is hardcoded, so nothing can redirect
6+
# the download off the trusted master pipeline.
7+
name: Get cache
8+
description: Get this commit's oleans into the local cache.
9+
inputs:
10+
working_directory:
11+
description: The lake project to fetch the cache for (e.g. the checked-out PR branch).
12+
required: true
13+
cache_bin:
14+
description: Path to the trusted `cache` binary, relative to `working_directory`.
15+
required: true
16+
runs:
17+
using: composite
18+
steps:
19+
# 1. Warm cache from the GitHub artifact. Resolve which snapshot to use: the one built
20+
# at this commit's merge-base with master (its unchanged files hash identically
21+
# there), else the newest still-retained one at-or-before it, else the latest (a
22+
# merge-base older than retention, or any failure, lands here). Canonical repo only.
23+
- name: Resolve cache snapshot
24+
id: resolve
25+
if: ${{ github.repository == 'leanprover-community/mathlib4' }}
26+
shell: bash
27+
env:
28+
GH_TOKEN: ${{ github.token }}
29+
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
30+
run: |
31+
set -uo pipefail
32+
runs="repos/leanprover-community/mathlib4/actions/workflows/build.yml/runs?branch=master&event=push&status=success"
33+
34+
# Each helper prints a matching successful master-push run-id, or empty.
35+
run_at() { gh api "${runs}&head_sha=$1" --jq '.workflow_runs[0].id // empty' 2>/dev/null || true; }
36+
latest_run() { gh api "${runs}&per_page=1" --jq '.workflow_runs[0].id // empty' 2>/dev/null || true; }
37+
# newest run created at-or-before date $1, but not older than cutoff $2
38+
newest_before() {
39+
gh api "${runs}&per_page=100" 2>/dev/null | jq -r --arg d "$1" --arg c "$2" \
40+
'[.workflow_runs[] | select(.created_at <= $d and ($c == "" or .created_at >= $c))][0].id // empty' \
41+
2>/dev/null || true
42+
}
43+
# True if run-id $1 actually carries a `cache-snapshot` artifact. Older runs
44+
# predate the feature and artifacts expire, so a successful run is not enough.
45+
# Filters server-side by name, but re-checks in jq in case `name` is ignored.
46+
has_snapshot() {
47+
[[ -n "$(gh api "repos/leanprover-community/mathlib4/actions/runs/$1/artifacts?name=cache-snapshot&per_page=100" \
48+
--jq '.artifacts[] | select(.name == "cache-snapshot") | .id' 2>/dev/null | head -1 || true)" ]]
49+
}
50+
51+
# This PR's merge-base with master (+ its commit date), and the cutoff below which
52+
# snapshots have expired (retention ~14d).
53+
mb_info=$(gh api "repos/leanprover-community/mathlib4/compare/master...${HEAD_SHA}" \
54+
--jq '.merge_base_commit | "\(.sha) \(.commit.committer.date)"' 2>/dev/null || true)
55+
read -r mb mb_date <<< "${mb_info}"
56+
cutoff=$(date -u -d '13 days ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || true)
57+
58+
# Prefer the merge-base's snapshot (while still retained), then the newest one
59+
# before it, then the latest of all.
60+
run_id=""
61+
if [[ -n "${mb}" && ( -z "${cutoff}" || "${mb_date}" > "${cutoff}" ) ]]; then
62+
run_id=$(run_at "${mb}")
63+
[[ -z "${run_id}" ]] && run_id=$(newest_before "${mb_date}" "${cutoff}")
64+
fi
65+
[[ -z "${run_id}" ]] && run_id=$(latest_run)
66+
67+
# The resolved run may carry no `cache-snapshot` artifact: an older merge-base
68+
# predating the feature, or one whose artifact already expired (older-than-today
69+
# runs often won't have one). Rather than let the download step hard-error on a
70+
# missing artifact, confirm it's present; if not, fall back to the latest master
71+
# run, and warm only if that one has it.
72+
if [[ -n "${run_id}" ]] && ! has_snapshot "${run_id}"; then
73+
echo "Run ${run_id} has no cache-snapshot artifact; falling back to latest master run."
74+
run_id=$(latest_run)
75+
if [[ -n "${run_id}" ]] && ! has_snapshot "${run_id}"; then
76+
run_id=""
77+
fi
78+
fi
79+
80+
echo "Resolved cache-snapshot run_id: '${run_id}' (merge-base: ${mb:-unknown})"
81+
echo "run_id=${run_id}" >> "$GITHUB_OUTPUT"
82+
83+
- name: Warm cache from GitHub artifact
84+
if: ${{ steps.resolve.outputs.run_id != '' }}
85+
continue-on-error: true # fail-safe: fall back to the remote fetch (step 2)
86+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
87+
with:
88+
name: cache-snapshot
89+
path: /home/lean/.cache/mathlib
90+
repository: leanprover-community/mathlib4
91+
run-id: ${{ steps.resolve.outputs.run_id }}
92+
github-token: ${{ github.token }}
93+
94+
# 2. Fetch this commit's oleans from the remote cache with the trusted `cache` binary
95+
# (outside landrun). Runs on every repo; the warm above just gives the canonical
96+
# repo a local head start. HEAD-scoped: reads only this commit's own cache scope.
97+
- name: Fetch cache from remote
98+
shell: bash
99+
env:
100+
WORKDIR: ${{ inputs.working_directory }}
101+
CACHE_BIN: ${{ inputs.cache_bin }}
102+
CACHE_REPO: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
103+
run: |
104+
set -eo pipefail
105+
cd "${WORKDIR}"
106+
rm -rf .lake/build/lib/lean/Mathlib
107+
log="${RUNNER_TEMP:-/tmp}/cache-get.log"
108+
# --repo so fork PRs also read their own repo-namespaced cache (master is read flat,
109+
# so this still gets the master bulk); for in-repo runs it resolves to the same repo.
110+
"${CACHE_BIN}" --repo="${CACHE_REPO}" get 2>&1 | tee "${log}"
111+
# Warmth = how much the snapshot covered HEAD: files already cached locally
112+
# (just decompressed) vs downloaded from Azure. Parsed best-effort from the log.
113+
warm=$(grep -oE 'Decompressing [0-9]+ already-cached' "${log}" | grep -oE '[0-9]+' | head -1 || true)
114+
cold=$(grep -oE 'Attempting to download [0-9]+' "${log}" | grep -oE '[0-9]+' | head -1 || true)
115+
echo "Cache warmth: ${warm:-0} already-cached (warm) / ${cold:-0} downloaded from Azure (cold)"

.github/actions/get-mathlib-ci/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ then use the local action:
2525

2626
```yaml
2727
- name: Checkout local actions
28-
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
28+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
2929
with:
3030
ref: ${{ github.workflow_sha }}
3131
fetch-depth: 1

.github/actions/get-mathlib-ci/action.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ inputs:
1010
# Default pinned commit used by workflows unless they explicitly override.
1111
# Update this ref as needed to pick up changes to mathlib-ci scripts
1212
# This is also updated automatically by .github/workflows/update_dependencies.yml
13-
default: 5aee9d4ce5a39050c72b4aa46015a824b0c189ac
13+
default: 5668fbbccf0fecefdfcddf539b8406db197dfc59
1414
path:
1515
description: Checkout destination path.
1616
required: false
@@ -33,7 +33,7 @@ runs:
3333
using: composite
3434
steps:
3535
- name: Get mathlib-ci
36-
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
36+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
3737
with:
3838
repository: leanprover-community/mathlib-ci
3939
ref: ${{ inputs.ref }}

.github/actions/get-tools/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ runs:
139139
140140
- name: Checkout tools branch (source build)
141141
if: ${{ steps.finalize.outputs.result == 'build' }}
142-
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
142+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
143143
with:
144144
ref: ${{ inputs.tools_source_ref }}
145145
path: ${{ inputs.path }}

0 commit comments

Comments
 (0)