Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,17 @@ When installing tools hosted on GitHub (like `gh`, `node`, `bun`, etc.), mise ne

**Note:** The action automatically uses `${{ github.token }}` as the default, so in most cases you don't need to explicitly provide it. However, if you encounter rate limit errors, make sure the token is being passed correctly.

## Lock Files

If a repo mise lock file such as `mise.lock` is present in the working
directory or one of its parents, this action automatically runs
`mise install --locked`. You can still pass `install_args`; `--locked`
will be added automatically unless you already included it yourself.

This auto-detection is intended for repo-managed config files. If you provide
`mise_toml` or `tool_versions` inputs, the action does not automatically force
locked mode.

## Alternative Installation

Alternatively, mise is easy to use in GitHub Actions even without this:
Expand Down
2 changes: 1 addition & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ inputs:
description: if false, will not run `mise install`
install_args:
required: false
description: Arguments to pass to `mise install` such as "bun" to only install bun
description: Arguments to pass to `mise install` such as "bun" to only install bun. When a repo mise lock file is present, the action automatically adds `--locked` unless you already provided it.
install_dir:
required: false
description: deprecated
Expand Down
77 changes: 76 additions & 1 deletion dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

38 changes: 19 additions & 19 deletions mise.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

100 changes: 98 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ const MISE_CONFIG_FILE_PATTERNS = [
const DEFAULT_CACHE_KEY_TEMPLATE =
'{{cache_key_prefix}}-{{platform}}{{#if version}}-{{version}}{{/if}}{{#if mise_env}}-{{mise_env}}{{/if}}{{#if install_args_hash}}-{{install_args_hash}}{{/if}}-{{#if file_hash}}{{file_hash}}{{else}}no-config{{/if}}'

const ROOT_MISE_LOCK_FILE_PATTERNS = [/^\.?mise(?:\.[^.]+)?\.lock$/]
const CONFIG_DIR_MISE_LOCK_FILE_PATTERNS = [/^mise(?:\.[^.]+)?\.lock$/]
const CONFIG_MISE_LOCK_FILE_PATTERNS = [/^config(?:\.[^.]+)?\.lock$/]

async function run(): Promise<void> {
try {
await setToolVersions()
Expand Down Expand Up @@ -490,8 +494,25 @@ async function setMiseToml(): Promise<void> {
}

const testMise = async (): Promise<number> => mise(['--version'])
const miseInstall = async (): Promise<number> =>
mise([`install ${core.getInput('install_args')}`])
let supportsLockedInstall: boolean | undefined

const miseInstall = async (): Promise<number> => {
const installArgs = core.getInput('install_args').trim()
const useLocked =
(await shouldUseLockedInstall()) &&
!/(^|\s)--locked(?:\s|$)/.test(installArgs)
const command = [
'install',
...(useLocked ? ['--locked'] : []),
...(installArgs ? [installArgs] : [])
].join(' ')

if (useLocked) {
core.info('Detected a mise lock file, running `mise install --locked`')
}

return mise([command])
}
Comment thread
greptile-apps[bot] marked this conversation as resolved.
const miseLs = async (): Promise<number> => mise([`ls`])
const miseReshim = async (): Promise<number> => mise([`reshim`, `-f`])
const mise = async (args: string[]): Promise<number> =>
Expand Down Expand Up @@ -532,6 +553,81 @@ function getCwd(): string {
)
}

async function shouldUseLockedInstall(): Promise<boolean> {
if (core.getInput('tool_versions') || core.getInput('mise_toml')) return false
if (!(await miseSupportsLockedInstall())) return false
return hasMiseLockFile(getCwd())
}

async function miseSupportsLockedInstall(): Promise<boolean> {
if (supportsLockedInstall !== undefined) return supportsLockedInstall

const { stdout, stderr } = await exec.getExecOutput(
'mise',
['install', '--help'],
{
cwd: getCwd(),
ignoreReturnCode: true,
silent: true
}
)

supportsLockedInstall = /(^|\s)--locked(?:[\s,]|$)/m.test(
`${stdout}\n${stderr}`
)
return supportsLockedInstall
}

function hasMiseLockFile(startDir: string): boolean {
let dir = path.resolve(startDir)

while (true) {
if (directoryHasMiseLockFile(dir)) return true

const parent = path.dirname(dir)
if (parent === dir) return false
dir = parent
}
}

function directoryHasMiseLockFile(dir: string): boolean {
return (
hasMatchingLockFile(dir, ROOT_MISE_LOCK_FILE_PATTERNS) ||
hasMatchingLockFile(
path.join(dir, '.config'),
CONFIG_DIR_MISE_LOCK_FILE_PATTERNS
) ||
hasMatchingLockFile(path.join(dir, '.config', 'mise'), [
...ROOT_MISE_LOCK_FILE_PATTERNS,
...CONFIG_MISE_LOCK_FILE_PATTERNS
]) ||
hasMatchingLockFile(path.join(dir, '.mise'), [
...ROOT_MISE_LOCK_FILE_PATTERNS,
...CONFIG_MISE_LOCK_FILE_PATTERNS
]) ||
hasMatchingLockFile(path.join(dir, 'mise'), [
...ROOT_MISE_LOCK_FILE_PATTERNS,
...CONFIG_MISE_LOCK_FILE_PATTERNS
])
)
}
Comment thread
greptile-apps[bot] marked this conversation as resolved.

function hasMatchingLockFile(dir: string, patterns: RegExp[]): boolean {
try {
const stat = fs.statSync(dir, { throwIfNoEntry: false })
if (!stat?.isDirectory()) return false

return fs
.readdirSync(dir, { withFileTypes: true })
.some(
entry =>
entry.isFile() && patterns.some(pattern => pattern.test(entry.name))
)
} catch {
return false
}
}

function miseDir(): string {
const dir = core.getState('MISE_DIR')
if (dir) return dir
Expand Down
Loading