fix: pass cwd to all exec calls in exportMiseEnv() (#390)

## 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>
This commit is contained in:
Andrew Thauer 2026-03-06 11:12:44 -05:00 committed by GitHub
parent e79ddf65a1
commit cea720d8cd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 29 additions and 9 deletions

17
dist/index.js generated vendored
View file

@ -81039,12 +81039,15 @@ async function run() {
}
async function exportMiseEnv() {
core.startGroup('Exporting mise environment variables');
const cwd = core.getInput('working_directory') ||
core.getInput('install_dir') ||
process.cwd();
// Check if mise supports --redacted flags based on version input
const supportsRedacted = checkMiseSupportsRedacted();
if (supportsRedacted) {
try {
// First, get the redacted values to identify what needs masking
const redactedOutput = await exec.getExecOutput('mise', ['env', '--redacted', '--json'], { silent: true });
const redactedOutput = await exec.getExecOutput('mise', ['env', '--redacted', '--json'], { silent: true, cwd });
const redactedVars = JSON.parse(redactedOutput.stdout);
// Mask sensitive values in GitHub Actions
for (const [key, actualValue] of Object.entries(redactedVars)) {
@ -81052,7 +81055,9 @@ async function exportMiseEnv() {
core.info(`Masked sensitive value for: ${key}`);
}
// Then get the actual values
const actualOutput = await exec.getExecOutput('mise', ['env', '--json']);
const actualOutput = await exec.getExecOutput('mise', ['env', '--json'], {
cwd
});
const actualVars = JSON.parse(actualOutput.stdout);
// Export all environment variables
for (const [key, value] of Object.entries(actualVars)) {
@ -81064,13 +81069,17 @@ async function exportMiseEnv() {
catch {
// Fall back to dotenv format if the redacted command fails
core.info('Falling back to dotenv format');
const output = await exec.getExecOutput('mise', ['env', '--dotenv']);
const output = await exec.getExecOutput('mise', ['env', '--dotenv'], {
cwd
});
fs.appendFileSync(process.env.GITHUB_ENV, output.stdout);
}
}
else {
// Fall back to the old --dotenv format for older versions
const output = await exec.getExecOutput('mise', ['env', '--dotenv']);
const output = await exec.getExecOutput('mise', ['env', '--dotenv'], {
cwd
});
fs.appendFileSync(process.env.GITHUB_ENV, output.stdout);
}
core.endGroup();

2
dist/index.js.map generated vendored

File diff suppressed because one or more lines are too long

View file

@ -82,6 +82,11 @@ async function run(): Promise<void> {
async function exportMiseEnv(): Promise<void> {
core.startGroup('Exporting mise environment variables')
const cwd =
core.getInput('working_directory') ||
core.getInput('install_dir') ||
process.cwd()
// Check if mise supports --redacted flags based on version input
const supportsRedacted = checkMiseSupportsRedacted()
@ -91,7 +96,7 @@ async function exportMiseEnv(): Promise<void> {
const redactedOutput = await exec.getExecOutput(
'mise',
['env', '--redacted', '--json'],
{ silent: true }
{ silent: true, cwd }
)
const redactedVars = JSON.parse(redactedOutput.stdout)
@ -102,7 +107,9 @@ async function exportMiseEnv(): Promise<void> {
}
// Then get the actual values
const actualOutput = await exec.getExecOutput('mise', ['env', '--json'])
const actualOutput = await exec.getExecOutput('mise', ['env', '--json'], {
cwd
})
const actualVars = JSON.parse(actualOutput.stdout)
// Export all environment variables
@ -114,12 +121,16 @@ async function exportMiseEnv(): Promise<void> {
} catch {
// Fall back to dotenv format if the redacted command fails
core.info('Falling back to dotenv format')
const output = await exec.getExecOutput('mise', ['env', '--dotenv'])
const output = await exec.getExecOutput('mise', ['env', '--dotenv'], {
cwd
})
fs.appendFileSync(process.env.GITHUB_ENV!, output.stdout)
}
} else {
// Fall back to the old --dotenv format for older versions
const output = await exec.getExecOutput('mise', ['env', '--dotenv'])
const output = await exec.getExecOutput('mise', ['env', '--dotenv'], {
cwd
})
fs.appendFileSync(process.env.GITHUB_ENV!, output.stdout)
}