Skip to content

Commit

Permalink
feat(manager/pep621): support pdm lock files (#22244)
Browse files Browse the repository at this point in the history
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
  • Loading branch information
secustor and viceice committed May 18, 2023
1 parent ffeb784 commit 2863361
Show file tree
Hide file tree
Showing 8 changed files with 398 additions and 3 deletions.
105 changes: 105 additions & 0 deletions lib/modules/manager/pep621/artifacts.spec.ts
@@ -0,0 +1,105 @@
import { join } from 'upath';
import { mockExecAll } from '../../../../test/exec-util';
import { fs, mockedFunction } from '../../../../test/util';
import { GlobalConfig } from '../../../config/global';
import type { RepoGlobalConfig } from '../../../config/types';
import { getPkgReleases as _getPkgReleases } from '../../datasource';
import type { UpdateArtifactsConfig } from '../types';
import { updateArtifacts } from './artifacts';

jest.mock('../../../util/fs');
jest.mock('../../datasource');

const getPkgReleases = mockedFunction(_getPkgReleases);

const config: UpdateArtifactsConfig = {};
const adminConfig: RepoGlobalConfig = {
localDir: join('/tmp/github/some/repo'),
cacheDir: join('/tmp/cache'),
containerbaseDir: join('/tmp/cache/containerbase'),
};

describe('modules/manager/pep621/artifacts', () => {
describe('updateArtifacts()', () => {
it('return null if all processors returns are empty', async () => {
const updatedDeps = [
{
packageName: 'dep1',
},
];
const result = await updateArtifacts({
packageFileName: 'pyproject.toml',
newPackageFileContent: '',
config,
updatedDeps,
});
expect(result).toBeNull();
});

it('return processor result', async () => {
const execSnapshots = mockExecAll();
GlobalConfig.set({ ...adminConfig, binarySource: 'docker' });
fs.getSiblingFileName.mockReturnValueOnce('pdm.lock');
fs.readLocalFile.mockResolvedValueOnce('old test content');
fs.readLocalFile.mockResolvedValueOnce('new test content');
// pdm
getPkgReleases.mockResolvedValueOnce({
releases: [{ version: 'v2.6.1' }, { version: 'v2.5.0' }],
});

const updatedDeps = [{ packageName: 'dep1' }];
const result = await updateArtifacts({
packageFileName: 'pyproject.toml',
newPackageFileContent: '',
config: {},
updatedDeps,
});
expect(result).toEqual([
{
file: {
contents: 'new test content',
path: 'pdm.lock',
type: 'addition',
},
},
]);
expect(execSnapshots).toMatchObject([
{
cmd: 'docker pull containerbase/sidecar',
options: {
encoding: 'utf-8',
},
},
{
cmd: 'docker ps --filter name=renovate_sidecar -aq',
options: {
encoding: 'utf-8',
},
},
{
cmd:
'docker run --rm --name=renovate_sidecar --label=renovate_child ' +
'-v "/tmp/github/some/repo":"/tmp/github/some/repo" ' +
'-v "/tmp/cache":"/tmp/cache" ' +
'-e BUILDPACK_CACHE_DIR ' +
'-e CONTAINERBASE_CACHE_DIR ' +
'-w "/tmp/github/some/repo" ' +
'containerbase/sidecar ' +
'bash -l -c "' +
'install-tool pdm v2.5.0 ' +
'&& ' +
'pdm update dep1' +
'"',
options: {
cwd: '/tmp/github/some/repo',
encoding: 'utf-8',
env: {
BUILDPACK_CACHE_DIR: '/tmp/cache/containerbase',
CONTAINERBASE_CACHE_DIR: '/tmp/cache/containerbase',
},
},
},
]);
});
});
});
23 changes: 23 additions & 0 deletions lib/modules/manager/pep621/artifacts.ts
@@ -0,0 +1,23 @@
import is from '@sindresorhus/is';
import { writeLocalFile } from '../../../util/fs';
import type { UpdateArtifact, UpdateArtifactsResult } from '../types';
import { processors } from './processors';

export async function updateArtifacts(
updateArtifact: UpdateArtifact
): Promise<UpdateArtifactsResult[] | null> {
const { packageFileName, newPackageFileContent } = updateArtifact;

await writeLocalFile(packageFileName, newPackageFileContent);

// process specific tool sets
const result: UpdateArtifactsResult[] = [];
for (const processor of processors) {
const artifactUpdates = await processor.updateArtifacts(updateArtifact);
if (is.array(artifactUpdates)) {
result.push(...artifactUpdates);
}
}

return result.length > 0 ? result : null;
}
3 changes: 3 additions & 0 deletions lib/modules/manager/pep621/index.ts
@@ -1,8 +1,11 @@
import { PypiDatasource } from '../../datasource/pypi';
export { extractPackageFile } from './extract';
export { updateArtifacts } from './artifacts';

export const supportedDatasources = [PypiDatasource.id];

export const supportsLockFileMaintenance = true;

export const defaultConfig = {
fileMatch: ['(^|/)pyproject\\.toml$'],
};
172 changes: 172 additions & 0 deletions lib/modules/manager/pep621/processors/pdm.spec.ts
@@ -0,0 +1,172 @@
import { join } from 'upath';
import { mockExecAll } from '../../../../../test/exec-util';
import { fs, mockedFunction } from '../../../../../test/util';
import { GlobalConfig } from '../../../../config/global';
import type { RepoGlobalConfig } from '../../../../config/types';
import { getPkgReleases as _getPkgReleases } from '../../../datasource';
import type { UpdateArtifactsConfig } from '../../types';
import { PdmProcessor } from './pdm';

jest.mock('../../../../util/fs');
jest.mock('../../../datasource');

const getPkgReleases = mockedFunction(_getPkgReleases);

const config: UpdateArtifactsConfig = {};
const adminConfig: RepoGlobalConfig = {
localDir: join('/tmp/github/some/repo'),
cacheDir: join('/tmp/cache'),
containerbaseDir: join('/tmp/cache/containerbase'),
};

const processor = new PdmProcessor();

describe('modules/manager/pep621/processors/pdm', () => {
describe('updateArtifacts()', () => {
it('return null if there is no lock file', async () => {
fs.getSiblingFileName.mockReturnValueOnce('pdm.lock');
const updatedDeps = [{ packageName: 'dep1' }];
const result = await processor.updateArtifacts({
packageFileName: 'pyproject.toml',
newPackageFileContent: '',
config,
updatedDeps,
});
expect(result).toBeNull();
});

it('return null if the lock file is unchanged', async () => {
const execSnapshots = mockExecAll();
GlobalConfig.set({ ...adminConfig, binarySource: 'docker' });
fs.getSiblingFileName.mockReturnValueOnce('pdm.lock');
fs.readLocalFile.mockResolvedValueOnce('test content');
fs.readLocalFile.mockResolvedValueOnce('test content');
// pdm
getPkgReleases.mockResolvedValueOnce({
releases: [{ version: 'v2.6.1' }, { version: 'v2.5.0' }],
});

const updatedDeps = [{ packageName: 'dep1' }];
const result = await processor.updateArtifacts({
packageFileName: 'pyproject.toml',
newPackageFileContent: '',
config: {},
updatedDeps,
});
expect(result).toBeNull();
expect(execSnapshots).toMatchObject([
{
cmd: 'docker pull containerbase/sidecar',
},
{
cmd: 'docker ps --filter name=renovate_sidecar -aq',
},
{
cmd:
'docker run --rm --name=renovate_sidecar --label=renovate_child ' +
'-v "/tmp/github/some/repo":"/tmp/github/some/repo" ' +
'-v "/tmp/cache":"/tmp/cache" ' +
'-e BUILDPACK_CACHE_DIR ' +
'-e CONTAINERBASE_CACHE_DIR ' +
'-w "/tmp/github/some/repo" ' +
'containerbase/sidecar ' +
'bash -l -c "' +
'install-tool pdm v2.5.0 ' +
'&& ' +
'pdm update dep1' +
'"',
},
]);
});

it('returns artifact error', async () => {
const execSnapshots = mockExecAll();
GlobalConfig.set({ ...adminConfig, binarySource: 'docker' });
fs.getSiblingFileName.mockReturnValueOnce('pdm.lock');
fs.readLocalFile.mockImplementationOnce(() => {
throw new Error('test error');
});

const updatedDeps = [{ packageName: 'dep1' }];
const result = await processor.updateArtifacts({
packageFileName: 'pyproject.toml',
newPackageFileContent: '',
config: {},
updatedDeps,
});
expect(result).toEqual([
{ artifactError: { lockFile: 'pdm.lock', stderr: 'test error' } },
]);
expect(execSnapshots).toEqual([]);
});

it('return update dep update', async () => {
const execSnapshots = mockExecAll();
GlobalConfig.set(adminConfig);
fs.getSiblingFileName.mockReturnValueOnce('pdm.lock');
fs.readLocalFile.mockResolvedValueOnce('test content');
fs.readLocalFile.mockResolvedValueOnce('changed test content');
// pdm
getPkgReleases.mockResolvedValueOnce({
releases: [{ version: 'v2.6.1' }, { version: 'v2.5.0' }],
});

const updatedDeps = [{ packageName: 'dep1' }, { packageName: 'dep2' }];
const result = await processor.updateArtifacts({
packageFileName: 'pyproject.toml',
newPackageFileContent: '',
config: {},
updatedDeps,
});
expect(result).toEqual([
{
file: {
contents: 'changed test content',
path: 'pdm.lock',
type: 'addition',
},
},
]);
expect(execSnapshots).toMatchObject([
{
cmd: 'pdm update dep1 dep2',
},
]);
});

it('return update on lockfileMaintenance', async () => {
const execSnapshots = mockExecAll();
GlobalConfig.set(adminConfig);
fs.getSiblingFileName.mockReturnValueOnce('pdm.lock');
fs.readLocalFile.mockResolvedValueOnce('test content');
fs.readLocalFile.mockResolvedValueOnce('changed test content');
// pdm
getPkgReleases.mockResolvedValueOnce({
releases: [{ version: 'v2.6.1' }, { version: 'v2.5.0' }],
});

const result = await processor.updateArtifacts({
packageFileName: 'pyproject.toml',
newPackageFileContent: '',
config: {
updateType: 'lockFileMaintenance',
},
updatedDeps: [],
});
expect(result).toEqual([
{
file: {
contents: 'changed test content',
path: 'pdm.lock',
type: 'addition',
},
},
]);
expect(execSnapshots).toMatchObject([
{
cmd: 'pdm update',
},
]);
});
});
});

0 comments on commit 2863361

Please sign in to comment.