Files
renovate/lib/util/fs
Thinh Nguyen ab105e6e42 feat(gomod): add gomodTidyAll option for indirect dependency updates in Go monorepos (#37138)
* 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>
2026-08-13 08:35:38 +00:00
..