diff --git a/lib/manager/gomod/__snapshots__/artifacts.spec.ts.snap b/lib/manager/gomod/__snapshots__/artifacts.spec.ts.snap index da1ab355e9456b21eced871c467a164f5462bd84..a2c73308b47f9d8e16d54c290ba779bba92254b0 100644 --- a/lib/manager/gomod/__snapshots__/artifacts.spec.ts.snap +++ b/lib/manager/gomod/__snapshots__/artifacts.spec.ts.snap @@ -120,7 +120,7 @@ Array [ }, }, Object { - "cmd": "docker run --rm --name=renovate_go --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/go\\":\\"/tmp/renovate/cache/others/go\\" -e GOPATH -e GOPROXY -e GONOSUMDB -e CGO_ENABLED -w \\"/tmp/github/some/repo\\" renovate/go:latest bash -l -c \\"git config --global url.\\\\\\"https://x-access-token:some-token@github.com/\\\\\\".insteadOf \\\\\\"https://github.com/\\\\\\" && go get -d ./...\\"", + "cmd": "docker run --rm --name=renovate_go --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/go\\":\\"/tmp/renovate/cache/others/go\\" -e GOPATH -e GOPROXY -e GONOSUMDB -e CGO_ENABLED -w \\"/tmp/github/some/repo\\" renovate/go:latest bash -l -c \\"git config --global url.\\\\\\"https://x-access-token:some-token@github.com/\\\\\\".insteadOf \\\\\\"https://github.com/\\\\\\" && go get -d ./... && go mod tidy\\"", "options": Object { "cwd": "/tmp/github/some/repo", "encoding": "utf-8", @@ -140,6 +140,17 @@ Array [ "timeout": 900000, }, }, +] +`; + +exports[`.updateArtifacts() supports docker mode without credentials 1`] = ` +Array [ + Object { + "cmd": "docker pull renovate/go:latest", + "options": Object { + "encoding": "utf-8", + }, + }, Object { "cmd": "docker ps --filter name=renovate_go -aq", "options": Object { @@ -147,7 +158,7 @@ Array [ }, }, Object { - "cmd": "docker run --rm --name=renovate_go --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/go\\":\\"/tmp/renovate/cache/others/go\\" -e GOPATH -e GOPROXY -e GONOSUMDB -e CGO_ENABLED -w \\"/tmp/github/some/repo\\" renovate/go:latest bash -l -c \\"git config --global url.\\\\\\"https://x-access-token:some-token@github.com/\\\\\\".insteadOf \\\\\\"https://github.com/\\\\\\" && go mod tidy\\"", + "cmd": "docker run --rm --name=renovate_go --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/go\\":\\"/tmp/renovate/cache/others/go\\" -e GOPATH -e GOPROXY -e GONOSUMDB -e CGO_ENABLED -w \\"/tmp/github/some/repo\\" renovate/go:latest bash -l -c \\"go get -d ./...\\"", "options": Object { "cwd": "/tmp/github/some/repo", "encoding": "utf-8", @@ -170,22 +181,57 @@ Array [ ] `; -exports[`.updateArtifacts() supports docker mode without credentials 1`] = ` +exports[`.updateArtifacts() supports global mode 1`] = ` Array [ Object { - "cmd": "docker pull renovate/go:latest", + "cmd": "go get -d ./...", "options": Object { + "cwd": "/tmp/github/some/repo", "encoding": "utf-8", + "env": Object { + "CGO_ENABLED": "1", + "GONOSUMDB": "1", + "GOPATH": "/tmp/renovate/cache/others/go", + "GOPROXY": "proxy.example.com", + "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", + }, + "timeout": 900000, }, }, +] +`; + +exports[`.updateArtifacts() supports vendor directory update 1`] = ` +Array [ Object { - "cmd": "docker ps --filter name=renovate_go -aq", + "cmd": "go get -d ./...", "options": Object { + "cwd": "/tmp/github/some/repo", "encoding": "utf-8", + "env": Object { + "CGO_ENABLED": "1", + "GONOSUMDB": "1", + "GOPATH": "/tmp/renovate/cache/others/go", + "GOPROXY": "proxy.example.com", + "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", + }, + "timeout": 900000, }, }, Object { - "cmd": "docker run --rm --name=renovate_go --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/go\\":\\"/tmp/renovate/cache/others/go\\" -e GOPATH -e GOPROXY -e GONOSUMDB -e CGO_ENABLED -w \\"/tmp/github/some/repo\\" renovate/go:latest bash -l -c \\"go get -d ./...\\"", + "cmd": "go mod tidy", "options": Object { "cwd": "/tmp/github/some/repo", "encoding": "utf-8", @@ -205,13 +251,29 @@ Array [ "timeout": 900000, }, }, -] -`; - -exports[`.updateArtifacts() supports global mode 1`] = ` -Array [ Object { - "cmd": "go get -d ./...", + "cmd": "go mod vendor", + "options": Object { + "cwd": "/tmp/github/some/repo", + "encoding": "utf-8", + "env": Object { + "CGO_ENABLED": "1", + "GONOSUMDB": "1", + "GOPATH": "/tmp/renovate/cache/others/go", + "GOPROXY": "proxy.example.com", + "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", + }, + "timeout": 900000, + }, + }, + Object { + "cmd": "go mod tidy", "options": Object { "cwd": "/tmp/github/some/repo", "encoding": "utf-8", diff --git a/lib/manager/gomod/artifacts.spec.ts b/lib/manager/gomod/artifacts.spec.ts index 255a15ccc8d87dc8e404dad1ed6bfa7697723be0..0e632f61d27251ef10cd225f0ea304e89029dc8e 100644 --- a/lib/manager/gomod/artifacts.spec.ts +++ b/lib/manager/gomod/artifacts.spec.ts @@ -73,6 +73,7 @@ describe('.updateArtifacts()', () => { }); it('returns null if unchanged', async () => { fs.readFile.mockResolvedValueOnce('Current go.sum' as any); + fs.readFile.mockResolvedValueOnce(null as any); // vendor modules filename const execSnapshots = mockExecAll(exec); git.getRepoStatus.mockResolvedValueOnce({ modified: [], @@ -89,11 +90,12 @@ describe('.updateArtifacts()', () => { }); it('returns updated go.sum', async () => { fs.readFile.mockResolvedValueOnce('Current go.sum' as any); + fs.readFile.mockResolvedValueOnce(null as any); // vendor modules filename const execSnapshots = mockExecAll(exec); git.getRepoStatus.mockResolvedValueOnce({ modified: ['go.sum'], } as StatusResult); - fs.readFile.mockReturnValueOnce('New go.sum' as any); + fs.readFile.mockResolvedValueOnce('New go.sum' as any); expect( await gomod.updateArtifacts({ packageFileName: 'go.mod', @@ -104,15 +106,52 @@ describe('.updateArtifacts()', () => { ).not.toBeNull(); expect(execSnapshots).toMatchSnapshot(); }); + it('supports vendor directory update', async () => { + const foo = join('vendor/github.com/foo/foo/go.mod'); + const bar = join('vendor/github.com/bar/bar/go.mod'); + const baz = join('vendor/github.com/baz/baz/go.mod'); + + fs.readFile.mockResolvedValueOnce('Current go.sum' as any); + fs.readFile.mockResolvedValueOnce('modules.txt content' as any); // vendor modules filename + const execSnapshots = mockExecAll(exec); + git.getRepoStatus.mockResolvedValueOnce({ + modified: ['go.sum', foo], + not_added: [bar], + deleted: [baz], + } as StatusResult); + fs.readFile.mockResolvedValueOnce('New go.sum' as any); + fs.readFile.mockResolvedValueOnce('Foo go.sum' as any); + fs.readFile.mockResolvedValueOnce('Bar go.sum' as any); + fs.readFile.mockResolvedValueOnce('New go.mod' as any); + const res = await gomod.updateArtifacts({ + packageFileName: 'go.mod', + updatedDeps: [], + newPackageFileContent: gomod1, + config: { + ...config, + postUpdateOptions: ['gomodTidy'], + }, + }); + expect(res).not.toBeNull(); + expect(res?.map(({ file }) => file)).toEqual([ + { contents: 'New go.sum', name: 'go.sum' }, + { contents: 'Foo go.sum', name: foo }, + { contents: 'Bar go.sum', name: bar }, + { contents: baz, name: '|delete|' }, + { contents: 'New go.mod', name: 'go.mod' }, + ]); + expect(execSnapshots).toMatchSnapshot(); + }); it('supports docker mode without credentials', async () => { jest.spyOn(docker, 'removeDanglingContainers').mockResolvedValueOnce(); await setUtilConfig({ ...config, binarySource: BinarySource.Docker }); fs.readFile.mockResolvedValueOnce('Current go.sum' as any); + fs.readFile.mockResolvedValueOnce(null as any); // vendor modules filename const execSnapshots = mockExecAll(exec); git.getRepoStatus.mockResolvedValueOnce({ modified: ['go.sum'], } as StatusResult); - fs.readFile.mockReturnValueOnce('New go.sum' as any); + fs.readFile.mockResolvedValueOnce('New go.sum' as any); expect( await gomod.updateArtifacts({ packageFileName: 'go.mod', @@ -128,11 +167,12 @@ describe('.updateArtifacts()', () => { }); it('supports global mode', async () => { fs.readFile.mockResolvedValueOnce('Current go.sum' as any); + fs.readFile.mockResolvedValueOnce(null as any); // vendor modules filename const execSnapshots = mockExecAll(exec); git.getRepoStatus.mockResolvedValueOnce({ modified: ['go.sum'], } as StatusResult); - fs.readFile.mockReturnValueOnce('New go.sum' as any); + fs.readFile.mockResolvedValueOnce('New go.sum' as any); expect( await gomod.updateArtifacts({ packageFileName: 'go.mod', @@ -153,11 +193,12 @@ describe('.updateArtifacts()', () => { token: 'some-token', }); fs.readFile.mockResolvedValueOnce('Current go.sum' as any); + fs.readFile.mockResolvedValueOnce(null as any); // vendor modules filename const execSnapshots = mockExecAll(exec); git.getRepoStatus.mockResolvedValueOnce({ modified: ['go.sum'], } as StatusResult); - fs.readFile.mockReturnValueOnce('New go.sum' as any); + fs.readFile.mockResolvedValueOnce('New go.sum' as any); expect( await gomod.updateArtifacts({ packageFileName: 'go.mod', @@ -178,14 +219,15 @@ describe('.updateArtifacts()', () => { token: 'some-token', }); fs.readFile.mockResolvedValueOnce('Current go.sum' as any); + fs.readFile.mockResolvedValueOnce(null as any); // vendor modules filename const execSnapshots = mockExecAll(exec); git.getRepoStatus.mockResolvedValueOnce({ modified: ['go.sum'], } as StatusResult); fs.readFile.mockResolvedValueOnce('New go.sum 1' as any); - fs.readFile.mockResolvedValueOnce(null as any); // vendor modules filename fs.readFile.mockResolvedValueOnce('New go.sum 2' as any); fs.readFile.mockResolvedValueOnce('New go.sum 3' as any); + fs.readFile.mockResolvedValueOnce('New go.mod' as any); try { global.appMode = true; expect( @@ -208,6 +250,7 @@ describe('.updateArtifacts()', () => { it('catches errors', async () => { const execSnapshots = mockExecAll(exec); fs.readFile.mockResolvedValueOnce('Current go.sum' as any); + fs.readFile.mockResolvedValueOnce(null as any); // vendor modules filename fs.outputFile.mockImplementationOnce(() => { throw new Error('This update totally doesnt work'); }); diff --git a/lib/manager/gomod/artifacts.ts b/lib/manager/gomod/artifacts.ts index 092c19725f8c808e4eb16353e3a9ab1c70e304b0..8c0bddc01ccb53f1514cf8ca0648ff59241b3561 100644 --- a/lib/manager/gomod/artifacts.ts +++ b/lib/manager/gomod/artifacts.ts @@ -44,6 +44,11 @@ export async function updateArtifacts({ logger.debug('No go.sum found'); return null; } + + const vendorDir = join(dirname(goModFileName), 'vendor/'); + const vendorModulesFileName = join(vendorDir, 'modules.txt'); + const useVendor = (await readLocalFile(vendorModulesFileName)) !== null; + try { const massagedGoMod = newGoModContent.replace( /\n(replace\s+[^\s]+\s+=>\s+\.\.\/.*)/g, @@ -53,6 +58,7 @@ export async function updateArtifacts({ logger.debug('Removed some relative replace statements from go.mod'); } await writeLocalFile(goModFileName, massagedGoMod); + const cmd = 'go'; const execOptions: ExecOptions = { cwdFile: goModFileName, @@ -71,47 +77,44 @@ export async function updateArtifacts({ }, }; let args = 'get -d ./...'; - logger.debug({ cmd, args }, 'go get command'); - await exec(`${cmd} ${args}`, execOptions); - if ( - config.postUpdateOptions && - config.postUpdateOptions.includes('gomodTidy') - ) { + logger.debug({ cmd, args }, 'go get command included'); + const execCommands = [`${cmd} ${args}`]; + + if (config.postUpdateOptions?.includes('gomodTidy')) { args = 'mod tidy'; - logger.debug({ cmd, args }, 'go mod tidy command'); - await exec(`${cmd} ${args}`, execOptions); + logger.debug({ cmd, args }, 'go mod tidy command included'); + execCommands.push(`${cmd} ${args}`); } - const res = []; - let status = await getRepoStatus(); + + if (useVendor) { + args = 'mod vendor'; + logger.debug({ cmd, args }, 'go mod vendor command included'); + execCommands.push(`${cmd} ${args}`); + if (config.postUpdateOptions?.includes('gomodTidy')) { + args = 'mod tidy'; + logger.debug({ cmd, args }, 'go mod tidy command included'); + execCommands.push(`${cmd} ${args}`); + } + } + + await exec(execCommands, execOptions); + + const status = await getRepoStatus(); if (!status.modified.includes(sumFileName)) { return null; } + logger.debug('Returning updated go.sum'); - res.push({ - file: { - name: sumFileName, - contents: await readLocalFile(sumFileName), + const res: UpdateArtifactsResult[] = [ + { + file: { + name: sumFileName, + contents: await readLocalFile(sumFileName), + }, }, - }); - const vendorDir = join(dirname(goModFileName), 'vendor/'); - const vendorModulesFileName = join(vendorDir, 'modules.txt'); - // istanbul ignore if - if (await readLocalFile(vendorModulesFileName)) { - args = 'mod vendor'; - logger.debug({ cmd, args }, 'go mod vendor command'); - await exec(`${cmd} ${args}`, execOptions); - if ( - config.postUpdateOptions && - config.postUpdateOptions.includes('gomodTidy') - ) { - args = 'mod tidy'; - if (cmd.includes('.insteadOf')) { - args += '"'; - } - logger.debug({ cmd, args }, 'go mod tidy command'); - await exec(`${cmd} ${args}`, execOptions); - } - status = await getRepoStatus(); + ]; + + if (useVendor) { for (const f of status.modified.concat(status.not_added)) { if (f.startsWith(vendorDir)) { res.push({ @@ -131,6 +134,7 @@ export async function updateArtifacts({ }); } } + const finalGoModContent = ( await readLocalFile(goModFileName, 'utf8') ).replace(/\/\/ renovate-replace /g, '');