mirror of
https://github.com/jdx/mise-action.git
synced 2026-06-17 20:29:34 +00:00
feat: support bootstrap mode (#522)
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 / fetch_from_github (push) Waiting to run
build-test / final (push) Blocked by required conditions
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
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 / fetch_from_github (push) Waiting to run
build-test / final (push) Blocked by required conditions
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
This commit is contained in:
parent
03d53910f9
commit
5f61b63aff
5 changed files with 128 additions and 16 deletions
19
README.md
19
README.md
|
|
@ -19,6 +19,9 @@ jobs:
|
|||
version: 2026.3.10 # [default: latest] mise version to install
|
||||
install: true # [default: true] run `mise install`
|
||||
install_args: "bun" # [default: ""] additional arguments to `mise install`
|
||||
bootstrap: false # [default: false] run `mise bootstrap` instead of `mise install`
|
||||
bootstrap_skip: "tools,task" # [default: ""] comma-separated parts to skip when bootstrapping
|
||||
bootstrap_args: "--yes" # [default: ""] additional arguments to `mise bootstrap`
|
||||
cache: true # [default: true] cache mise using GitHub's cache
|
||||
experimental: true # [default: false] enable experimental features
|
||||
log_level: debug # [default: info] log level
|
||||
|
|
@ -72,6 +75,7 @@ Available template variables:
|
|||
- `{{file_hash}}` - Hash of all mise configuration files
|
||||
- `{{mise_env}}` - The MISE_ENV environment variable value
|
||||
- `{{install_args_hash}}` - SHA256 hash of the sorted tools from install args
|
||||
- `{{bootstrap_hash}}` - SHA256 hash of bootstrap mode, skip list, and args
|
||||
- `{{default}}` - The processed default cache key (useful for extending)
|
||||
|
||||
Conditional logic is also supported using Handlebars syntax like `{{#if version}}...{{/if}}`.
|
||||
|
|
@ -123,6 +127,21 @@ 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.
|
||||
|
||||
## Bootstrap
|
||||
|
||||
Set `bootstrap: true` to run `mise bootstrap` instead of `mise install`:
|
||||
|
||||
```yaml
|
||||
- uses: jdx/mise-action@v4
|
||||
with:
|
||||
bootstrap: true
|
||||
```
|
||||
|
||||
When a repo mise lock file is present, the action automatically runs
|
||||
`mise --locked bootstrap`. `install_args` cannot be combined with
|
||||
`bootstrap: true`; use `bootstrap_skip` and `bootstrap_args` for bootstrap
|
||||
customization.
|
||||
|
||||
## Alternative Installation
|
||||
|
||||
Alternatively, mise is easy to use in GitHub Actions even without this:
|
||||
|
|
|
|||
16
action.yml
16
action.yml
|
|
@ -26,10 +26,20 @@ inputs:
|
|||
install:
|
||||
required: false
|
||||
default: "true"
|
||||
description: if false, will not run `mise install`
|
||||
description: if false, will not run `mise install` or `mise bootstrap`
|
||||
install_args:
|
||||
required: false
|
||||
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.
|
||||
bootstrap:
|
||||
required: false
|
||||
default: "false"
|
||||
description: if true, will run `mise bootstrap` instead of `mise install`
|
||||
bootstrap_skip:
|
||||
required: false
|
||||
description: Comma-separated bootstrap parts to skip, such as "tools,task". Passed as `mise bootstrap --skip`.
|
||||
bootstrap_args:
|
||||
required: false
|
||||
description: Additional arguments to pass to `mise bootstrap`.
|
||||
install_dir:
|
||||
required: false
|
||||
description: deprecated
|
||||
|
|
@ -49,8 +59,8 @@ inputs:
|
|||
required: false
|
||||
description: |
|
||||
Override the complete cache key (ignores all other cache key options).
|
||||
Supports template variables: {{version}}, {{cache_key_prefix}}, {{platform}}, {{file_hash}},
|
||||
{{mise_env}}, {{install_args_hash}}, {{default}}, {{env.VAR_NAME}} for environment variables,
|
||||
Supports template variables: {{version}}, {{cache_key_prefix}}, {{platform}}, {{file_hash}},
|
||||
{{mise_env}}, {{install_args_hash}}, {{bootstrap_hash}}, {{default}}, {{env.VAR_NAME}} for environment variables,
|
||||
and conditional logic like {{#if version}}...{{/if}}
|
||||
experimental:
|
||||
required: false
|
||||
|
|
|
|||
49
dist/index.js
generated
vendored
49
dist/index.js
generated
vendored
|
|
@ -89242,7 +89242,7 @@ const MISE_CONFIG_FILE_PATTERNS = [
|
|||
`**/.tool-versions`
|
||||
];
|
||||
// Default cache key template
|
||||
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 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 bootstrap_hash}}-{{bootstrap_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$/];
|
||||
|
|
@ -89284,10 +89284,14 @@ async function run() {
|
|||
}
|
||||
await testMise();
|
||||
if (getBooleanInput('install')) {
|
||||
await miseInstall();
|
||||
if (cacheKey && getBooleanInput('cache_save')) {
|
||||
await saveCache(cacheKey);
|
||||
if (getBooleanInput('bootstrap')) {
|
||||
await miseBootstrap();
|
||||
}
|
||||
else {
|
||||
await miseInstall();
|
||||
}
|
||||
if (cacheKey && getBooleanInput('cache_save'))
|
||||
await saveCache(cacheKey);
|
||||
}
|
||||
await miseLs();
|
||||
const loadEnv = getBooleanInput('env');
|
||||
|
|
@ -89422,8 +89426,10 @@ async function setEnvVars() {
|
|||
exportVariable(k, v);
|
||||
}
|
||||
};
|
||||
if (getBooleanInput('experimental'))
|
||||
if (getBooleanInput('experimental') ||
|
||||
getBooleanInput('bootstrap')) {
|
||||
set('MISE_EXPERIMENTAL', '1');
|
||||
}
|
||||
const logLevel = getInput('log_level');
|
||||
if (logLevel)
|
||||
set('MISE_LOG_LEVEL', logLevel);
|
||||
|
|
@ -89633,6 +89639,26 @@ const miseInstall = async () => {
|
|||
}
|
||||
return mise([command]);
|
||||
};
|
||||
const miseBootstrap = async () => {
|
||||
const installArgs = getInput('install_args').trim();
|
||||
if (installArgs) {
|
||||
throw new Error('`install_args` cannot be used when `bootstrap` is true because `mise bootstrap` does not support partial tool install args.');
|
||||
}
|
||||
const bootstrapSkip = getInput('bootstrap_skip').trim();
|
||||
const bootstrapArgs = getInput('bootstrap_args').trim();
|
||||
const useLocked = (await shouldUseLockedInstall()) &&
|
||||
!/(^|\s)--locked(?:\s|$)/.test(bootstrapArgs);
|
||||
const command = [
|
||||
...(useLocked ? ['--locked'] : []),
|
||||
'bootstrap',
|
||||
...(bootstrapSkip ? ['--skip', bootstrapSkip] : []),
|
||||
...(bootstrapArgs ? [bootstrapArgs] : [])
|
||||
].join(' ');
|
||||
if (useLocked) {
|
||||
info('Detected a mise lock file, running `mise --locked bootstrap`');
|
||||
}
|
||||
return mise([command]);
|
||||
};
|
||||
const miseLs = async () => mise([`ls`]);
|
||||
const miseReshim = async () => mise([`reshim`, `-f`]);
|
||||
const mise = async (args) => await group(`Running mise ${args.join(' ')}`, async () => {
|
||||
|
|
@ -89775,6 +89801,9 @@ async function processCacheKeyTemplate(template) {
|
|||
// Get all available variables
|
||||
const version = getInput('version');
|
||||
const installArgs = getInput('install_args');
|
||||
const bootstrap = getBooleanInput('bootstrap');
|
||||
const bootstrapSkip = getInput('bootstrap_skip');
|
||||
const bootstrapArgs = getInput('bootstrap_args');
|
||||
const cacheKeyPrefix = getInput('cache_key_prefix') || 'mise-v1';
|
||||
const miseEnv = process.env.MISE_ENV?.replace(/,/g, '-');
|
||||
const platform = `${await getTarget()}-${getRunnerImageId()}`;
|
||||
|
|
@ -89792,6 +89821,13 @@ async function processCacheKeyTemplate(template) {
|
|||
installArgsHash = crypto$1.createHash('sha256').update(tools).digest('hex');
|
||||
}
|
||||
}
|
||||
let bootstrapHash = '';
|
||||
if (bootstrap) {
|
||||
bootstrapHash = crypto$1
|
||||
.createHash('sha256')
|
||||
.update([String(bootstrap), bootstrapSkip, bootstrapArgs].join('\0'))
|
||||
.digest('hex');
|
||||
}
|
||||
// Prepare base template data
|
||||
const baseTemplateData = {
|
||||
version,
|
||||
|
|
@ -89799,7 +89835,8 @@ async function processCacheKeyTemplate(template) {
|
|||
platform,
|
||||
file_hash: fileHash,
|
||||
mise_env: miseEnv,
|
||||
install_args_hash: installArgsHash
|
||||
install_args_hash: installArgsHash,
|
||||
bootstrap_hash: bootstrapHash
|
||||
};
|
||||
// Calculate the default cache key by processing the default template
|
||||
const defaultTemplate = libExports.compile(DEFAULT_CACHE_KEY_TEMPLATE);
|
||||
|
|
|
|||
2
dist/index.js.map
generated
vendored
2
dist/index.js.map
generated
vendored
File diff suppressed because one or more lines are too long
58
src/index.ts
58
src/index.ts
|
|
@ -40,7 +40,7 @@ const MISE_CONFIG_FILE_PATTERNS = [
|
|||
|
||||
// Default cache key template
|
||||
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}}'
|
||||
'{{cache_key_prefix}}-{{platform}}{{#if version}}-{{version}}{{/if}}{{#if mise_env}}-{{mise_env}}{{/if}}{{#if install_args_hash}}-{{install_args_hash}}{{/if}}{{#if bootstrap_hash}}-{{bootstrap_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$/]
|
||||
|
|
@ -86,10 +86,13 @@ async function run(): Promise<void> {
|
|||
}
|
||||
await testMise()
|
||||
if (core.getBooleanInput('install')) {
|
||||
await miseInstall()
|
||||
if (cacheKey && core.getBooleanInput('cache_save')) {
|
||||
await saveCache(cacheKey)
|
||||
if (core.getBooleanInput('bootstrap')) {
|
||||
await miseBootstrap()
|
||||
} else {
|
||||
await miseInstall()
|
||||
}
|
||||
if (cacheKey && core.getBooleanInput('cache_save'))
|
||||
await saveCache(cacheKey)
|
||||
}
|
||||
await miseLs()
|
||||
const loadEnv = core.getBooleanInput('env')
|
||||
|
|
@ -243,7 +246,12 @@ async function setEnvVars(): Promise<void> {
|
|||
core.exportVariable(k, v)
|
||||
}
|
||||
}
|
||||
if (core.getBooleanInput('experimental')) set('MISE_EXPERIMENTAL', '1')
|
||||
if (
|
||||
core.getBooleanInput('experimental') ||
|
||||
core.getBooleanInput('bootstrap')
|
||||
) {
|
||||
set('MISE_EXPERIMENTAL', '1')
|
||||
}
|
||||
|
||||
const logLevel = core.getInput('log_level')
|
||||
if (logLevel) set('MISE_LOG_LEVEL', logLevel)
|
||||
|
|
@ -513,6 +521,32 @@ const miseInstall = async (): Promise<number> => {
|
|||
|
||||
return mise([command])
|
||||
}
|
||||
const miseBootstrap = async (): Promise<number> => {
|
||||
const installArgs = core.getInput('install_args').trim()
|
||||
if (installArgs) {
|
||||
throw new Error(
|
||||
'`install_args` cannot be used when `bootstrap` is true because `mise bootstrap` does not support partial tool install args.'
|
||||
)
|
||||
}
|
||||
|
||||
const bootstrapSkip = core.getInput('bootstrap_skip').trim()
|
||||
const bootstrapArgs = core.getInput('bootstrap_args').trim()
|
||||
const useLocked =
|
||||
(await shouldUseLockedInstall()) &&
|
||||
!/(^|\s)--locked(?:\s|$)/.test(bootstrapArgs)
|
||||
const command = [
|
||||
...(useLocked ? ['--locked'] : []),
|
||||
'bootstrap',
|
||||
...(bootstrapSkip ? ['--skip', bootstrapSkip] : []),
|
||||
...(bootstrapArgs ? [bootstrapArgs] : [])
|
||||
].join(' ')
|
||||
|
||||
if (useLocked) {
|
||||
core.info('Detected a mise lock file, running `mise --locked bootstrap`')
|
||||
}
|
||||
|
||||
return mise([command])
|
||||
}
|
||||
const miseLs = async (): Promise<number> => mise([`ls`])
|
||||
const miseReshim = async (): Promise<number> => mise([`reshim`, `-f`])
|
||||
const mise = async (args: string[]): Promise<number> =>
|
||||
|
|
@ -689,6 +723,9 @@ async function processCacheKeyTemplate(template: string): Promise<string> {
|
|||
// Get all available variables
|
||||
const version = core.getInput('version')
|
||||
const installArgs = core.getInput('install_args')
|
||||
const bootstrap = core.getBooleanInput('bootstrap')
|
||||
const bootstrapSkip = core.getInput('bootstrap_skip')
|
||||
const bootstrapArgs = core.getInput('bootstrap_args')
|
||||
const cacheKeyPrefix = core.getInput('cache_key_prefix') || 'mise-v1'
|
||||
const miseEnv = process.env.MISE_ENV?.replace(/,/g, '-')
|
||||
const platform = `${await getTarget()}-${getRunnerImageId()}`
|
||||
|
|
@ -709,6 +746,14 @@ async function processCacheKeyTemplate(template: string): Promise<string> {
|
|||
}
|
||||
}
|
||||
|
||||
let bootstrapHash = ''
|
||||
if (bootstrap) {
|
||||
bootstrapHash = crypto
|
||||
.createHash('sha256')
|
||||
.update([String(bootstrap), bootstrapSkip, bootstrapArgs].join('\0'))
|
||||
.digest('hex')
|
||||
}
|
||||
|
||||
// Prepare base template data
|
||||
const baseTemplateData = {
|
||||
version,
|
||||
|
|
@ -716,7 +761,8 @@ async function processCacheKeyTemplate(template: string): Promise<string> {
|
|||
platform,
|
||||
file_hash: fileHash,
|
||||
mise_env: miseEnv,
|
||||
install_args_hash: installArgsHash
|
||||
install_args_hash: installArgsHash,
|
||||
bootstrap_hash: bootstrapHash
|
||||
}
|
||||
|
||||
// Calculate the default cache key by processing the default template
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue