From a07cee1b52632a5dd0622c6bb4c1a12c89639552 Mon Sep 17 00:00:00 2001 From: praveshtora <pravesh.tora@gmail.com> Date: Mon, 22 Jul 2019 11:08:22 +0530 Subject: [PATCH] feat(gomod): upgrade dependencies in replace directive (#4059) --- lib/manager/gomod/extract.js | 15 ++++-- lib/manager/gomod/update.js | 29 ++++++---- .../gomod/__snapshots__/extract.spec.js.snap | 8 +++ .../gomod/__snapshots__/update.spec.js.snap | 4 ++ test/manager/gomod/_fixtures/1/go.mod | 2 + test/manager/gomod/extract.spec.js | 3 +- test/manager/gomod/update.spec.js | 54 +++++++++++++++++++ 7 files changed, 100 insertions(+), 15 deletions(-) diff --git a/lib/manager/gomod/extract.js b/lib/manager/gomod/extract.js index c8cd5b1e35..5e8ac9a7ad 100644 --- a/lib/manager/gomod/extract.js +++ b/lib/manager/gomod/extract.js @@ -5,14 +5,14 @@ module.exports = { extractPackageFile, }; -function getDep(lineNumber, match) { +function getDep(lineNumber, match, type) { const [, , currentValue] = match; let [, depName] = match; depName = depName.replace(/"/g, ''); const dep = { lineNumber, depName, - depType: 'require', + depType: type, currentValue, }; if (!isVersion(currentValue)) { @@ -43,10 +43,17 @@ function extractPackageFile(content) { const lines = content.split('\n'); for (let lineNumber = 0; lineNumber < lines.length; lineNumber += 1) { let line = lines[lineNumber]; + const replaceMatch = line.match( + /^replace\s+[^\s]+[\s]+[=][>]\s+([^\s]+)\s+([^\s]+)/ + ); + if (replaceMatch) { + const dep = getDep(lineNumber, replaceMatch, 'replace'); + deps.push(dep); + } const requireMatch = line.match(/^require\s+([^\s]+)\s+([^\s]+)/); if (requireMatch) { logger.trace({ lineNumber }, `require line: "${line}"`); - const dep = getDep(lineNumber, requireMatch); + const dep = getDep(lineNumber, requireMatch, 'require'); deps.push(dep); } if (line.trim() === 'require (') { @@ -58,7 +65,7 @@ function extractPackageFile(content) { logger.trace(`reqLine: "${line}"`); if (multiMatch) { logger.trace({ lineNumber }, `require line: "${line}"`); - const dep = getDep(lineNumber, multiMatch); + const dep = getDep(lineNumber, multiMatch, 'require'); dep.multiLine = true; deps.push(dep); } else if (line.trim() !== ')') { diff --git a/lib/manager/gomod/update.js b/lib/manager/gomod/update.js index e6b0ca5230..87f0dc5eef 100644 --- a/lib/manager/gomod/update.js +++ b/lib/manager/gomod/update.js @@ -8,7 +8,7 @@ module.exports = { function updateDependency(currentFileContent, upgrade) { try { logger.debug(`gomod.updateDependency: ${upgrade.newValue}`); - const { depName } = upgrade; + const { depName, depType } = upgrade; let depNameNoVersion = depName .split('/') .slice(0, 3) @@ -28,13 +28,19 @@ function updateDependency(currentFileContent, upgrade) { ); return null; } - let requireLine; - if (upgrade.multiLine) { - requireLine = new RegExp(/^(\s+[^\s]+)(\s+)([^\s]+)/); - } else { - requireLine = new RegExp(/^(require\s+[^\s]+)(\s+)([^\s]+)/); + let updateLineExp; + if (depType === 'replace') { + updateLineExp = new RegExp( + /^(replace\s+[^\s]+[\s]+[=][>]+\s+)([^\s]+\s+)([^\s]+)/ + ); + } else if (depType === 'require') { + if (upgrade.multiLine) { + updateLineExp = new RegExp(/^(\s+[^\s]+)(\s+)([^\s]+)/); + } else { + updateLineExp = new RegExp(/^(require\s+[^\s]+)(\s+)([^\s]+)/); + } } - if (!lineToChange.match(requireLine)) { + if (!lineToChange.match(updateLineExp)) { logger.debug('No image line found'); return null; } @@ -53,9 +59,9 @@ function updateDependency(currentFileContent, upgrade) { ); const currentDateTime = DateTime.local().toFormat('yyyyMMddHHmmss'); const newValue = `v0.0.0-${currentDateTime}-${newDigestRightSized}`; - newLine = lineToChange.replace(requireLine, `$1$2${newValue}`); + newLine = lineToChange.replace(updateLineExp, `$1$2${newValue}`); } else { - newLine = lineToChange.replace(requireLine, `$1$2${upgrade.newValue}`); + newLine = lineToChange.replace(updateLineExp, `$1$2${upgrade.newValue}`); } if (upgrade.updateType === 'major') { logger.debug({ depName }, 'gomod: major update'); @@ -73,7 +79,10 @@ function updateDependency(currentFileContent, upgrade) { ) { if (upgrade.currentValue.match(/^v(0|1)\./)) { // Add version - newLine = newLine.replace(requireLine, `$1/v${upgrade.newMajor}$2$3`); + newLine = newLine.replace( + updateLineExp, + `$1/v${upgrade.newMajor}$2$3` + ); } else { // Replace version const [oldV] = upgrade.currentValue.split('.'); diff --git a/test/manager/gomod/__snapshots__/extract.spec.js.snap b/test/manager/gomod/__snapshots__/extract.spec.js.snap index 24ffa3972b..23f2cabd79 100644 --- a/test/manager/gomod/__snapshots__/extract.spec.js.snap +++ b/test/manager/gomod/__snapshots__/extract.spec.js.snap @@ -636,5 +636,13 @@ Array [ "depType": "require", "lineNumber": 8, }, + Object { + "currentValue": "v0.0.0", + "datasource": "go", + "depName": "github.com/pravesht/gocql", + "depNameShort": "pravesht/gocql", + "depType": "replace", + "lineNumber": 11, + }, ] `; diff --git a/test/manager/gomod/__snapshots__/update.spec.js.snap b/test/manager/gomod/__snapshots__/update.spec.js.snap index 06173bcf04..ddc3707e96 100644 --- a/test/manager/gomod/__snapshots__/update.spec.js.snap +++ b/test/manager/gomod/__snapshots__/update.spec.js.snap @@ -12,6 +12,8 @@ require gopkg.in/russross/blackfriday.v2 v2.0.0 require github.com/Azure/azure-sdk-for-go v25.1.0+incompatible replace github.com/pkg/errors => ../errors +replace golang.org/x/foo => github.com/pravesht/gocql v0.0.0 + " `; @@ -94,5 +96,7 @@ require gopkg.in/russross/blackfriday.v1 v1.0.0 require github.com/Azure/azure-sdk-for-go v25.1.0+incompatible replace github.com/pkg/errors => ../errors +replace golang.org/x/foo => github.com/pravesht/gocql v0.0.0 + " `; diff --git a/test/manager/gomod/_fixtures/1/go.mod b/test/manager/gomod/_fixtures/1/go.mod index a3e27f4b42..479f73c809 100644 --- a/test/manager/gomod/_fixtures/1/go.mod +++ b/test/manager/gomod/_fixtures/1/go.mod @@ -9,3 +9,5 @@ require gopkg.in/russross/blackfriday.v1 v1.0.0 require github.com/Azure/azure-sdk-for-go v25.1.0+incompatible replace github.com/pkg/errors => ../errors +replace golang.org/x/foo => github.com/pravesht/gocql v0.0.0 + diff --git a/test/manager/gomod/extract.spec.js b/test/manager/gomod/extract.spec.js index c4e47b93cd..0b01a595b4 100644 --- a/test/manager/gomod/extract.spec.js +++ b/test/manager/gomod/extract.spec.js @@ -12,8 +12,9 @@ describe('lib/manager/gomod/extract', () => { it('extracts single-line requires', () => { const res = extractPackageFile(gomod1).deps; expect(res).toMatchSnapshot(); - expect(res).toHaveLength(7); + expect(res).toHaveLength(8); expect(res.filter(e => e.skipReason)).toHaveLength(1); + expect(res.filter(e => e.depType === 'replace')).toHaveLength(1); }); it('extracts multi-line requires', () => { const res = extractPackageFile(gomod2).deps; diff --git a/test/manager/gomod/update.spec.js b/test/manager/gomod/update.spec.js index 32bddeff6a..d182176616 100644 --- a/test/manager/gomod/update.spec.js +++ b/test/manager/gomod/update.spec.js @@ -11,6 +11,7 @@ describe('manager/gomod/update', () => { depName: 'github.com/pkg/errors', lineNumber: 2, newValue: 'v0.8.0', + depType: 'require', }; const res = goUpdate.updateDependency(gomod1, upgrade); expect(res).not.toEqual(gomod1); @@ -21,6 +22,7 @@ describe('manager/gomod/update', () => { depName: 'github.com/pkg/errors', lineNumber: 2, newValue: 'v0.8.0', + depType: 'require', }; const res1 = goUpdate.updateDependency(gomod1, upgrade1); expect(res1).not.toEqual(gomod1); @@ -29,6 +31,7 @@ describe('manager/gomod/update', () => { depName: 'github.com/aws/aws-sdk-go', lineNumber: 3, newValue: 'v1.15.36', + depType: 'require', }; const res2 = goUpdate.updateDependency(res1, upgrade2); expect(res2).not.toEqual(res1); @@ -51,6 +54,7 @@ describe('manager/gomod/update', () => { updateType: 'major', currentValue: 'v0.7.0', newValue: 'v2.0.0', + depType: 'require', }; const res = goUpdate.updateDependency(gomod1, upgrade); expect(res).not.toEqual(gomod2); @@ -65,6 +69,7 @@ describe('manager/gomod/update', () => { updateType: 'major', currentValue: 'v1.0.0', newValue: 'v2.0.0', + depType: 'require', }; const res = goUpdate.updateDependency(gomod1, upgrade); expect(res).toMatchSnapshot(); @@ -92,6 +97,7 @@ describe('manager/gomod/update', () => { lineNumber: 8, multiLine: true, newValue: 'v1.8.0', + depType: 'require', }; const res = goUpdate.updateDependency(gomod2, upgrade); expect(res).not.toEqual(gomod2); @@ -103,6 +109,7 @@ describe('manager/gomod/update', () => { lineNumber: 57, multiLine: true, newValue: 'v4.8.0', + depType: 'require', }; const res = goUpdate.updateDependency(gomod2, upgrade); expect(res).toMatchSnapshot(); @@ -118,6 +125,7 @@ describe('manager/gomod/update', () => { newValue: 'v2.0.0', newMajor: 2, updateType: 'major', + depType: 'require', }; const res = goUpdate.updateDependency(gomod2, upgrade); expect(res).not.toEqual(gomod2); @@ -133,6 +141,7 @@ describe('manager/gomod/update', () => { newValue: 'v3.0.0', newMajor: 3, updateType: 'major', + depType: 'require', }; const res = goUpdate.updateDependency(gomod2, upgrade); expect(res).not.toEqual(gomod2); @@ -148,6 +157,7 @@ describe('manager/gomod/update', () => { updateType: 'digest', currentDigest: '14d3d4c51834', newDigest: '123456123456abcdef', + depType: 'require', }; const res = goUpdate.updateDependency(gomod2, upgrade); expect(res).not.toEqual(gomod2); @@ -163,6 +173,7 @@ describe('manager/gomod/update', () => { updateType: 'digest', currentDigest: 'abcdefabcdef', newDigest: '14d3d4c51834000000', + depType: 'require', }; const res = goUpdate.updateDependency(gomod2, upgrade); expect(res).toEqual(gomod2); @@ -172,6 +183,7 @@ describe('manager/gomod/update', () => { depName: 'github.com/fatih/color', lineNumber: 8, newValue: 'v1.8.0', + depType: 'require', }; const res = goUpdate.updateDependency(gomod2, upgrade); expect(res).toBeNull(); @@ -181,11 +193,53 @@ describe('manager/gomod/update', () => { depName: 'github.com/Azure/azure-sdk-for-go', lineNumber: 8, newValue: 'v26.0.0', + depType: 'require', }; const res = goUpdate.updateDependency(gomod1, upgrade); expect(res).not.toEqual(gomod1); // Assert that the version still contains +incompatible tag. expect(res.includes(upgrade.newValue + '+incompatible')).toBe(true); }); + it('handles replace line with minor version update', () => { + const upgrade = { + depName: 'github.com/pravesht/gocql', + lineNumber: 11, + newValue: 'v0.0.1', + depType: 'replace', + }; + const res = goUpdate.updateDependency(gomod1, upgrade); + expect(res).not.toEqual(gomod1); + expect(res.includes(upgrade.newValue)).toBe(true); + }); + it('handles replace line with major version update', () => { + const upgrade = { + depName: 'github.com/pravesht/gocql', + lineNumber: 11, + newValue: 'v2.0.0', + depType: 'replace', + currentValue: 'v0.7.0', + newMajor: 2, + updateType: 'major', + }; + const res = goUpdate.updateDependency(gomod1, upgrade); + expect(res).not.toEqual(gomod1); + expect(res.includes(upgrade.newValue)).toBe(true); + }); + it('handles replace line with digest', () => { + const upgrade = { + depName: 'github.com/pravesht/gocql', + lineNumber: 11, + newValue: 'v2.0.0', + depType: 'replace', + currentValue: 'v0.7.0', + newMajor: 2, + updateType: 'digest', + currentDigest: '14d3d4c51834', + newDigest: '123456123456abcdef', + }; + const res = goUpdate.updateDependency(gomod1, upgrade); + expect(res).not.toEqual(gomod1); + expect(res.includes(upgrade.newDigest.substring(0, 12))).toBe(true); + }); }); }); -- GitLab