From 72d50cc5d61db16f5f7c73cdc3d5b087e1e03cf1 Mon Sep 17 00:00:00 2001 From: Atsushi Watanabe <atsushi.w@ieee.org> Date: Wed, 20 Oct 2021 20:28:09 +0900 Subject: [PATCH] fix(gomod): Do not tidy go.mod on major update without gomodUpdateImportPaths (#11976) Co-authored-by: Rhys Arkins <rhys@arkins.net> --- docs/usage/configuration-options.md | 2 +- docs/usage/golang.md | 2 +- .../__snapshots__/artifacts.spec.ts.snap | 70 +++++++++++++++---- lib/manager/gomod/artifacts.spec.ts | 51 ++++++++++++++ lib/manager/gomod/artifacts.ts | 12 +++- lib/manager/gomod/readme.md | 2 +- 6 files changed, 121 insertions(+), 18 deletions(-) diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 4956dbc50a..17ccab605d 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 e724dbec3a..bd5122e108 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 a446d705f8..e55225009a 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 78d487b864..2b3234323e 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 d770c9edcc..2d35392c22 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 ba2ae2ee41..4902635cb5 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. -- GitLab