mirror of
https://github.com/renovatebot/renovate.git
synced 2026-10-27 07:50:47 +00:00
2e951d2254
* mise: support selector lockfile updates * fix(mise): handle empty lockfile AST * test(mise): use valid empty TOML AST fixture * fix(mise): support current regex utility * fix: clarify lockfile-only lookup handling * fix(mise): handle selector lockfile updates correctly * test(mise): cover selector lockfile review fixes * fix(mise): scope selector artifact refresh * chore: retrigger CI * fix(mise): remove unreachable lockfile guard * refactor(lookup): clarify lockfile-only value handling * refactor(mise): use shared TOML utilities * fix(mise): handle selector lockfile edge cases * fix(mise): satisfy selector CI coverage * fix(mise): require dependency names * fix(mise): preserve configured dependency names * fix(mise): address selector lockfile review feedback * test(mise): cover major selector lockfile updates * chore(static-data): auto-update Java LTS versions So we don't have a hardcoded set of data in the mise manager. Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io> * fix(mise): address selector lockfile feedback * test(manager/mise): cover nonnumeric current version prefix formatLockedVersion()'s currentPrefix fallback to '' only runs when the current version has no leading numeric match, which no existing test reached. Co-Authored-By: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io> --------- Co-authored-by: Jamie Tanna <jamie.tanna@mend.io> Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
107 lines
3.9 KiB
TypeScript
107 lines
3.9 KiB
TypeScript
import upath from 'upath';
|
|
import { regEx } from '../../../util/regex.ts';
|
|
import type { MiseLockFile, MiseLockTool } from './schema.ts';
|
|
import type { MiseConfigType } from './types.ts';
|
|
|
|
/**
|
|
* Parses the config file name to determine its type (local, env-specific, or default).
|
|
* Used to derive the correct lock file name and `mise lock` flags.
|
|
*/
|
|
export function getConfigType(configPath: string): MiseConfigType {
|
|
const filename = upath.basename(configPath);
|
|
const isLocal = filename.endsWith('.local.toml');
|
|
// Patterns: mise.{env}.toml, mise.{env}.local.toml, .mise.{env}.toml, config.{env}.toml
|
|
const envMatch = regEx(
|
|
/^(?:\.?mise|config)\.(?<env>[^.]+)(?:\.local)?\.toml$/,
|
|
).exec(filename);
|
|
const env =
|
|
envMatch?.groups?.env === 'local' ? undefined : envMatch?.groups?.env;
|
|
return { isLocal, env };
|
|
}
|
|
|
|
/**
|
|
* Derives the lock file path from a mise config file path.
|
|
* Matches mise's lockfile_path_for_config() logic from src/lockfile.rs
|
|
*/
|
|
export function getLockFileName(configPath: string): string {
|
|
const dirname = upath.dirname(configPath);
|
|
const parentDirname = upath.basename(dirname);
|
|
|
|
// For conf.d files, lock file goes in parent directory
|
|
const lockDir = parentDirname === 'conf.d' ? upath.dirname(dirname) : dirname;
|
|
|
|
const { isLocal, env } = getConfigType(configPath);
|
|
|
|
let lockFileName: string;
|
|
if (env && isLocal) {
|
|
lockFileName = `mise.${env}.local.lock`;
|
|
} else if (env) {
|
|
lockFileName = `mise.${env}.lock`;
|
|
} else if (isLocal) {
|
|
lockFileName = 'mise.local.lock';
|
|
} else {
|
|
lockFileName = 'mise.lock';
|
|
}
|
|
|
|
return upath.join(lockDir, lockFileName);
|
|
}
|
|
|
|
/**
|
|
* Get the locked version for a dependency from the parsed lock file.
|
|
*
|
|
* Mise lock files use different key formats depending on whether a tool is in
|
|
* the mise registry:
|
|
* - Registry tools (e.g., node, python): key is the short name ("node")
|
|
* - Non-registry tools (e.g., ubi:owner/repo): key is the full name ("ubi:owner/repo")
|
|
*
|
|
* When a user specifies "core:node" in their config, mise resolves it to the
|
|
* registry short name "node" in the lock file. But "aqua:cli/cli" (not in
|
|
* registry) stays as "aqua:cli/cli" in the lock file.
|
|
*
|
|
* We use a fallback approach (Option A) rather than checking the registry (Option B):
|
|
*
|
|
* Option A (implemented): Try full depName first, then try stripped short name.
|
|
* Pros: Simple, no registry dependency, works even if Renovate's registry
|
|
* is out of sync with mise's registry.
|
|
* Cons: Theoretical collision risk if both "foo" and "backend:foo" exist
|
|
* in the same lock file (practically impossible - mise wouldn't generate this).
|
|
*
|
|
* Option B (not implemented): Check miseTooling/asdfTooling to determine if
|
|
* the tool is in the registry, then use short name or full name accordingly.
|
|
* Pros: Matches mise's exact logic.
|
|
* Cons: More complex, requires passing registry data, fails if Renovate's
|
|
* registry doesn't include a tool that mise's registry does.
|
|
*
|
|
* Option A is preferred because it's simpler, has no practical downsides, and
|
|
* doesn't couple lock file parsing to Renovate's registry coverage.
|
|
*/
|
|
export function getLockedVersion(
|
|
lockFileData: MiseLockFile,
|
|
depName: string,
|
|
): string | undefined {
|
|
return getLockedTool(lockFileData, depName)?.[0]?.version;
|
|
}
|
|
|
|
/**
|
|
* Returns the lockfile entries for a dependency, using the same backend-name
|
|
* fallback as getLockedVersion().
|
|
*/
|
|
export function getLockedTool(
|
|
lockFileData: MiseLockFile,
|
|
depName: string,
|
|
): MiseLockTool[] | undefined {
|
|
// Try full name first (for non-registry tools like ubi:, aqua:)
|
|
let lockedTools = lockFileData.tools[depName];
|
|
|
|
// If not found and has backend prefix, try stripped name (for registry tools)
|
|
if (!lockedTools) {
|
|
const delimiterIndex = depName.indexOf(':');
|
|
if (delimiterIndex !== -1) {
|
|
const shortName = depName.substring(delimiterIndex + 1);
|
|
lockedTools = lockFileData.tools[shortName];
|
|
}
|
|
}
|
|
|
|
return lockedTools;
|
|
}
|