- Shell 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
The nightly [Update Functional Test Toolchain](https://github.com/leanprover/lean-action/actions/workflows/update_functional_test_toolchain.yml) job fails whenever a newer Lean release exists ([example run](https://github.com/leanprover/lean-action/actions/runs/30730139508)). It detects the release and rewrites `.github/workflows/functional_tests.yml` correctly, then dies on the push: ``` ! [remote rejected] auto-update/functional-test-toolchain (refusing to allow a GitHub App to create or update workflow `.github/workflows/functional_tests.yml` without `workflows` permission) ``` GitHub blocks any token from committing to files under `.github/workflows/` unless it carries the `workflow` scope. The default `GITHUB_TOKEN` cannot have it — `workflows: write` is not a grantable key in a workflow's `permissions:` block — so no permissions change can fix this. This PR removes the need for such a token by moving the pinned toolchain out of the workflow file: - `.github/functional_test_toolchain` (new) holds `leanprover/lean4:v4.32.2`, mirroring the format of Lean's own `lean-toolchain` files. - `functional_tests.yml` gains a `resolve-toolchain` job that reads that file — or the `workflow_dispatch` input when one is given — and exposes the result as a job output. The toolchain-consuming jobs take `needs: resolve-toolchain` and reference `${{ needs.resolve-toolchain.outputs.toolchain }}`. The two legacy-`leanchecker` jobs are unchanged, since nothing auto-edits `legacy_toolchain`. - The updater reads and writes the new file, so it no longer touches `.github/workflows/` and the default `GITHUB_TOKEN` suffices. - The new file is added to the `paths:` filter so a toolchain bump still triggers the functional tests. ### Notes - The `workflow_dispatch` input default is now `""` rather than a prefilled version; leaving it blank uses the pinned toolchain. The screenshot in `CONTRIBUTING.md` is slightly stale in that respect. - This fixes the push failure only. PRs opened with `GITHUB_TOKEN` still do not trigger `pull_request` workflows, so functional tests will not run automatically on the generated PR. Setting `TOOLCHAIN_UPDATE_TOKEN` — now needing only `contents` and `pull-requests`, not `workflow` — or closing and reopening the PR remains the workaround. That caveat is still documented in the updater's header comment. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
| .github | ||
| scripts | ||
| action.yml | ||
| CHANGELOG.md | ||
| CONTRIBUTING.md | ||
| LICENSE | ||
| README.md | ||
| RELEASING.md | ||
lean-action - CI for Lean Projects
lean-action provides steps to build, test, and lint Lean projects on GitHub
Quick Setup
To setup lean-action to run on pushes and pull request in your repo, create the following ci.yml file the .github/workflows
name: CI
on:
push:
branches: ["main"] # replace "main" with the default branch
pull_request:
branches: ["main"]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# uses lean standard action with all default input values
- uses: leanprover/lean-action@v1
Important
lean-actionis tested onubuntu-latest,macos-latest, andwindows-latestGitHub-hosted runners. We recommend using one of these runners for the best experience, however if you encounter an issue when using a different runner, please still open an issue.
Caching .lake directory with GitHub's actions\cache
By default, lean-action uses actions\cache to cache the .lake directory and speed up builds.
Note
GitHub caching is distinct from Mathlib caching with
lake exe cache get
Cache keys
lean-action uses cache keys to save and restore caches.
First it uses a primary key, composed of the runner operating system, the runner architecture (X86, X64, ARM, ARM64), the Lake manifest, and the git commit hash, to save/restore caches from an exact git commit.
If there is no primary key cache hit, lean-action uses a fallback key,
composed of the operating system, the architecture, and the Lake manifest but not the git commit hash,
to restore a cache from a previous commit.
Troubleshooting problems with caching
Because caches are shared across different jobs, caching build files can lead to unexpected behavior and errors.
To determine if the GitHub cache is causing problems you can disable caching with the use-github-cache input.
- uses: leanprover/lean-action@v1
with:
use-github-cache: false
For more complex workflows, you may want more control over how the actions\cache caches the build in your workflow,
(.e.g., modifying the cache key to respect a build matrix)
you can wrap lean/action with use-github-cache: false in your own call to actions\cache.
Configuring which features lean-action runs
Most use cases only require a subset of lean-action's features
in a specific GitHub workflow.
Additionally, you may want to break up usage of lean-action
across multiple workflows with different triggers,
e.g., one workflow for PRs and another workflow scheduled by a cron job.
To support these use cases,
lean-action provides inputs to specify the subset of desired features of lean-action.
Directly specifying a desired feature with specific feature inputs
Each feature of lean-action has a corresponding input which users can set to true or false.
Specific feature inputs have the highest precedence
when lean-action determines which features to run.
When a feature input is set lean-action will always try to run the corresponding step.
If lean-action is unable to successfully run the step, lean-action will fail.
lean-action provides the following feature inputs:
buildtestlintmk_all-checkcheck-reservoir-eligibilityleancheckernanoda
Automatic configuration
After feature inputs, lean-action uses the auto-config input
to determine if it should use the Lake workspace to decide which steps to run automatically.
When auto-config: true, lean-action will use the Lake workspace to detect targets
and run the corresponding Lake command.
When auto-config: false, lean-action will only run features specified directly through specific feature inputs.
Users can combine auto-config with specific feature inputs to override the automatic configuration of lean-action.
lean-action can automatically configure the following features:
buildtestlint
Breaking up lean-action across workflows
Sometimes it is useful to break up usage of lean-action
across multiple workflows with different triggers,
e.g., one workflow for PRs and another workflow scheduled by a cron job.
auto-config: false allows users to run only a specific subset of features of lean-action.
For example, run only leanchecker in a cron job workflow:
- name: "run `lean-action` with only `leanchecker: true`"
id: lean-action
uses: leanprover/lean-action@v1
with:
auto-config: false
leanchecker: true
Differences between using auto-config and feature inputs
When you specify a feature with a feature input, lean-action will fail if it can't complete that step.
However, if you use auto-config,
lean-action will only fail if it detects a target in the Lake workspace and the detected target fails.
For example, if the lakefile.lean contains an improperly configured test_driver target
and you configure lean-action with test: true, lean-action will fail.
However the same improperly configured test_driver may not cause a lean-action failure with auto-config: true,
because lean-action may not detect the test_driver in the Lake workspace.
To be certain lean-action runs a step, specify the desire feature with a feature input.
Customization
lean-action provides optional configuration inputs to customize the behavior for your specific workflow.
- uses: leanprover/lean-action@v1
with:
# Automatically configure `lean-action` based on the Lake workspace.
# When set to "true", `lean-action` will use the Lake workspace to determine
# the set of features to run on the repository, such as `lake build` and `lake test`.
# Even when set to "true", the user can still override the auto configuration
# with the `build` and `test` inputs.
# Allowed values: "true" or "false".
# Default: "true"
auto-config: ""
# Run `lake build`.
# Note, this input takes precedence over `auto-config`.
# Allowed values: "true" | "false" | "default".
build: ""
# Run `lake test`.
# Note, this input takes precedence over `auto-config`.
# Allowed values: "true" | "false" | "default".
test: ""
# Run `lake lint`.
# Note, this input takes precedence over `auto-config`.
# Allowed values: "true" | "false" | "default".
lint: ""
# Check all files are imported with `lake exe mk_all --check`.
# Allowed values: "true" | "false".
mk_all-check: ""
# Build arguments to pass to `lake build {build-args}`.
# For example, `build-args: "--quiet"` will run `lake build --quiet`.
# By default, `lean-action` calls `lake build` with no arguments.
build-args: ""
# Test arguments to pass to `lake test {test-args}`.
# For example, `test-args: "--quiet"` will run `lake test --quiet`.
# By default, `lean-action` calls `lake test` with no arguments.
test-args: ""
# By default, `lean-action` attempts to automatically detect a Mathlib dependency and run `lake exe cache get` accordingly.
# Setting `use-mathlib-cache` will override automatic detection and run (or not run) `lake exe cache get`.
# Project must be downstream of Mathlib to use the Mathlib cache.
# Allowed values: "true" | "false" | "auto".
# Default: "auto"
use-mathlib-cache: ""
# Check if the repository is eligible for the Reservoir.
# Allowed values: "true" | "false".
# Default: "false"
check-reservoir-eligibility: ""
# Check environment with leanchecker.
# Uses the bundled `leanchecker` binary on Lean `nightly-2026-01-09` / `v4.28.0-rc1`
# and newer, and falls back to the external `lean4checker` repository on older versions.
# Allowed values: "true" | "false".
# Default: "false"
leanchecker: ""
# Deprecated alias for `leanchecker`.
lean4checker: ""
# Check environment with nanoda external type checker.
# nanoda is an independent Lean 4 type checker written in Rust.
# Requires Rust toolchain (will be installed automatically if not present).
# Allowed values: "true" | "false".
# Default: "false"
nanoda: ""
# When running nanoda, permit the sorryAx axiom.
# Set to "false" if your project should have no sorry placeholders.
# Allowed values: "true" | "false".
# Default: "true"
nanoda-allow-sorry: ""
# Enable GitHub caching.
# Allowed values: "true" or "false".
# If use-github-cache input is not provided, the action will use GitHub caching by default.
# Default: "true"
use-github-cache: ""
# The directory where `lean-action` will look for a Lake package and run `lake build`, etc.
# Allowed values: a valid directory containing a Lake package.
# If lake-package-directory is not provided, `lean-action` will use the root directory of the repository by default.
lake-package-directory: ""
# Always reinstall the Lean toolchain if it is a transient one, hosted on the lean4-pr-releases repository.
# This ensures that CI always uses the latest build of that toolchain.
# This setting only applies to `lean4-pr-releases/pr-release-XXXX` toolchains:
# regular Lean toolchain releases remain cached.
# The toolchain version is determined from the `lean-toolchain` file.
# Allowed values: "true" | "false".
# Default: "false"
reinstall-transient-toolchain: ""
Output Parameters
lean-action provides the following output parameters for downstream steps:
build-status- Values: "SUCCESS" | "FAILURE" | ""
test-status- Values: "SUCCESS" | "FAILURE" | ""
lint-status- Values: "SUCCESS" | "FAILURE" | ""
mk_all-status- Values: "SUCCESS" | "FAILURE" | ""
nanoda-status- Values: "SUCCESS" | "FAILURE" | ""
Note, a value of empty string indicates lean-action did not run the corresponding feature.
Example: Use test-status output parameter in downstream step
- name: "run `lean-action` with `lake test`"
id: lean-action
uses: leanprover/lean-action@v1
continue-on-error: true
with:
test: true
- name: log `lean-action` `test-status` output
env:
TEST_STATUS: ${{ steps.lean-action.outputs.test-status }}
run: echo "Test status: $TEST_STATUS"
Additional Examples
Check package for reservoir eligibility
- uses: leanprover/lean-action@v1
with:
check-reservoir-eligibility: true
Don't run lake test or use Mathlib cache
- uses: leanprover/lean-action@v1
with:
test: false
use-mathlib-cache: false
Run lake build with --wfail
- uses: leanprover/lean-action@v1
with:
build-args: "--wfail"
Run additional steps after lean-action using the Lean environment
After calling lean-action you can leverage the Lean environment in later workflow steps.
For example, leanprover-community/import-graph uses the setup from lean-action to test the graph executable with lake exe graph:
steps:
- uses: leanprover/lean-action@v1
with:
check-reservoir-eligibility: true
# use setup from lean-action to perform the following steps
- name: verify `lake exe graph` works
run: |
lake exe graph
rm import_graph.dot
External Type Checking with nanoda
nanoda is an independent Lean 4 type checker written in Rust. It provides additional assurance that your project's declarations are well-typed by verifying them with a completely separate implementation.
Enable nanoda verification
- uses: leanprover/lean-action@v1
with:
nanoda: true
Require no sorry placeholders
By default, nanoda permits the sorryAx axiom for projects with incomplete proofs. To require all proofs be complete:
- uses: leanprover/lean-action@v1
with:
nanoda: true
nanoda-allow-sorry: false
Daily nanoda verification with notifications
For daily verification runs with automatic failure notifications, use the reusable workflow:
# .github/workflows/nanoda-daily.yml
name: Daily nanoda verification
on:
schedule:
- cron: '0 0 * * *'
workflow_dispatch:
jobs:
verify:
uses: leanprover/lean-action/.github/workflows/nanoda-daily.yml@v1
# Optional: configure notification method
# with:
# notify: 'issue' # default: creates GitHub issue on failure
# For webhook (Slack/Discord):
# with:
# notify: 'webhook'
# secrets:
# webhook-url: ${{ secrets.WEBHOOK_URL }}
# For Zulip:
# with:
# notify: 'zulip'
# zulip-org-url: 'leanprover.zulipchat.com'
# secrets:
# zulip-api-key: ${{ secrets.ZULIP_API_KEY }}
Projects which use lean-action
Keep the action updated with dependabot
Because Lean is under heavy development, changes to Lean or Lake could break outdated versions of lean-action. You can configure dependabot to automatically create a PR to update lean-action when a new stable version is released.
Here is an example .github/dependabot.yml which configures dependabot to check daily for updates to all GitHub actions in your repository:
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
See the dependabot documentation for all configuration options.