mirror of
https://github.com/renovatebot/renovate.git
synced 2026-10-24 14:34:21 +00:00
fix(exec): re-run install-tool when switching back to an earlier tool version (#46823)
`install-tool` installs a version and also makes it the active one. The memo skipped `install-tool` for any tool version already installed in the run, so after A -> B -> A the last command ran on B. Track the active version per tool instead and skip only when the requested version is already active. Co-authored-by: Claude Opus 5.5 <michael.kriese+claude-code@mend.io>
This commit is contained in:
@@ -337,6 +337,27 @@ describe('util/exec/containerbase', () => {
|
||||
generateInstallCommands(toolConstraints, true),
|
||||
).resolves.toEqual(['install-tool composer 2.2.0']);
|
||||
});
|
||||
|
||||
it('re-issues the install command when switching back to an earlier version', async () => {
|
||||
const toolConstraints: ToolConstraint[] = [{ toolName: 'composer' }];
|
||||
await expect(
|
||||
generateInstallCommands(toolConstraints, true),
|
||||
).resolves.toEqual(['install-tool composer 2.1.0']);
|
||||
|
||||
datasource.getPkgReleases.mockResolvedValueOnce({
|
||||
releases: [{ version: '2.2.0' }],
|
||||
});
|
||||
await expect(
|
||||
generateInstallCommands(toolConstraints, true),
|
||||
).resolves.toEqual(['install-tool composer 2.2.0']);
|
||||
|
||||
datasource.getPkgReleases.mockResolvedValueOnce({
|
||||
releases: [{ version: '2.1.0' }],
|
||||
});
|
||||
await expect(
|
||||
generateInstallCommands(toolConstraints, true),
|
||||
).resolves.toEqual(['install-tool composer 2.1.0']);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -382,7 +382,9 @@ export async function resolveConstraint(
|
||||
|
||||
// Docker execs run in a fresh `--rm` container each time, so `memoize` must
|
||||
// stay false there - only the persistent-host (binarySource=install) path
|
||||
// can safely skip a tool it has already installed this run.
|
||||
// can safely skip a tool whose requested version is already active.
|
||||
// `install-tool` also activates the version it installs, so the memo tracks
|
||||
// the active version per tool, not every installed version.
|
||||
export async function generateInstallCommands(
|
||||
toolConstraints: Opt<ToolConstraint[]>,
|
||||
memoize = false,
|
||||
@@ -393,11 +395,11 @@ export async function generateInstallCommands(
|
||||
const toolVersion = await resolveConstraint(toolConstraint);
|
||||
const { toolName } = toolConstraint;
|
||||
if (memoize) {
|
||||
const cacheKey = `containerbase-installed:${toolName}:${toolVersion}`;
|
||||
if (memCache.get<boolean | undefined>(cacheKey)) {
|
||||
const cacheKey = `containerbase-active:${toolName}`;
|
||||
if (memCache.get<string | undefined>(cacheKey) === toolVersion) {
|
||||
continue;
|
||||
}
|
||||
memCache.set(cacheKey, true);
|
||||
memCache.set(cacheKey, toolVersion);
|
||||
}
|
||||
const installCommand = `install-tool ${toolName} ${quote(toolVersion)}`;
|
||||
installCommands.push(installCommand);
|
||||
|
||||
Reference in New Issue
Block a user