Commit Graph

171 Commits

Author SHA1 Message Date
Alex Sweet 87111d8141 fix(manager/gomod): match gofmt-style unindented closing paren in block end regex (#45781)
* fix(manager/gomod): match gofmt-style unindented closing paren in block end regex

gofmt places the closing ) of require/replace/exclude blocks at column 0,
but endBlockRegex required at least one leading whitespace character. This
caused inExcludeBlock to never reset after an exclude (...) block formatted
by gofmt, silently discarding every subsequent line in the file, including
all later require/replace blocks.

* fix(manager/gomod): correct test expectation for valid version

v0.17.3 is a valid version so no skipReason is set; the test incorrectly
asserted skipReason: 'invalid-version', copied from other fixtures using
the deliberately invalid v1.2 placeholder.
2026-09-21 08:54:34 +00:00
Sebastian Poxhofer bf5ff94d28 refactor(manager): build artifact results with the shared helpers (#46092)
Migrate apm, bun, cargo, cocoapods, composer, conan, copier, deno,
devbox, gomod, helmv3, jsonnet-bundler, kustomize, mix, nuget and vendir
onto `fileAddition()`, `artifactError()` and `artifactErrorResult()`.
copier's private `artifactError()` is replaced by the shared one.

Behaviour change: artifact error text now comes from
`artifactErrorMessageFromExecError` everywhere, i.e. a non-blank
`err.stderr`, else a non-blank `err.stdout`, else `err.message`.
Previously apm used `${err}` ("Error: " prefix), cocoapods used a
nullish coalesce that kept an empty stderr, nuget preferred stdout over
stderr, and jsonnet-bundler emitted an undefined stderr with no
fallback. The rest used `err.message` only and are unchanged for errors
without output.
2026-09-16 13:13:41 +00:00
Sebastian Poxhofer 9defb36404 refactor(manager): share repo status to file change conversion (#46090)
Add `collectFileChanges()` next to the other repository helpers, plus a
thin `fileChangesToArtifactResults()` in `lib/modules/manager/util.ts`,
and migrate the managers which re-implemented the same status loops:
apm, cocoapods, composer, copier, gomod, helmv3, jsonnet-bundler,
kustomize and vendir.

Each site keeps its own status bucket selection and path filter, so the
emitted artifacts are unchanged. Two dead pieces of logic are dropped:
vendir's `vendorDir || isFileInVendorDir` condition, which was always
true, and kustomize's optional chaining on a non-nullable status, which
only ever mattered for an unset test mock (now set explicitly).
2026-09-16 13:13:40 +00:00
Michael Kriese 1ea8602aaa test(manager): reach 100% branch coverage by closing the else-if chains (#46222)
* test(manager): cover twelve else-if branches

The trailing `else if` of a chain leaves v8 counting an implicit else
that no coverage-ignore hint can suppress. Fourteen of those were marked
as structurally unreachable, but only two of them actually are -- each of
these twelve has an input that takes it:

- `bazel`: an archive url whose file name is only a suffix, which strips
  to an empty value, so neither value nor digest is set
- `cargo`: a `[package]` section with no `version` at all
- `composer`: an inline `package` repository, which the discriminated
  union does carry, contrary to the comment that claimed otherwise
- `deps-edn`: an `:mvn/repos` entry whose spec is a plain string
- `gomod`: an update where only the `go` directive changed, leaving no
  additional dependencies to count
- `helmfile`: a release with an empty chart name, which is neither a
  local path nor an oci ref and yields an empty repo name
- `nuget`: a lock file that is gone after the restore
- `swift`: a comma where `from` expects a colon, and where `from:`
  expects a version -- both are labels the state machine searches for and
  then ignores
- `terraform`: a module source too short to be a registry module
- `tflint-plugin`: a quoted attribute that is neither version nor source
- `travis`: a matrix `node_js` that is a number

The stale comments go with them. Three more in `swift` were already
wrong before this change: the branches they described were covered.

Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io>

* refactor(manager): collapse two exhaustive else-if chains

`glasskube` and `gradle` were the only two of the fourteen trailing
`else if` branches that really are unreachable, and both are provable
from a type rather than from a reading of the surrounding code:

- `glasskube` parses resources with a schema that admits exactly
  `Package`, `ClusterPackage` and `PackageRepository`, and filters
  anything else out
- `gradle`'s `ContentDescriptorSpec.mode` is `'include' | 'exclude'`

Turning the final `else if` into a plain `else` drops the phantom branch
v8 was counting. With these, the manager tree reaches 100% branch
coverage. The glasskube check is inverted so that the single-literal
discriminant narrows for the compiler.

Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io>

* test(manager/travis): inline the numeric node_js fixture

The three-line fixture went into `__fixtures__` only because every other
fixture in this spec is loaded through `Fixtures.get`. A reader of the
test should be able to see the input without opening a second file, so
write it inline with `codeBlock`.

Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io>

---------

Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io>
2026-09-16 06:43:03 +00:00
Michael Kriese 55a7341be2 test(manager): close long-tail branch coverage gaps (#45954)
* test(manager): close azure-pipelines, bundler and cocoapods gaps

Adds a pipeline whose step task is not versioned, so nothing is
extracted, and a gem lock line carrying no version, which is skipped.

Marks four guards that cannot be false: `extractContainer()` always
returns a dep, `getLockFilePath()` always returns a path, and the
cocoapods dep name, spec name and git account all derive from values
their enclosing check already proved present.

Co-Authored-By: Claude Opus 5 <michael.kriese+claude-code@mend.io>

* test(manager): close cargo, composer and cpanfile gaps

Adds a composer repository map that disables something other than
packagist, which is dropped rather than recorded.

Marks five guards: the cargo warning only fires for a crate dep and its
retry only runs when a dep was already current, a gitlab rule without a
token never passes the auth check, and both cpanfile handlers run only
once their match produced a value.

Two implicit elses stay counted, in the cargo version resolver and the
composer repository mapper, since a coverage-ignore hint does not attach
to an `else if`.

Co-Authored-By: Claude Opus 5 <michael.kriese+claude-code@mend.io>

* test(manager): close deps-edn, docker-compose and dockerfile gaps

Adds three extractions: a deps.edn alias whose value is not a map, a
compose extension carrying no image, and a dockerfile escape directive
naming a character other than a backtick, which leaves the default in
place.

Marks the deps-edn repository name check, since object keys are always
strings, and notes the repository spec chain, where a coverage-ignore
hint does not attach to an `else if`.

Co-Authored-By: Claude Opus 5 <michael.kriese+claude-code@mend.io>

* test(manager/flux): close the flux coverage gaps

Adds two GitRepository resources whose url is ssh rather than http, one
pinned to a tag and one to a commit. Neither yields a source url, since
only http urls can be turned into one.

Marks the Kustomization image guard: the schema rejects an image without
a name, so `extractImage()` cannot return null there.

Co-Authored-By: Claude Opus 5 <michael.kriese+claude-code@mend.io>

* test(manager): mark github-actions, gitlabci and glasskube guards

None of these six needs a test. A parsed action ref is either a docker
or a repository ref, `getDep()` always returns a dep for a job container
and a service, and the remaining three need a listed file that cannot be
read, a listed file that yields no deps, or a manifest whose
repositories match no name.

The glasskube resource kind chain stays counted, since a coverage-ignore
hint does not attach to an `else if`.

Co-Authored-By: Claude Opus 5 <michael.kriese+claude-code@mend.io>

* test(manager): mark gomod and gradle-wrapper guards

Four guards that need setups no test provides: a removed dep that is not
added back, a go.mod the replace massaging leaves unchanged, and a
daemon-jvm file carrying no toolchain version. A parsed go directive
always yields a version.

The additional-dependency count chain stays counted, since a
coverage-ignore hint does not attach to an `else if`.

Co-Authored-By: Claude Opus 5 <michael.kriese+claude-code@mend.io>

---------

Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io>
2026-09-15 07:10:10 +00:00
Sebastian Poxhofer 4b4d14ec00 feat(manager): pass extracted constraints to updateArtifacts (#45826)
* feat(manager): pass extracted constraints to updateArtifacts

`extractedConstraints` were collected during extraction but only ever read
by `fetch.ts` for the lookup. At artifact time every manager had to derive
the same tool constraints a second time, and when the updated package file
no longer carried the constraint there was nothing to fall back to.

`generateBranchConfig()` now merges the `extractedConstraints` of all
upgrades of a branch onto the branch config, which reaches `updateArtifacts()`
through `patchConfigForArtifactsUpdate()`. `UpdateArtifactsConfig` declares
the field and documents what it contains.

The new `resolveToolConstraint()` helper implements the ladder once:
user `constraints` > an optional artifact-time derivation > the extracted
value. The derivation is ranked above the extracted value on purpose: it
reads the package files as the branch changed them, so poetry (python is an
updatable dependency there), composer, pipenv (`pipenv` can be a dev
package) and pep621 (`requires-python` is an updatable dependency) would
otherwise regress to a stale constraint. pipenv, pep621 uv/pdm, poetry and
composer are migrated to the helper and keep their derivation.

Behaviour change: these managers now use the extract-time constraint as a
last resort instead of running unconstrained, for example on lock file
maintenance where pipenv deletes `Pipfile.lock` before deriving.

`execute-post-upgrade-commands.ts` is unaffected: it reads
`upgrade.constraints` per upgrade, and the extracted values are kept in a
separate field rather than folded into `constraints`, so post-upgrade task
tool constraints still come from user config only.

Not migrated, because their constraints are never extracted, so the
fallback would be dead code: bundler (`ruby`/`bundler`), pixi (`pixi`),
pep621 uv (`required-version`) and npm's node ladder, whose last step
already reads `package.json` engines.

* refactor(manager): resolve tool constraints through resolveToolConstraint()

Every manager now obtains the constraint of a tool it runs through
`resolveToolConstraint()` instead of reading `config.constraints` itself, so
the precedence "user config, then a value derived from the updated files, then
the constraints collected during extraction" applies everywhere. The helper
treats an empty string as not set at every step and accepts the
`PostUpdateConfig` shape, whose `constraints` may be `null`.

Behaviour changes that go beyond the new fallback to extracted constraints:

- `mix` applies its hardcoded erlang default only after the extracted
  constraint, so an erlang version collected at extraction can win over it.
- `kustomize` decides `HELM_EXPERIMENTAL_OCI` from the fully resolved helm
  constraint; `generateHelmEnvs()` takes that value instead of the config.
- `npm` (yarn): an upgrade of yarn without a new value now consults the user
  constraint before deriving one from package.json or the lock file.
- The "Using <tool> constraint from config" debug lines in bundler, composer,
  copier and pip-compile are gone, as the helper is the only reader of the
  config now.

Helpers that read the config synchronously became async: bundler
`getBundlerConstraint()`, copier `getPythonVersionConstraint()` and
`getCopierVersionConstraint()`, pip-compile `get*VersionConstraint()` and
`getToolVersionConstraint()`, gomod `deriveGoToolchainConstraints()` and
`getUpdateImportPathCmds()`, mise `getMiseLockToolConstraints()`. composer
`getPhpConstraint()` is removed.

Each converted manager has a test showing the extracted constraint reaching
the executed tool, and, where a derive callback exists, that the derived value
still wins over it.

* refactor(linters): add prefer-resolve-tool-constraint rule

Reports member reads and destructuring of `constraints` and
`extractedConstraints` from a manager config in `lib/modules/manager/**`, so
that tool constraints are resolved through `resolveToolConstraint()` in
`lib/modules/manager/util.ts` only. Writes and the same properties on package
files, which extraction has to populate, are not reported. The helper itself
and spec files are exempt in `.oxlintrc.json`.

* refactor(manager): inline thin resolveToolConstraint wrappers

Drop copier/utils.ts and the pip-compile getPipToolsVersionConstraint /
getUvVersionConstraint helpers, which only forwarded to
resolveToolConstraint(). Callers now call it directly.

* docs(development): note lock file maintenance in tool constraints section

* refactor(manager): address review on tool constraint resolution

composer only runs extractConstraints() when a user constraint is missing,
via Lazy. UpdateArtifactsConfig no longer re-declares constraints and
extractedConstraints, which ToolConstraintsConfig already provides.
2026-09-14 11:09:07 +00:00
Sebastian Poxhofer 05e1271376 test: use expect().resolves instead of awaiting inside expect (#45672)
Enables the vitest/prefer-expect-resolves oxlint rule and applies its
autofix across the spec suite.
2026-09-04 10:40:46 +00:00
Sebastian Poxhofer 300e3a616c test: shrink oversized fixtures to representative examples (#45666)
* test: reduce oversized expectation literals to representative examples

* test: shrink oversized fixtures instead of trimming assertions

Cut the real-world fixtures down to a representative set of entries that still covers every parser shape, and assert the complete output again with a single toEqual.
2026-09-04 10:40:45 +00:00
Sebastian Poxhofer 2fc46bdcfa test(manager): replace file snapshots with explicit assertions (#45656)
* test(manager): replace file snapshots with explicit assertions

* test(manager): replace inline snapshots with explicit assertions

* test(manager): assert on relevant sections instead of full bodies

* test(manager): drop assertions implied by full equality

* test(manager): address review feedback

* test(manager): assert depType and versioning in the regex matcher
2026-09-04 06:36:39 +00:00
Sebastian Poxhofer 3412de84ce refactor(linters): enable oxlint rule prefer-named-capture-group (#44714)
* refactor(lint): enable oxlint prefer-named-capture-group at error

Numbered capture groups (m[1], $1) break silently when a regex is
edited and group order shifts. Named groups (?<name>...) make intent
explicit and accesses (m.groups.name) resilient to reordering.

This enables the built-in eslint rule prefer-named-capture-group,
surfacing 321 pre-existing unnamed-group violations across ~121
files to be burned down incrementally in follow-up commits.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk

* refactor(versioning): name capture groups for prefer-named-capture-group

Burns down all prefer-named-capture-group violations in
lib/modules/versioning/. Unused capture groups (only reachable via
.test() or whole-match) become non-capturing (?:...); groups whose
value is read become named (?<name>...), with accesses rewritten to
match.groups!.<name> (or destructured from .groups!) instead of
positional match[n]/$n so a future edit that reorders groups cannot
silently break the reader.

Two cases needed extra care to preserve behavior:
- semver/common.ts and poetry/patterns.ts split() on a regex whose
  capture group is relied upon by String.prototype.split to keep the
  separator in the output array; the group is kept capturing and
  named, not converted to non-capturing.
- hashicorp/convertor.ts's semverRegex is only ever embedded via
  .source into a named `(?<version>...)` group elsewhere and never
  matched directly, so its internal groups are safe to make
  non-capturing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk

* refactor(datasource): name capture groups for prefer-named-capture-group

Burns down all prefer-named-capture-group violations under
lib/modules/datasource/. Same treatment as the versioning module:
unused groups become non-capturing, used groups get names, and
positional match[n] reads move to match.groups!.<name>.

docker/ecr.ts and pypi/common.ts keep their positional destructuring
(`const [, region] = ...`, `!!m &&`) working unchanged since a named
capture group is still addressable by its numeric index in
JavaScript — only pypi/common.ts's access was rewritten to
m.groups!.owner for clarity since it read a single group directly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk

* refactor(platform): name capture groups for prefer-named-capture-group

Burns down all prefer-named-capture-group violations under
lib/modules/platform/. Uses the repo's established idiom of
`match.groups?.<name>` after an optional-chained exec()/match() (see
bitbucket/index.ts hostnameWithoutApiPrefix, gerrit/utils.ts
extractSourceBranch) and `$<name>` in String.replace replacement
strings. Unused groups (markdown/HTML massaging regexes matched only
to be stripped) become non-capturing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk

* refactor(manager): name capture groups in ansible-galaxy for prefer-named-capture-group

Burns down prefer-named-capture-group violations in
lib/modules/manager/ansible-galaxy/. newBlockRegEx and blockLineRegEx
dropped their unused outer wrapping group (only the inner key/value
groups were ever read) and named the key/value groups; nameMatchRegex's
remaining unused groups (protocol/user-info/port alternatives) become
non-capturing since only source/hostname/depName/version are read via
.groups. Accesses in collections.ts and roles.ts move from
lineMatch[2]/lineMatch[3] to lineMatch.groups!.key/value.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk

* refactor(manager): name capture groups for prefer-named-capture-group (batch 1)

Burns down prefer-named-capture-group violations across the first
alphabetical slice of lib/modules/manager/ (ansible through mix).
Used groups get names with accesses rewritten to match.groups!.<name>
(or $<name> in replacement strings); groups whose value is never read
become non-capturing (?:...). Two String.split() call sites
(git-submodules/extract.ts, meteor/extract.ts) keep the established
"named group still readable positionally from the split() result
array" idiom instead of restructuring the destructuring.

bazel/rules/go.ts and buildpacks/extract.ts dockerRef verified
byte-for-byte equivalent before/after via a quick node script since
several nested groups collapsed to non-capturing at once.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk

* refactor(manager): name capture groups for prefer-named-capture-group (batch 2)

Burns down prefer-named-capture-group violations across the remaining
alphabetical slice of lib/modules/manager/ (npm through terragrunt).
Same treatment as batch 1: used groups get names with accesses moved
to match.groups!.<name> or $<name> replacement strings; unused groups
(wrapping alternations, quantifier repetition groups only consumed via
.test(), or values never read from a match) become non-capturing.

terraform/extractors/others/modules.ts and terragrunt/modules.ts share
near-identical URL-parsing regexes (github/bitbucket/git/azure-devops
ref matchers) — the same set of always-unused `depth=`/`&depth=`
query-string groups is converted to non-capturing in both files.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk

* refactor(config): name capture groups for prefer-named-capture-group

Burns down prefer-named-capture-group violations in lib/config/.
Used groups get names with replacement strings switched from $1/$2 to
$<name>; the unused separator group in schedule-migration.ts's
afterBeforeRegex becomes non-capturing. presets/parse.ts keeps
assigning through the already-declared `repo` variable rather than
array-destructuring the exec() result, matching this file's existing
style for the other named-group regexes just above it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk

* refactor(util): name capture groups for prefer-named-capture-group

Burns down prefer-named-capture-group violations across lib/util/ and
lib/logger/. Same treatment as previous batches: named groups for
values that are read (via $<name> replacement strings, .groups!.<name>,
or destructured from .groups), non-capturing groups where nothing reads
the captured value (e.g. semantic.ts's angular-commit .test()-only
regex). www-authenticate.ts's tokenizer entries each get their own
named group but keep accessing the match generically via match[1],
since a positionally-indexed named group is still readable by index.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk

* refactor(workers): name capture groups for prefer-named-capture-group

Burns down prefer-named-capture-group violations in lib/workers/.
Used groups get names with $<name> replacement strings; unused
wrapper/alternation groups (e.g. semantic-commit-message.ts's optional
scope/issue wrappers, release-notes.ts's date-heading and
horizontal-rule matchers that are only probed with .search()/replaced
wholesale) become non-capturing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk

* refactor(test,tools): name capture groups for prefer-named-capture-group

Finishes the prefer-named-capture-group burndown: test/, tools/, and
vitest.config.mts. Groups whose value is read get names ($<name>
replacement strings or .groups.<name> access); groups only used via
.test()/.search() or that feed a .match(/…/g) call (whose return value
is the array of whole matches, not captured groups) become
non-capturing.

This is the last remaining slice of pre-existing violations, so the
rule (already enabled at error repo-wide) now passes with zero
findings across the whole codebase.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk

* fix prettier failure

* refactor(lint): use a named capture group in `v8-ignore-no-count`

New rule from main trips the newly enabled `prefer-named-capture-group` oxlint rule.

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-09-03 09:54:40 +00:00
Jamie Tanna 9ecbaa8581 chore(manager/gomod): clarify how artifact updates work with minimumReleaseAge (#45526)
When Go updates dependencies using i.e. `go get` or `go mod download`,
it uses Minimal Version Selection (MVS)[0], which takes the lowest
version available from the given packages.

In the case of an updated dependency, in practice this means that Go
will chose the version of an indirect (transitive) package dependency as
the version that the updated package points to in their `go.mod`, which
must be older than the updated package, as the updated package has only
just been updated.

This protects against cases in other ecosystems where an unpinned
transitive dependency can be pulled by an updated package, potentially
bypassing `minimumReleaseAge`.

However, I can imagine there may be some questions about this, so we can
preemptively add a note into the `Artifact update notice` when
`minimumReleaseAge` is set.

[0]: https://go.dev/ref/mod#minimal-version-selection
2026-08-28 11:39:19 +00:00
Sebastian Poxhofer fbedd41e82 test: replace env operation with vi.stubEnv() (#45490)
* test: replace manual process.env mutation with vi.stubEnv

Enable Vitest's `unstubEnvs` so env stubs are reverted automatically
before every test, and convert the manual `process.env.X = ...` /
`delete process.env.X` pairs in specs to `vi.stubEnv()`.

This removes the hand-written `afterEach` cleanup blocks and the
`const OLD_ENV = process.env` / `process.env = { ...OLD_ENV }`
save-restore dance, which silently leaked state between tests when a
test set a variable without a matching delete.

Left as-is (incompatible with `unstubEnvs`, which unstubs before each
test, not after):
- module top-level env writes (cocoapods, gomod, post-update, pip-compile
  and bundler artifacts specs)
- `beforeAll` env writes -- the two in `util/http` moved to `beforeEach`

* test: stop asserting on ambient environment variables

Three specs asserted on values that the surrounding environment can
override, so they only passed on a machine that happened not to set them:

- `util/exec/env`: `getChildProcessEnv()` forwards every entry of
  `basicEnvVars`, but the spec only seeded a subset. Any other forwarded
  variable that was set ambiently (e.g. a lowercase `http_proxy`) leaked
  into the `toEqual` assertion. Clear all of them first.
- `util/git/index`: `process.env.GIT_SSH_COMMAND` deliberately overrides
  the default that the two env-inheritance tests assert on. Clear it.
- `logger/pretty-stdout`: the colorized level strings are built at import
  time, so the `beforeEach` setting `FORCE_COLOR` could never affect them
  -- it was dead code, and the test silently assumed a terminal without
  colour support. Derive the expectation the same way the module does.

* test(datasource/nuget): use a throwaway cache dir for nupkg downloads

The `determine source URL from nupkg` tests do not mock the filesystem,
so they really wrote downloaded packages into a fixed `/tmp/cache` path.
That fails wherever the system tmpdir is not writable, and two checkouts
running the suite at once would share the same directory.

Use `tmp.dir({ unsafeCleanup: true })` and clean it up afterwards, which
is the pattern the other specs that touch disk already use.

* feat(lint): add renovate/prefer-stub-env rule

Enforces in specs what the migration to `vi.stubEnv` established:

- assigning to or deleting `process.env.X` inside `beforeEach`, `afterEach`,
  `it` or `test` is reported, with a fixer that rewrites it to `vi.stubEnv()`
- module scope, `describe` bodies and `beforeAll` / `afterAll` are left alone:
  `unstubEnvs` reverts stubs *before* each test, so a stub created there is
  gone by the time the first test runs, and those must keep assigning directly
- replacing the `process.env` object is reported everywhere and never fixed.
  `vi.stubEnv()` captures the original object when the worker starts, so after
  a reassignment its deletes silently target the old object

The rule found 28 further violations in specs the earlier sweep missed, since
that one was anchored on `delete process.env`. Twelve were auto-fixed; the
rest replaced `process.env` wholesale and are now `clearEnv()` from test/util.

`util/exec/index.spec.ts` opts out with a comment: it asserts on the whole
child env, and `vi.stubEnv()` cannot express that because it maps `PROD`,
`DEV` and `SSR` onto '' instead of deleting them.
2026-08-28 09:26:20 +00:00
Pradeep Ashwathanarayan cee4515c2e fix(manager/gomod): handle bare ../ replace paths in gomodTidyAll (#45392)
fix(gomod): handle bare ../ replace paths in gomodTidyAll

When a go.mod file uses a replace directive pointing to the parent
directory with no sub-path (e.g. `replace example.com/root => ../`),
gomodTidyAll would silently skip running `go mod tidy` on that module
and any of its dependents.

The root cause was in the `localReplace` regex where the localPath
capture group used `\S+` (one or more non-whitespace), so `../` —
with nothing after the slash — was never matched. Only paths like
`../subdir` were picked up.

Changing `\S+` to `\S*` allows zero-or-more trailing characters,
so bare `../` and `./` now parse correctly and the dependency graph
is built properly.
2026-08-26 09:40:47 +00:00
Jamie Tanna 5b1749983c feat: always set CI=true for subprocesses
As noted in #43761, we had recently set `CI=true` for the Renovate and
Containerbase orgs on Mend-hosted apps due to a pnpm v11 requirement:

    ERR_PNPM_ABORTED_REMOVE_MODULES_DIR_NO_TTY  Aborted removal of
      modules directory due to no TTY

    If you are running pnpm in CI, set the CI environment variable to
      "true", or set "confirmModulesPurge" to "false".

Similarly in #43606, it was noted that we should do this for `mise lock`
to mark the workspace as "trusted".

Although we went with a different situation, there will be cases where
this is useful for tools being executed, for instance when we invoke `yarn`.

We also make sure to keep our documentation up-to-date as we add to the
specific overrides.

With help from Claude Sonnet and Opus to:

- perform some of the mechanical updates as part of this change
- ensure that the Docker sidecar always has `hardcodedProcessEnv` passed
  into it
- catch a needed change to `exposeAllEnv` handling

Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-08-24 17:21:24 +01:00
Sebastian Poxhofer a473e73b3e fix(linters): forbid inert counts in v8 coverage-ignore comments (#45287)
Adds a custom oxlint rule renovate/v8-ignore-no-count that flags the
count form '/* v8 ignore next <N> */'. The count is not honored by
vitest's ast-v8-to-istanbul hint parser, which captures only the
keyword (if/else/next/file); 'next' always exempts exactly the next
AST node. Trailing counts therefore suggest a line range that is never
applied and mislead readers.

The rule is autofixable (drops the count, preserving actual behavior)
and has been applied to all existing occurrences.
2026-08-22 11:25:31 +00:00
Jamie Tanna d8705054b0 fix(datasource/go): prefer later releaseTimestamp from GitHub Releases (#45315)
As noted in #45314, there are cases where we may see as similar case to
the GitHub Releases datasource in #43451, where a Go module's published
`Time` matches the time that the commit the Git tag points to was
committed, rather than the time that the release was created.

If we do have a GitHub repository, we can look up the GitHub Releases
(or we'll get the Git Tags, if no Releases are present) and use the date
if it's /newer/

Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
2026-08-17 19:01:23 +00:00
Sebastian Poxhofer a1971afa78 fix(linters): add linting rule to enforce usage of our regEx utility (#44690)
* ci(linter): add renovate/require-regex-util rule

Adds a custom oxlint rule that flags raw RegExp usage in lib/
production code: any `new RegExp(...)` call and any regex literal
that is not the direct first argument of `regEx(...)`. The regEx()
helper from lib/util/regex.ts uses the RE2 engine for ReDoS-safe
matching and caches compiled patterns. lib/util/regex.ts itself is
exempt.

The rule is disabled for **/*.spec.ts, test/**, and tools/** via
config overrides, because vitest APIs such as expect.stringMatching
need bare RegExp instances (a past commit reverted regEx() there).

Severity is set to "warn" instead of "error": the repo currently has
197 pre-existing violations (above the agreed mechanical-fix
threshold of 80), and a number of them are deliberately
RE2-incompatible patterns (lookahead/lookbehind/named backreferences,
see TODO #12872/#12875 markers in e.g. lib/modules/versioning/rez/
pattern.ts and lib/modules/manager/dockerfile/extract.ts) that need
per-site judgment before they can be wrapped in regEx() or suppressed
with a justified disable comment. No violation fixes are included in
this commit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* ci(linter): enforce renovate/require-regex-util at error

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor: use regEx() for regex literals and RegExp construction in lib

Burn down all renovate/require-regex-util violations (197):

- wrap RE2-compatible regex literals and RegExp constructions in regEx()
- rewrite lookaround patterns where behavior is provably preserved:
  goproxy separator split, sbt-package link extraction, leiningen
  comment stripping and keyword search, npm GitHub owner validation
  (unit-count bound replaced by an explicit length check)
- keep native RegExp with disable comments where RE2 cannot be used:
  moo / good-enough-parser lexer patterns (moo rejects RE2 instances),
  MigrationsService propertyName (matched via isRegExp, which RE2
  instances fail), rez named backreferences and lookaheads, GitHub
  markdown link negative lookbehind, emoji astral-plane matching
- drop stale TODO #12875 comments for patterns current re2 handles

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor: reduce require-regex-util disable comments

Rewrite the github massage-markdown-links URL regex to capture an
optional `api.` prefix in a named group (skipped in code) instead of
relying on a negative lookbehind, so both the base and global variants
can use regEx()/RE2 and their two disable comments are removed. Add
spec cases for api-prefixed URLs that match the URL shape.

Consolidate the four related line disables in rez/pattern.ts (bound and
range patterns emulating Python conditional patterns via named
backreferences and lookaheads, which RE2 cannot express) into a single
block disable/enable pair, matching the treatment of the lexer files.

Disable comment count drops from 13 to 8.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor(datasource/sbt-package): use named capture group in link regex

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor(manager/cake): restore original multiLineComment regex spelling

The [^] -> [\\s\\S] rewrite was only needed for an RE2 wrap that was
later reverted; keep the diff minimal.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(datasource/go): skip empty GOPROXY segments

The switch from a lookahead split to a capture-group split (needed because
RE2 has no lookahead support) changed how empty GOPROXY segments parse:
`a|,b` yielded `{ url: ',', fallback: '|' }` before and
`{ url: '', fallback: ',' }` after. The comma fallback only continues on
404/410, so a failing proxy ahead of an empty segment silently stopped the
lookup instead of falling through to the remaining proxies.

Empty segments carry no url to query, so drop them.

* refactor(datasource/go): use isTruthy for empty segment filter

* fix(datasource/go): filter empty segments before mapping

Filtering after the map broke the contextual typing from the
GoproxyItem[] annotation, widening fallback to string.

* refactor(platform/github): use regEx() for merge queue query stripping

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-14 14:30:46 +00:00
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
Sergei Zharinov cca6227dfa fix(git): resolve child env before adding authentication (#45184)
* fix(git): preserve approved runtime config with authentication

* test(git): remove redundant authentication cases

* test(git): update post-upgrade environment assertions

* test(hermit): cover uninstall setup failure

* refactor(git): clarify authentication host types

* refactor(git): coerce exec options

* refactor(git): coerce docker env vars

* refactor(exec): coerce docker env vars
2026-08-10 11:54:18 +00:00
Jamie Tanna b017c7548a fix(exec/docker): single-quote the sidecar bash command
When executing commands for `binarySource=docker`, we have two areas
that a command could have shell expansion/injection:

- on the host (when constructing the `bash -l -c`)
- in the container (when running a manager-specific command)

When constructing the host's command, we previously would escape the
`"`, which allows Bash syntax for `${VAR}` and `$(...)` syntax inside
it.

While managers use `quote()` to make the inputs safer, the use of `"`
around that would not provide any protection, and lead to cases where
the `quote()` could be expanded on the host, before `docker run`
executes.

After recent changes to each manager - and removal of `shell: true` -
this doesn't seem to be exploitable, but this hardens it further.

Additionally, we never escaped `\`, so a value containing `\"` produces
a command that `shlex.split` rejects, and the update fails rather than
running.

Instead, we can quote the whole `-c` argument with `quote()`, which
round-trips through both `shlex.split` - the default, no-shell path - and
a real shell.

This removes the `lgtm [js/incomplete-sanitization]` suppression as
we're now correctly sanitising this.

Note this doesn't remove the need for the managers to quote their own
values, as the second area above is still a real shell.

Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
2026-08-07 14:25:42 +01:00
Jamie Tanna c9cec1affb fix(manager/gomod): quote module path in import path update command
To prevent the possibility of a Go module name including
shell metacharacters (which is unlikely, but potentially possible
through a well-crafted payload), which could lead to command execution,
we can make sure they are quoted appropriately.

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-08-07 14:22:55 +01:00
Maximilian Herrmann e5ace746bb fix(gomod): pseudo-version digest updates produce no change when module is absent from go proxy (#44477)
* fix(gomod): pseudo-version digest updates produce no change when module
    is absent from go proxy

* Update lib/modules/manager/gomod/update.spec.ts

Co-authored-by: RahulGautamSingh <rahultesnik@gmail.com>

---------

Co-authored-by: RahulGautamSingh <rahultesnik@gmail.com>
2026-07-21 07:17:45 +00:00
Jamie Tanna 0e6429b13e refactor(types): document localDir isn't a globalOnly option (#44635)
* refactor(types): document `localDir` isn't a `globalOnly` option

To make sure that it's clear when reviewing `GlobalConfig`, as well as
working with our types, we can move the `localDir` definition into a
separate type.

* fixup! refactor(types): document `localDir` isn't a `globalOnly` option

* fixup! refactor(types): document `localDir` isn't a `globalOnly` option

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>

* fixup! refactor(types): document `localDir` isn't a `globalOnly` option

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>

* fixup! refactor(types): document `localDir` isn't a `globalOnly` option

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>

---------

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-07-20 08:07:17 +00:00
Sebastian Poxhofer 58771bb183 refactor(linters): enabled oxlints func-style (#44691)
* refactor(oxlint): enable func-style

Enable the built-in func-style rule as ["warn", "declaration"] so that
named functions are written as function declarations instead of arrow or
function expressions assigned to variables, matching the convention in
docs/development/best-practices.md (Functions section). Inline arrow
callbacks are unaffected; prefer-arrow-callback continues to cover the
callback direction.

Severity is "warn" instead of "error" as a fallback: a repo-wide run
found 196 pre-existing violations (70 in spec files, 126 in production
code), exceeding the 80-violation fix threshold for this change, so no
violations were fixed here. Follow-up work can convert the offenders
(largest clusters: lib/modules/versioning/ruby, lib/util/cache/package,
lib/modules/versioning/maven, lib/modules/versioning/gradle) and then
raise the rule to "error". Note oxlint 1.72 also supports an
allowTypeAnnotation option if typed consts should remain arrows.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* ci(linter): enforce func-style at error

* refactor(func-style): convert const-arrow functions to declarations in with-cache spec and ruby versioning

* refactor(func-style): convert const-arrow functions to declarations in maven/gradle modules

* refactor(func-style): convert const-arrow functions to declarations in remaining versioning modules

* refactor(func-style): convert const-arrow functions to declarations in platform modules

Discriminated-union closures (ensureCommentRemoval byTopic/byContent
helpers in github, gitlab, bitbucket, bitbucket-server) needed the
narrowed field passed explicitly as a parameter, since function
declarations are hoisted and lose the outer if-narrowing that inline
arrow-function closures previously relied on.

* refactor(func-style): convert const-arrow functions to declarations across util/manager/datasource modules

One case (logger/renovate-logger.ts logOnceFn) is kept as an arrow
function with a documented oxlint-disable: it is stored on
this.logger.once[level] and relies on lexically-bound this, which a
hoisted function declaration would not preserve.

* refactor(func-style): convert remaining const-arrow test helpers to declarations

get-updated.spec.ts: hoisted expectPipCompilePackageAndLockFile to
module scope (it only closes over the module-level pipCompile mock)
and added a documented oxlint-disable for vitest/expect-expect on its
caller test, since oxlint's expect-expect check does not trace
assertions through an externally-defined helper function.

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 11:14:22 +00:00
Sebastian Poxhofer 27cc994470 refactor(oxlint): enable vitest/no-standalone-expect (#44417)
Wrap `expect` calls that sat directly in `describe` bodies in their
own `it` blocks (gomod and haskell-cabal extract/index specs), then
re-enable the rule.

Part of #43845

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 10:06:16 +00:00
Sebastian Poxhofer 9a27d7aa78 ci(prettier): add prettier plugin for admonitions (#43615)
* ci: add local mkdocs-admonitions plugin for prettier to allow admonition preservation

* docs: remove uses of `prettier-ignore` for admonitions

* test: rather use await expect

* chore: use named group exclusively
2026-05-27 09:39:52 +00:00
Jamie Tanna 33e857e04a docs: migrate all admonitions and lists to using 2-space indents (#43607)
* docs: ensure 2 spaces used for generated admonitions

As a follow-up to 4b0146ab7b and
1844916259b6dc17f532e491eb93f6116327c324., this correctly renders
admonitions with 2 spaces (1 indent).

* fixup! docs: use 2-space indentation for Markdown (#43537)

Plus using 3-space for mixed-style `<ul>` and `<ol>`s.

* fixup! docs: use 2-space indentation for Markdown (#43537)

As otherwise it breaks the rendering of the table.
2026-05-26 20:03:23 +00:00
Sebastian Poxhofer d004b52a91 test: add coverage for lines detected by pnpm check (#43589)
tests: add coverage for lines detected by pnpm check
2026-05-26 07:53:07 +00:00
Sebastian Poxhofer 73b90e958b refactor: remove string concetation for production code (#43442)
refactor: prefer templates rather than `+`
2026-05-19 13:31:27 +00:00
Jamie Tanna 68cb7c71d5 test: ensure we set binarySource=global (#43382)
* test: ensure we set `binarySource=global`

As part of future changes, we'll correctly return the default value from
`GlobalConfig.get`, instead of `undefined` if no default is provided in
the `get` call.

As `binarySource=install` is the default, this then leads to these tests
failing, as they're intended to run with `binarySource=global`.

Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>

* fixup! test: ensure we set `binarySource=global`

* fixup! fixup! test: ensure we set `binarySource=global`

---------

Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
2026-05-15 15:40:22 +00:00
Qixiang Wan f944c8d12e fix(gomod): write full pseudo-version instead of bare hash on digest updates (#41588)
When a Go dependency uses a pseudo-version (v0.0.0-timestamp-hash) and
Renovate detects a newer pseudo-version, updateType is set to 'digest'
via the gomod special-case in lookup/index.ts. The digest update code
path was then writing only the 12-character bare commit hash, producing
invalid go.mod syntax:

  - knative.dev/pkg v0.0.0-20250312035536-b7bbf4be5dbd
  + knative.dev/pkg 4a022ed9999a

Historical cause:

In 2018, the Go module proxy did not yet exist. Renovate queried the
GitHub API for the latest commit SHA and had no way to obtain the correct
commit timestamp, so it fabricated a pseudo-version using the wall-clock
time when Renovate ran. The result was syntactically valid but semantically
wrong. Go 1.11 and 1.12 did not validate pseudo-version timestamps, and
`go get` would normalise the fabricated version to the correct one anyway,
so this worked in practice.

Go 1.13 (2019) introduced strict pseudo-version timestamp validation,
rejecting any pseudo-version whose timestamp does not match the actual
commit time. Renovate's fix (31ce47297) was to drop the fabricated
timestamp entirely and write just the bare commit hash, then rely on
`go get` to expand it into a canonical pseudo-version. However, when
the `go get` command or other subsequent operations fail, Renovate may
leave the go.mod file containing dependencies pinned to bare commit hashes.

Why the fix is now safe:

Since the 2024 goproxy datasource changes, both newValue and newDigest are
extracted from the same proxy version string via pseudoVersionToRelease().
They always reference the same commit, so writing newValue directly produces
correct, syntactically valid go.mod output without depending on `go get` to
clean it up afterward.

Signed-off-by: Qixiang Wan <qwan@outlook.com>
2026-05-06 16:06:01 +00:00
Jamie Tanna dfe0938b42 feat(datasource/go): conditionally expose constraints (#42569)
* feat(datasource/go): conditionally expose `constraints`

As noted in #42567, some Go modules are constrained by their
compatibility with the source compatibility with the Go language as per
the `go` directive.

Bumping the `go` directive will result in all of a library's consumers
also needing to bump their own `go`, which can be something library
authors will attempt to avoid.

Previously, Renovate users would receive an update from any modules that
have a new release, regardless of whether they will bump the `go`
directive.

With this change, users who use `constraintsFiltering=strict` will have
the filtering applied, so they only receive updates for Go modules in
their current minor version.

Due to the additional API calls needed, this is an opt-in feature, and
only includes the API calls when the using
`constraintsFiltering=strict`.

We can also add an integration test to build our confidence in the
end-to-end flow.

* fix(datasource/go): correctly check Go directive for major version bumps

As we weren't passing around the `pkg` (which included the Semantic
Module Import Path), we were incorrectly lacking major version upgrades.

Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>

* chore: remove `fallback`

As it's unnecessary.

* docs(gomod): rephrase

---------

Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
2026-04-29 14:48:53 +00:00
Jamie Tanna 0e5e384237 feat(manager/gomod): extract the go and toolchain directives as constraints (#42582)
As part of future changes in #42567 to surface the `constraints` of a
given Go module, we should first extract the constraints from the
package file.

To make this simpler for users, we can make sure we extract these at
parse time:

- the `toolchain` directive becomes the `golang` constraint, which
  matches the `golang` tool name already in use for Containerbase
- the `go` directive becomes a new `%goMod` constraint, which keeps it
  separate from the version of the Go toolchain actually used to run, as
  well as clearly not for the Go tooling, or something that
  Containerbase knows about
- we make sure to extract it with a SemVer range that can then be used
  to ensure that, in future changes, using `constraintsFiltering=strict`
  will allow filtering releases from the Go datasource based on this
  constraint.
- because we're now returning the `constraintsVersioning`, we need to
  make sure this is part of our types
2026-04-29 13:20:13 +00:00
Jamie Tanna 1054439929 refactor(gomod): extract deriveGoToolchainConstraints function (#42956)
As part of future changes, we'll introduce additional constraints that
may take priority, so we should ensure we have coverage of the existing
logic.

Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
2026-04-28 08:05:11 +00:00
Jamie Tanna 01a01f6b88 feat(manager/gomod): improve commitMessageTopic for go/toolchain directive bumps (#42891)
As noted in #42519, the preivous commit/PR title wasn't quite as clear
with what was actually changing.

To make this more explicit, we can override `commitMessageTopic`.
2026-04-27 16:30:52 +00:00
renovate[bot] a561b74314 chore(deps): update dependency @biomejs/biome to v2.4.11 (main) (#42034)
* chore(deps): update dependency @biomejs/biome to v2.4.11

| datasource | package        | from  | to     |
| ---------- | -------------- | ----- | ------ |
| npm        | @biomejs/biome | 2.4.6 | 2.4.11 |

* fixup linter changes

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Sebastian Poxhofer <secustor@users.noreply.github.com>
Co-authored-by: secustor <sebastian@poxhofer.at>
2026-04-20 21:45:46 +00:00
Michael Kriese 440e353145 chore: use ts extension (#42300) 2026-04-01 07:46:34 +00:00
Jamie Tanna 2d239d2cc1 docs: explicitly document depTypes each manager supports (#42142)
* docs: explicitly document `depTypes` each manager supports

A long-standing question we receive is "what `depTypes` can I match
against in my project".

Although the best recommendation we usually have is "check the
`packageFiles with updates" log line (as a very key log line for users),
we can go one step further and try and create a stronger contract.

To do this, I've used Claude Sonnet 4.6 to work through the codebase,
determine areas that a `depType` is set in a manager (statically or
dynamically) and generate a structured, typed, means to document how
they're used.

Through a few iterations of the process, and attempts at human-written
documentation, we've settled on:

- prioritising autogenerated documentation (for humans to read) to note
  what `depTypes` are known, and what they are
- `knownDepTypes`, to describe any known, static, `depType`s and their
  human-readable meaning
  - with the `prettyDepType`, if used
- `supportsDynamicDepTypesNote`, to add a Markdown note to the generated
  documentation

While here, we also:

- make sure to note this in the "adding a new package manager"
  documentation
- remove any hand-written references to `depTypes` in each manager's
  documentation page
- correct the Gleam `depTypes`
- make sure to use the `knownDepTypes`'s `prettyDepType` definition if
  we know it, for a given `depType`

The descriptions have been generated by Claude Sonnet, with some
human-written tweaks where appropriate.

[0]: https://github.com/renovatebot/renovate/discussions/15176

Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>

* fixup! docs: explicitly document `depTypes` each manager supports

* docs(manager): display `depTypes` documentation if none present

For consistency, and to make it more explicit.

---------

Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
2026-03-31 12:08:39 +00:00
Michael Kriese 3953a78123 refactor: pass packageFile to updateDependency (#42253) 2026-03-30 17:32:36 +00:00
Jamie Tanna 2d1e57532f refactor(types): rename lockFile to fileName in ArtifactError (#41631)
As `fileName` makes more sense (as it's not always a lock file we're
updating).

Also, if you set `fileName`, it would never actually output the
filename.

This renames the usages of `lockFile` to `fileName`.

Co-authored-by: Claude Sonnet 4.5 <jamie.tanna+github-copilot@mend.io>
2026-03-10 09:57:31 +00:00
Roger Coll ab409e951f fix(gomod): add -modfile flag for non-default go.mod filenames (#41640)
* fix(gomod): add -modfile flag for non-default go.mod filenames

When using managerFilePatterns to manage non-standard go.mod files
(e.g. tools.mod), the go commands (get, mod tidy, mod vendor) now
include the -modfile flag so they operate on the correct module file
instead of defaulting to go.mod in the working directory

* Update lib/modules/manager/gomod/artifacts.ts

Co-authored-by: Michael Kriese <michael.kriese@gmx.de>

* Update lib/modules/manager/gomod/artifacts.ts

Co-authored-by: Michael Kriese <michael.kriese@gmx.de>

* use string templates

---------

Co-authored-by: Michael Kriese <michael.kriese@gmx.de>
2026-03-05 11:53:42 +00:00
Jamie Tanna 59de755283 fix(gomod): support local module paths in replace directives (#41520)
* fix(gomod): support non-public module paths in `replace` directives

As noted in #41518, we allow extracting `require` directives that
include a module path that's non-public, so we should also support this
for `replace` directives.

* fixup! fix(gomod): support non-public module paths in `replace` directives
2026-02-26 14:56:23 +00:00
Jamie Tanna dcabd52332 fix(gomod): skip placeholder pseudo versions (#41521)
As a follow-up to #41517, when we have a placeholder pseudo version, we
attempt to look up updates for the module.

However, because these are handled by a `replace` directive, there's no
point attempting to look them up.

Especially, as noted in #41517, this could be a non-public module, so
the lookup will fail unnecessarily.

Co-authored-by: Claude Sonnet 4.5 <jamie.tanna+github-copilot@mend.io>
2026-02-26 13:33:17 +00:00
Tobias dda653f55a test(manager/gomod): use real hostRules implementation in tests (#41515)
chore(manager/gomod): use real hostRules implementation in tests
2026-02-26 12:37:28 +00:00
Jamie Tanna d04b07f89b fix(gomod): support major version on replaces with the same Go module (#41359)
As noted in #41260, if a Go module is using a `replace` with both
modules with the same name, the major upgrade fails to produce a valid
`go.mod`, as the `replace` will still partially reference the old
package.
2026-02-24 22:05:13 +00:00
Jamie Tanna d992c98857 test(gomod): remove duplicated test (#41358)
We've already got a test that covers the usage of a `replace` with a
`major` update.
2026-02-20 21:19:11 +00:00
Sergei Zharinov 9d857c1f68 refactor(lint): Organize imports with biome (#40966) 2026-02-06 13:40:01 +00:00
Michael Kriese cd0426babd feat(sidecar): use renovatebot/base-image instead of containerbase/sidecar (#40772)
* feat(sidecar): use `renovatebot/base-image` instead of `containerbase/sidecar`

* refactor: simplify sidecar handling

* test: fixup

* docs: fixup
2026-01-29 10:05:24 +00:00
Jamie Tanna 783002c7de docs: correct references to binarySource=install for Mend-hosted (#40740) 2026-01-28 11:38:18 +00:00
Sergei Zharinov 930cf6633c refactor: Rewrite imports with .ts extensions (#40700)
fix: Additional vi.mock path corrections and prettier formatting
2026-01-26 22:48:17 +00:00