Skip to content

Commit

Permalink
feat(pip): support hash updating (#6460)
Browse files Browse the repository at this point in the history
  • Loading branch information
rarkins committed Jun 26, 2020
1 parent af203f6 commit 8302fb7
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 1 deletion.
64 changes: 64 additions & 0 deletions lib/manager/pip_requirements/artifacts.spec.ts
@@ -0,0 +1,64 @@
import _fs from 'fs-extra';
import { updateArtifacts } from './artifacts';

const fs: jest.Mocked<typeof _fs> = _fs as any;

jest.mock('fs-extra');
jest.mock('child_process');
jest.mock('../../util/exec');

const config = {};

const newPackageFileContent = `atomicwrites==1.4.0 \
--hash=sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4 \
--hash=sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6`;

describe('.updateArtifacts()', () => {
beforeEach(() => {
jest.resetAllMocks();
jest.resetModules();
});
it('returns null if no updatedDeps were provided', async () => {
expect(
await updateArtifacts({
packageFileName: 'requirements.txt',
updatedDeps: [],
newPackageFileContent,
config,
})
).toBeNull();
});
it('returns null if unchanged', async () => {
fs.readFile.mockResolvedValueOnce(newPackageFileContent as any);
expect(
await updateArtifacts({
packageFileName: 'requirements.txt',
updatedDeps: ['atomicwrites'],
newPackageFileContent,
config,
})
).toBeNull();
});
it('returns updated file', async () => {
fs.readFile.mockResolvedValueOnce('new content' as any);
expect(
await updateArtifacts({
packageFileName: 'requirements.txt',
updatedDeps: ['atomicwrites'],
newPackageFileContent,
config,
})
).toHaveLength(1);
});
it('catches and returns errors', async () => {
fs.readFile.mockResolvedValueOnce('new content' as any);
expect(
await updateArtifacts({
packageFileName: null,
updatedDeps: ['atomicwrites'],
newPackageFileContent,
config,
})
).toHaveLength(1);
});
});
65 changes: 65 additions & 0 deletions lib/manager/pip_requirements/artifacts.ts
@@ -0,0 +1,65 @@
import is from '@sindresorhus/is';
import { logger } from '../../logger';
import { ExecOptions, exec } from '../../util/exec';
import { readLocalFile } from '../../util/fs';
import { UpdateArtifact, UpdateArtifactsResult } from '../common';

export async function updateArtifacts({
packageFileName,
updatedDeps,
newPackageFileContent,
config,
}: UpdateArtifact): Promise<UpdateArtifactsResult[] | null> {
logger.debug(`pip_requirements.updateArtifacts(${packageFileName})`);
if (!is.nonEmptyArray(updatedDeps)) {
logger.debug('No updated pip_requirements deps - returning null');
return null;
}
try {
const cmd: string[] = [];
const rewrittenContent = newPackageFileContent.replace(/\\\n/g, '');
const lines = rewrittenContent.split('\n').map((line) => line.trim());
for (const dep of updatedDeps) {
const hashLine = lines.find(
(line) => line.startsWith(`${dep}==`) && line.includes('--hash=')
);
if (hashLine) {
const depConstraint = hashLine.split(' ')[0];
cmd.push(`hashin ${depConstraint} -r ${packageFileName}`);
}
}
const execOptions: ExecOptions = {
cwdFile: packageFileName,
docker: {
image: 'renovate/python',
tagScheme: 'pip_requirements',
preCommands: ['pip install hashin'],
},
};
await exec(cmd, execOptions);
const newContent = await readLocalFile(packageFileName, 'utf8');
if (newContent === newPackageFileContent) {
logger.debug(`${packageFileName} is unchanged`);
return null;
}
logger.debug(`Returning updated ${packageFileName}`);
return [
{
file: {
name: packageFileName,
contents: newContent,
},
},
];
} catch (err) {
logger.debug({ err }, `Failed to update ${packageFileName} file`);
return [
{
artifactError: {
lockFile: packageFileName,
stderr: err.stdout + '\n' + err.stderr,
},
},
];
}
}
2 changes: 1 addition & 1 deletion lib/manager/pip_requirements/extract.ts
Expand Up @@ -57,7 +57,7 @@ export function extractPackageFile(
dep.skipReason = SkipReason.Ignored;
}
regex.lastIndex = 0;
const matches = regex.exec(line);
const matches = regex.exec(line.split(' \\')[0]);
if (!matches) {
return null;
}
Expand Down
1 change: 1 addition & 0 deletions lib/manager/pip_requirements/index.ts
@@ -1,5 +1,6 @@
import { LANGUAGE_PYTHON } from '../../constants/languages';

export { updateArtifacts } from './artifacts';
export { extractPackageFile } from './extract';
export { getRangeStrategy } from './range';

Expand Down

0 comments on commit 8302fb7

Please sign in to comment.