Skip to content

feat: opt in to caching mise rust toolchains#467

Closed
risu729 wants to merge 8 commits into
jdx:mainfrom
risu729:risu/cache-rust-toolchains
Closed

feat: opt in to caching mise rust toolchains#467
risu729 wants to merge 8 commits into
jdx:mainfrom
risu729:risu/cache-rust-toolchains

Conversation

@risu729
Copy link
Copy Markdown
Contributor

@risu729 risu729 commented May 10, 2026

Summary

  • add cache_rust: true as an explicit opt-in for caching Rust toolchains installed by mise
  • when enabled, export MISE_RUSTUP_HOME and MISE_CARGO_HOME before cache restore/install so rustup toolchains and cargo/rustup proxies are saved with the existing mise cache
  • add a -rust segment to the default cache key, expose {{cache_rust}} to custom cache key templates, document the compatibility tradeoffs, and add a lightweight workflow check for the opt-in path

Fixes #215
Addresses #184
Refs #353

Research notes

Failure mode

The failure mode in #215/#184/#353 is specific to Rust because mise delegates Rust installation to rustup instead of placing the complete toolchain under ~/.local/share/mise/installs like most tools.

When mise-action restores only the mise data dir, the cached installs/rust/... symlink/marker can make mise install report that Rust is already installed, while the corresponding rustup toolchain/components are absent from the runner. The next plain cargo fmt or cargo clippy then goes through rustup, which may auto-install only the base toolchain and fail because rustfmt/clippy were never restored.

Primary references:

What must be restored

Rustup and Cargo split state across two homes:

  • RUSTUP_HOME: rustup metadata and installed toolchains/components.
  • CARGO_HOME: cargo/rustup proxy binaries in bin, Cargo-installed binary metadata, registry cache, and git dependency cache.

For the mise-action bug, the required restore set is the rustup toolchain/component state plus the proxy binaries that make plain cargo, rustfmt, and clippy resolve to the same mise-managed toolchain after mise env exports RUSTUP_HOME/CARGO_HOME.

Cache-key scope and Cargo safety

A single mise-action cache key is appropriate for the toolchain/proxy state because the Rust version/components come from mise config and mise.lock, which are already part of the default file_hash key.

CARGO_HOME can also contain Cargo registry and git caches. Those caches are generally correctness-safe because Cargo validates package versions/checksums and refreshes as needed, but they are not ideal to key only by mise config. They can also be large. This PR therefore documents cache_rust as a toolchain/proxy cache, not a replacement for Cargo dependency or target build caching.

For workflows that need dependency/build caches, the recommended shape is:

  • mise-action with cache_rust: true to restore mise-owned rustup/Cargo proxy state.
  • Swatinem/rust-cache after mise-action to manage Cargo registry, git dependency, and target caches using Rust/Cargo lockfile-aware keys.
  • cache-bin: "false" on rust-cache when mise should remain the owner of cargo/rustup proxy binaries and Cargo tools installed by mise.

Related rust-cache docs:

Workarounds found in issue/PR references

I checked the cross-reference timelines for #215, #184, and #353, then followed code-search references to their workflow workarounds.

Direct issue/PR references:

Additional public workflow workarounds:

These workarounds all point to the same missing primitive: mise-action needs an opt-in way to restore the rustup toolchain home and the Cargo proxy/bin home together with the mise install marker.

Downstream verification

Verified in risu729/biwa#606: risu729/biwa#606

That PR removed the existing mise install --locked rust --force workaround, enabled cache_rust: true, and combined this action with Swatinem/rust-cache.

Evidence from the retry run on the PR branch:

  • CI run: https://github.com/risu729/biwa/actions/runs/25633217083
  • Lint job restored a mise cache key containing -rust: mise-v1-linux-x64-ubuntu24-rust-2026.5.5-13c29379e886bda7bbab6becd116612e36e434b18dc6a761629fce60be0103f7-release
  • the same job exported CARGO_HOME=/home/runner/.local/share/mise/cargo and RUSTUP_HOME=/home/runner/.local/share/mise/rustup
  • cargo clippy --all-targets -- --deny warnings and cargo fmt --check both passed without the force reinstall workaround
  • Test restored the same -rust mise cache and also restored rust-cache's separate Cargo cache

Evidence after #606 was merged to main:

  • CI run: https://github.com/risu729/biwa/actions/runs/25646318121
  • Lint job got an exact mise cache hit for mise-v1-linux-x64-ubuntu24-rust-2026.5.5-13c29379e886bda7bbab6becd116612e36e434b18dc6a761629fce60be0103f7
  • the job then ran mise install --locked, cargo clippy --all-targets -- --deny warnings, and cargo fmt --check successfully
  • Swatinem/rust-cache restored a separate cache keyed from Rust/Cargo environment and lockfiles, showing the two caches can coexist

The functional verification used commit f2054108d3926f722fd54c7fc70a1224cb691032. Later commits update documentation/action metadata, merge current upstream/main, regenerate dist against the merged lockfile, and make the rust_cache_setup smoke test derive its expected mise data dir instead of hardcoding $HOME/.local/share/mise. The runtime Rust cache implementation is unchanged after the verified commit.

