diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 4956dbc50ab499b9019dcdbfd2eb0298294c8252..17ccab605d76e26f4d6aa08004b7b997849722fb 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -1680,7 +1680,7 @@ Though this option is enabled by default, you can fine tune the behavior by sett ## postUpdateOptions -- `gomodTidy`: Run `go mod tidy` after Go module updates. This is implicitly enabled for major module updates. +- `gomodTidy`: Run `go mod tidy` after Go module updates. This is implicitly enabled for major module updates when `gomodUpdateImportPaths` is enabled - `gomodUpdateImportPaths`: Update source import paths on major module updates, using [mod](https://github.com/marwan-at-work/mod) - `npmDedupe`: Run `npm dedupe` after `package-lock.json` updates - `yarnDedupeFewer`: Run `yarn-deduplicate --strategy fewer` after `yarn.lock` updates diff --git a/docs/usage/golang.md b/docs/usage/golang.md index e724dbec3a95a01b1462e3fabc3f07f9a2a4b798..bd5122e1084b04e30a311234c787e7fdfa0c701c 100644 --- a/docs/usage/golang.md +++ b/docs/usage/golang.md @@ -16,7 +16,7 @@ Renovate supports upgrading dependencies in `go.mod` files and their accompanyin 1. Renovate runs `go get` to update the `go.sum` files 1. If the user has enabled the option `gomodUpdateImportPaths` in the [`postUpdateOptions`](https://docs.renovatebot.com/configuration-options/#postupdateoptions) array, then Renovate uses [mod](https://github.com/marwan-at-work/mod) to update import paths on major updates, which can update any Go source file 1. If the user has enabled the option `gomodTidy` in the [`postUpdateOptions`](https://docs.renovatebot.com/configuration-options/#postupdateoptions) array, then Renovate runs `go mod tidy`, which itself can update `go.mod` and `go.sum`. - 1. This is implicitly enabled for major updates + 1. This is implicitly enabled for major updates if the user has enabled the option `gomodUpdateImportPaths` in the [`postUpdateOptions`](https://docs.renovatebot.com/configuration-options/#postupdateoptions) array 1. `go mod vendor` is run if vendored modules are detected 1. A PR will be created with `go.mod`,`go.sum`, and any updated vendored files updated in the one commit 1. If the source repository has either a "changelog" file or uses GitHub releases, then Release Notes for each version will be embedded in the generated PR diff --git a/lib/manager/gomod/__snapshots__/artifacts.spec.ts.snap b/lib/manager/gomod/__snapshots__/artifacts.spec.ts.snap index a446d705f88a71d649085491fa28f1a6dc36b934..e55225009a0f75a4ab2bbb48484149355f567fea 100644 --- a/lib/manager/gomod/__snapshots__/artifacts.spec.ts.snap +++ b/lib/manager/gomod/__snapshots__/artifacts.spec.ts.snap @@ -2,9 +2,24 @@ exports[`manager/gomod/artifacts catches errors 1`] = `Array []`; -exports[`manager/gomod/artifacts returns if no go.sum found 1`] = `Array []`; +exports[`manager/gomod/artifacts does not execute go mod tidy when none of gomodTidy and gomodUpdateImportPaths are set 1`] = ` +Array [ + Object { + "file": Object { + "contents": "New go.sum", + "name": "go.sum", + }, + }, + Object { + "file": Object { + "contents": "New main.go", + "name": "go.mod", + }, + }, +] +`; -exports[`manager/gomod/artifacts returns null if unchanged 1`] = ` +exports[`manager/gomod/artifacts does not execute go mod tidy when none of gomodTidy and gomodUpdateImportPaths are set 2`] = ` Array [ Object { "cmd": "go get -d ./...", @@ -34,7 +49,9 @@ Array [ ] `; -exports[`manager/gomod/artifacts returns updated go.sum 1`] = ` +exports[`manager/gomod/artifacts returns if no go.sum found 1`] = `Array []`; + +exports[`manager/gomod/artifacts returns null if unchanged 1`] = ` Array [ Object { "cmd": "go get -d ./...", @@ -64,7 +81,7 @@ Array [ ] `; -exports[`manager/gomod/artifacts skips updating import paths for gopkg.in dependencies 1`] = ` +exports[`manager/gomod/artifacts returns updated go.sum 1`] = ` Array [ Object { "cmd": "go get -d ./...", @@ -91,8 +108,30 @@ Array [ "timeout": 900000, }, }, +] +`; + +exports[`manager/gomod/artifacts skips gomodTidy without gomodUpdateImportPaths on major update 1`] = ` +Array [ Object { - "cmd": "go mod tidy", + "file": Object { + "contents": "New go.sum", + "name": "go.sum", + }, + }, + Object { + "file": Object { + "contents": "New main.go", + "name": "go.mod", + }, + }, +] +`; + +exports[`manager/gomod/artifacts skips gomodTidy without gomodUpdateImportPaths on major update 2`] = ` +Array [ + Object { + "cmd": "go get -d ./...", "options": Object { "cwd": "/tmp/github/some/repo", "encoding": "utf-8", @@ -116,8 +155,13 @@ Array [ "timeout": 900000, }, }, +] +`; + +exports[`manager/gomod/artifacts skips updating import paths for gopkg.in dependencies 1`] = ` +Array [ Object { - "cmd": "go mod tidy", + "cmd": "go get -d ./...", "options": Object { "cwd": "/tmp/github/some/repo", "encoding": "utf-8", @@ -141,13 +185,8 @@ Array [ "timeout": 900000, }, }, -] -`; - -exports[`manager/gomod/artifacts skips updating import paths with gomodUpdateImportPaths on v0 to v1 1`] = ` -Array [ Object { - "cmd": "go get -d ./...", + "cmd": "go mod tidy", "options": Object { "cwd": "/tmp/github/some/repo", "encoding": "utf-8", @@ -196,8 +235,13 @@ Array [ "timeout": 900000, }, }, +] +`; + +exports[`manager/gomod/artifacts skips updating import paths with gomodUpdateImportPaths on v0 to v1 1`] = ` +Array [ Object { - "cmd": "go mod tidy", + "cmd": "go get -d ./...", "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 78d487b8649399de36cf1209af6018a11237b908..2b3234323ef6cdc7b776a2eaf3e501e03e656f27 100644 --- a/lib/manager/gomod/artifacts.spec.ts +++ b/lib/manager/gomod/artifacts.spec.ts @@ -318,6 +318,57 @@ describe('manager/gomod/artifacts', () => { ]); expect(execSnapshots).toMatchSnapshot(); }); + it('skips gomodTidy without gomodUpdateImportPaths on major update', 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', 'main.go'], + } as StatusResult); + fs.readFile + .mockResolvedValueOnce('New go.sum' as any) + .mockResolvedValueOnce('New main.go' as any) + .mockResolvedValueOnce('New go.mod' as any); + expect( + await gomod.updateArtifacts({ + packageFileName: 'go.mod', + updatedDeps: [{ depName: 'github.com/google/go-github/v24' }], + newPackageFileContent: gomod1, + config: { + ...config, + updateType: 'major', + newMajor: 28, + postUpdateOptions: ['gomodTidy'], + }, + }) + ).toMatchSnapshot(); + expect(execSnapshots).toMatchSnapshot(); + }); + it('does not execute go mod tidy when none of gomodTidy and gomodUpdateImportPaths are set', 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', 'main.go'], + } as StatusResult); + fs.readFile + .mockResolvedValueOnce('New go.sum' as any) + .mockResolvedValueOnce('New main.go' as any) + .mockResolvedValueOnce('New go.mod' as any); + expect( + await gomod.updateArtifacts({ + packageFileName: 'go.mod', + updatedDeps: [{ depName: 'github.com/google/go-github/v24' }], + newPackageFileContent: gomod1, + config: { + ...config, + updateType: 'major', + newMajor: 28, + }, + }) + ).toMatchSnapshot(); + expect(execSnapshots).toMatchSnapshot(); + }); it('updates import paths with specific tool version from constraint', async () => { fs.readFile.mockResolvedValueOnce('Current go.sum' as any); fs.readFile.mockResolvedValueOnce(null as any); // vendor modules filename diff --git a/lib/manager/gomod/artifacts.ts b/lib/manager/gomod/artifacts.ts index d770c9edcc3bd3da5d0f90e8737958e927ec2dac..2d35392c22924407b7802efb56d9de92d9f8c727 100644 --- a/lib/manager/gomod/artifacts.ts +++ b/lib/manager/gomod/artifacts.ts @@ -159,9 +159,17 @@ export async function updateArtifacts({ } } - const isGoModTidyRequired = - config.postUpdateOptions?.includes('gomodTidy') || + const mustSkipGoModTidy = + !config.postUpdateOptions?.includes('gomodUpdateImportPaths') && config.updateType === 'major'; + if (mustSkipGoModTidy) { + logger.debug({ cmd, args }, 'go mod tidy command skipped'); + } + + const isGoModTidyRequired = + !mustSkipGoModTidy && + (config.postUpdateOptions?.includes('gomodTidy') || + (config.updateType === 'major' && isImportPathUpdateRequired)); if (isGoModTidyRequired) { args = 'mod tidy'; logger.debug({ cmd, args }, 'go mod tidy command included'); diff --git a/lib/manager/gomod/readme.md b/lib/manager/gomod/readme.md index ba2ae2ee413262fb8fb1ab4659ae52dc92372cc6..4902635cb5b971011a8e486b919cf77ea0456e47 100644 --- a/lib/manager/gomod/readme.md +++ b/lib/manager/gomod/readme.md @@ -1,7 +1,7 @@ You might be interested in the following `postUpdateOptions`: 1. `gomodTidy` - if you'd like Renovate to run `go mod tidy` after every update before raising the PR. - 1. This is implicitly enabled for major updates + 1. This is implicitly enabled for major updates if the user has enabled the option `gomodUpdateImportPaths` 1. `gomodUpdateImportPaths` - if you'd like Renovate to update your source import paths on major updates before raising the PR. When Renovate is running using `binarySource=docker` (such as in the hosted WhiteSource Renovate app) then it will pick the latest compatible version of Go to run, i.e. the latest `1.x` release.