diff --git a/lib/modules/manager/pip-compile/__snapshots__/artifacts.spec.ts.snap b/lib/modules/manager/pip-compile/__snapshots__/artifacts.spec.ts.snap deleted file mode 100644 index 04c3f4a1b394e20213c4820edd873150c397b000..0000000000000000000000000000000000000000 --- a/lib/modules/manager/pip-compile/__snapshots__/artifacts.spec.ts.snap +++ /dev/null @@ -1,73 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`modules/manager/pip-compile/artifacts returns null if unchanged 1`] = ` -Array [ - Object { - "cmd": "pip-compile requirements.in", - "options": Object { - "cwd": "/tmp/github/some/repo", - "encoding": "utf-8", - "env": Object { - "HOME": "/home/user", - "HTTPS_PROXY": "https://example.com", - "HTTP_PROXY": "http://example.com", - "LANG": "en_US.UTF-8", - "LC_ALL": "en_US", - "NO_PROXY": "localhost", - "PATH": "/tmp/path", - "PIP_CACHE_DIR": "/tmp/renovate/cache/others/pip", - }, - "maxBuffer": 10485760, - "timeout": 900000, - }, - }, -] -`; - -exports[`modules/manager/pip-compile/artifacts returns updated requirements.txt 1`] = ` -Array [ - Object { - "cmd": "pip-compile requirements.in", - "options": Object { - "cwd": "/tmp/github/some/repo", - "encoding": "utf-8", - "env": Object { - "HOME": "/home/user", - "HTTPS_PROXY": "https://example.com", - "HTTP_PROXY": "http://example.com", - "LANG": "en_US.UTF-8", - "LC_ALL": "en_US", - "NO_PROXY": "localhost", - "PATH": "/tmp/path", - "PIP_CACHE_DIR": "/tmp/renovate/cache/others/pip", - }, - "maxBuffer": 10485760, - "timeout": 900000, - }, - }, -] -`; - -exports[`modules/manager/pip-compile/artifacts returns updated requirements.txt when doing lockfile maintenance 1`] = ` -Array [ - Object { - "cmd": "pip-compile requirements.in", - "options": Object { - "cwd": "/tmp/github/some/repo", - "encoding": "utf-8", - "env": Object { - "HOME": "/home/user", - "HTTPS_PROXY": "https://example.com", - "HTTP_PROXY": "http://example.com", - "LANG": "en_US.UTF-8", - "LC_ALL": "en_US", - "NO_PROXY": "localhost", - "PATH": "/tmp/path", - "PIP_CACHE_DIR": "/tmp/renovate/cache/others/pip", - }, - "maxBuffer": 10485760, - "timeout": 900000, - }, - }, -] -`; diff --git a/lib/modules/manager/pip-compile/artifacts.spec.ts b/lib/modules/manager/pip-compile/artifacts.spec.ts index 7fe989fd81babf4f1a80798c432907a921ad9ec6..6076f30988a7d574b3f1c8884df24804ee0d53a6 100644 --- a/lib/modules/manager/pip-compile/artifacts.spec.ts +++ b/lib/modules/manager/pip-compile/artifacts.spec.ts @@ -1,8 +1,7 @@ -import _fs from 'fs-extra'; import { join } from 'upath'; import { envMock, mockExecAll } from '../../../../test/exec-util'; import { Fixtures } from '../../../../test/fixtures'; -import { env, git } from '../../../../test/util'; +import { env, fs, git } from '../../../../test/util'; import { GlobalConfig } from '../../../config/global'; import type { RepoGlobalConfig } from '../../../config/types'; import { logger } from '../../../logger'; @@ -12,14 +11,12 @@ import type { UpdateArtifactsConfig } from '../types'; import { constructPipCompileCmd } from './artifacts'; import { updateArtifacts } from '.'; -jest.mock('fs-extra'); jest.mock('../../../util/exec/env'); +jest.mock('../../../util/fs'); jest.mock('../../../util/git'); jest.mock('../../../util/host-rules'); jest.mock('../../../util/http'); -const fs: jest.Mocked<typeof _fs> = _fs as any; - const adminConfig: RepoGlobalConfig = { // `join` fixes Windows CI localDir: join('/tmp/github/some/repo'), @@ -45,6 +42,7 @@ describe('modules/manager/pip-compile/artifacts', () => { }); it('returns if no requirements.txt found', async () => { + const execSnapshots = mockExecAll(); expect( await updateArtifacts({ packageFileName: 'requirements.in', @@ -53,12 +51,13 @@ describe('modules/manager/pip-compile/artifacts', () => { config, }) ).toBeNull(); + expect(execSnapshots).toEqual([]); }); it('returns null if unchanged', async () => { - fs.readFile.mockResolvedValueOnce('content' as any); + fs.readLocalFile.mockResolvedValueOnce('content'); const execSnapshots = mockExecAll(); - fs.readFile.mockResolvedValueOnce('content' as any); + fs.readLocalFile.mockResolvedValueOnce('content'); expect( await updateArtifacts({ packageFileName: 'requirements.in', @@ -67,16 +66,18 @@ describe('modules/manager/pip-compile/artifacts', () => { config, }) ).toBeNull(); - expect(execSnapshots).toMatchSnapshot(); + expect(execSnapshots).toMatchObject([ + { cmd: 'pip-compile requirements.in' }, + ]); }); it('returns updated requirements.txt', async () => { - fs.readFile.mockResolvedValueOnce('current requirements.txt' as any); + fs.readLocalFile.mockResolvedValueOnce('current requirements.txt'); const execSnapshots = mockExecAll(); git.getRepoStatus.mockResolvedValue({ modified: ['requirements.txt'], } as StatusResult); - fs.readFile.mockResolvedValueOnce('New requirements.txt' as any); + fs.readLocalFile.mockResolvedValueOnce('New requirements.txt'); expect( await updateArtifacts({ packageFileName: 'requirements.in', @@ -85,7 +86,9 @@ describe('modules/manager/pip-compile/artifacts', () => { config: { ...config, constraints: { python: '3.7' } }, }) ).not.toBeNull(); - expect(execSnapshots).toMatchSnapshot(); + expect(execSnapshots).toMatchObject([ + { cmd: 'pip-compile requirements.in' }, + ]); }); it('supports docker mode', async () => { @@ -94,7 +97,8 @@ describe('modules/manager/pip-compile/artifacts', () => { git.getRepoStatus.mockResolvedValue({ modified: ['requirements.txt'], } as StatusResult); - fs.readFile.mockResolvedValueOnce('new lock' as any); + fs.readLocalFile.mockResolvedValueOnce('new lock'); + fs.ensureCacheDir.mockResolvedValueOnce('/tmp/renovate/cache/others/pip'); expect( await updateArtifacts({ packageFileName: 'requirements.in', @@ -127,13 +131,13 @@ describe('modules/manager/pip-compile/artifacts', () => { ]); }); - it('supports iunstall mode', async () => { + it('supports install mode', async () => { GlobalConfig.set({ ...adminConfig, binarySource: 'install' }); const execSnapshots = mockExecAll(); git.getRepoStatus.mockResolvedValue({ modified: ['requirements.txt'], } as StatusResult); - fs.readFile.mockResolvedValueOnce('new lock' as any); + fs.readLocalFile.mockResolvedValueOnce('new lock'); expect( await updateArtifacts({ packageFileName: 'requirements.in', @@ -154,8 +158,9 @@ describe('modules/manager/pip-compile/artifacts', () => { }); it('catches errors', async () => { - fs.readFile.mockResolvedValueOnce('Current requirements.txt' as any); - fs.outputFile.mockImplementationOnce(() => { + const execSnapshots = mockExecAll(); + fs.readLocalFile.mockResolvedValueOnce('Current requirements.txt'); + fs.writeLocalFile.mockImplementationOnce(() => { throw new Error('not found'); }); expect( @@ -170,15 +175,16 @@ describe('modules/manager/pip-compile/artifacts', () => { artifactError: { lockFile: 'requirements.txt', stderr: 'not found' }, }, ]); + expect(execSnapshots).toEqual([]); }); it('returns updated requirements.txt when doing lockfile maintenance', async () => { - fs.readFile.mockResolvedValueOnce('Current requirements.txt' as any); + fs.readLocalFile.mockResolvedValueOnce('Current requirements.txt'); const execSnapshots = mockExecAll(); git.getRepoStatus.mockResolvedValue({ modified: ['requirements.txt'], } as StatusResult); - fs.readFile.mockReturnValueOnce('New requirements.txt' as any); + fs.readLocalFile.mockResolvedValueOnce('New requirements.txt'); expect( await updateArtifacts({ packageFileName: 'requirements.in', @@ -187,7 +193,9 @@ describe('modules/manager/pip-compile/artifacts', () => { config: lockMaintenanceConfig, }) ).not.toBeNull(); - expect(execSnapshots).toMatchSnapshot(); + expect(execSnapshots).toMatchObject([ + { cmd: 'pip-compile requirements.in' }, + ]); }); it('uses pipenv version from config', async () => { @@ -196,7 +204,8 @@ describe('modules/manager/pip-compile/artifacts', () => { git.getRepoStatus.mockResolvedValue({ modified: ['requirements.txt'], } as StatusResult); - fs.readFile.mockResolvedValueOnce('new lock' as any); + fs.readLocalFile.mockResolvedValueOnce('new lock'); + fs.ensureCacheDir.mockResolvedValueOnce('/tmp/renovate/cache/others/pip'); expect( await updateArtifacts({ packageFileName: 'requirements.in', diff --git a/lib/modules/manager/poetry/__fixtures__/pyproject.10.toml b/lib/modules/manager/poetry/__fixtures__/pyproject.10.toml index 14c589fab7736df2c332883be90d1d017f0975e4..65c5e06ba8d947daca002419a032a68c13d4a719 100644 --- a/lib/modules/manager/poetry/__fixtures__/pyproject.10.toml +++ b/lib/modules/manager/poetry/__fixtures__/pyproject.10.toml @@ -15,3 +15,7 @@ url = "last.url" [[tool.poetry.source]] name = "five" + +[build-system] +requires = ["poetry_core>=1.0", "wheel"] +build-backend = "poetry.masonry.api" diff --git a/lib/modules/manager/poetry/__snapshots__/artifacts.spec.ts.snap b/lib/modules/manager/poetry/__snapshots__/artifacts.spec.ts.snap deleted file mode 100644 index dd7b68266df9794d02ea9794fff88d55d77d3774..0000000000000000000000000000000000000000 --- a/lib/modules/manager/poetry/__snapshots__/artifacts.spec.ts.snap +++ /dev/null @@ -1,236 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`modules/manager/poetry/artifacts catches errors 1`] = ` -Array [ - Object { - "artifactError": Object { - "lockFile": "poetry.lock", - "stderr": "undefined -undefined", - }, - }, -] -`; - -exports[`modules/manager/poetry/artifacts passes private credential environment vars 1`] = ` -Array [ - Object { - "cmd": "poetry update --lock --no-interaction dep1", - "options": Object { - "cwd": "/tmp/github/some/repo", - "encoding": "utf-8", - "env": Object { - "HOME": "/home/user", - "HTTPS_PROXY": "https://example.com", - "HTTP_PROXY": "http://example.com", - "LANG": "en_US.UTF-8", - "LC_ALL": "en_US", - "NO_PROXY": "localhost", - "PATH": "/tmp/path", - "PIP_CACHE_DIR": "/tmp/cache/others/pip", - "POETRY_HTTP_BASIC_FOUR_OH_FOUR_PASSWORD": "passwordFour", - "POETRY_HTTP_BASIC_ONE_PASSWORD": "passwordOne", - "POETRY_HTTP_BASIC_ONE_USERNAME": "usernameOne", - "POETRY_HTTP_BASIC_TWO_USERNAME": "usernameTwo", - }, - "maxBuffer": 10485760, - "timeout": 900000, - }, - }, -] -`; - -exports[`modules/manager/poetry/artifacts prioritizes pypi-scoped credentials 1`] = ` -Array [ - Object { - "cmd": "poetry update --lock --no-interaction dep1", - "options": Object { - "cwd": "/tmp/github/some/repo", - "encoding": "utf-8", - "env": Object { - "HOME": "/home/user", - "HTTPS_PROXY": "https://example.com", - "HTTP_PROXY": "http://example.com", - "LANG": "en_US.UTF-8", - "LC_ALL": "en_US", - "NO_PROXY": "localhost", - "PATH": "/tmp/path", - "PIP_CACHE_DIR": "/tmp/cache/others/pip", - "POETRY_HTTP_BASIC_ONE_PASSWORD": "scoped-password", - }, - "maxBuffer": 10485760, - "timeout": 900000, - }, - }, -] -`; - -exports[`modules/manager/poetry/artifacts returns null if unchanged 1`] = ` -Array [ - Object { - "cmd": "poetry update --lock --no-interaction dep1", - "options": Object { - "cwd": "/tmp/github/some/repo", - "encoding": "utf-8", - "env": Object { - "HOME": "/home/user", - "HTTPS_PROXY": "https://example.com", - "HTTP_PROXY": "http://example.com", - "LANG": "en_US.UTF-8", - "LC_ALL": "en_US", - "NO_PROXY": "localhost", - "PATH": "/tmp/path", - "PIP_CACHE_DIR": "/tmp/cache/others/pip", - }, - "maxBuffer": 10485760, - "timeout": 900000, - }, - }, -] -`; - -exports[`modules/manager/poetry/artifacts returns updated poetry.lock 1`] = ` -Array [ - Object { - "cmd": "poetry update --lock --no-interaction dep1", - "options": Object { - "cwd": "/tmp/github/some/repo", - "encoding": "utf-8", - "env": Object { - "HOME": "/home/user", - "HTTPS_PROXY": "https://example.com", - "HTTP_PROXY": "http://example.com", - "LANG": "en_US.UTF-8", - "LC_ALL": "en_US", - "NO_PROXY": "localhost", - "PATH": "/tmp/path", - "PIP_CACHE_DIR": "/tmp/cache/others/pip", - }, - "maxBuffer": 10485760, - "timeout": 900000, - }, - }, -] -`; - -exports[`modules/manager/poetry/artifacts returns updated poetry.lock using docker (constraints) 1`] = ` -Array [ - Object { - "cmd": "docker pull renovate/sidecar", - "options": Object { - "encoding": "utf-8", - }, - }, - Object { - "cmd": "docker ps --filter name=renovate_sidecar -aq", - "options": Object { - "encoding": "utf-8", - }, - }, - Object { - "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 PIP_CACHE_DIR -e BUILDPACK_CACHE_DIR -w \\"/tmp/github/some/repo\\" renovate/sidecar bash -l -c \\"install-tool python 1.2.0 && pip install --user 'poetry>=1.0' && poetry update --lock --no-interaction dep1\\"", - "options": Object { - "cwd": "/tmp/github/some/repo", - "encoding": "utf-8", - "env": Object { - "BUILDPACK_CACHE_DIR": "/tmp/cache/buildpack", - "HOME": "/home/user", - "HTTPS_PROXY": "https://example.com", - "HTTP_PROXY": "http://example.com", - "LANG": "en_US.UTF-8", - "LC_ALL": "en_US", - "NO_PROXY": "localhost", - "PATH": "/tmp/path", - "PIP_CACHE_DIR": "/tmp/cache/others/pip", - }, - "maxBuffer": 10485760, - "timeout": 900000, - }, - }, -] -`; - -exports[`modules/manager/poetry/artifacts returns updated poetry.lock using docker 1`] = ` -Array [ - Object { - "cmd": "docker pull renovate/sidecar", - "options": Object { - "encoding": "utf-8", - }, - }, - Object { - "cmd": "docker ps --filter name=renovate_sidecar -aq", - "options": Object { - "encoding": "utf-8", - }, - }, - Object { - "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 PIP_CACHE_DIR -e BUILDPACK_CACHE_DIR -w \\"/tmp/github/some/repo\\" renovate/sidecar bash -l -c \\"install-tool python 1.2.0 && pip install --user 'poetry>=1.0' && poetry update --lock --no-interaction dep1\\"", - "options": Object { - "cwd": "/tmp/github/some/repo", - "encoding": "utf-8", - "env": Object { - "BUILDPACK_CACHE_DIR": "/tmp/cache/buildpack", - "HOME": "/home/user", - "HTTPS_PROXY": "https://example.com", - "HTTP_PROXY": "http://example.com", - "LANG": "en_US.UTF-8", - "LC_ALL": "en_US", - "NO_PROXY": "localhost", - "PATH": "/tmp/path", - "PIP_CACHE_DIR": "/tmp/cache/others/pip", - }, - "maxBuffer": 10485760, - "timeout": 900000, - }, - }, -] -`; - -exports[`modules/manager/poetry/artifacts returns updated poetry.lock when doing lockfile maintenance 1`] = ` -Array [ - Object { - "cmd": "poetry update --lock --no-interaction", - "options": Object { - "cwd": "/tmp/github/some/repo", - "encoding": "utf-8", - "env": Object { - "HOME": "/home/user", - "HTTPS_PROXY": "https://example.com", - "HTTP_PROXY": "http://example.com", - "LANG": "en_US.UTF-8", - "LC_ALL": "en_US", - "NO_PROXY": "localhost", - "PATH": "/tmp/path", - "PIP_CACHE_DIR": "/tmp/cache/others/pip", - }, - "maxBuffer": 10485760, - "timeout": 900000, - }, - }, -] -`; - -exports[`modules/manager/poetry/artifacts returns updated pyproject.lock 1`] = ` -Array [ - Object { - "cmd": "poetry update --lock --no-interaction dep1", - "options": Object { - "cwd": "/tmp/github/some/repo", - "encoding": "utf-8", - "env": Object { - "HOME": "/home/user", - "HTTPS_PROXY": "https://example.com", - "HTTP_PROXY": "http://example.com", - "LANG": "en_US.UTF-8", - "LC_ALL": "en_US", - "NO_PROXY": "localhost", - "PATH": "/tmp/path", - "PIP_CACHE_DIR": "/tmp/cache/others/pip", - }, - "maxBuffer": 10485760, - "timeout": 900000, - }, - }, -] -`; diff --git a/lib/modules/manager/poetry/artifacts.spec.ts b/lib/modules/manager/poetry/artifacts.spec.ts index 49432cc37442bcdfa99cdb42dede11d5dff44d17..c524a84ba5e940de4af72cc20393f7431a20c6b4 100644 --- a/lib/modules/manager/poetry/artifacts.spec.ts +++ b/lib/modules/manager/poetry/artifacts.spec.ts @@ -1,8 +1,7 @@ -import _fs from 'fs-extra'; import { join } from 'upath'; import { envMock, mockExecAll } from '../../../../test/exec-util'; import { Fixtures } from '../../../../test/fixtures'; -import { env, mocked } from '../../../../test/util'; +import { env, fs, mocked } from '../../../../test/util'; import { GlobalConfig } from '../../../config/global'; import type { RepoGlobalConfig } from '../../../config/types'; import * as docker from '../../../util/exec/docker'; @@ -14,14 +13,13 @@ import { updateArtifacts } from '.'; const pyproject1toml = Fixtures.get('pyproject.1.toml'); const pyproject10toml = Fixtures.get('pyproject.10.toml'); -jest.mock('fs-extra'); jest.mock('../../../util/exec/env'); +jest.mock('../../../util/fs'); jest.mock('../../datasource'); jest.mock('../../../util/host-rules'); process.env.BUILDPACK = 'true'; -const fs: jest.Mocked<typeof _fs> = _fs as any; const datasource = mocked(_datasource); const hostRules = mocked(_hostRules); @@ -41,6 +39,7 @@ describe('modules/manager/poetry/artifacts', () => { }); it('returns null if no poetry.lock found', async () => { + const execSnapshots = mockExecAll(); const updatedDeps = [{ depName: 'dep1' }]; expect( await updateArtifacts({ @@ -50,9 +49,11 @@ describe('modules/manager/poetry/artifacts', () => { config, }) ).toBeNull(); + expect(execSnapshots).toEqual([]); }); it('returns null if updatedDeps is empty', async () => { + const execSnapshots = mockExecAll(); expect( await updateArtifacts({ packageFileName: 'pyproject.toml', @@ -61,12 +62,14 @@ describe('modules/manager/poetry/artifacts', () => { config, }) ).toBeNull(); + expect(execSnapshots).toEqual([]); }); it('returns null if unchanged', async () => { - fs.readFile.mockReturnValueOnce('Current poetry.lock' as any); const execSnapshots = mockExecAll(); - fs.readFile.mockReturnValueOnce('Current poetry.lock' as any); + fs.ensureCacheDir.mockResolvedValueOnce('/tmp/renovate/cache/others/pip'); + fs.readLocalFile.mockResolvedValueOnce('Current poetry.lock'); + fs.readLocalFile.mockResolvedValueOnce('Current poetry.lock'); const updatedDeps = [{ depName: 'dep1' }]; expect( await updateArtifacts({ @@ -76,13 +79,23 @@ describe('modules/manager/poetry/artifacts', () => { config, }) ).toBeNull(); - expect(execSnapshots).toMatchSnapshot(); + expect(execSnapshots).toMatchObject([ + { + cmd: 'poetry update --lock --no-interaction dep1', + options: { + cwd: '/tmp/github/some/repo', + env: { PIP_CACHE_DIR: '/tmp/renovate/cache/others/pip' }, + }, + }, + ]); }); it('returns updated poetry.lock', async () => { - fs.readFile.mockResolvedValueOnce('[metadata]\n' as never); const execSnapshots = mockExecAll(); - fs.readFile.mockReturnValueOnce('New poetry.lock' as any); + // poetry.lock + fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); + fs.readLocalFile.mockResolvedValueOnce('[metadata]\n'); + fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); const updatedDeps = [{ depName: 'dep1' }]; expect( await updateArtifacts({ @@ -91,16 +104,29 @@ describe('modules/manager/poetry/artifacts', () => { newPackageFileContent: '{}', config, }) - ).not.toBeNull(); - expect(execSnapshots).toMatchSnapshot(); + ).toEqual([ + { + file: { + type: 'addition', + path: 'poetry.lock', + contents: 'New poetry.lock', + }, + }, + ]); + expect(execSnapshots).toMatchObject([ + { cmd: 'poetry update --lock --no-interaction dep1' }, + ]); }); it('passes private credential environment vars', async () => { - // TODO #7154 - fs.readFile.mockResolvedValueOnce(null as never); - fs.readFile.mockResolvedValueOnce('[metadata]\n' as never); + // poetry.lock + fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); + fs.readLocalFile.mockResolvedValueOnce(null); + // pyproject.lock + fs.getSiblingFileName.mockReturnValueOnce('pyproject.lock'); + fs.readLocalFile.mockResolvedValueOnce('[metadata]\n'); const execSnapshots = mockExecAll(); - fs.readFile.mockReturnValueOnce('New poetry.lock' as any); + fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); hostRules.find.mockReturnValueOnce({ username: 'usernameOne', password: 'passwordOne', @@ -116,17 +142,30 @@ describe('modules/manager/poetry/artifacts', () => { newPackageFileContent: pyproject10toml, config, }) - ).not.toBeNull(); + ).toEqual([ + { + file: { + type: 'addition', + path: 'pyproject.lock', + contents: 'New poetry.lock', + }, + }, + ]); expect(hostRules.find.mock.calls).toHaveLength(4); - expect(execSnapshots).toMatchSnapshot(); + expect(execSnapshots).toMatchObject([ + { cmd: 'poetry update --lock --no-interaction dep1' }, + ]); }); it('prioritizes pypi-scoped credentials', async () => { - // TODO #7154 - fs.readFile.mockResolvedValueOnce(null as never); - fs.readFile.mockResolvedValueOnce(Buffer.from('[metadata]\n')); const execSnapshots = mockExecAll(); - fs.readFile.mockResolvedValueOnce(Buffer.from('New poetry.lock')); + // poetry.lock + fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); + fs.readLocalFile.mockResolvedValueOnce(null); + // pyproject.lock + fs.getSiblingFileName.mockReturnValueOnce('pyproject.lock'); + fs.readLocalFile.mockResolvedValueOnce('[metadata]\n'); + fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); hostRules.find.mockImplementation((search) => ({ password: search.hostType === 'pypi' ? 'scoped-password' : 'unscoped-password', @@ -143,16 +182,29 @@ describe('modules/manager/poetry/artifacts', () => { `, config, }) - ).not.toBeNull(); - expect(execSnapshots).toMatchSnapshot(); + ).toEqual([ + { + file: { + type: 'addition', + path: 'pyproject.lock', + contents: 'New poetry.lock', + }, + }, + ]); + expect(execSnapshots).toMatchObject([ + { cmd: 'poetry update --lock --no-interaction dep1' }, + ]); }); it('returns updated pyproject.lock', async () => { - // TODO #7154 - fs.readFile.mockResolvedValueOnce(null as never); - fs.readFile.mockResolvedValueOnce('[metadata]\n' as never); const execSnapshots = mockExecAll(); - fs.readFile.mockReturnValueOnce('New poetry.lock' as any); + // poetry.lock + fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); + fs.readLocalFile.mockResolvedValueOnce(null); + // pyproject.lock + fs.getSiblingFileName.mockReturnValueOnce('pyproject.lock'); + fs.readLocalFile.mockResolvedValueOnce('[metadata]\n'); + fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); const updatedDeps = [{ depName: 'dep1' }]; expect( await updateArtifacts({ @@ -161,24 +213,28 @@ describe('modules/manager/poetry/artifacts', () => { newPackageFileContent: '{}', config, }) - ).not.toBeNull(); - expect(execSnapshots).toMatchSnapshot(); + ).toEqual([ + { + file: { + type: 'addition', + path: 'pyproject.lock', + contents: 'New poetry.lock', + }, + }, + ]); + expect(execSnapshots).toMatchObject([ + { cmd: 'poetry update --lock --no-interaction dep1' }, + ]); }); it('returns updated poetry.lock using docker', async () => { GlobalConfig.set({ ...adminConfig, binarySource: 'docker' }); - // poetry.lock - fs.readFile.mockResolvedValueOnce('[metadata]\n' as any); const execSnapshots = mockExecAll(); - fs.readFile.mockReturnValueOnce('New poetry.lock' as any); - // poetry - datasource.getPkgReleases.mockResolvedValueOnce({ - releases: [ - { version: '1.0.0' }, - { version: '1.1.0' }, - { version: '1.2.0' }, - ], - }); + fs.ensureCacheDir.mockResolvedValueOnce('/tmp/renovate/cache/others/pip'); + // poetry.lock + fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); + fs.readLocalFile.mockResolvedValueOnce('[metadata]\n'); + fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); // python datasource.getPkgReleases.mockResolvedValueOnce({ releases: [{ version: '2.7.5' }, { version: '3.4.2' }], @@ -196,26 +252,49 @@ describe('modules/manager/poetry/artifacts', () => { }, }, }) - ).not.toBeNull(); - expect(execSnapshots).toMatchSnapshot(); + ).toEqual([ + { + file: { + type: 'addition', + path: 'poetry.lock', + contents: 'New poetry.lock', + }, + }, + ]); + expect(execSnapshots).toMatchObject([ + { cmd: 'docker pull renovate/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 PIP_CACHE_DIR ' + + '-e BUILDPACK_CACHE_DIR ' + + '-w "/tmp/github/some/repo" ' + + 'renovate/sidecar ' + + 'bash -l -c "' + + 'install-tool python 3.4.2 ' + + '&& ' + + "pip install --user 'poetry>=1.0' " + + '&& ' + + 'poetry update --lock --no-interaction dep1' + + '"', + }, + ]); }); it('returns updated poetry.lock using docker (constraints)', async () => { GlobalConfig.set({ ...adminConfig, binarySource: 'docker' }); + const execSnapshots = mockExecAll(); + + fs.ensureCacheDir.mockResolvedValueOnce('/tmp/renovate/cache/others/pip'); // poetry.lock - fs.readFile.mockResolvedValueOnce( - '[metadata]\npython-versions = "~2.7 || ^3.4"' as any + fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); + fs.readLocalFile.mockResolvedValueOnce( + '[metadata]\npython-versions = "~2.7 || ^3.4"' ); - const execSnapshots = mockExecAll(); - fs.readFile.mockReturnValueOnce('New poetry.lock' as any); - // poetry - datasource.getPkgReleases.mockResolvedValueOnce({ - releases: [ - { version: '1.0.0' }, - { version: '1.1.0' }, - { version: '1.2.0' }, - ], - }); + fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); // python datasource.getPkgReleases.mockResolvedValueOnce({ releases: [{ version: '2.7.5' }, { version: '3.3.2' }], @@ -231,26 +310,47 @@ describe('modules/manager/poetry/artifacts', () => { constraints: {}, }, }) - ).not.toBeNull(); - expect(execSnapshots).toMatchSnapshot(); + ).toEqual([ + { + file: { + type: 'addition', + path: 'poetry.lock', + contents: 'New poetry.lock', + }, + }, + ]); + expect(execSnapshots).toMatchObject([ + { cmd: 'docker pull renovate/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 PIP_CACHE_DIR ' + + '-e BUILDPACK_CACHE_DIR ' + + '-w "/tmp/github/some/repo" ' + + 'renovate/sidecar ' + + 'bash -l -c "' + + 'install-tool python 3.3.2 ' + + '&& ' + + "pip install --user 'poetry>=1.0' " + + '&& ' + + 'poetry update --lock --no-interaction dep1' + + '"', + }, + ]); }); it('returns updated poetry.lock using install mode', async () => { GlobalConfig.set({ ...adminConfig, binarySource: 'install' }); + const execSnapshots = mockExecAll(); // poetry.lock - fs.readFile.mockResolvedValueOnce( - '[metadata]\npython-versions = "~2.7 || ^3.4"' as any + fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); + fs.readLocalFile.mockResolvedValueOnce( + '[metadata]\npython-versions = "~2.7 || ^3.4"' ); - const execSnapshots = mockExecAll(); - fs.readFile.mockReturnValueOnce('New poetry.lock' as any); - // poetry - datasource.getPkgReleases.mockResolvedValueOnce({ - releases: [ - { version: '1.0.0' }, - { version: '1.1.0' }, - { version: '1.2.0' }, - ], - }); + fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); // python datasource.getPkgReleases.mockResolvedValueOnce({ releases: [{ version: '2.7.5' }, { version: '3.3.2' }], @@ -277,18 +377,18 @@ describe('modules/manager/poetry/artifacts', () => { ]); expect(execSnapshots).toMatchObject([ - { cmd: 'install-tool python 1.2.0' }, + { cmd: 'install-tool python 3.3.2' }, { cmd: "pip install --user 'poetry>=1.0'" }, - { - cmd: 'poetry update --lock --no-interaction dep1', - options: { cwd: '/tmp/github/some/repo' }, - }, + { cmd: 'poetry update --lock --no-interaction dep1' }, ]); }); it('catches errors', async () => { - fs.readFile.mockResolvedValueOnce('Current poetry.lock' as any); - fs.outputFile.mockImplementationOnce(() => { + const execSnapshots = mockExecAll(); + // poetry.lock + fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); + fs.readLocalFile.mockResolvedValueOnce('Current poetry.lock'); + fs.writeLocalFile.mockImplementationOnce(() => { throw new Error('not found'); }); const updatedDeps = [{ depName: 'dep1' }]; @@ -299,13 +399,16 @@ describe('modules/manager/poetry/artifacts', () => { newPackageFileContent: '{}', config, }) - ).toMatchSnapshot([{ artifactError: { lockFile: 'poetry.lock' } }]); + ).toMatchObject([{ artifactError: { lockFile: 'poetry.lock' } }]); + expect(execSnapshots).toMatchObject([]); }); it('returns updated poetry.lock when doing lockfile maintenance', async () => { - fs.readFile.mockResolvedValueOnce('Old poetry.lock' as any); const execSnapshots = mockExecAll(); - fs.readFile.mockReturnValueOnce('New poetry.lock' as any); + // poetry.lock + fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); + fs.readLocalFile.mockResolvedValueOnce('Old poetry.lock'); + fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); expect( await updateArtifacts({ packageFileName: 'pyproject.toml', @@ -316,7 +419,17 @@ describe('modules/manager/poetry/artifacts', () => { updateType: 'lockFileMaintenance', }, }) - ).not.toBeNull(); - expect(execSnapshots).toMatchSnapshot(); + ).toEqual([ + { + file: { + contents: 'New poetry.lock', + path: 'poetry.lock', + type: 'addition', + }, + }, + ]); + expect(execSnapshots).toMatchObject([ + { cmd: 'poetry update --lock --no-interaction' }, + ]); }); }); diff --git a/lib/modules/manager/poetry/update-locked.spec.ts b/lib/modules/manager/poetry/update-locked.spec.ts index 3118f8afe3b21113174360a8ad2734e63054995e..fe736a6444f7dcf07313ad4e6a08e10c69caa95b 100644 --- a/lib/modules/manager/poetry/update-locked.spec.ts +++ b/lib/modules/manager/poetry/update-locked.spec.ts @@ -29,4 +29,14 @@ describe('modules/manager/poetry/update-locked', () => { }; expect(updateLockedDependency(config).status).toBe('unsupported'); }); + + it('returns unsupported for mising locked content', () => { + const config: UpdateLockedConfig = { + packageFile, + lockFile, + depName: 'urllib3', + newVersion: '1.26.4', + }; + expect(updateLockedDependency(config).status).toBe('unsupported'); + }); });