Repository navigation
Conversation
Adds a `lake-check` input that runs `lake check` (added in Lean `v4.35.0-rc1`): it builds the project, exports it, and replays the result through one or more kernels inside a bubblewrap sandbox, erroring on any use of a non-standard axiom. `lake-check: "true"` uses Lean's own kernel. `"paranoid"` (`--paranoid`, added in `v4.35.0-rc2`) additionally runs every checker the toolchain bundles: `leanchecker-paranoid`, `lean4lean`, `nanoda`, `con-leche` and `con-ron`. Release toolchains ship all five, so nothing is cloned or compiled. Support is feature-detected from the content of `lake check --help` rather than from version strings, because toolchains are frequently nightlies or PR builds whose versions do not order usefully. A Lake without `lake check` prints its top-level help and still exits 0, so the detection cannot key off the exit status. A requested check that cannot run is an error rather than a silent pass. The sandbox is probed before the check runs, because `lake check` exits 1 both when it rejects a project and when bubblewrap fails to start, and reporting a sandbox failure as a rejection would blame the project for a setup problem. The probe's diagnostic decides which remedy the error names: a denied uid map means the runner restricts user namespaces, while a denied `pivot_root` means the job is in a container and needs a privileged one. This script does not build the project. `lake check` builds it inside the sandbox, and whether it is also built on the runner first is the `build` input's business, so running one unconditionally here would override that choice.
0decfaf to
a4136f4
Compare
Resolve the CHANGELOG conflict with the SHA pinning of #193, and pin the checkout steps this PR adds to the same SHA. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The deprecation of `nanoda` points users at `lake-check: paranoid`, which #190 adds, so this PR now builds on it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Thanks @kim-em. Looking forward to using Would you be open to simplifying Some of the script reproduces errors Lake already reports clearly, and the rest adds complexity we may not need. Running it locally:
So I think we can drop the help-text feature detection, the I'd keep the mode validation, the One ordering caveat: since the probe runs before Thoughts? |
This PR adds a
lake-checkinput that runslake check(added in Leanv4.35.0-rc1): it builds the project, exports it, and replays the result through one or more kernels inside a bubblewrap sandbox, erroring on any use of a non-standard axiom. The reference manual places this among the other ways to validate a proof, in Validating a Lean Proof.lake-check: "true"uses Lean's own kernel;"paranoid"(--paranoid, added inv4.35.0-rc2) additionally runs every checker the toolchain bundles:leanchecker-paranoid,lean4lean,nanoda,con-lecheandcon-ron. Release toolchains ship all five, so nothing is cloned or compiled.The script does not build the project itself.
lake checkbuilds it inside the sandbox, and whether it is also built on the runner first is thebuildinput's business: leavingbuildon is faster, becauselake checkthen starts from a populated.lake, whilebuild: falsekeeps the project's code off the runner. Building unconditionally here would take that choice away.Support is feature-detected from the content of
lake check --helprather than from version strings, because toolchains are frequently nightlies or PR builds whose versions do not order usefully. A Lake withoutlake checkprints its top-level help and still exits 0, so the detection cannot key off the exit status.A requested check that cannot run is an error rather than a silent pass. The sandbox is probed before the check runs, because
lake checkexits 1 both when it rejects a project and when bubblewrap fails to start, and reporting a sandbox failure as a rejection would blame the project for a setup problem. The probe's own diagnostic picks the remedy the error names: a denied uid map means the runner restricts user namespaces, while a deniedpivot_rootmeans the job is running in a container and needs a privileged one.Those two cases are the two runner families this was tested against. GitHub-hosted runners restrict user namespaces, so they need them granted before
lean-actionis called, which the README shows. Namespace runners fail differently, atpivot_root, for root as well as for the job user, and neednamespace-features:container.privileged=truewith the-with-featuressuffix on the machine label; such a container permits user namespaces too, so it needs nothing else. Automating the GitHub-hosted case is deliberately left to a follow-up, because it means runningsudoto change a runner's security posture and deserves its own review.Two functional tests, pinned to
v4.35.0-rc2, cover this:paranoidon a privileged Namespace runner, asserting it passes on a clean package and fails once asorryis introduced, and one asserting an unsupported toolchain fails loudly. The second pins the legacy toolchain rather than the moving default, so that it cannot quietly stop testing feature detection once the default gainslake check.🤖 Prepared with Claude+Codex