Repository: leanprover/lean-action
Pull request #122: feat: reinstall transient `lean4-pr-releases` toolchains
Author: login: Vierkantor
Created: 2025-04-10T10:49:21Z | Merged: 2025-04-21T21:37:59Z

This PR adds the option to check if the current toolchain is a transient one hosted on the lean4-pr-releases repository. If so, `lean-action` will remove the old version of the toolchain. This ensures a fresh version of the toolchain is always used to run CI.

This is an important step in many Mathlib CI workflows, and adding it to this action would allow us to switch some custom workflows over to run mostly via `lean-action`.


Diff:
diff --git a/.github/functional_tests/reinstall-transient-toolchain/action.yml b/.github/functional_tests/reinstall-transient-toolchain/action.yml
new file mode 100644
index 0000000..55f91f7
--- /dev/null
+++ b/.github/functional_tests/reinstall-transient-toolchain/action.yml
@@ -0,0 +1,70 @@
+name: 'Reinstall Transient Toolchain Functional Test'
+description: |
+  Run `lean-action` with `reinstall-transient-toolchain: true`.
+  Verify that the toolchain will be redownloaded.
+inputs:
+  toolchain:
+    description: 'Toolchain to use for `lake init` (not the toolchain that will be tested for reinstallation).'
+    required: true
+runs: 
+  using: 'composite'
+  steps:
+    # TODO: once `lean-action` supports just setup, use it here
+    - name: install elan
+      run: |
+        set -o pipefail
+        curl https://raw.githubusercontent.com/leanprover/elan/master/elan-init.sh -sSf | sh -s -- -y --default-toolchain ${{ inputs.toolchain }}
+        echo "$HOME/.elan/bin" >> "$GITHUB_PATH"
+      shell: bash
+
+    - name: create lake package
+      run: |
+        lake init transienttoolchain .lean
+        lake update
+      shell: bash
+
+    - name: set a toolchain
+      run: |
+        echo "leanprover/lean4-pr-releases:pr-release-6627" > lean-toolchain
+      shell: bash
+
+    - name: "run `lean-action` to install the toolchain"
+      id: lean-action-install
+      uses: ./
+      with:
+        auto-config: true
+        use-github-cache: false
+
+    - name: verify the toolchain is installed
+      run: |
+        elan toolchain list | grep -qFx "leanprover/lean4-pr-releases:pr-release-6627"
+      shell: bash
+
+    - name: verify `lean-action` outcome success
+      env:
+        OUTPUT_NAME: "lean-action-install.outcome"
+        EXPECTED_VALUE: "success"
+        ACTUAL_VALUE: ${{ steps.lean-action-install.outcome }}
+      run: .github/functional_tests/test_helpers/verify_action_output.sh
+      shell: bash
+
+    - name: "run `lean-action` to uninstall the toolchain"
+      id: lean-action-uninstall
+      uses: ./
+      with:
+        reinstall-transient-toolchain: true
+        auto-config: false
+        use-github-cache: false
+
+    - name: verify the toolchain is no longer installed
+      run: |
+        ! elan toolchain list | grep -qFx "leanprover/lean4-pr-releases:pr-release-6627"
+      shell: bash
+
+    - name: verify `lean-action` outcome success
+      env:
+        OUTPUT_NAME: "lean-action.outcome"
+        EXPECTED_VALUE: "success"
+        ACTUAL_VALUE: ${{ steps.lean-action-uninstall.outcome }}
+      run: .github/functional_tests/test_helpers/verify_action_output.sh
+      shell: bash
diff --git a/.github/workflows/functional_tests.yml b/.github/workflows/functional_tests.yml
index bb7a7cb..4189cac 100644
--- a/.github/workflows/functional_tests.yml
+++ b/.github/workflows/functional_tests.yml
@@ -126,6 +126,14 @@ jobs:
         with:
           toolchain: ${{ env.toolchain }}
 
+  reinstall-transient-toolchain:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+      - uses: ./.github/functional_tests/reinstall-transient-toolchain
+        with:
+          toolchain: ${{ env.toolchain }}
+
   macos-runner:
     runs-on: macos-latest
     steps:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4d6e5e8..180f28f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## Unreleased
 
+### Added
+
+- add option to reinstall `lean4-pr-releases` toolchains, ensuring CI runs with thev latest version
+
 ## v1.1.2 - 2025-03-28
 
 ### Fixed
diff --git a/README.md b/README.md
index f847577..631e583 100644
--- a/README.md
+++ b/README.md
@@ -202,6 +202,15 @@ To be certain `lean-action` runs a step, specify the desire feature with a featu
     # 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
diff --git a/action.yml b/action.yml
index 136a39e..44fab4f 100644
--- a/action.yml
+++ b/action.yml
@@ -84,6 +84,13 @@ inputs:
       If lake-package-directory is not provided, `lean-action` will use the root directory of the repository by default.
     required: false
     default: "."
+  reinstall-transient-toolchain:
+    description: |
+      When the `lean-toolchain` file specifies a `lean-pr-release` toolchain, uninstall it before running any `lake` commands.
+      This ensures the latest build of the toolchain will be downloaded and used to run CI steps.
+      Allowed values: "true" | "false".
+    required: false
+    default: "false"
 outputs:
   build-status:
     description: |
@@ -129,6 +136,17 @@ runs:
       shell: bash
       working-directory: ${{ inputs.lake-package-directory }}
 
