diff --git a/lib/manager/composer/artifacts.js b/lib/manager/composer/artifacts.js index 583e710a6ab892048a12bfbbc2d242da524d06b6..0c9642afbded6d87cfff9f716d684841e49172d9 100644 --- a/lib/manager/composer/artifacts.js +++ b/lib/manager/composer/artifacts.js @@ -35,6 +35,9 @@ async function updateArtifacts( const localPackageFileName = upath.join(config.localDir, packageFileName); await fs.outputFile(localPackageFileName, newPackageFileContent); const localLockFileName = upath.join(config.localDir, lockFileName); + if (config.isLockFileMaintenance) { + await fs.remove(localLockFileName); + } const authJson = {}; let credentials = hostRules.find({ hostType: 'github', @@ -115,10 +118,16 @@ async function updateArtifacts( logger.info('Running composer via global composer'); cmd = 'composer'; } - const args = - ('update ' + updatedDeps.join(' ')).trim() + - ' --ignore-platform-reqs --no-ansi --no-interaction --no-scripts --no-autoloader --with-dependencies'; - logger.debug({ cmd, args }, 'composer update command'); + let args; + if (config.isLockFileMaintenance) { + args = 'install'; + } else { + args = + ('update ' + updatedDeps.join(' ')).trim() + ' --with-dependencies'; + } + args += + ' --ignore-platform-reqs --no-ansi --no-interaction --no-scripts --no-autoloader'; + logger.debug({ cmd, args }, 'composer command'); ({ stdout, stderr } = await exec(`${cmd} ${args}`, { cwd, shell: true, diff --git a/lib/manager/composer/index.js b/lib/manager/composer/index.js index 568ada54abc83a3b76b2d7b5b566778f7d83ef54..e31490e30d7ca86d5572c08e37e29bb89e4b3f5f 100644 --- a/lib/manager/composer/index.js +++ b/lib/manager/composer/index.js @@ -11,6 +11,5 @@ module.exports = { language, updateDependency, getRangeStrategy, - // TODO: support this - // supportsLockFileMaintenance: true, + supportsLockFileMaintenance: true, }; diff --git a/lib/workers/branch/get-updated.js b/lib/workers/branch/get-updated.js index f8b0c54253566d29e1fb9ef5c915c22ea8694d5d..fe955912295b9c44935089ccf69214fb0c6a86bf 100644 --- a/lib/workers/branch/get-updated.js +++ b/lib/workers/branch/get-updated.js @@ -11,14 +11,16 @@ async function getUpdatedPackageFiles(config) { const updatedFileContents = {}; const packageFileManagers = {}; const packageFileUpdatedDeps = {}; - + const lockFileMaintenanceFiles = []; for (const upgrade of config.upgrades) { const { manager, packageFile, depName } = upgrade; packageFileManagers[packageFile] = manager; packageFileUpdatedDeps[packageFile] = packageFileUpdatedDeps[packageFile] || []; packageFileUpdatedDeps[packageFile].push(depName); - if (upgrade.updateType !== 'lockFileMaintenance') { + if (upgrade.updateType === 'lockFileMaintenance') { + lockFileMaintenanceFiles.push(packageFile); + } else { const existingContent = updatedFileContents[packageFile] || (await platform.getFile(packageFile, config.parentBranch)); @@ -90,6 +92,34 @@ async function getUpdatedPackageFiles(config) { } } } + if (!config.parentBranch) { + // Only perform lock file maintenance if it's a fresh commit + for (const packageFile of lockFileMaintenanceFiles) { + const manager = packageFileManagers[packageFile]; + const updateArtifacts = get(manager, 'updateArtifacts'); + if (updateArtifacts) { + const packageFileContents = + updatedFileContents[packageFile] || + (await platform.getFile(packageFile, config.parentBranch)); + const results = await updateArtifacts( + packageFile, + [], + packageFileContents, + config + ); + if (is.nonEmptyArray(results)) { + for (const res of results) { + const { file, artifactError } = res; + if (file) { + updatedArtifacts.push(file); + } else if (artifactError) { + artifactErrors.push(artifactError); + } + } + } + } + } + } return { parentBranch: config.parentBranch, // Need to overwrite original config updatedPackageFiles, diff --git a/lib/workers/pr/pr-body.js b/lib/workers/pr/pr-body.js index 179b0e904f5d13d0ae23c035fc9ab0355e3ff270..fdd3b7211c3c694c515af92329fe0d72a23657e3 100644 --- a/lib/workers/pr/pr-body.js +++ b/lib/workers/pr/pr-body.js @@ -159,7 +159,7 @@ async function getPrBody(config) { if (config.updateType === 'lockFileMaintenance') { prBody += - ':wrench: This Pull Request updates `package.json` lock files to use the latest dependency versions.\n\n'; + ':wrench: This Pull Request updates lock files to use the latest dependency versions.\n\n'; } if (config.isPin) { diff --git a/test/manager/composer/artifacts.spec.js b/test/manager/composer/artifacts.spec.js index 5bf5e76a76af5d522a779c4f8fa9adda0cb2110a..5fbc84598fe0a6b692ddc9af2711983816fab512 100644 --- a/test/manager/composer/artifacts.spec.js +++ b/test/manager/composer/artifacts.spec.js @@ -73,6 +73,21 @@ describe('.updateArtifacts()', () => { await composer.updateArtifacts('composer.json', [], '{}', config) ).not.toBeNull(); }); + it('performs lockFileMaintenance', async () => { + platform.getFile.mockReturnValueOnce('Current composer.lock'); + exec.mockReturnValueOnce({ + stdout: '', + stderror: '', + }); + fs.readFile = jest.fn(() => 'New composer.lock'); + platform.getRepoStatus.mockResolvedValue({ modified: ['composer.lock'] }); + expect( + await composer.updateArtifacts('composer.json', [], '{}', { + ...config, + isLockFileMaintenance: true, + }) + ).not.toBeNull(); + }); it('supports docker mode', async () => { platform.getFile.mockReturnValueOnce('Current composer.lock'); exec.mockReturnValueOnce({ diff --git a/test/workers/branch/__snapshots__/get-updated.spec.js.snap b/test/workers/branch/__snapshots__/get-updated.spec.js.snap index ef9ad00feaf863f3f00c619bad12a38abd766d2f..0b5271543dc9f668eef5634cb50ddeb30f6fe829 100644 --- a/test/workers/branch/__snapshots__/get-updated.spec.js.snap +++ b/test/workers/branch/__snapshots__/get-updated.spec.js.snap @@ -60,3 +60,31 @@ Object { ], } `; + +exports[`workers/branch/get-updated getUpdatedPackageFiles() handles lockFileMaintenance 1`] = ` +Object { + "artifactErrors": Array [], + "parentBranch": undefined, + "updatedArtifacts": Array [ + Object { + "contents": "some contents", + "name": "composer.json", + }, + ], + "updatedPackageFiles": Array [], +} +`; + +exports[`workers/branch/get-updated getUpdatedPackageFiles() handles lockFileMaintenance error 1`] = ` +Object { + "artifactErrors": Array [ + Object { + "name": "composer.lock", + "stderr": "some error", + }, + ], + "parentBranch": undefined, + "updatedArtifacts": Array [], + "updatedPackageFiles": Array [], +} +`; diff --git a/test/workers/branch/get-updated.spec.js b/test/workers/branch/get-updated.spec.js index 4bacff0a4a51e33fcc3c198a64d922c58fbe9e1b..a00e4e988052fb730f12e0d5d3c89ff45b44b293 100644 --- a/test/workers/branch/get-updated.spec.js +++ b/test/workers/branch/get-updated.spec.js @@ -55,6 +55,40 @@ describe('workers/branch/get-updated', () => { const res = await getUpdatedPackageFiles(config); expect(res).toMatchSnapshot(); }); + it('handles lockFileMaintenance', async () => { + // config.parentBranch = 'some-branch'; + config.upgrades.push({ + manager: 'composer', + updateType: 'lockFileMaintenance', + }); + composer.updateArtifacts.mockReturnValue([ + { + file: { + name: 'composer.json', + contents: 'some contents', + }, + }, + ]); + const res = await getUpdatedPackageFiles(config); + expect(res).toMatchSnapshot(); + }); + it('handles lockFileMaintenance error', async () => { + // config.parentBranch = 'some-branch'; + config.upgrades.push({ + manager: 'composer', + updateType: 'lockFileMaintenance', + }); + composer.updateArtifacts.mockReturnValue([ + { + artifactError: { + name: 'composer.lock', + stderr: 'some error', + }, + }, + ]); + const res = await getUpdatedPackageFiles(config); + expect(res).toMatchSnapshot(); + }); it('handles lock file errors', async () => { config.parentBranch = 'some-branch'; config.upgrades.push({ diff --git a/test/workers/pr/__snapshots__/index.spec.js.snap b/test/workers/pr/__snapshots__/index.spec.js.snap index 05de881dd5b5e6c1c4d344e0adc5bc5dfee4fd10..8885b22f7b82f6f5f044341ee8df9f44731beb64 100644 --- a/test/workers/pr/__snapshots__/index.spec.js.snap +++ b/test/workers/pr/__snapshots__/index.spec.js.snap @@ -140,7 +140,7 @@ note 2 :abcd: If you wish to disable git hash updates, add \`\\":disableDigestUpdates\\"\` to the extends array in your config. -:wrench: This Pull Request updates \`package.json\` lock files to use the latest dependency versions. +:wrench: This Pull Request updates lock files to use the latest dependency versions. ---