Compatibility and cache behavior

Default behavior is unchanged. cache_rust defaults to false, so existing workflows keep the same cache paths, cache keys, and environment unless they opt in.

When cache_rust: true, this action uses mise-specific settings (MISE_RUSTUP_HOME, MISE_CARGO_HOME) instead of setting generic RUSTUP_HOME/CARGO_HOME for everyone. That keeps setup scoped to Rust as managed by mise and avoids silently taking over workflows that install Rust through rustup, setup-rust-toolchain, or another Rust setup action while using mise for unrelated tools.

The default cache key gains -rust only when the option is enabled. This avoids restoring older mise-only caches where the installs/rust/... marker exists but the rustup/cargo homes were never cached. Users with a custom cache_key should include {{cache_rust}} or manually invalidate their key when enabling this option.

The current workaround, mise install --locked rust --force or rustup component add rustfmt clippy after cache restore, should no longer be needed once cache_rust: true has produced a Rust-enabled cache entry.

Test plan

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a cache_rust option to allow caching of Rust toolchains installed by mise. It updates the documentation, action configuration, and core logic to manage MISE_RUSTUP_HOME and MISE_CARGO_HOME within the cache. Feedback was provided to improve the implementation by using asynchronous file system operations for setupRustCache to maintain consistency with other setup functions and prevent blocking the event loop.

Comment thread src/index.ts Outdated
Comment thread src/index.ts Outdated
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 10, 2026

Greptile Summary

This PR adds an explicit cache_rust: true opt-in that fixes a long-standing cache-correctness bug where a restored mise cache could leave Rust's install marker in place while the actual rustup toolchain and components (e.g. rustfmt, clippy) were absent. Default behavior is completely unchanged.

  • Exports MISE_RUSTUP_HOME and MISE_CARGO_HOME to subdirectories of the mise data dir before cache restore, so rustup state is saved and restored together with the rest of the mise cache.
  • Appends a -rust segment to the default cache key when the option is enabled, preventing stale mise-only cache entries from being reused as Rust-enabled ones.
  • Documents scope limitations (toolchain/proxy cache only, not a Cargo.lock-aware dependency cache) and the recommended Swatinem/rust-cache composition for full Rust caching.

Confidence Score: 5/5

Safe to merge — the change is a pure opt-in with no effect on existing workflows that leave cache_rust at its default of false.

The implementation is carefully ordered: env vars are exported before cache restore so both restore and save operate on consistent paths; isPathInside correctly avoids redundant cache path entries for the default layout where rustup/cargo homes are already inside miseDir(); the -rust cache key segment prevents stale cache reuse on first enable; and warnings are emitted for known misconfigurations. No changed code path alters behavior for workflows that do not opt in.

No files require special attention.

Important Files Changed

Filename Overview
src/index.ts Adds setupRustCache(), rustCacheHomes(), miseCachePaths(), and isPathInside() to opt-in Rust toolchain caching; integrates them into the restore/save flow and the cache key template
action.yml Adds cache_rust input (default false) with clear description and updates the cache_key description to include {{cache_rust}}
.github/workflows/test.yml Adds a rust_cache_setup smoke-test job verifying MISE_RUSTUP_HOME/MISE_CARGO_HOME env vars and directory creation; wires it into the check gate job
README.md Documents cache_rust input, {{cache_rust}} template variable, Rust toolchain cache mechanics, scope limitations vs Cargo dependency caching, and Swatinem/rust-cache interop

Reviews (5): Last reviewed commit: "test: avoid hardcoded rust cache paths" | Re-trigger Greptile

Comment thread src/index.ts
Comment thread src/index.ts Outdated
@risu729

This comment was marked as off-topic.

@risu729

This comment was marked as outdated.

@risu729 risu729 marked this pull request as ready for review May 11, 2026 12:01
@risu729 risu729 requested a review from jdx as a code owner May 11, 2026 12:01
Comment thread action.yml
description: |
Opt in to caching Rust toolchains installed by mise's Rust backend.

When `true`, the action exports `MISE_RUSTUP_HOME` and `MISE_CARGO_HOME`
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just use asdf-rust for this behavior

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't use rustup, so it can't support components or other options.
I can make a vfox plugin and use it, but I think it's better if we can support Rust in mise-action. Currently, it just doesn't work properly.
Should we fix mise itself to detect broken Rust in installs/rust? I'm not sure if we can, but it might be better; I can cache the default RUSTUP_HOME and CARGO_HOME if I would like to.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

idk, but I don't think "cache rust" is really communicating what this is doing. I don't think I want to support this model in any case though.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. I'll have a look at some other solutions.

@risu729
Copy link
Copy Markdown
Contributor Author

risu729 commented May 13, 2026

Closing this in favor of fixing the Rust install-completeness check in mise itself: jdx/mise#9839. That keeps mise-action from owning a separate Rust cache model, while still making restored mise install markers correct for mise install decisions.

The docs-only follow-up for Cargo/Rust cache composition is here: #474.

This comment was generated by an AI coding assistant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cache breaks rustfmt install

2 participants