Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: tag pipenv version to install #7688

Merged
merged 39 commits into from
Nov 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
09d689e
Tag pipenv version to install
javulticat Nov 10, 2020
13131ff
Update snapshot
javulticat Nov 10, 2020
df2e73c
Get pipenv version from lock file or config
javulticat Nov 10, 2020
176ec8d
Revert snapshot change
javulticat Nov 10, 2020
c78a5dd
Return empty string
javulticat Nov 10, 2020
93d948d
Add unit tests
javulticat Nov 10, 2020
82560e9
Fix formatting
javulticat Nov 10, 2020
e68e9ce
Update snapshot for new unit tests
javulticat Nov 10, 2020
5d8d705
Improve test
javulticat Nov 10, 2020
0af021e
Fix version string
javulticat Nov 10, 2020
a998b0e
Fix other version string
javulticat Nov 10, 2020
c2bc6ae
Add 1
javulticat Nov 10, 2020
368360e
Fix tests to use docker
javulticat Nov 10, 2020
c019c0e
Fix docker tests
javulticat Nov 10, 2020
d7136d4
Add missing docker cmds
javulticat Nov 10, 2020
d6e209b
Linting
javulticat Nov 10, 2020
8d3e6eb
Linting
javulticat Nov 10, 2020
bb141d9
Fix tests
javulticat Nov 10, 2020
5cd1521
Fix snapshot
javulticat Nov 10, 2020
bcc5704
Add test for pipenv in Pipfile dev packages
javulticat Nov 10, 2020
6faf104
Add dev packages snapshot
javulticat Nov 10, 2020
629731e
Fix linting
javulticat Nov 10, 2020
eaea956
Fix usage of template literals
javulticat Nov 11, 2020
96f9deb
Lint
javulticat Nov 11, 2020
ce3c83f
Merge branch 'master' into fix/tag-pipenv-version
rarkins Nov 11, 2020
ea44d52
Use constraints in extract.ts
javulticat Nov 12, 2020
667158b
JS != Python
javulticat Nov 12, 2020
0fb437c
Linting
javulticat Nov 12, 2020
ee0b382
Add 'requires' to PipFile interface
javulticat Nov 12, 2020
8c999d0
Fix for hyphen in attribute name
javulticat Nov 12, 2020
5922718
Update extract snapshot with constraints
javulticat Nov 12, 2020
8c4278c
Change quotes for prettier
javulticat Nov 12, 2020
2f80971
Try to appease prettier - attempt 2
javulticat Nov 12, 2020
0a149ba
More linting
javulticat Nov 12, 2020
7f02b5c
Even more linting
javulticat Nov 12, 2020
8bba3b3
Add unit tests for constraint extraction
javulticat Nov 12, 2020
bd4f72a
Typos
javulticat Nov 12, 2020
4480b05
Fix constraint extract tests
javulticat Nov 12, 2020
ad4551f
Prettier
javulticat Nov 12, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions lib/manager/pipenv/__snapshots__/artifacts.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,108 @@ Array [
},
]
`;
exports[`.updateArtifacts() uses pipenv version from Pipfile 1`] = `
Array [
Object {
"cmd": "docker pull renovate/python",
"options": Object {
"encoding": "utf-8",
},
},
Object {
"cmd": "docker ps --filter name=renovate_python -aq",
"options": Object {
"encoding": "utf-8",
},
},
Object {
"cmd": "docker run --rm --name=renovate_python --label=renovate_child --user=foobar -v \\"/tmp/github/some/repo\\":\\"/tmp/github/some/repo\\" -v \\"/tmp/renovate/cache\\":\\"/tmp/renovate/cache\\" -v \\"/tmp/renovate/cache/others/pipenv\\":\\"/tmp/renovate/cache/others/pipenv\\" -e PIPENV_CACHE_DIR -w \\"/tmp/github/some/repo\\" renovate/python bash -l -c \\"pip install --user pipenv==2020.8.13 && pipenv lock\\"",
"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",
"PIPENV_CACHE_DIR": "/tmp/renovate/cache/others/pipenv",
},
"maxBuffer": 10485760,
"timeout": 900000,
},
},
]
`;
exports[`.updateArtifacts() uses pipenv version from Pipfile dev packages 1`] = `
Array [
Object {
"cmd": "docker pull renovate/python",
"options": Object {
"encoding": "utf-8",
},
},
Object {
"cmd": "docker ps --filter name=renovate_python -aq",
"options": Object {
"encoding": "utf-8",
},
},
Object {
"cmd": "docker run --rm --name=renovate_python --label=renovate_child --user=foobar -v \\"/tmp/github/some/repo\\":\\"/tmp/github/some/repo\\" -v \\"/tmp/renovate/cache\\":\\"/tmp/renovate/cache\\" -v \\"/tmp/renovate/cache/others/pipenv\\":\\"/tmp/renovate/cache/others/pipenv\\" -e PIPENV_CACHE_DIR -w \\"/tmp/github/some/repo\\" renovate/python bash -l -c \\"pip install --user pipenv==2020.8.13 && pipenv lock\\"",
"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",
"PIPENV_CACHE_DIR": "/tmp/renovate/cache/others/pipenv",
},
"maxBuffer": 10485760,
"timeout": 900000,
},
},
]
`;
exports[`.updateArtifacts() uses pipenv version from config 1`] = `
Array [
Object {
"cmd": "docker pull renovate/python",
"options": Object {
"encoding": "utf-8",
},
},
Object {
"cmd": "docker ps --filter name=renovate_python -aq",
"options": Object {
"encoding": "utf-8",
},
},
Object {
"cmd": "docker run --rm --name=renovate_python --label=renovate_child --user=foobar -v \\"/tmp/github/some/repo\\":\\"/tmp/github/some/repo\\" -v \\"/tmp/renovate/cache\\":\\"/tmp/renovate/cache\\" -v \\"/tmp/renovate/cache/others/pipenv\\":\\"/tmp/renovate/cache/others/pipenv\\" -e PIPENV_CACHE_DIR -w \\"/tmp/github/some/repo\\" renovate/python bash -l -c \\"pip install --user pipenv==2020.1.1 && pipenv lock\\"",
"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",
"PIPENV_CACHE_DIR": "/tmp/renovate/cache/others/pipenv",
},
"maxBuffer": 10485760,
"timeout": 900000,
},
},
]
`;
10 changes: 10 additions & 0 deletions lib/manager/pipenv/__snapshots__/extract.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

exports[`lib/manager/pipenv/extract extractPackageFile() extracts dependencies 1`] = `
Object {
"constraints": Object {
"python": "== 3.6.*",
},
"deps": Array [
Object {
"currentValue": "==0.3.1",
Expand Down Expand Up @@ -57,6 +60,9 @@ Object {

exports[`lib/manager/pipenv/extract extractPackageFile() extracts example pipfile 1`] = `
Object {
"constraints": Object {
"python": "== 2.7.*",
},
"deps": Array [
Object {
"depName": "requests",
Expand Down Expand Up @@ -126,6 +132,9 @@ Object {

exports[`lib/manager/pipenv/extract extractPackageFile() extracts multiple dependencies 1`] = `
Object {
"constraints": Object {
"python": "== 3.6.*",
},
"deps": Array [
Object {
"currentValue": "==1",
Expand Down Expand Up @@ -171,6 +180,7 @@ Object {

exports[`lib/manager/pipenv/extract extractPackageFile() supports custom index 1`] = `
Object {
"constraints": Object {},
"deps": Array [
Object {
"currentValue": "==0.21.0",
Expand Down
66 changes: 65 additions & 1 deletion lib/manager/pipenv/artifacts.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ describe('.updateArtifacts()', () => {

await setUtilConfig(config);
docker.resetPrefetchedImages();
pipFileLock = { _meta: { requires: {} } };
pipFileLock = {
_meta: { requires: {} },
default: { pipenv: {} },
develop: { pipenv: {} },
};
});

it('returns if no Pipfile.lock found', async () => {
Expand Down Expand Up @@ -153,4 +157,64 @@ describe('.updateArtifacts()', () => {
).not.toBeNull();
expect(execSnapshots).toMatchSnapshot();
});
it('uses pipenv version from Pipfile', async () => {
jest.spyOn(docker, 'removeDanglingContainers').mockResolvedValueOnce();
await setUtilConfig(dockerConfig);
pipFileLock.default.pipenv.version = '==2020.8.13';
fs.readFile.mockResolvedValueOnce(JSON.stringify(pipFileLock) as any);
const execSnapshots = mockExecAll(exec);
git.getRepoStatus.mockResolvedValue({
modified: ['Pipfile.lock'],
} as StatusResult);
fs.readFile.mockReturnValueOnce('new lock' as any);
expect(
await pipenv.updateArtifacts({
packageFileName: 'Pipfile',
updatedDeps: [],
newPackageFileContent: 'some new content',
config: dockerConfig,
})
).not.toBeNull();
expect(execSnapshots).toMatchSnapshot();
});
it('uses pipenv version from Pipfile dev packages', async () => {
jest.spyOn(docker, 'removeDanglingContainers').mockResolvedValueOnce();
await setUtilConfig(dockerConfig);
pipFileLock.develop.pipenv.version = '==2020.8.13';
fs.readFile.mockResolvedValueOnce(JSON.stringify(pipFileLock) as any);
const execSnapshots = mockExecAll(exec);
git.getRepoStatus.mockResolvedValue({
modified: ['Pipfile.lock'],
} as StatusResult);
fs.readFile.mockReturnValueOnce('new lock' as any);
expect(
await pipenv.updateArtifacts({
packageFileName: 'Pipfile',
updatedDeps: [],
newPackageFileContent: 'some new content',
config: dockerConfig,
})
).not.toBeNull();
expect(execSnapshots).toMatchSnapshot();
});
it('uses pipenv version from config', async () => {
jest.spyOn(docker, 'removeDanglingContainers').mockResolvedValueOnce();
await setUtilConfig(dockerConfig);
pipFileLock.default.pipenv.version = '==2020.8.13';
fs.readFile.mockResolvedValueOnce(JSON.stringify(pipFileLock) as any);
const execSnapshots = mockExecAll(exec);
git.getRepoStatus.mockResolvedValue({
modified: ['Pipfile.lock'],
} as StatusResult);
fs.readFile.mockReturnValueOnce('new lock' as any);
expect(
await pipenv.updateArtifacts({
packageFileName: 'Pipfile',
updatedDeps: [],
newPackageFileContent: 'some new content',
config: { ...dockerConfig, constraints: { pipenv: '==2020.1.1' } },
})
).not.toBeNull();
expect(execSnapshots).toMatchSnapshot();
});
});
36 changes: 35 additions & 1 deletion lib/manager/pipenv/artifacts.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { quote } from 'shlex';
import { logger } from '../../logger';
import { ExecOptions, exec } from '../../util/exec';
import {
Expand Down Expand Up @@ -41,6 +42,33 @@ function getPythonConstraint(
return undefined;
}

function getPipenvConstraint(
existingLockFileContent: string,
config: UpdateArtifactsConfig
): string | null {
const { constraints = {} } = config;
const { pipenv } = constraints;

if (pipenv) {
logger.debug('Using pipenv constraint from config');
return pipenv;
}
try {
const pipfileLock = JSON.parse(existingLockFileContent);
if (pipfileLock?.default?.pipenv?.version) {
const pipenvVersion: string = pipfileLock.default.pipenv.version;
return pipenvVersion;
}
if (pipfileLock?.develop?.pipenv?.version) {
const pipenvVersion: string = pipfileLock.develop.pipenv.version;
return pipenvVersion;
}
} catch (err) {
// Do nothing
}
return '';
}

export async function updateArtifacts({
packageFileName: pipfileName,
newPackageFileContent: newPipfileContent,
Expand All @@ -64,6 +92,10 @@ export async function updateArtifacts({
}
const cmd = 'pipenv lock';
const tagConstraint = getPythonConstraint(existingLockFileContent, config);
const pipenvConstraint = getPipenvConstraint(
existingLockFileContent,
config
);
const execOptions: ExecOptions = {
extraEnv: {
PIPENV_CACHE_DIR: cacheDir,
Expand All @@ -72,7 +104,9 @@ export async function updateArtifacts({
image: 'renovate/python',
tagConstraint,
tagScheme: 'pep440',
preCommands: ['pip install --user pipenv'],
preCommands: [
`pip install --user ${quote(`pipenv${pipenvConstraint}`)}`,
],
volumes: [cacheDir],
},
};
Expand Down
24 changes: 24 additions & 0 deletions lib/manager/pipenv/extract.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,29 @@ describe('lib/manager/pipenv/extract', () => {
expect(res.deps[0].registryUrls).toBeDefined();
expect(res.deps[0].registryUrls).toHaveLength(1);
});
it('gets python constraint from python_version', () => {
const content =
'[packages]\r\nfoo = "==1.0.0"\r\n' +
'[requires]\r\npython_version = "3.8"';
const res = extractPackageFile(content);
expect(res.constraints.python).toEqual('== 3.8.*');
});
it('gets python constraint from python_full_version', () => {
const content =
'[packages]\r\nfoo = "==1.0.0"\r\n' +
'[requires]\r\npython_full_version = "3.8.6"';
const res = extractPackageFile(content);
expect(res.constraints.python).toEqual('== 3.8.6');
});
it('gets pipenv constraint from packages', () => {
const content = '[packages]\r\npipenv = "==2020.8.13"';
const res = extractPackageFile(content);
expect(res.constraints.pipenv).toEqual('==2020.8.13');
});
it('gets pipenv constraint from dev-packages', () => {
const content = '[dev-packages]\r\npipenv = "==2020.8.13"';
const res = extractPackageFile(content);
expect(res.constraints.pipenv).toEqual('==2020.8.13');
});
});
});
23 changes: 20 additions & 3 deletions lib/manager/pipenv/extract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ interface PipFile {

packages?: Record<string, PipRequirement>;
'dev-packages'?: Record<string, PipRequirement>;
requires?: Record<string, string>;
}

interface PipRequirement {
Expand Down Expand Up @@ -136,8 +137,24 @@ export function extractPackageFile(content: string): PackageFile | null {
...extractFromSection(pipfile, 'packages'),
...extractFromSection(pipfile, 'dev-packages'),
];
if (res.deps.length) {
return res;
if (!res.deps.length) {
return null;
}

const constraints: Record<string, any> = {};

if (is.nonEmptyString(pipfile.requires?.python_version)) {
constraints.python = `== ${pipfile.requires.python_version}.*`;
} else if (is.nonEmptyString(pipfile.requires?.python_full_version)) {
constraints.python = `== ${pipfile.requires.python_full_version}`;
}
return null;

if (is.nonEmptyString(pipfile.packages?.pipenv)) {
constraints.pipenv = pipfile.packages.pipenv;
} else if (is.nonEmptyString(pipfile['dev-packages']?.pipenv)) {
constraints.pipenv = pipfile['dev-packages'].pipenv;
}

res.constraints = constraints;
return res;
}