fix: install mise-shim.exe on Windows (#476)
Some checks are pending
Check dist/ / Check dist/ (push) Waiting to run
Continuous Integration / TypeScript Tests (push) Waiting to run
CodeQL / Analyze (push) Waiting to run
release-plz / release-plz (push) Waiting to run
Test Redacted Environment Variables / test-redacted-env (push) Waiting to run
build-test / build (push) Waiting to run
build-test / alpine (push) Waiting to run
build-test / macos (push) Waiting to run
build-test / ubuntu (push) Waiting to run
build-test / windows (push) Waiting to run
build-test / specific_version (push) Waiting to run
build-test / checksum_failure (push) Waiting to run
build-test / custom_cache_key (push) Waiting to run
build-test / fetch_from_github (push) Waiting to run
build-test / final (push) Blocked by required conditions
zizmor / zizmor (push) Waiting to run

This commit is contained in:
Taku Kodama 2026-05-15 05:38:13 +10:00 committed by GitHub
parent a0eaf7aa03
commit 93ca8a4cef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 169 additions and 25 deletions

View file

@ -65,6 +65,15 @@ jobs:
- run: mise x jq -- jq --version
- run: which jq
- run: jq --version
- name: Check Windows shim binary
if: runner.os == 'Windows'
shell: pwsh
run: |
$miseBinDir = Split-Path -Parent (Get-Command mise).Source
$miseShim = Join-Path $miseBinDir "mise-shim.exe"
if (!(Test-Path -LiteralPath $miseShim)) {
throw "mise-shim.exe was not installed next to mise.exe"
}
- run: . scripts/test.sh
shell: bash

74
dist/index.js generated vendored
View file

@ -89459,6 +89459,8 @@ async function restoreMiseCache() {
async function setupMise(version, fetchFromGitHub = false) {
const miseBinDir = path$1.join(miseDir(), 'bin');
const miseBinPath = path$1.join(miseBinDir, process.platform === 'win32' ? 'mise.exe' : 'mise');
const miseShimPath = path$1.join(miseBinDir, 'mise-shim.exe');
let installedVersion;
if (!fs.existsSync(path$1.join(miseBinPath))) {
startGroup(version ? `Download mise@${version}` : 'Setup mise');
await fs.promises.mkdir(miseBinDir, { recursive: true });
@ -89479,13 +89481,16 @@ async function setupMise(version, fetchFromGitHub = false) {
else {
url = `https://github.com/jdx/mise/releases/download/v${resolvedVersion}/mise-v${resolvedVersion}-${await getTarget()}${ext}`;
}
const archivePath = path$1.join(os.tmpdir(), `mise${ext}`);
installedVersion = resolvedVersion;
switch (ext) {
case '.zip':
await exec('curl', ['-fsSL', url, '--output', archivePath]);
await exec('unzip', [archivePath, '-d', os.tmpdir()]);
await mv(path$1.join(os.tmpdir(), 'mise/bin/mise.exe'), miseBinPath);
case '.zip': {
await withExtractedZip(url, 'mise.zip', async (extractDir) => {
const extractedMiseBinDir = path$1.join(extractDir, 'mise', 'bin');
await mv(path$1.join(extractedMiseBinDir, 'mise.exe'), miseBinPath);
await installWindowsMiseShim(extractedMiseBinDir, miseShimPath);
});
break;
}
case '.tar.zst':
await exec('sh', [
'-c',
@ -89507,19 +89512,19 @@ async function setupMise(version, fetchFromGitHub = false) {
else {
const requestedVersion = cleanVersion(getInput('version'));
if (requestedVersion !== '') {
const versionOutput = await getExecOutput(miseBinPath, ['version', '--json'], { silent: true });
const versionJson = JSON.parse(versionOutput.stdout);
const version = cleanVersion(versionJson.version.split(' ')[0]);
if (requestedVersion === version) {
installedVersion = await getInstalledMiseVersion(miseBinPath);
if (requestedVersion === installedVersion) {
info(`mise already installed`);
}
else {
info(`mise already installed (${version}), but different version requested (${requestedVersion})`);
info(`mise already installed (${installedVersion}), but different version requested (${requestedVersion})`);
await exec(miseBinPath, ['self-update', requestedVersion, '-y']);
info(`mise updated to version ${requestedVersion}`);
installedVersion = requestedVersion;
}
}
}
await ensureWindowsMiseShim(miseBinPath, miseShimPath, installedVersion);
// compare with provided hash
const want = getInput('sha256');
if (want) {
@ -89532,6 +89537,55 @@ async function setupMise(version, fetchFromGitHub = false) {
}
addPath(miseBinDir);
}
async function withExtractedZip(url, archiveName, fn) {
const tempDir = await fs.promises.mkdtemp(path$1.join(os.tmpdir(), 'mise-action-'));
try {
const archivePath = path$1.join(tempDir, archiveName);
const extractDir = path$1.join(tempDir, 'extract');
await exec('curl', ['-fsSL', url, '--output', archivePath]);
await exec('unzip', [archivePath, '-d', extractDir]);
await fn(extractDir);
}
finally {
await rmRF(tempDir);
}
}
async function installWindowsMiseShim(extractedMiseBinDir, miseShimPath) {
if (process.platform !== 'win32')
return;
const extractedMiseShimPath = path$1.join(extractedMiseBinDir, 'mise-shim.exe');
if (!fs.existsSync(extractedMiseShimPath)) {
info('mise-shim.exe not found in the mise archive; skipping');
return;
}
await mv(extractedMiseShimPath, miseShimPath);
}
async function ensureWindowsMiseShim(miseBinPath, miseShimPath, version) {
if (process.platform !== 'win32')
return;
if (fs.existsSync(miseShimPath))
return;
info('mise-shim.exe not found next to mise.exe; installing it from the matching release archive');
try {
const installedVersion = version || (await getInstalledMiseVersion(miseBinPath));
const archiveName = `mise-v${installedVersion}-${await getTarget()}.zip`;
const url = `https://github.com/jdx/mise/releases/download/v${installedVersion}/${archiveName}`;
await withExtractedZip(url, archiveName, async (extractDir) => {
await installWindowsMiseShim(path$1.join(extractDir, 'mise', 'bin'), miseShimPath);
});
}
catch (err) {
warning(`Failed to install mise-shim.exe: ${errorMessage(err)}. Continuing because mise can fall back to file shim mode on Windows.`);
}
}
async function getInstalledMiseVersion(miseBinPath) {
const versionOutput = await getExecOutput(miseBinPath, ['version', '--json'], { silent: true });
const versionJson = JSON.parse(versionOutput.stdout);
return cleanVersion(versionJson.version.split(' ')[0]);
}
function errorMessage(err) {
return err instanceof Error ? err.message : String(err);
}
async function zstdInstalled() {
try {
await exec('zstd', ['--version']);

2
dist/index.js.map generated vendored

File diff suppressed because one or more lines are too long

View file

@ -296,6 +296,8 @@ async function setupMise(
miseBinDir,
process.platform === 'win32' ? 'mise.exe' : 'mise'
)
const miseShimPath = path.join(miseBinDir, 'mise-shim.exe')
let installedVersion: string | undefined
if (!fs.existsSync(path.join(miseBinPath))) {
core.startGroup(version ? `Download mise@${version}` : 'Setup mise')
await fs.promises.mkdir(miseBinDir, { recursive: true })
@ -316,13 +318,16 @@ async function setupMise(
} else {
url = `https://github.com/jdx/mise/releases/download/v${resolvedVersion}/mise-v${resolvedVersion}-${await getTarget()}${ext}`
}
const archivePath = path.join(os.tmpdir(), `mise${ext}`)
installedVersion = resolvedVersion
switch (ext) {
case '.zip':
await exec.exec('curl', ['-fsSL', url, '--output', archivePath])
await exec.exec('unzip', [archivePath, '-d', os.tmpdir()])
await io.mv(path.join(os.tmpdir(), 'mise/bin/mise.exe'), miseBinPath)
case '.zip': {
await withExtractedZip(url, 'mise.zip', async extractDir => {
const extractedMiseBinDir = path.join(extractDir, 'mise', 'bin')
await io.mv(path.join(extractedMiseBinDir, 'mise.exe'), miseBinPath)
await installWindowsMiseShim(extractedMiseBinDir, miseShimPath)
})
break
}
case '.tar.zst':
await exec.exec('sh', [
'-c',
@ -343,24 +348,20 @@ async function setupMise(
} else {
const requestedVersion = cleanVersion(core.getInput('version'))
if (requestedVersion !== '') {
const versionOutput = await exec.getExecOutput(
miseBinPath,
['version', '--json'],
{ silent: true }
)
const versionJson = JSON.parse(versionOutput.stdout)
const version = cleanVersion(versionJson.version.split(' ')[0])
if (requestedVersion === version) {
installedVersion = await getInstalledMiseVersion(miseBinPath)
if (requestedVersion === installedVersion) {
core.info(`mise already installed`)
} else {
core.info(
`mise already installed (${version}), but different version requested (${requestedVersion})`
`mise already installed (${installedVersion}), but different version requested (${requestedVersion})`
)
await exec.exec(miseBinPath, ['self-update', requestedVersion, '-y'])
core.info(`mise updated to version ${requestedVersion}`)
installedVersion = requestedVersion
}
}
}
await ensureWindowsMiseShim(miseBinPath, miseShimPath, installedVersion)
// compare with provided hash
const want = core.getInput('sha256')
if (want) {
@ -377,6 +378,86 @@ async function setupMise(
core.addPath(miseBinDir)
}
async function withExtractedZip(
url: string,
archiveName: string,
fn: (extractDir: string) => Promise<void>
): Promise<void> {
const tempDir = await fs.promises.mkdtemp(
path.join(os.tmpdir(), 'mise-action-')
)
try {
const archivePath = path.join(tempDir, archiveName)
const extractDir = path.join(tempDir, 'extract')
await exec.exec('curl', ['-fsSL', url, '--output', archivePath])
await exec.exec('unzip', [archivePath, '-d', extractDir])
await fn(extractDir)
} finally {
await io.rmRF(tempDir)
}
}
async function installWindowsMiseShim(
extractedMiseBinDir: string,
miseShimPath: string
): Promise<void> {
if (process.platform !== 'win32') return
const extractedMiseShimPath = path.join(extractedMiseBinDir, 'mise-shim.exe')
if (!fs.existsSync(extractedMiseShimPath)) {
core.info('mise-shim.exe not found in the mise archive; skipping')
return
}
await io.mv(extractedMiseShimPath, miseShimPath)
}
async function ensureWindowsMiseShim(
miseBinPath: string,
miseShimPath: string,
version?: string
): Promise<void> {
if (process.platform !== 'win32') return
if (fs.existsSync(miseShimPath)) return
core.info(
'mise-shim.exe not found next to mise.exe; installing it from the matching release archive'
)
try {
const installedVersion =
version || (await getInstalledMiseVersion(miseBinPath))
const archiveName = `mise-v${installedVersion}-${await getTarget()}.zip`
const url = `https://github.com/jdx/mise/releases/download/v${installedVersion}/${archiveName}`
await withExtractedZip(url, archiveName, async extractDir => {
await installWindowsMiseShim(
path.join(extractDir, 'mise', 'bin'),
miseShimPath
)
})
} catch (err) {
core.warning(
`Failed to install mise-shim.exe: ${errorMessage(err)}. Continuing because mise can fall back to file shim mode on Windows.`
)
}
}
async function getInstalledMiseVersion(miseBinPath: string): Promise<string> {
const versionOutput = await exec.getExecOutput(
miseBinPath,
['version', '--json'],
{ silent: true }
)
const versionJson = JSON.parse(versionOutput.stdout) as { version: string }
return cleanVersion(versionJson.version.split(' ')[0])
}
function errorMessage(err: unknown): string {
return err instanceof Error ? err.message : String(err)
}
async function zstdInstalled(): Promise<boolean> {
try {
await exec.exec('zstd', ['--version'])