From 381fa55753b5541ab7c9eeaff1d4a859836c60c7 Mon Sep 17 00:00:00 2001 From: Chance Zibolski Date: Tue, 11 Jun 2024 03:24:02 -0700 Subject: [PATCH] feat(gomod): Support go work vendor (#29216) --- lib/modules/manager/gomod/artifacts.spec.ts | 102 ++++++++++++++++++++ lib/modules/manager/gomod/artifacts.ts | 43 ++++++++- 2 files changed, 140 insertions(+), 5 deletions(-) diff --git a/lib/modules/manager/gomod/artifacts.spec.ts b/lib/modules/manager/gomod/artifacts.spec.ts index 42d09c0a0602e8..d584ed2dbdf93d 100644 --- a/lib/modules/manager/gomod/artifacts.spec.ts +++ b/lib/modules/manager/gomod/artifacts.spec.ts @@ -278,6 +278,108 @@ describe('modules/manager/gomod/artifacts', () => { ]); }); + it('supports vendor directory update with go.work', 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.readLocalFile.mockResolvedValueOnce('Current go.sum'); + fs.readLocalFile.mockResolvedValueOnce('modules.txt content'); // vendor modules filename + fs.findLocalSiblingOrParent.mockResolvedValueOnce('go.work'); + const execSnapshots = mockExecAll(); + git.getRepoStatus.mockResolvedValueOnce( + partial({ + modified: ['go.sum', 'go.work.sum', foo], + not_added: [bar], + deleted: [baz], + }), + ); + fs.readLocalFile.mockResolvedValueOnce('New go.sum'); + fs.readLocalFile.mockResolvedValueOnce('New go.work.sum'); + fs.readLocalFile.mockResolvedValueOnce('Foo go.sum'); + fs.readLocalFile.mockResolvedValueOnce('Bar go.sum'); + fs.readLocalFile.mockResolvedValueOnce('New go.mod'); + const res = await gomod.updateArtifacts({ + packageFileName: 'go.mod', + updatedDeps: [], + newPackageFileContent: gomod1, + config: { + ...config, + postUpdateOptions: ['gomodTidy'], + }, + }); + expect(res).toEqual([ + { + file: { + contents: 'New go.sum', + path: 'go.sum', + type: 'addition', + }, + }, + { + file: { + contents: 'New go.work.sum', + path: 'go.work.sum', + type: 'addition', + }, + }, + { + file: { + contents: 'Foo go.sum', + path: 'vendor/github.com/foo/foo/go.mod', + type: 'addition', + }, + }, + { + file: { + contents: 'Bar go.sum', + path: 'vendor/github.com/bar/bar/go.mod', + type: 'addition', + }, + }, + { + file: { + path: 'vendor/github.com/baz/baz/go.mod', + type: 'deletion', + }, + }, + { + file: { + contents: 'New go.mod', + path: 'go.mod', + type: 'addition', + }, + }, + ]); + + expect(execSnapshots).toMatchObject([ + { + cmd: 'go get -d -t ./...', + options: { cwd: '/tmp/github/some/repo' }, + }, + { + cmd: 'go mod tidy', + options: { cwd: '/tmp/github/some/repo' }, + }, + { + cmd: 'go work vendor', + options: { cwd: '/tmp/github/some/repo' }, + }, + { + cmd: 'go work sync', + options: { cwd: '/tmp/github/some/repo' }, + }, + { + cmd: 'go mod tidy', + options: { cwd: '/tmp/github/some/repo' }, + }, + { + cmd: 'go mod tidy', + options: { cwd: '/tmp/github/some/repo' }, + }, + ]); + }); + it('supports docker mode without credentials', async () => { GlobalConfig.set({ ...adminConfig, binarySource: 'docker' }); fs.readLocalFile.mockResolvedValueOnce('Current go.sum'); diff --git a/lib/modules/manager/gomod/artifacts.ts b/lib/modules/manager/gomod/artifacts.ts index fa1c13a573e0b4..ad9b0447461b02 100644 --- a/lib/modules/manager/gomod/artifacts.ts +++ b/lib/modules/manager/gomod/artifacts.ts @@ -11,6 +11,7 @@ import type { ExecOptions } from '../../../util/exec/types'; import { filterMap } from '../../../util/filter-map'; import { ensureCacheDir, + findLocalSiblingOrParent, isValidLocalPath, readLocalFile, writeLocalFile, @@ -128,7 +129,9 @@ export async function updateArtifacts({ return null; } - const vendorDir = upath.join(upath.dirname(goModFileName), 'vendor/'); + const goModDir = upath.dirname(goModFileName); + + const vendorDir = upath.join(goModDir, 'vendor/'); const vendorModulesFileName = upath.join(vendorDir, 'modules.txt'); const useVendor = (await readLocalFile(vendorModulesFileName)) !== null; @@ -283,10 +286,28 @@ export async function updateArtifacts({ execCommands.push(`${cmd} ${args}`); } + const goWorkSumFileName = upath.join(goModDir, 'go.work.sum'); if (useVendor) { - args = 'mod vendor'; - logger.debug('go mod tidy command included'); - execCommands.push(`${cmd} ${args}`); + // If we find a go.work, then use go workspace vendoring. + const goWorkFile = await findLocalSiblingOrParent( + goModFileName, + 'go.work', + ); + + if (goWorkFile) { + args = 'work vendor'; + logger.debug('using go work vendor'); + execCommands.push(`${cmd} ${args}`); + + args = 'work sync'; + logger.debug('using go work sync'); + execCommands.push(`${cmd} ${args}`); + } else { + args = 'mod vendor'; + logger.debug('using go mod vendor'); + execCommands.push(`${cmd} ${args}`); + } + if (isGoModTidyRequired) { args = 'mod tidy' + tidyOpts; logger.debug('go mod tidy command included'); @@ -306,7 +327,8 @@ export async function updateArtifacts({ const status = await getRepoStatus(); if ( !status.modified.includes(sumFileName) && - !status.modified.includes(goModFileName) + !status.modified.includes(goModFileName) && + !status.modified.includes(goWorkSumFileName) ) { return null; } @@ -323,6 +345,17 @@ export async function updateArtifacts({ }); } + if (status.modified.includes(goWorkSumFileName)) { + logger.debug('Returning updated go.work.sum'); + res.push({ + file: { + type: 'addition', + path: goWorkSumFileName, + contents: await readLocalFile(goWorkSumFileName), + }, + }); + } + // Include all the .go file import changes if (isImportPathUpdateRequired) { logger.debug('Returning updated go source files for import path changes');