├── .github ├── dependabot.yml └── workflows │ ├── autotag-releases.yml │ └── ci.yml ├── .pre-commit-config.yaml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── action.yml ├── rust.json └── test-workspace ├── Cargo.lock ├── Cargo.toml └── src └── main.rs /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "github-actions" 9 | directory: "/" 10 | schedule: 11 | interval: "weekly" 12 | -------------------------------------------------------------------------------- /.github/workflows/autotag-releases.yml: -------------------------------------------------------------------------------- 1 | # Create tags with only major or major.minor version 2 | # This runs for every created release. Releases are expected to use vmajor.minor.patch as tags. 3 | 4 | name: Autotag Release 5 | on: 6 | release: 7 | types: [released] 8 | workflow_dispatch: 9 | permissions: read-all 10 | 11 | jobs: 12 | autotag_release: 13 | runs-on: ubuntu-latest 14 | if: startsWith(github.ref, 'refs/tags/v') 15 | permissions: 16 | contents: write 17 | steps: 18 | - uses: actions/checkout@v5 19 | - name: Get version from tag 20 | id: tag_name 21 | run: | 22 | echo "current_version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT 23 | shell: bash 24 | - name: Create and push tags 25 | run: | 26 | MINOR="$(echo -n ${{ steps.tag_name.outputs.current_version }} | cut -d. -f1-2)" 27 | MAJOR="$(echo -n ${{ steps.tag_name.outputs.current_version }} | cut -d. -f1)" 28 | git tag -f "${MINOR}" 29 | git tag -f "${MAJOR}" 30 | git push -f origin "${MINOR}" 31 | git push -f origin "${MAJOR}" 32 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: { branches: [main] } 5 | pull_request: 6 | schedule: [cron: "40 1 * * *"] 7 | 8 | jobs: 9 | install: 10 | name: Rust ${{matrix.rust || '(default)'}} (toolchain-file=${{matrix.write-toolchain-file}}) (${{matrix.os}}) 11 | runs-on: ${{matrix.os}} 12 | strategy: 13 | fail-fast: false 14 | max-parallel: 5 15 | matrix: 16 | os: 17 | - ubuntu-latest 18 | - windows-latest 19 | - macos-latest 20 | write-toolchain-file: 21 | - false 22 | - true 23 | rust: 24 | # use stable toolchain as default 25 | - null 26 | 27 | # Test that the sparse registry check works. 28 | # 1.66 and 1.67 don't support stable sparse registry. 29 | - "1.66" 30 | 31 | - "nightly" 32 | - "beta" 33 | - "stable" 34 | steps: 35 | - uses: actions/checkout@v5 36 | 37 | # Test toolchain file support 38 | - name: Write rust-toolchain.toml 39 | if: matrix.write-toolchain-file 40 | shell: bash 41 | run: | 42 | cat <>rust-toolchain.toml 43 | [toolchain] 44 | channel = "nightly-2024-01-10" 45 | components = [ "rustfmt", "rustc-dev" ] 46 | targets = [ "wasm32-unknown-unknown", "thumbv7m-none-eabi" ] 47 | profile = "minimal" 48 | EOF 49 | 50 | - id: toolchain 51 | name: Run actions-rust-lang/setup-rust-toolchain ${{matrix.rust || 'on toolchain file'}} 52 | uses: ./ 53 | with: 54 | toolchain: ${{matrix.rust}} 55 | components: clippy 56 | 57 | - name: Check ${{'${{steps.toolchain.outputs.rustc-version}}'}} 58 | run: echo '${{steps.toolchain.outputs.rustc-version}}' 59 | 60 | - name: Check ${{'${{steps.toolchain.outputs.cargo-version}}'}} 61 | run: echo '${{steps.toolchain.outputs.cargo-version}}' 62 | 63 | - name: Check ${{'${{steps.toolchain.outputs.rustup-version}}'}} 64 | run: echo '${{steps.toolchain.outputs.rustup-version}}' 65 | 66 | - name: Check lack of toolchain input or file results in stable 67 | if: matrix.write-toolchain-file == false && matrix.rust == null 68 | shell: bash 69 | run: |- 70 | rustcv="$(rustc --version)" 71 | [[ "$rustcv" != *"nightly"* && "$rustcv" != *"beta"* ]] 72 | 73 | - name: Check toolchain file is being overridden 74 | if: matrix.write-toolchain-file 75 | shell: bash 76 | run: |- 77 | rustcv="$(rustc --version)" 78 | [[ ! ( "$rustcv" == *"nightly"* && "$rustcv" == *"2024-01-10"* ) ]] 79 | 80 | - shell: bash 81 | run: rustc --version && cargo --version 82 | 83 | # Test with creating a small project 84 | - run: cargo init . --bin --name ci 85 | 86 | # Add tiny empty crate. 87 | # This checks that registry access works. 88 | - run: cargo add serde_as 89 | 90 | - run: cargo clippy 91 | 92 | cache: 93 | name: Cache 94 | runs-on: ubuntu-latest 95 | steps: 96 | - uses: actions/checkout@v5 97 | 98 | - name: Install Rust 99 | uses: ./ 100 | with: 101 | components: clippy 102 | cache: true 103 | cache-workspaces: |- 104 | ./test-workspace 105 | 106 | - run: cargo clippy --manifest-path=./test-workspace/Cargo.toml 107 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v4.6.0 4 | hooks: 5 | - id: check-case-conflict 6 | - id: check-executables-have-shebangs 7 | - id: check-merge-conflict 8 | - id: check-json 9 | - id: check-yaml 10 | - id: end-of-file-fixer 11 | - id: trailing-whitespace 12 | args: [--markdown-linebreak-ext=md] 13 | - repo: https://github.com/python-jsonschema/check-jsonschema 14 | rev: 0.29.2 15 | hooks: 16 | - id: check-dependabot 17 | - id: check-github-actions 18 | - id: check-github-workflows 19 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ## [1.15.2] - 2025-10-04 11 | 12 | * Fix: Run the version detection steps in the selected `rust-src-dir` directory. 13 | This should enable the version selection even without a default toolchain installed. 14 | Fixes #74. 15 | 16 | ## [1.15.1] - 2025-09-23 17 | 18 | * Update `Swatinem/rust-cache` to v2.8.1 19 | 20 | ## [1.15.0] - 2025-09-14 21 | 22 | * Add support for non-root source directory. 23 | Accept source code and `rust-toolchain.toml` file in subdirectories of the repository. 24 | Adds a new parameter `rust-src-dir` that controls the lookup for toolchain files and sets a default value for the `cache-workspace` input. (#69 by @Kubaryt) 25 | 26 | ## [1.14.1] - 2025-08-28 27 | 28 | * Pin `Swatinem/rust-cache` action to a full commit SHA (#68 by @JohnTitor) 29 | 30 | ## [1.14.0] - 2025-08-23 31 | 32 | * Add new parameters `cache-all-crates` and `cache-workspace-crates` that are propagated to `Swatinem/rust-cache` as `cache-all-crates` and `cache-workspace-crates` 33 | 34 | ## [1.13.0] - 2025-06-16 35 | 36 | * Add new parameter `cache-provider` that is propagated to `Swatinem/rust-cache` as `cache-provider` (#65 by @mindrunner) 37 | 38 | ## [1.12.0] - 2025-04-23 39 | 40 | * Add support for installing rustup on Windows (#58 by @maennchen) 41 | This adds support for using Rust on the GitHub provided Windows ARM runners. 42 | 43 | ## [1.11.0] - 2025-02-24 44 | 45 | * Add new parameter `cache-bin` that is propagated to `Swatinem/rust-cache` as `cache-bin` (#51 by @enkhjile) 46 | * Add new parameter `cache-shared-key` that is propagated to `Swatinem/rust-cache` as `shared-key` (#52 by @skanehira) 47 | 48 | ## [1.10.1] - 2024-10-01 49 | 50 | * Fix problem matcher for rustfmt output. 51 | The format has changed since https://github.com/rust-lang/rustfmt/pull/5971 and now follows the form "filename:line". 52 | Thanks to @0xcypher02 for pointing out the problem. 53 | 54 | ## [1.10.0] - 2024-09-23 55 | 56 | * Add new parameter `cache-directories` that is propagated to `Swatinem/rust-cache` (#44 by @pranc1ngpegasus) 57 | * Add new parameter `cache-key` that is propagated to `Swatinem/rust-cache` as `key` (#41 by @iainlane) 58 | * Make rustup toolchain installation more robust in light of planned changes https://github.com/rust-lang/rustup/issues/3635 and https://github.com/rust-lang/rustup/pull/3985 59 | * Allow installing multiple Rust toolchains by specifying multiple versions in the `toolchain` input parameter. 60 | * Configure the `rustup override` behavior via the new `override` input. (#38) 61 | 62 | ## [1.9.0] - 2024-06-08 63 | 64 | * Add extra argument `cache-on-failure` and forward it to `Swatinem/rust-cache`. (#39 by @samuelhnrq) 65 | Set the default the value to true. 66 | This will result in more caching than previously. 67 | This helps when large dependencies are compiled only for testing to fail. 68 | 69 | ## [1.8.0] - 2024-01-13 70 | 71 | * Allow specifying subdirectories for cache. 72 | * Fix toolchain file overriding. 73 | 74 | ## [1.7.0] - 2024-01-11 75 | 76 | * Allow overriding the toolchain file with explicit `toolchain` input. (#26) 77 | 78 | ## [1.6.0] - 2023-12-04 79 | 80 | ### Added 81 | 82 | * Allow disabling problem matchers (#27) 83 | This can be useful when having a matrix of jobs, that produce the same errors. 84 | 85 | ## [1.5.0] - 2023-05-29 86 | 87 | ### Added 88 | 89 | * Support installing additional components and targets that are not listed in `rust-toolchain` (#14) 90 | Before only the items listed in `rust-toolchain` were installed. 91 | Now all the items from the toolchain file are installed and then all the `target`s and `components` that are provided as action inputs. 92 | This allows installing extra tools only for CI or simplify testing special targets in CI. 93 | * Allow skipping the creation of a `RUSTFLAGS` environment variable. 94 | Cargos logic for rustflags is complicated, and setting the `RUSTFLAGS` environment variable prevents other ways of working. 95 | Provide a new `rustflags` input, which controls the environment variable creation. 96 | If the value is set to the empty string, then `RUSTFLAGS` is not created. 97 | 98 | Pre-existing `RUSTFLAGS` variables are never modified by this extension. 99 | 100 | ## [1.4.4] - 2023-03-18 101 | 102 | ### Fixed 103 | 104 | * Use color aware problem matcher. 105 | The problem matcher currently runs against the colored terminal output ([Bug 1](https://github.com/actions/runner/issues/2341), [Bug 2](https://github.com/actions/runner/pull/2430)). 106 | The previous matcher was not aware of ANSII color codes and did not work. 107 | 108 | ## [1.4.3] - 2023-02-21 109 | 110 | ### Fixed 111 | 112 | * Executing the action twice for different toolchains now no longer fails around unstable features #12. 113 | If multiple toolchains are installed, the "CARGO_REGISTRIES_CRATES_IO_PROTOCOL" can be downgraded to "git" if any of the installed toolchains require it. 114 | 115 | ## [1.4.2] - 2023-02-15 116 | 117 | ### Fixed 118 | 119 | * Tweak sparse registry version regex to better work with 1.68 nightly versions. 120 | * Fix command not found issue 121 | 122 | ## [1.4.1] - 2023-02-13 123 | 124 | ### Fixed 125 | 126 | * Fixed running on macOS #9 #10 127 | The macOS images have an ancient version of bash, but the action relies on "newer" features than 2014. 128 | We install bash via brew (already pre-installed) to have a new enough version. 129 | 130 | The CI is extended to also run on Windows and macOS to catch such issues earlier in the future. 131 | 132 | Thanks to @GeorgeHahn for reporting the issue. 133 | 134 | ## [1.4.0] - 2023-02-13 135 | 136 | ### Changed 137 | 138 | * Only set environment variables, if they are not set before. 139 | This allows setting environment variables before using this action and keeping their values. 140 | * Enable stable sparse registry, except on versions 1.66 and 1.67 where this leads to errors. 141 | 142 | ## [1.3.7] - 2023-01-31 143 | 144 | ### Fixed 145 | 146 | * Disable the stable access to the sparse registry. 147 | Setting the value causes problem on version before stabilization, e.g., 1.67. 148 | For example, "cargo add" fails. 149 | 150 | ## [1.3.6] - 2023-01-31 151 | 152 | ### Fixed 153 | 154 | * The the correct environment variable to enable the sparse registry access. 155 | The pull request originally had the wrong value, without `CARGO_` prefix. 156 | 157 | ## [1.3.5] - 2023-01-21 158 | 159 | ### Changed 160 | 161 | * Use the newly stabilized setting to enable sparse registry access. 162 | This speeds up access to the crate registry and is in addition to the unstable nightly env var. 163 | 164 | 165 | ## [1.3.4] - 2022-10-15 166 | 167 | ### Changed 168 | 169 | * The last version did not fix all "set-output" commands 170 | 171 | ## [1.3.3] - 2022-10-13 172 | 173 | ### Changed 174 | 175 | * Switch from set-output to $GITHUB_OUTPUT to avoid warning 176 | https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/ 177 | 178 | ## [1.3.2] - 2022-09-15 179 | 180 | ### Fixed 181 | 182 | * Fix setting `$CARGO_HOME` to a valid path, in case rustup is installed from the internet. 183 | Thanks to @nahsi for providing the fix. 184 | 185 | ## [1.3.1] - 2022-08-14 186 | 187 | ### Changed 188 | 189 | * Use the sparse-registry on nightly for faster access to the crate registry on nightly. 190 | 191 | 192 | ## [1.3.0] - 2022-07-30 193 | 194 | ### Added 195 | 196 | * An option to disable configuring Rust cache. 197 | Thanks to @filips123 for the PR. 198 | 199 | ## [1.2.1] - 2022-07-29 200 | 201 | ### Fixed 202 | 203 | * Set environment variables before invoking the cache action. 204 | This ensures restoring and saving are using the same cache key. 205 | 206 | ## [1.2.0] - 2022-07-21 207 | 208 | ### Added 209 | 210 | * Prefer toolchain definitions in `rust-toolchain` or `rust-toolchain.toml` files ([Toolchain File](https://rust-lang.github.io/rustup/overrides.html#the-toolchain-file)). 211 | Other input values are ignored if either file is found. 212 | 213 | ## [1.1.0] - 2022-07-19 214 | 215 | ### Added 216 | 217 | * Install rustup if not available in the CI environment. (Linux only) 218 | The code is taken from this issue: 219 | * Add rustc version output suitable as a cache key. 220 | This is based on and . 221 | 222 | ### Changed 223 | 224 | * Update to `Swatinem/rust-cache@v2`. 225 | 226 | ## [1.0.2] - 2022-05-02 227 | 228 | ### Changed 229 | 230 | * Enable colored cargo output. 231 | * Print short backtraces during test failure. 232 | 233 | ## [1.0.1] - 2022-04-20 234 | 235 | ### Added 236 | 237 | * Release action on marketplace 238 | 239 | ## [1.0.0] - 2022-04-20 240 | 241 | Initial Version 242 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 actions-rust-lang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Install Rust Toolchain 2 | 3 | This GitHub Action installs a Rust toolchain using rustup. 4 | It further integrates into the ecosystem. 5 | Caching for Rust tools and build artifacts is enabled. 6 | Environment variables are set to optimize the cache hits. 7 | [Problem Matchers] are provided for build messages (cargo, clippy) and formatting (rustfmt). 8 | 9 | The action is heavily inspired by _dtolnay_'s and extends it with further features. 10 | 11 | ## Example workflow 12 | 13 | ```yaml 14 | name: "Test Suite" 15 | on: 16 | push: 17 | pull_request: 18 | 19 | jobs: 20 | test: 21 | name: cargo test 22 | runs-on: ubuntu-latest 23 | steps: 24 | - uses: actions/checkout@v5 25 | - uses: actions-rust-lang/setup-rust-toolchain@v1 26 | - run: cargo test --all-features 27 | 28 | # Check formatting with rustfmt 29 | formatting: 30 | name: cargo fmt 31 | runs-on: ubuntu-latest 32 | steps: 33 | - uses: actions/checkout@v5 34 | # Ensure rustfmt is installed and setup problem matcher 35 | - uses: actions-rust-lang/setup-rust-toolchain@v1 36 | with: 37 | components: rustfmt 38 | - name: Rustfmt Check 39 | uses: actions-rust-lang/rustfmt@v1 40 | ``` 41 | 42 | ## Inputs 43 | 44 | All inputs are optional. 45 | If a [toolchain file](https://rust-lang.github.io/rustup/overrides.html#the-toolchain-file) (i.e., `rust-toolchain` or `rust-toolchain.toml`) is found in the root of the repository and no `toolchain` value is provided, all items specified in the toolchain file will be installed. 46 | If a `toolchain` value is provided, the toolchain file will be ignored. 47 | If no `toolchain` value or toolchain file is present, it will default to `stable`. 48 | First, all items specified in the toolchain file are installed. 49 | Afterward, the `components` and `target` specified via inputs are installed in addition to the items from the toolchain file. 50 | 51 | | Name | Description | Default | 52 | | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | 53 | | `toolchain` | Comma-separated list of Rustup toolchain specifier e.g. `stable`, `nightly`, `1.42.0`. The last version is the default. | stable | 54 | | `target` | Additional target support to install e.g. `wasm32-unknown-unknown` | | 55 | | `components` | Comma-separated string of additional components to install e.g. `clippy, rustfmt` | | 56 | | `cache` | Automatically configure Rust cache (using [`Swatinem/rust-cache`]) | true | 57 | | `cache-directories` | Propagates the value to [`Swatinem/rust-cache`] | | 58 | | `cache-workspaces` | Propagates the value to [`Swatinem/rust-cache`]. Influenced by the value of `rust-src-dir`. | | 59 | | `cache-on-failure` | Propagates the value to [`Swatinem/rust-cache`] | true | 60 | | `cache-key` | Propagates the value to [`Swatinem/rust-cache`] as `key` | | 61 | | `cache-shared-key` | Propagates the value to [`Swatinem/rust-cache`] as `shared-key` | | 62 | | `cache-bin` | Propagates the value to [`Swatinem/rust-cache`] as `cache-bin` | true | 63 | | `cache-provider` | Propagates the value to [`Swatinem/rust-cache`] as `cache-provider` | 'github' | 64 | | `cache-all-crates` | Propagates the value to [`Swatinem/rust-cache`] as `cache-all-crates` | false | 65 | | `cache-workspace-crates` | Propagates the value to [`Swatinem/rust-cache`] as `cache-workspace-crates` | false | 66 | | `matcher` | Enable problem matcher to surface build messages and formatting issues | true | 67 | | `rustflags` | Set the value of `RUSTFLAGS` (set to empty string to avoid overwriting existing flags) | "-D warnings" | 68 | | `override` | Setup the last installed toolchain as the default via `rustup override` | true | 69 | | `rust-src-dir` | Path from root directory to directory with the Rust source directory (if its not in the root of the repository). Sets a default value for `cache-workspaces` that enables caching. | | 70 | 71 | [`Swatinem/rust-cache`]: https://github.com/Swatinem/rust-cache 72 | 73 | ### RUSTFLAGS 74 | 75 | By default, this action sets the `RUSTFLAGS` environment variable to `-D warnings`. 76 | However, rustflags sources are mutually exclusive, so setting this environment variable omits any configuration through `target.*.rustflags` or `build.rustflags`. 77 | 78 | - If `RUSTFLAGS` is already set, no modifications of the variable are made and the original value remains. 79 | - If `RUSTFLAGS` is unset and the `rustflags` input is empty (i.e., the empty string), then it will remain unset. 80 | Use this, if you want to prevent the value from being set because you make use of `target.*.rustflags` or `build.rustflags`. 81 | - Otherwise, the environment variable `RUSTFLAGS` is set to the content of `rustflags`. 82 | 83 | To prevent this from happening, set the `rustflags` input to an empty string, which will 84 | prevent the action from setting `RUSTFLAGS` at all, keeping any existing preferences. 85 | 86 | You can read more rustflags, and their load order, in the [Cargo reference]. 87 | 88 | ## Outputs 89 | 90 | | Name | Description | 91 | | ---------------- | ------------------------------------------- | 92 | | `rustc-version` | Version as reported by `rustc --version` | 93 | | `cargo-version` | Version as reported by `cargo --version` | 94 | | `rustup-version` | Version as reported by `rustup --version` | 95 | | `cachekey` | A short hash of the installed rustc version | 96 | 97 | ## Dependencies 98 | 99 | The action works best on the GitHub-hosted runners, but can work on self-hosted ones too, provided the necessary dependencies are available. 100 | PRs to add support for more environments are welcome. 101 | 102 | - bash 5 103 | - brew (macOS only) 104 | - rustup or curl 105 | - using other node actions 106 | 107 | ## License 108 | 109 | The scripts and documentation in this project are released under the [MIT 110 | License]. 111 | 112 | [MIT License]: LICENSE 113 | [Problem Matchers]: https://github.com/actions/toolkit/blob/main/docs/problem-matchers.md 114 | [Cargo reference]: https://doc.rust-lang.org/cargo/reference/config.html?highlight=unknown#buildrustflags 115 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: Setup Rust Toolchain for GitHub CI 2 | description: | 3 | Setup specific Rust versions with caching pre-configured. 4 | It provides problem matchers for cargo and rustfmt issues. 5 | 6 | branding: 7 | icon: "play" 8 | color: "gray-dark" 9 | 10 | # Add option to install directly from rust-toolchain file 11 | # Blocked on rustup support: https://github.com/rust-lang/rustup/issues/2686 12 | # 13 | # The action is heavily inspired by https://github.com/dtolnay/rust-toolchain 14 | inputs: 15 | toolchain: 16 | description: "Comma-separated list of Rust toolchain specifications. Last version becomes the default. -- see https://rust-lang.github.io/rustup/concepts/toolchains.html#toolchain-specification" 17 | required: false 18 | target: 19 | description: "Target triple to install for this toolchain" 20 | required: false 21 | components: 22 | description: "Comma-separated list of components to be additionally installed" 23 | required: false 24 | cache: 25 | description: "Automatically configure Rust cache" 26 | required: false 27 | default: "true" 28 | cache-workspaces: 29 | description: "Paths to multiple Cargo workspaces and their target directories, separated by newlines." 30 | required: false 31 | cache-directories: 32 | description: "Additional non workspace directories to be cached, separated by newlines." 33 | required: false 34 | cache-on-failure: 35 | description: "Cache even if the build fails." 36 | default: "true" 37 | required: false 38 | cache-key: 39 | description: "An additional cache key that is added alongside the automatic `job`-based cache key and can be used to further differentiate jobs." 40 | required: false 41 | cache-shared-key: 42 | description: "A cache key that is used instead of the automatic `job`-based key, and is stable over multiple jobs." 43 | required: false 44 | cache-bin: 45 | description: "Determines whether to cache ${CARGO_HOME}/bin." 46 | required: false 47 | default: "true" 48 | cache-provider: 49 | description: "Determines which provider to use for caching. Options are github, buildjet, or warpbuild. Defaults to github." 50 | required: false 51 | default: "github" 52 | cache-all-crates: 53 | description: "Determines which crates are cached. If `true` all crates will be cached, otherwise only dependent crates will be cached." 54 | required: false 55 | default: "false" 56 | cache-workspace-crates: 57 | description: "Determines which crates are cached. If `true` all crates will be cached, otherwise only dependent crates will be cached." 58 | required: false 59 | default: "false" 60 | matcher: 61 | description: "Enable the Rust problem matcher" 62 | required: false 63 | default: "true" 64 | rustflags: 65 | description: "set RUSTFLAGS environment variable, set to empty string to avoid overwriting build.rustflags" 66 | required: false 67 | default: "-D warnings" 68 | override: 69 | description: "Setup the last installed toolchain as the default via `rustup override`" 70 | required: false 71 | default: "true" 72 | rust-src-dir: 73 | description: "Specify path from root directory to the Rust source directory. By default root directory will be used." 74 | required: false 75 | 76 | outputs: 77 | rustc-version: 78 | description: "Version as reported by `rustc --version`" 79 | value: ${{steps.versions.outputs.rustc-version}} 80 | cargo-version: 81 | description: "Version as reported by `cargo --version`" 82 | value: ${{steps.versions.outputs.cargo-version}} 83 | rustup-version: 84 | description: "Version as reported by `rustup --version`" 85 | value: ${{steps.versions.outputs.rustup-version}} 86 | cachekey: 87 | description: A short hash of the rustc version, appropriate for use as a cache key. "20220627a831" 88 | value: ${{steps.versions.outputs.cachekey}} 89 | 90 | runs: 91 | using: composite 92 | steps: 93 | # The later code uses "newer" bash features, which are not available in the ancient bash 3 (from 2014) of macOS 94 | - name: Unbork mac 95 | if: runner.os == 'macOS' 96 | run: | 97 | brew install bash 98 | shell: bash 99 | 100 | - id: flags 101 | env: 102 | targets: ${{inputs.target}} 103 | components: ${{inputs.components}} 104 | shell: bash 105 | run: | 106 | : construct rustup command line 107 | echo "targets=$(for t in ${targets//,/ }; do echo -n ' --target' $t; done)" >> $GITHUB_OUTPUT 108 | echo "components=$(for c in ${components//,/ }; do echo -n ' --component' $c; done)" >> $GITHUB_OUTPUT 109 | echo "downgrade=${{contains(inputs.toolchain, 'nightly') && inputs.components && ' --allow-downgrade' || ''}}" >> $GITHUB_OUTPUT 110 | 111 | # The environment variables always need to be set before the caching action 112 | - name: Setting Environment Variables 113 | env: 114 | NEW_RUSTFLAGS: ${{inputs.rustflags}} 115 | shell: bash 116 | run: | 117 | if [[ ! -v CARGO_INCREMENTAL ]]; then 118 | echo "CARGO_INCREMENTAL=0" >> $GITHUB_ENV 119 | fi 120 | if [[ ! -v CARGO_PROFILE_DEV_DEBUG ]]; then 121 | echo "CARGO_PROFILE_DEV_DEBUG=0" >> $GITHUB_ENV 122 | fi 123 | if [[ ! -v CARGO_TERM_COLOR ]]; then 124 | echo "CARGO_TERM_COLOR=always" >> $GITHUB_ENV 125 | fi 126 | if [[ ! -v RUST_BACKTRACE ]]; then 127 | echo "RUST_BACKTRACE=short" >> $GITHUB_ENV 128 | fi 129 | if [[ ( ! -v RUSTFLAGS ) && $NEW_RUSTFLAGS != "" ]]; then 130 | echo "RUSTFLAGS=$NEW_RUSTFLAGS" >> $GITHUB_ENV 131 | fi 132 | # Enable faster sparse index on nightly 133 | # The value is ignored on stable and causes no problems 134 | # https://internals.rust-lang.org/t/call-for-testing-cargo-sparse-registry/16862 135 | if [[ ! -v CARGO_UNSTABLE_SPARSE_REGISTRY ]]; then 136 | echo "CARGO_UNSTABLE_SPARSE_REGISTRY=true" >> $GITHUB_ENV 137 | fi 138 | if [[ ! -v CARGO_REGISTRIES_CRATES_IO_PROTOCOL ]]; then 139 | echo "CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse" >> $GITHUB_ENV 140 | fi 141 | 142 | - name: Install Rust Problem Matcher 143 | if: inputs.matcher == 'true' 144 | shell: bash 145 | run: echo "::add-matcher::${{ github.action_path }}/rust.json" 146 | 147 | - name: Install rustup, if needed 148 | shell: bash 149 | run: | 150 | if ! command -v rustup &> /dev/null ; then 151 | curl --proto '=https' --tlsv1.2 --retry 10 --retry-connrefused -fsSL "https://sh.rustup.rs" | sh -s -- --default-toolchain none -y 152 | 153 | # Resolve the correct CARGO_HOME path depending on OS 154 | if [[ "$RUNNER_OS" == "Windows" ]]; then 155 | echo "${CARGO_HOME:-$USERPROFILE/.cargo}/bin" | sed 's|/|\\|g' >> $GITHUB_PATH 156 | else 157 | echo "${CARGO_HOME:-$HOME/.cargo}/bin" >> $GITHUB_PATH 158 | fi 159 | fi 160 | env: 161 | RUNNER_OS: "${{ runner.os }}" 162 | 163 | - name: rustup toolchain install ${{inputs.toolchain || 'stable'}} 164 | env: 165 | toolchain: ${{inputs.toolchain}} 166 | targets: ${{inputs.target}} 167 | components: ${{inputs.components}} 168 | override: ${{inputs.override}} 169 | rust_src_dir: ${{inputs.rust-src-dir}} 170 | shell: bash 171 | run: | 172 | # Check if value is set 173 | if [[ -n "$rust_src_dir" ]] 174 | then 175 | # If value is set the directory must exist 176 | if [[ -d "$rust_src_dir" ]] 177 | then 178 | cd "$rust_src_dir" 179 | else 180 | echo "'rust-src-dir' does not point to an existing directory" >&2 181 | echo "The value of 'rust-src-dir' is: ${rust_src_dir}" >&2 182 | exit 1 183 | fi 184 | fi 185 | if [[ -z "$toolchain" && ( -f "rust-toolchain" || -f "rust-toolchain.toml") ]] 186 | then 187 | # Install the toolchain as specified in the file 188 | # rustup show is the old way that implicitly installed a toolchain 189 | # rustup toolchain install is the new explicit way 190 | # https://github.com/rust-lang/rustup/issues/3635#issuecomment-2343511297 191 | rustup show active-toolchain || rustup toolchain install 192 | if [[ -n $components ]]; then 193 | rustup component add ${components//,/ } 194 | fi 195 | if [[ -n $targets ]]; then 196 | rustup target add ${targets//,/ } 197 | fi 198 | else 199 | if [[ -z "$toolchain" ]] 200 | then 201 | toolchain=stable 202 | fi 203 | rustup toolchain install ${toolchain//,/ } ${{steps.flags.outputs.targets}}${{steps.flags.outputs.components}} --profile minimal${{steps.flags.outputs.downgrade}} --no-self-update 204 | # Take the last element from the list 205 | if [[ "$override" == "true" ]] 206 | then 207 | rustup override set ${toolchain//*,/ } 208 | fi 209 | fi 210 | 211 | - id: versions 212 | name: Print installed versions 213 | shell: bash 214 | # Switch to the Rust sub-directory 215 | working-directory: ${{inputs.rust-src-dir || '.'}} 216 | run: | 217 | echo "rustc-version=$(rustc --version)" >> $GITHUB_OUTPUT 218 | rustc --version --verbose 219 | echo "cargo-version=$(cargo --version)" >> $GITHUB_OUTPUT 220 | cargo --version --verbose 221 | echo "rustup-version=$(rustup --version)" >> $GITHUB_OUTPUT 222 | rustup --version 223 | 224 | DATE=$(rustc --version --verbose | sed -ne 's/^commit-date: \(20[0-9][0-9]\)-\([01][0-9]\)-\([0-3][0-9]\)$/\1\2\3/p') 225 | HASH=$(rustc --version --verbose | sed -ne 's/^commit-hash: //p') 226 | echo "cachekey=$(echo $DATE$HASH | head -c12)" >> $GITHUB_OUTPUT 227 | 228 | - name: Downgrade registry access protocol when needed 229 | shell: bash 230 | run: | 231 | # Not all versions support setting CARGO_REGISTRIES_CRATES_IO_PROTOCOL 232 | # On versions 1.66, 1.67, and 1.68.0-nightly the value "sparse" is still unstable. 233 | # https://github.com/dtolnay/rust-toolchain/pull/69#discussion_r1107268108 234 | # If we detect an incompatible value, set it to "git" which is always supported. 235 | if [[ "${{steps.versions.outputs.rustc-version}}" =~ ^rustc\ (1\.6[67]\.|1\.68\.0-nightly) && "${CARGO_REGISTRIES_CRATES_IO_PROTOCOL}" == "sparse" ]]; then 236 | echo "Downgrade cargo registry protocol to git" 237 | echo "CARGO_REGISTRIES_CRATES_IO_PROTOCOL=git" >> $GITHUB_ENV 238 | fi 239 | 240 | - name: Setup Rust Caching 241 | if: inputs.cache == 'true' 242 | uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1 243 | with: 244 | workspaces: ${{ inputs.cache-workspaces || inputs.rust-src-dir }} 245 | cache-directories: ${{inputs.cache-directories}} 246 | cache-on-failure: ${{inputs.cache-on-failure}} 247 | cache-bin: ${{inputs.cache-bin}} 248 | cache-provider: ${{inputs.cache-provider}} 249 | cache-all-crates: ${{inputs.cache-all-crates}} 250 | cache-workspace-crates: ${{inputs.cache-workspace-crates}} 251 | key: ${{inputs.cache-key}} 252 | shared-key: ${{inputs.cache-shared-key}} 253 | -------------------------------------------------------------------------------- /rust.json: -------------------------------------------------------------------------------- 1 | { 2 | "problemMatcher": [ 3 | { 4 | "owner": "rustfmt", 5 | "severity": "warning", 6 | "pattern": [ 7 | { 8 | "regexp": "^(Diff in (.+))(?: at line |:)(\\d+):$", 9 | "message": 1, 10 | "file": 2, 11 | "line": 3 12 | } 13 | ] 14 | }, 15 | { 16 | "owner": "clippy", 17 | "pattern": [ 18 | { 19 | "regexp": "^(?:\\x1b\\[[\\d;]+m)*(warning|warn|error)(?:\\x1b\\[[\\d;]+m)*(\\[(.*)\\])?(?:\\x1b\\[[\\d;]+m)*:(?:\\x1b\\[[\\d;]+m)* ([^\\x1b]*)(?:\\x1b\\[[\\d;]+m)*$", 20 | "severity": 1, 21 | "message": 4, 22 | "code": 3 23 | }, 24 | { 25 | "regexp": "^(?:\\x1b\\[[\\d;]+m)*\\s*(?:\\x1b\\[[\\d;]+m)*\\s*--> (?:\\x1b\\[[\\d;]+m)*(.*):(\\d*):(\\d*)(?:\\x1b\\[[\\d;]+m)*$", 26 | "file": 1, 27 | "line": 2, 28 | "column": 3 29 | } 30 | ] 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /test-workspace/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "ci" 7 | version = "0.1.0" 8 | dependencies = [ 9 | "serde_as", 10 | ] 11 | 12 | [[package]] 13 | name = "serde_as" 14 | version = "0.0.1" 15 | source = "registry+https://github.com/rust-lang/crates.io-index" 16 | checksum = "4ee4afe4c5c3b69699c4267ae42b838e911466d7ca0005046adc93ac95bb16dd" 17 | -------------------------------------------------------------------------------- /test-workspace/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ci" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | serde_as = "0.0.1" 10 | -------------------------------------------------------------------------------- /test-workspace/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("Hello, world!"); 3 | } 4 | --------------------------------------------------------------------------------