## Summary
- Extracts the duplicated working-directory resolution expression
(`core.getInput('working_directory') || core.getInput('install_dir') ||
process.cwd()`) into a `getCwd()` helper function.
- Replaces the 2 identical inline expressions in `exportMiseEnv()` and
`mise()` with calls to `getCwd()`.
## Motivation
Separated from #402 to allow independent review. This is a pure refactor
with no behavioral change, intended to simplify the diff in #402 by
providing a smaller, self-contained improvement.
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
## Problem
The `exportMiseEnv()` function ignores the `working_directory` (and
`install_dir`) input when running `mise env --json`. It always executes
in the process default CWD — the GitHub Actions workspace root —
regardless of what directory was used for `mise install`.
This means if a caller sets `working_directory: path/to/subdir`, mise
resolves environment variables against the workspace root's `mise.toml`,
not the intended subdirectory's config.
### Impact
Since mise 2026.2.0, lockfiles are enabled by default. When `mise env
--json` runs without a `mise.lock` present (e.g. because the correct
`working_directory` was not used), mise attempts to resolve loose tool
versions (like `"latest"`) from the network. In environments with
private npm registries, this causes `npm view` calls that fail with 403
errors. Mise retries indefinitely, spawning 20+ orphaned npm processes
and eventually hitting `EAGAIN` (OS error 11), hanging CI permanently.
The other mise commands (`miseInstall`, `miseReshim`, etc.) already pass
`cwd` correctly via the shared `mise()` helper. Only `exportMiseEnv()`
was missing this.
## Fix
Resolve `working_directory` (falling back to `install_dir`, then
`process.cwd()`) at the top of `exportMiseEnv()` and pass `{ cwd }` to
all four `exec.getExecOutput` calls within the function:
- `mise env --redacted --json`
- `mise env --json`
- `mise env --dotenv` (redacted fallback)
- `mise env --dotenv` (legacy fallback)
## Related
- Issue #267: `working_directory` not respected for env export
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
## Summary
Refs #382 (Problem 1).
The default cache key template placed `file_hash` before conditional
segments (`version`, `mise_env`, `install_args_hash`). Because
`@actions/cache` `restoreCache` performs prefix matching on the primary
key, a key without optional trailing segments was always a prefix of a
key with them, causing different workflow configurations to restore each
other's caches unintentionally.
## The bug
Old template:
```
{{cache_key_prefix}}-{{platform}}-{{file_hash}}{{#if version}}-{{version}}{{/if}}{{#if mise_env}}-{{mise_env}}{{/if}}{{#if install_args_hash}}-{{install_args_hash}}{{/if}}
```
Example: Workflow A (no `install_args`) produces key
`mise-v0-linux-x64-<hash>`, which is a prefix of Workflow B's key
`mise-v0-linux-x64-<hash>-<args_hash>`. If only B's cache exists, A
restores it via prefix match.
## The fix
Move `file_hash` to the end of the template so it acts as a terminator:
```
{{cache_key_prefix}}-{{platform}}{{#if version}}-{{version}}{{/if}}{{#if mise_env}}-{{mise_env}}{{/if}}{{#if install_args_hash}}-{{install_args_hash}}{{/if}}-{{file_hash}}
```
Since `file_hash` is always present, no valid cache key can be a prefix
of another.
Also bumps `cache_key_prefix` default from `mise-v0` to `mise-v1` (in
both `src/index.ts` and `action.yml`) to intentionally invalidate
existing caches that may have been saved under incorrect prefix-matched
keys.
## Changes
- `src/index.ts` L43: Reorder `DEFAULT_CACHE_KEY_TEMPLATE` — move
`file_hash` to end
- `src/index.ts` L432: Bump fallback `cache_key_prefix` from `mise-v0`
to `mise-v1`
- `action.yml` L46: Bump default `cache_key_prefix` from `mise-v0` to
`mise-v1`
- Rebuilt `dist/`
Reverts jdx/mise-action#360https://github.com/jdx/mise-action/issues/363
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Reverts the monorepo cache isolation change and simplifies caching to
a single cache for the entire `mise` directory.
>
> - Replace binary/tools caches with a single cache via
`restoreMiseCache`/`saveCache`; set `cache-hit` from one restore
> - Default key template drops `dir_hash`; `file_hash` computed from
repo-wide glob patterns (no `working_directory`-specific config walk)
> - Persist `PRIMARY_KEY` and `MISE_DIR` in action state; `miseDir()`
reads from state
> - Remove monorepo cache isolation workflow `test-monorepo-cache.yml`;
minor cleanup in `AGENTS.md`
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
a157c4e176. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Problem
-------
mise-action hashes ALL mise config files in the repo to compute a single
default cache key. In a monorepo with multiple projects (e.g.,
apps/frontend, apps/backend), this causes cache pollution:
1. Job A runs for apps/frontend, installs only frontend tools
2. Cache is saved with a key based on ALL configs
3. Job B runs for apps/backend, gets cache HIT (same key)
4. Job B finds frontend tools but not backend tools
5. Job B has to install all tools because they are missing from cache
Additionally, any change to an unrelated project config would bust the
cache for all projects.
Solution
--------
When working_directory is set, compute the default cache key using only
the config files that affect that directory (detected via `mise config
ls --json`) instead of globbing all configs in the repo.
This required separating binary and tools caching:
- Binary cache: restored first so mise is available for `mise config ls`
- Tools cache: default key computed after mise is installed
Key Implementation Details
--------------------------
1. Cache separation:
- restoreMiseBinaryCache/saveMiseBinaryCache for the mise binary
- restoreToolsCache/saveToolsCache for the full mise directory
- Binary cache key: `{prefix}-binary-{platform}-{version}-{dirHash}`
- Tools default cache key: based on config file contents for
working_directory
2. Binary backup during tools cache restore: The tools cache includes
bin/, which could overwrite the binary that setupMise() just installed.
We use withBinaryBackup() to backup the binary before restoring the
tools cache and restore it afterward.
An alternative approach would be to only cache installs/ and shims/
instead of the full miseDir(), but that would change the caching
behavior for existing users. Using withBinaryBackup() retains the
original caching behavior while preventing the binary from being
overwritten.
3. Binary cache key includes mise_dir hash: Prevents cache collision
when users change mise_dir between runs. Without this, a cache hit could
restore the binary to the wrong location.
4. Explicit mise binary path: Uses full path to mise binary instead of
relying on PATH lookup, avoiding potential race conditions with
core.addPath().
5. Lock file handling:
- .toml files: look for corresponding .lock file
- .tool-versions: look for mise.lock in the same directory
6. Graceful degradation: If `mise config ls` fails when
working_directory is set, caching is disabled with a warning rather
than:
- Failing the action entirely, or
- Falling back to glob patterns (which would reintroduce the bug)
Backward Compatibility
----------------------
- working_directory not set: No change, uses existing glob of all
configs
- working_directory set: Default cache key based on `mise config ls`
output
Note on cache_key input: The `cache_key` input now only controls the
tools cache key. The binary cache key is always computed automatically
based on platform, version, and mise_dir. This is generally better since
the binary cache is version-stable and does not need custom key logic.
Test Coverage
-------------
Added test-monorepo-cache.yml with 8 test scenarios:
- install-backend/restore-frontend: Verify cache isolation
- install-frontend/unrelated-change-no-bust: Verify unrelated changes do
not bust cache
- parent-config-change: Verify parent config changes bust child cache
- lock-file-change: Verify lock file changes bust cache
- install-default-mise-dir/restore-custom-mise-dir: Verify mise_dir in
cache key
Final Note
----------
Currently, the default tool cache key includes the mise version. This
was in place prior, so it was left intact. With this change and the
splitting of the mise version cache from the tool cache, we could safely
remove the mise version from the tool cache key. Left this for a
subsequent change if desired.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Fixes cache key pollution in monorepos by scoping tool cache keys to
the `working_directory`'s config hierarchy and separating binary vs.
tools caching.
>
> - New cache flow: `restoreMiseBinaryCache/saveMiseBinaryCache` (key:
`{prefix}-binary-{platform}-{version}-{dirHash}`) runs before
installation; `restoreToolsCache/saveToolsCache` uses a default key
derived from `mise config ls --json` for the specified
`working_directory`
> - Uses explicit `mise` binary path and preserves it during tools cache
restore via `withBinaryBackup` to avoid overwrites
> - Default tools key still supports template inputs; includes lockfile
handling and guards to disable caching on failures
> - `mise_dir` hash included in binary cache key to prevent cross-dir
collisions
> - Adds `.github/workflows/test-monorepo-cache.yml` with scenarios
verifying monorepo cache isolation, unrelated-config no-bust,
parent-config change bust, lockfile change bust, identical-content
different-path isolation, and `mise_dir`-key differentiation
> - Updates compiled `dist/` artifacts; minor docs entry `AGENTS.md`
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
434d5feca5. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Summary
- Environment variables are now always passed to mise commands
- Previously, env vars were only passed when in debug mode, meaning
`MISE_ENV` and other `MISE_*` variables set in the workflow were not
passed through during `mise install`
Fixes#289
## Usage
```yaml
env:
MISE_ENV: production
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: jdx/mise-action@v2
# MISE_ENV=production is now passed to mise install
```
## Test plan
- [ ] Verify setting `MISE_ENV` in workflow env is passed to `mise
install`
- [ ] Verify debug mode still works (adds `MISE_LOG_LEVEL: debug`)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Always pass sanitized workflow environment variables to all `mise`
invocations, adding `MISE_LOG_LEVEL=debug` only in debug mode.
>
> - **Action runtime**:
> - Always pass environment variables to `mise` commands via a sanitized
`baseEnv` (filters out `undefined`).
> - In debug mode, extends `baseEnv` with `MISE_LOG_LEVEL=debug`;
otherwise uses `baseEnv` unchanged.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
fb448d9e635736cb69b6190690272e10a34bc890. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary
- Add `add_shims_to_path` input (default: `true`) to control whether the
mise shims directory is added to PATH
- Setting this to `false` allows users who already have mise configured
to avoid conflicts with their existing setup
Fixes#337
## Usage
```yaml
- uses: jdx/mise-action@v2
with:
add_shims_to_path: false
```
## Test plan
- [ ] Verify shims are added to PATH by default (existing behavior)
- [ ] Verify shims are NOT added to PATH when `add_shims_to_path: false`
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Adds `add_shims_to_path` input (default true) to optionally skip
adding `mise/shims` to PATH.
>
> - **Action input/behavior**
> - Add `inputs.add_shims_to_path` (default: `true`).
> - Conditionally add `mise/shims` to `PATH` only when
`add_shims_to_path` is `true`.
> - **Build/dist updates (non-functional to action API)**
> - Minor runtime tweaks in bundled libs: safer `abortSignal`
reassignment, improved `File` stream creation, user-agent OS field
formatting, `randomUUID` fallback for Node, and updated internal SDK
version constants.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f90b26afa3. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Hello 👋
1st of all thanks for your work on mise, it's really a game changer 😁
## Why
This PR tries to address the issue #165 (mise-action cannot upgrade
mise)
## What
I've decided to use `mise self-update` if mise is already installed to
switch to the desired version
Let me know if this is an OK fix for you
## Tests
To test this feature, I've run the action on my repo and screenshot the
newly created output
<img width="591" height="538" alt="Screenshot 2025-10-01 at 22 14 46"
src="https://github.com/user-attachments/assets/9a10a33a-d86f-410b-8bdc-71b07b3036f6"
/>
The sha of the commit was suposed to match the sha of the screenshot,
but I've fixup and rebase the PR
Happy to do a new one if you want live proof
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> When mise is already installed, compare the requested `version` input
to the installed version and run `self-update` to align if they differ.
>
> - **Action Logic (`src/index.ts`)**:
> - **Existing Installation Handling**:
> - Read `version` input; fetch installed version via `mise version
--json`.
> - If versions differ, execute `mise self-update <version> -y`;
otherwise log that mise is already installed.
> - Download path and SHA256 verification remain unchanged.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
941208cb9b7a6e796cdc7e96a8dcf6560d4d207c. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Fixes https://github.com/jdx/mise-action/issues/276
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Replaces commas in MISE_ENV with hyphens when constructing the cache
key to ensure stable/valid keys.
>
> - **Cache Key Generation**:
> - In `src/index.ts`, normalizes `MISE_ENV` via `replace(/,/g, '-')`
and uses it as `mise_env` when building the cache key template.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
899df938a6. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
I added support for customizing the key, but forgot the most important
piece that we need, being able to reference an environment variable
value. Our CI runner provider is now exposing an environment variable
that indicates if the OS configuration changes, and we plan to use that
one to invalidate the cache, otherwise we get errors because the cached
dependencies are linking against an invalid / non-existent `glibc`
version.
> [!IMPORTANT]
> I wrote the code with `claude code` and reviewed it afterwards
## Summary (Claude-generated)
- Add support for `{{env.VAR_NAME}}` syntax in cache key templates to
allow reading environment variable values
- Enables more flexible cache key customization based on CI/CD
environment variables like branch names, deployment environments, or
custom build identifiers
- Maintains backward compatibility with existing cache key templates
## Examples
```yaml
# Include branch name from environment
cache_key: 'mise-{{env.GITHUB_REF_NAME}}-{{platform}}-{{file_hash}}'
# Use custom deployment environment
cache_key: 'mise-{{env.DEPLOY_ENV}}-{{platform}}-{{file_hash}}'
# Conditional logic with environment variables
cache_key: '{{default}}{{#if env.CUSTOM_SUFFIX}}-{{env.CUSTOM_SUFFIX}}{{/if}}'
```
## Changes
- Modified `processCacheKeyTemplate()` in `src/index.ts` to include
`process.env` in template data
- Updated `action.yml` documentation to include the new
`{{env.VAR_NAME}}` syntax
- All existing functionality remains unchanged
## Test plan
- [x] Build and package successfully with `npm run all`
- [x] Linting and formatting pass
- [ ] Manual testing with environment variables in cache key templates
- [ ] Verify backward compatibility with existing cache key
configurations
* support checksum
* support checksum
* support checksum
* support checksum
* support checksum
* support checksum
* support checksum
* support checksum
* support checksum
* support checksum
* support checksum
* support checksum
* support checksum
* support checksum
* support checksum
* support checksum
* support checksum
* support checksum
* support checksum
* support checksum
* Change test tool for future alpine CI testing
* replace node with jq as it doesnt require any build on alpine
* Fix alpine musl container install
* add tests around mise install in alpine container
* add support for musl os
Fixes: https://github.com/jdx/mise-action/issues/186
* alpine needs bash to run test.sh script
* remove unneeded logs
* Update test.yml
* Update test.yml
As the log_level parameter defaults to info the MISE_LOG_LEVEL
environment variable needs to be overriden or otherwise it is not set.
This also means that mise-action will always run with debug logging when
it is ran with debugging enabled, no matter what log level the user has
set.
* feat: use debug logging when in debug mode (#128)
* chore: remove unnecessary getExperimental function
* chore: fix setupMise typing
As `core.getInput` returns always a string, the type of `version` in
`setupMise` should be just a `string`. When the string is empty it means
to use the latest version. This could be made cleaner but this is how it
works.
* feat: only set MISE_LOG_LEVEL when required
Previously MISE_LOG_LEVEL was always set, even when log_level parameter
wasn't configured. This changes that behaviour so that the environment
variable is only set when log_level is set by the user and that the
MISE_LOG_LEVEL is set to debug only for this action when in debug mode.
---------
Co-authored-by: Jeff Dickey <216188+jdx@users.noreply.github.com>