+    - name: reinstall transient toolchain
+      if: ${{ inputs.reinstall-transient-toolchain == 'true' }}
+      run: |
+        : Reinstall Transient Toolchains
+        if [[ "$(cat lean-toolchain)" =~ ^leanprover/lean4-pr-releases:pr-release-[0-9]+$ ]]; then
+          printf 'Uninstalling transient toolchain %s\n' "$(cat lean-toolchain)"
+          elan toolchain uninstall "$(cat lean-toolchain)"
+        fi
+      shell: bash
+      working-directory: ${{ inputs.lake-package-directory }}
+
     - uses: actions/cache/restore@v4
       if: ${{ inputs.use-github-cache == 'true' }}
       with:


Reviews:
user: login: grunweg
body: Two small nits
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-23T12:21:31Z
user: login: Vierkantor
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T12:23:48Z
user: login: Vierkantor
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T12:24:14Z
user: login: Vierkantor
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T12:26:59Z
user: login: grunweg
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-23T13:27:12Z

Review comments:
diff_hunk: @@ -0,0 +1,70 @@
+name: 'Reinstall Transient Toolchain Functional Test'
+description: |
+  Run `lean-action` with `reinstall-transient-toolchain: true`.
+  Verify that the toolchain will be redownloaded.
+inputs:
+  toolchain:
+    description: 'Toolchain to use for `lake init` (not the toolchain that will be tested for reinstallation).'
+    required: true
+runs: 
+  using: 'composite'
+  steps:
+    # TODO: once `lean-action` supports just setup, use it here
path: .github/functional_tests/reinstall-transient-toolchain/action.yml
user: login: grunweg
body: Isn't that possible now, given that mathlib uses this? (Or should the comment refer to something else?)
created_at: 2025-04-23T12:21:02Z
author_association: NONE
diff_hunk: @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## Unreleased
 
+### Added
+
+- add option to reinstall `lean4-pr-releases` toolchains, ensuring CI runs with thev latest version
path: CHANGELOG.md
user: login: grunweg
body: ```suggestion
- add option to always reinstall `lean4-pr-releases` toolchains, ensuring CI runs with the latest version
created_at: 2025-04-23T12:21:24Z
author_association: NONE
diff_hunk: @@ -0,0 +1,70 @@
+name: 'Reinstall Transient Toolchain Functional Test'
+description: |
+  Run `lean-action` with `reinstall-transient-toolchain: true`.
+  Verify that the toolchain will be redownloaded.
+inputs:
+  toolchain:
+    description: 'Toolchain to use for `lake init` (not the toolchain that will be tested for reinstallation).'
+    required: true
+runs: 
+  using: 'composite'
+  steps:
+    # TODO: once `lean-action` supports just setup, use it here
path: .github/functional_tests/reinstall-transient-toolchain/action.yml
user: login: Vierkantor
body: The problem, I believe, is that the setup step still needs a lake package (`lean-toolchain` file to be precise). So this is still relevant to the tests.
created_at: 2025-04-23T12:23:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## Unreleased
 
+### Added
+
+- add option to reinstall `lean4-pr-releases` toolchains, ensuring CI runs with thev latest version
path: CHANGELOG.md
user: login: Vierkantor
body: Thanks! I'll open a new PR to fix this. :)
created_at: 2025-04-23T12:24:14Z
author_association: CONTRIBUTOR
diff_hunk: @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## Unreleased
 
+### Added
+
+- add option to reinstall `lean4-pr-releases` toolchains, ensuring CI runs with thev latest version
path: CHANGELOG.md
user: login: Vierkantor
body: #123
created_at: 2025-04-23T12:26:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,70 @@
+name: 'Reinstall Transient Toolchain Functional Test'
+description: |
+  Run `lean-action` with `reinstall-transient-toolchain: true`.
+  Verify that the toolchain will be redownloaded.
+inputs:
+  toolchain:
+    description: 'Toolchain to use for `lake init` (not the toolchain that will be tested for reinstallation).'
+    required: true
+runs: 
+  using: 'composite'
+  steps:
+    # TODO: once `lean-action` supports just setup, use it here
path: .github/functional_tests/reinstall-transient-toolchain/action.yml
user: login: grunweg
body: :bulb: Thanks for clarifying!
created_at: 2025-04-23T13:27:12Z
author_association: NONE

PR comments:
user: login: austinletson
created_at: 2025-04-10T22:30:21Z
body: This looks great! Thank you for adding the test.

Could you add `reinstall-transient-toolchain` to the usage in the [Customization](https://github.com/leanprover/lean-action?tab=readme-ov-file#customization) section of the README.md? Other than that this looks good to merge.


author_association: COLLABORATOR
user: login: austinletson
created_at: 2025-04-21T21:37:47Z
body: Thanks for updating the README.md!
author_association: COLLABORATOR
user: login: austinletson
created_at: 2025-04-21T21:42:04Z
body: @Vierkantor now that this is merged, the `reinstall-transient-toolchain` parameter will be available on `lean-action@main`, if you would like to do any testing before I cut a release.

Is there anything else required for Mathlib CI we should include in that release?
author_association: COLLABORATOR
user: login: Vierkantor
created_at: 2025-04-22T08:54:08Z
body: Thanks! I believe this step is the main missing ingredient, with the rest being more specific to Mathlib (so better put that in its own action that references this one).
author_association: CONTRIBUTOR
user: login: austinletson
created_at: 2025-04-24T14:18:58Z
body: > Thanks! I believe this step is the main missing ingredient, with the rest being more specific to Mathlib (so better put that in its own action that references this one).

Sounds good! I am traveling this weekend, but I will cut a new release early next week.
author_association: COLLABORATOR