diff --git a/lib/modules/manager/pip-compile/artifacts.spec.ts b/lib/modules/manager/pip-compile/artifacts.spec.ts index a22f9aca75dd55..2bd1c0e1072166 100644 --- a/lib/modules/manager/pip-compile/artifacts.spec.ts +++ b/lib/modules/manager/pip-compile/artifacts.spec.ts @@ -9,7 +9,7 @@ import { logger } from '../../../logger'; import * as docker from '../../../util/exec/docker'; import type { StatusResult } from '../../../util/git/types'; import * as _datasource from '../../datasource'; -import type { UpdateArtifactsConfig } from '../types'; +import type { UpdateArtifactsConfig, Upgrade } from '../types'; import { constructPipCompileCmd } from './artifacts'; import { updateArtifacts } from '.'; @@ -272,6 +272,33 @@ describe('modules/manager/pip-compile/artifacts', () => { ]); }); + it('uses --upgrade-package only for isLockfileUpdate', async () => { + fs.readLocalFile.mockResolvedValueOnce(simpleHeader); + const execSnapshots = mockExecAll(); + git.getRepoStatus.mockResolvedValue( + partial({ + modified: ['requirements.txt'], + }), + ); + fs.readLocalFile.mockResolvedValueOnce('New requirements.txt'); + expect( + await updateArtifacts({ + packageFileName: 'requirements.in', + updatedDeps: [ + { depName: 'foo', newVersion: '1.0.2', isLockfileUpdate: true }, + { depName: 'bar', newVersion: '2.0.0' }, + ] satisfies Upgrade[], + newPackageFileContent: '{}', + config: { ...lockMaintenanceConfig, lockFiles: ['requirements.txt'] }, + }), + ).not.toBeNull(); + expect(execSnapshots).toMatchObject([ + { + cmd: 'pip-compile --no-emit-index-url requirements.in --upgrade-package=foo==1.0.2', + }, + ]); + }); + it('uses pip-compile version from config', async () => { fs.readLocalFile.mockResolvedValueOnce(simpleHeader); GlobalConfig.set(dockerAdminConfig); @@ -408,5 +435,23 @@ describe('modules/manager/pip-compile/artifacts', () => { ), ).toThrow(/custom/); }); + + it('add --upgrade-package to command if Upgrade[] passed', () => { + expect( + constructPipCompileCmd( + getCommandInHeader( + 'pip-compile --output-file=requirements.txt requirements.in', + ), + 'subdir/requirements.txt', + false, + [ + { depName: 'foo', newVersion: '1.0.2' }, + { depName: 'bar', newVersion: '2.0.0' }, + ] satisfies Upgrade[], + ), + ).toBe( + 'pip-compile --no-emit-index-url --output-file=requirements.txt requirements.in --upgrade-package=foo==1.0.2 --upgrade-package=bar==2.0.0', + ); + }); }); }); diff --git a/lib/modules/manager/pip-compile/artifacts.ts b/lib/modules/manager/pip-compile/artifacts.ts index 48172d6f601624..abbbc6ff929845 100644 --- a/lib/modules/manager/pip-compile/artifacts.ts +++ b/lib/modules/manager/pip-compile/artifacts.ts @@ -10,7 +10,7 @@ import { } from '../../../util/fs'; import { getRepoStatus } from '../../../util/git'; import * as pipRequirements from '../pip_requirements'; -import type { UpdateArtifact, UpdateArtifactsResult } from '../types'; +import type { UpdateArtifact, UpdateArtifactsResult, Upgrade } from '../types'; import { extractHeaderCommand, getExecOptions, @@ -21,6 +21,7 @@ export function constructPipCompileCmd( content: string, outputFileName: string, haveCredentials: boolean, + upgradePackages: Upgrade[] = [], ): string { const compileArgs = extractHeaderCommand(content, outputFileName); if (compileArgs.isCustomCommand) { @@ -56,12 +57,18 @@ export function constructPipCompileCmd( ) { compileArgs.argv.splice(1, 0, '--no-emit-index-url'); } + for (const dep of upgradePackages) { + compileArgs.argv.push( + `--upgrade-package=${quote(dep.depName + '==' + dep.newVersion)}`, + ); + } return compileArgs.argv.map(quote).join(' '); } export async function updateArtifacts({ packageFileName: inputFileName, newPackageFileContent: newInputContent, + updatedDeps, config, }: UpdateArtifact): Promise { if (!config.lockFiles) { @@ -89,12 +96,14 @@ export async function updateArtifacts({ if (config.isLockFileMaintenance) { await deleteLocalFile(outputFileName); } + const upgradePackages = updatedDeps.filter((dep) => dep.isLockfileUpdate); const packageFile = pipRequirements.extractPackageFile(newInputContent); const registryUrlVars = getRegistryUrlVarsFromPackageFile(packageFile); const cmd = constructPipCompileCmd( existingOutput, outputFileName, registryUrlVars.haveCredentials, + upgradePackages, ); const execOptions = await getExecOptions( config,