mirror of
https://github.com/renovatebot/renovate.git
synced 2026-11-02 10:33:39 +00:00
ab105e6e42
* feat(gomod): add `gomodTidyAll` option for indirect dependency updates in Go monorepos In Go monorepos it is common for one module to depend on another in the same repo via a local `replace` directive (e.g. `replace example.com/shared => ../shared`). When Renovate updates the shared module, today `go mod tidy` runs only in that module, leaving dependent `go.sum` files stale. Add a new `gomodTidyAll` post-update option that: - Discovers every `go.mod` in the repo and parses its local `replace` directives (both inline and block form). - Builds a dependency graph with `graph-data-structure`, with edges from dependency → dependent, matching the existing NuGet convention. - Runs `go mod tidy` on every transitive dependent in topological order, propagating any `gomodTidy1.17` / `gomodTidyE` flags to the dependent commands. - Collects updated `go.mod` and `go.sum` files from each dependent directory into the artifact result. - Implies `gomodTidy` so users only need to enable one option. Supporting changes: - Extract `getMatchingFiles` and `resolveRelativePathToRoot` into `lib/util/fs/util.ts` so NuGet and gomod can share them instead of each having its own glob/resolve helper. - Refactor `lib/modules/manager/nuget/package-tree.ts` to use the shared `getMatchingFiles` helper and rename local variables for clarity (`deps` → `visited`, `dep` → `dependent`) per review feedback. Docs and config: - Register `gomodTidyAll` in `postUpdateOptions` `allowedValues`. - Add a row for `gomodTidyAll` to the `postUpdateOptions` table in `docs/usage/configuration-options.md`. - Add a "Monorepo tidying for local `replace` directives" subsection to `docs/usage/golang.md` describing when to use the option. Tests and coverage: - `lib/modules/manager/gomod/package-tree.spec.ts` — parse/graph/topo order, 100% line/branch/function coverage. - `lib/modules/manager/gomod/artifacts-gomodtidyall.spec.ts` — six integration cases covering subshell commands, `tidyOpts` propagation, result collection, no-op with no dependents, error handling, and the disabled path. - Full `lib/modules/manager/gomod` suite (151 tests) and NuGet package-tree suite (9 tests) pass; new code is fully covered. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor(gomod): use named capture groups and direct fs util imports * fix(gomod): use `go -C` for dependent module tidy commands A subshell only works in Docker mode, where all commands are concatenated into a single `bash -l -c`. With `binarySource=install` or `global` each command is split with shlex and run without a shell, so `(cd dir && ...)` is treated as the name of a binary. * refactor(gomod): simplify parsing of local `replace` directives A single regex now covers both the single line form and the lines inside a `replace (...)` block. The previous block pattern stopped at the first `)`, so a block containing a comment with a bracket was skipped, and the single line pattern did not allow a trailing comment. Also keeps the NuGet package tree unchanged apart from the two helpers it now shares. * docs(gomod): warn against combining `gomodTidyAll` with `gomodMassage` Massaging comments out the relative `replace` directives that `gomodTidyAll` follows, so the two options work against each other. * refactor(fs): use `matchRegexOrGlob` in `getMatchingFiles` --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
124 lines
6.3 KiB
Markdown
124 lines
6.3 KiB
Markdown
### Updating of Go mod and toolchain directives
|
|
|
|
In `go.mod`, the `go` directive essentially means "Compatible with this version or later".
|
|
It is generally recommended for Go projects to _not_ bump this version unless necessary, and therefore Renovate's default behavior is not to propose upgrades to it.
|
|
If you need to update it once or irregularly, it's recommended to do it manually.
|
|
If you are sure you want to always bump it to latest, then you need the following configuration:
|
|
|
|
```json
|
|
{
|
|
"packageRules": [
|
|
{
|
|
"matchManagers": ["gomod"],
|
|
"matchDepNames": ["go"],
|
|
"matchDepTypes": ["golang"],
|
|
"rangeStrategy": "bump"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
In `go.mod`, the `toolchain` directive essentially means "Use this exact version of go".
|
|
Unlike the `go` directive, it's valid to keep bumping this, and you should see updates to it proposed by default.
|
|
|
|
### Only suggesting updates that match your `go` directive
|
|
|
|
In `go.mod`, the `go` directive essentially means "Compatible with this version or later".
|
|
It is generally recommended for Go projects to _not_ bump this version unless necessary.
|
|
|
|
As [noted above](#updating-of-go-mod-and-toolchain-directives), Renovate doesn't update this directly, but dependency updates can lead to a package you rely on bumping their `go` directive, which means you can't accept the proposed update without also bumping your `go` directive.
|
|
|
|
To make this simpler, you can use [`constraintsFiltering=strict`](../../../configuration-options.md#constraintsfiltering) to make sure that Renovate will only propose updates that match the [`constraints`](../../../configuration-options.md#constraints) you specify.
|
|
|
|
For example, given the `go.mod`:
|
|
|
|
```gomod
|
|
module example
|
|
|
|
go 1.24.0
|
|
|
|
require golang.org/x/mod v0.32.0
|
|
```
|
|
|
|
We can then configure Renovate to set the same constraint when updating any Go dependencies:
|
|
|
|
```json
|
|
{
|
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
|
"packageRules": [
|
|
{
|
|
"description": "Ensure source compatibility with Go version used by this project",
|
|
"matchManagers": ["gomod"],
|
|
"constraintsFiltering": "strict"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
In this case, Renovate would only propose an update to a version of `golang.org/x/mod` that supports Go 1.24.x.
|
|
|
|
!!! note
|
|
It is recommended to read the [`constraintsFiltering`](../../../configuration-options.md#constraintsfiltering) documentation and [Language constraints and upgrading](../../../language-constraints-and-upgrading.md) for more information about how the filtering works and how _strict_ this can be.
|
|
|
|
### Post-Update Options
|
|
|
|
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 if the user has enabled the option `gomodUpdateImportPaths`
|
|
1. `gomodTidy1.17` - if you'd like Renovate to run `go mod tidy -compat=1.17` after every update before raising the PR
|
|
1. `gomodTidyE` - if you'd like Renovate to run `go mod tidy -e` after every update before raising the PR
|
|
1. `gomodTidyAll` - if you'd like Renovate to also run `go mod tidy` on every other module which depends on the updated one through a local `replace` directive
|
|
- This implies `gomodTidy`, needs Go 1.20 or later, and should not be combined with `gomodMassage`
|
|
1. `gomodUpdateImportPaths` - if you'd like Renovate to update your source import paths on major updates before raising the PR
|
|
1. `gomodMassage` - to enable massaging of all `replace` statements prior to running `go` so that they will be ignored
|
|
1. `goGenerate` - to run `go generate ./...` after vendoring.
|
|
- Will only run if the [`allowedUnsafeExecutions`](../../../self-hosted-configuration.md#allowedunsafeexecutions) global option includes `goGenerate`
|
|
- This will not install any additional tools required to run `go generate`, you can use [tools](https://tip.golang.org/doc/go1.24#tools) as one option
|
|
- If `gomodTidy` is not set, you may encounter failures in the Go toolchain due to `missing go.sum entry`
|
|
|
|
When Renovate is running using `binarySource=install` (such as in the Mend Renovate App) then it will pick the latest compatible version of Go to run, i.e. the latest `1.x` release.
|
|
Even if the `go.mod` has a version like `go 1.22`, Renovate will treat it as a `^1.22` constraint and not `=1.22`.
|
|
|
|
Unless matching `tool` directives exist, indirect updates are disabled by default. To enable them, add a package rule such as:
|
|
|
|
```json
|
|
{
|
|
"packageRules": [
|
|
{
|
|
"matchManagers": ["gomod"],
|
|
"matchDepTypes": ["indirect"],
|
|
"enabled": true
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Private Modules Authentication
|
|
|
|
Before running the `go` commands to update the `go.sum`, Renovate exports `git` [`insteadOf`](https://git-scm.com/docs/git-config#Documentation/git-config.txt-urlltbasegtinsteadOf) directives in environment variables.
|
|
|
|
The following logic is executed prior to "artifacts" updating:
|
|
|
|
The token from the `hostRules` entry matching `hostType=github` and `matchHost=api.github.com` is added as the default authentication for `github.com`.
|
|
For those running against `github.com`, this token will be the default platform token.
|
|
|
|
Next, all `hostRules` with both a token or username/password and `matchHost` will be fetched, except for any github.com one from above.
|
|
|
|
Rules from this list are converted to environment variable directives if they match _any_ of the following characteristics:
|
|
|
|
- No `hostType` is defined, or
|
|
- `hostType` is `go`, or
|
|
- `hostType` is a platform (`github`, `gitlab`, `azure`, etc.)
|
|
|
|
### Major upgrades of dependencies
|
|
|
|
Major upgrades in Go are different from most other ecosystems, because both the version and module name need to be changed.
|
|
It is very common that such upgrades require changes to application code, which Renovate doesn't do.
|
|
|
|
By default, Renovate will make such change in the `go.mod` files but nothing else - the rest is up to you.
|
|
If you add `gomodUpdateImportPaths` to `postUpdateOptions` then Renovate will also use a third-party tool to migrate import paths within application code, but there may still be actual application logic which needs to be changed too.
|
|
|
|
Ultimately: it is known and unavoidable that the majority of major Go upgrades won't be immediately mergeable.
|
|
You might prefer to configure such major updates with `dependencyDashboardApproval=true` so that you can request them on demand, on supported platforms.
|