Commit Graph

3913 Commits

Author SHA1 Message Date
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 1fc0a3e5bd docs(manager/gradle): add link to Dependency Verification docs (#45384)
Plus make it very clear that this needs to be `allowUnsafeExecutions`'d.
2026-08-21 10:51:35 +00:00
Christoph Mathys adce441ee5 feat(manager/devcontainer): add folder pattern to list of managerFilePatterns (#45377)
fix(devcontainer): add folder pattern to list of managerFilePatterns

This extension is according to the spec found here:
https://containers.dev/implementors/spec/#devcontainerjson
2026-08-21 08:49:52 +00:00
Jamie Tanna a61de24310 fix(datasource/npm): don't break on non-string homepage (#45358)
As reported in #45357, changes in
116c3d610c caused a regression for cases
where an npm package had `homepage: [...]`.

We should restore the `catch(undefined)` and add a test to make sure
this isn't broken in the future.

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-08-19 20:41:56 +00:00
Simon Marquis 8ea65f77d2 fix(kotlin-script): support vararg arguments in @file:DependsOn and @file:Repository (#44762)
* fix(kotlin-script): support vararg arguments in @file:DependsOn and @file:Repository

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(kotlin-script): remove unreachable branch to restore code coverage

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor(kotlin-script): restore functional style after vararg fix

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(kotlin-script): use non-null assertion to avoid uncovered branches

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Implement requested changes

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-19 14:09:53 +00:00
Simon Marquis c77ac1f29c fix(gradle): collision with well-known Android APIs (#45350)
Discussion: https://github.com/renovatebot/renovate/discussions/45349
2026-08-19 13:46:51 +00:00
Luigi Cerone dd72cf0cd2 feat(manager/poetry): pass POETRY_SOLVER_MIN_RELEASE_AGE when minimumReleaseAge is configured (#43429)
* feat(manager/poetry): pass POETRY_SOLVER_MIN_RELEASE_AGE when minimumReleaseAge is configured

* test(manager/poetry): add coverage for invalid minimumReleaseAge duration

* refactor(poetry): remove pyproject.toml solver logic

* style: apply prettier formatting

* fix(poetry): address review comments

* fix: review changes

* fix: review changes

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

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

* fix: linting

---------

Co-authored-by: Michael Kriese <michael.kriese@gmx.de>
2026-08-19 09:39:52 +00:00
RahulGautamSingh 37444eff27 fix(datasource): keep merged releases when a registry is rate-limited (#45299)
* fix(datasource): keep merged releases when a registry is rate-limited

* apply suggestions
2026-08-18 09:21:54 +00:00
Felipe Santos 2606ae2bd3 feat(pypi): add support for JSON-based Simple API (PEP 691) (#44222)
* feat(pypi): add support for JSON-based Simple API (PEP 691)

* Fix some stuff

* Clean some things up

* Fix coverage

* Simplify JSON parse

* Remove useless tests

* Align terminology

* Incorporate some changes from PR #44182

Co-authored-by: Andreas Hippler <andreas.hippler@goto.com>

* Use isNonEmptyString to filter requires_python

* Address review feedback

* Warn once actually

* fixup! review comments

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

* fixup! fixup! review comments

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

* fixup! review comments

As the list of status codes we retry on was based on an unverified
claim that Artifactory, Nexus and devpi answer a rejected `Accept`
header with `400`/`403`/`415`, we should only retry on `406`, which is
what RFC 9110 specifies for a request whose `Accept` cannot be
satisfied.

Our `Accept` header ends with `text/html; q=0.01`, so any conforming
registry can satisfy it, `415` refers to the request body's
`Content-Type` rather than `Accept`, and retrying on `403` doubles the
requests for a registry we're not authenticated against.

The unwrapping of `ExternalHostError` is unaffected, as that's needed
for the `abortOnError` case regardless of which status codes we retry.

Co-Authored-By: Claude Opus 5 <claude-code@jamietanna.co.uk>

* fixup! review comments

As the note about `upload-time` sat in the paragraph about the Simple
API, it read as if `minimumReleaseAge` needs a registry which supports
the JSON-based Simple API (PEP 691).

That's only true of the Simple API. The JSON API has always exposed
`upload_time`, and as the default registry of `https://pypi.org/pypi/`
doesn't end in `/simple/`, that's the lookup most users get, so
`minimumReleaseAge` already works for them.

We can split the two apart, so that the guarantee for each API is
stated separately.

Co-Authored-By: Claude Opus 5 <claude-code@jamietanna.co.uk>

* reword

* fixup! review comments

As the JSON-based Simple API's release timestamps were only covered by
hand-written responses, we didn't have the equivalent of the real world
coverage added for the JSON API in
e942788539.

We can add a `numpy` fixture from PyPI's JSON-based Simple API, trimmed
to 1.5.0 and 1.5.1, so we assert against a response a registry has
actually served. 1.5.1 is the interesting case, as it was released in
2010 but gained a wheel in 2014 which PyPI lists first.

This also covers the `upload-time` format the Simple API uses, of
`2010-11-18T14:16:58.801332Z`, rather than the JSON API's
`2010-11-18T14:16:58`, so that we know `asTimestamp` normalises both.

Unlike the JSON API, there's no previous behaviour to characterise
first, as before these changes the Simple API exposed no timestamps at
all.

Co-Authored-By: Claude Opus 5 <claude-code@jamietanna.co.uk>

* fixup! fixup! review comments

* fixups

* fixups

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

* fixup! comments

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

---------

Co-authored-by: Andreas Hippler <andreas.hippler@goto.com>
Co-authored-by: Jamie Tanna <jamie.tanna@mend.io>
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Opus 5 <claude-code@jamietanna.co.uk>
2026-08-18 09:03:12 +00:00
Gregor Zeitlinger a53aaf4141 refactor(java-version): extract adoptium HTTP logic from datasource class (#42604)
* refactor(java-version): extract adoptium HTTP logic from datasource class

Move getPageReleases and the Adoptium fetch logic out of the
JavaVersionDatasource class into a standalone adoptium.ts module.
This makes the code easier to test in isolation and decouples
Adoptium-specific logic from the datasource class.

No behavior change — customRegistrySupport remains false, and the
hardcoded adoptiumRegistryUrl replaces the previously injected
defaultRegistryUrl (which was always the same value).

* fix(java-version): remove unused adoptiumRegistryUrl import from test

* test(java-version): use partial helper in spec

* refactor(java-version): extract adoptium HTTP logic from datasource class

* fix(java-version): pass Adoptium schema to HTTP client

* test(java-version): move Adoptium test to module spec

* chore(ci): retrigger failed checks
2026-08-18 08:13:54 +00:00
Sebastian Poxhofer 41da033756 refactor: remove escapeRegExp and replace with RegExp.escape (#45322) 2026-08-18 06:24:47 +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
Aleksandr Mezin 5e8bf3c010 fix(github): recognize another "needs approving review" message (#45052)
* fix(github): recognize another "needs approving review" message

    "response": {
      "message": "Repository rule violations found\n\nNew changes require approval from someone other than the last pusher.\n\n",
      "documentation_url": "https://docs.github.com/rest/pulls/pulls#merge-a-pull-request",
      "status": "405"
    }

* Add tests

* Include message in test name
2026-08-17 13:47:53 +00:00
Jamie Tanna e942788539 fix(datasource/pypi): use the earliest upload_time of a version (#45313)
* test(datasource/pypi): cover which `upload_time` a version reports

As part of future changes to how we calculate the `releaseTimestamp`, it
was clear we don't have as much coverage of this logic.

To make this more explicit, we can add new test coverage.

Additionally, we can introduce a new example from a package to guide
this.

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

* fix(datasource/pypi): use the earliest `upload_time` of a version

When calculating the `releaseTimestamp` for the PyPI datasource, we've
been looking at the first entry in the response, which isn't always
the first time this package existed.

In the case that a Wheel is uploaded after the package first was
released - for instance, to support a new version of Python, at an
existing pinned version of the package - this would lead to a
potentially incorrect calculation for the `releaseTimestamp`.

This can lead to Renovate seeing a package as newer than it is, which
can mean that i.e. `minimumReleaseAge` can show as pending for a package
that shouldn't be.

As part of upstream changes[0], this should be less frequent in the
ecosystem, but existing packages still exist with this behaviour.

To fix this, we can make sure that we filter a given Release's
to find the earliest `upload_time`.

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

[0]: https://blog.pypi.org/posts/2026-07-22-releases-now-reject-new-files-after-14-days/

---------

Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
2026-08-17 11:01:26 +00:00
Jamie Tanna 5e93fc225d test(datasource/pypi): add regression test for constraintsFiltering=strict (#45312)
test(datasource/pypi): add regression

As per changes suggested by Claude Opus 5 in a commit in #44222, a
regression could be triggered with our handling of
`constraintsFiltering=strict`, breaking a key piece of functionality.

To prevent this, we can add a regression test for this functionality.

Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
2026-08-17 10:05:26 +00:00
Jamie Tanna 116c3d610c fix(datasource/npm): handle absent homepages (#45219)
* fix(datasource/npm): handle absent `homepage`s

As a follow-up to 89f526e0b1, this handles
it at the response from the npm registry.

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

* fixup! fix(datasource/npm): handle absent `homepage`s

* fixup! fix(datasource/npm): handle absent `homepage`s

---------

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-08-17 09:34:29 +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
Arnaud Dezandee 6a782d3a18 feat(terraform-provider): use OpenTofu packages API for lockfile hashes (#43573)
* feat(terraform-provider): use OpenTofu packages API for lockfile hashes

* refactor(terraform-provider): reuse OpenTofu registry constant

* refactor(terraform-provider): test file structure consistency

* refactor(terraform-provider): simplify hashes with flatMap

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

* fix(terraform-provider): handle OpenTofu API URL for lockfile hashes

* perf(terraform-provider): skip /versions request for OpenTofu lockfile hashes

* refactor(terraform-provider): improve function return flow

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

* docs(terraform-provider): clarify OpenTofu packages endpoint behavior

* test(terraform-provider): add message to toThrow assertion

* fix(terraform-provider): wrap OpenTofu packages errors in ExternalHostError

* test(terraform-provider): cover OpenTofu package errors

* refactor(terraform-provider): use async/await for provider packages

* refactor(terraform-provider): use LooseRecord for schema packages prop

Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com>

* fix(terraform-provider): import LooseRecord in schema

---------

Co-authored-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: RahulGautamSingh <rahultesnik@gmail.com>
Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com>
2026-08-14 09:51:00 +00:00
Michael Kriese c953fafcdc fix(platform/github): abort branch update when PR is in merge queue (#45252)
* fix(platform/github): skip PR update when PR is in merge queue

Updating a PR that is queued for merging can remove it from the merge
queue. Check the PR's merge queue status via GraphQL before updating
and skip the update if it is queued. The check is skipped on GHES
<3.12.0 and fails open on errors.

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

* fix(platform/github): dequeue PR from merge queue instead of skipping update

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

* docs(platform/github): note re-queue behavior after dequeue

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

* refactor(platform/github): dequeue merge queue PR in commitAndPush

Dequeue on push instead of on PR metadata update, since pushing to the
branch is what invalidates the queued merge result.

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

* refactor(platform/github): extract dequeuePr to pr.ts

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

* fix(platform/github): abort branch update when PR is in merge queue

Instead of dequeueing the PR, throw PR_ALREADY_IN_MERGE_QUEUE from
commitAndPush and handle it gracefully in processBranch.

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

* feat(platform/github): check merge queue enablement per base branch

Cache merge queue enablement per base branch like branchForceRebase and
skip the per-PR merge queue check when the base branch has no merge
queue. Errors are treated as enabled.

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

* feat(platform/github): fetch default branch merge queue status in initRepo

Include mergeQueue in repoInfoQuery so no extra query is needed for the
default branch, stripping it on GHES <3.12.0 like other unsupported
fields.

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

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-14 07:05:12 +00:00
Sebastian Poxhofer 16ef1715e9 refactor(linters): add rules for @sindresorhus/is helpers (#45229)
* feat(lint): add renovate/prefer-is-helpers and renovate/prefer-is-object rules

Flag ad-hoc type checks that have @sindresorhus/is equivalents:
- .filter(Boolean) -> .filter(isTruthy)
- typeof x === 'string' -> isString(x)
- x === null || x === undefined -> isNullOrUndefined(x) (and negation)

The typeof x === 'object' shape lives in a separate suggestion-only rule
(renovate/prefer-is-object, kept at warn) because isObject()/isPlainObject()
are not drop-in equivalents: null, arrays and functions behave differently.

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

* refactor: fix renovate/prefer-is-helpers violations

Replace ad-hoc type checks with @sindresorhus/is helpers across lib/:
- 13x .filter(Boolean) -> .filter(isTruthy)
- 36x typeof x ==/!== 'string' -> isString(x) / !isString(x)
- 6x x === null || x === undefined -> isNullOrUndefined(x) (and negation)

Promote renovate/prefer-is-helpers to error now that the codebase is clean.
renovate/prefer-is-object stays at warn: its 15 remaining sites guard
parsed YAML/JSON or unknown values where isObject()/isPlainObject() are
not provably equivalent (null/array/function semantics).

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

* refactor: enforce renovate/prefer-is-object at error level

Resolve the 15 remaining warnings and raise the rule from warn to error:

- Migrate 10 sites to isObject() where the guarded value provably cannot
  be a function (parsed YAML/JSON, typed exec command arguments, or
  test-controlled fixtures): helm-values, woodpecker, bun, pre-commit
  managers, exec utils, file package cache, and the github http spec.
  In the bun manager this also fixes a latent crash where a null
  `workspaces` value would throw on the `in` operator.
- Keep 5 sites as reasoned oxlint-disable comments where excluding
  functions is load-bearing: the byte-exact fingerprint canonicalizer
  (2), the circularity walker, the zod result guard, and the generic
  hasKey helper.

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

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-13 14:22:03 +00:00
Sebastian Poxhofer 874f3e3953 feat(presets): support relative paths inside a preset repo (#45211)
* feat(presets): support relative `extends` references inside presets

Presets which are fetched from a repository can now reference sibling
presets relatively, instead of repeating their own source, repository and
tag:

- `./x` resolves against the directory of the preset file with the
  reference
- `../x` resolves against the parent directory of that file
- `/x` resolves against the root of the preset repository

The source, repository and tag of the preset which holds the reference are
inherited, so `./system/registries` inside `github>org/repo#v2.0.0`
resolves to `github>org/repo//system/registries#v2.0.0`. A reference which
resolves to the `default` preset at the repository root is emitted in the
plain repository form, so `github>org/repo#v2.0.0`, which keeps it
deduplicated against the way consumers spell the very same preset.

A reference must stay inside its repository, its final path segment must
name a preset file rather than a directory, and it can carry parameters
but neither its own `#tag` nor a `:subPreset`. Parameters may contain a
Handlebars template, including a sub-expression such as
`./group({{ lower (env.TEAM) }})`, while a templated path cannot be
resolved and is left alone. A reference must also not carry a source
prefix, so strings such as `local>./x` or `github>../x` are rejected as
invalid.

References are canonicalized lazily, while the preset which holds them is
fetched in `getPreset()`, after migration and massaging. Only presets from
a repository hosted source, so `github`, `gitlab`, `gitea`, `forgejo` and
`local`, are walked. A relative reference which has no parent preset, for
example in a repository config, an inherited config or in `globalExtends`,
is reported as a validation error for that entry.

Relative entries of a preset's `ignorePresets` are resolved in the same
way, so a preset can neutralize a preset which it references relatively,
as long as the consuming repository does not set `ignorePresets` itself.
A reference which cannot be resolved is kept raw and logged, which lets
consumers neutralize it with `ignorePresets`, and it only fails per entry.

Because relative references cannot be resolved while a config is
validated, they are stripped from a `packageRules` entry before its
presets are resolved. A rule which is then left without any selector is
reported as a warning rather than as an error, since the stripped preset
may still provide the missing selectors. Rules without relative references
keep failing hard as before.

The `renovate-config` manager reports relative and unparsable `extends`
entries with a skipReason, instead of dropping them, and ignores templated
entries which can only be resolved at runtime.

Behavior change: an `extends` string which starts with `./`, `../` or `/`,
such as `./x`, `../x` or `/x`, is now read as a relative reference. Before
it was parsed as a local repository name, which in rare cases could
accidentally resolve through the dot segment normalization of the request
URL. For the same reason a source prefixed relative looking string, such
as `local>/org/repo`, `github>./x` or `npm>./x`, is now rejected as an
invalid preset.

* fix(presets): parse scoped npm presets with explicit `npm>` prefix

`npm>@scope/name` was parsed as a local preset, because the heuristic for
local presets matched before the `npm>` prefix was stripped.

Every other use of `npm>` keeps its current behavior, so `npm>foo` still
falls back to the npm package `renovate-config-foo`, `npm>owner/repo` is
still resolved as a local preset and nested prefixes such as
`local>npm>foo` keep working.

* refactor: remove duplicated preset source

* docs: streamline new docs

* add more docs for skipReason and add requested changes

* Apply suggestions from code review

Co-authored-by: Jamie Tanna <github@jamietanna.co.uk>

* test(presets): drop object literal type casts in relative preset spec

---------

Co-authored-by: Jamie Tanna <github@jamietanna.co.uk>
2026-08-13 13:54:50 +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
Lukas Backström 481f9b6d46 fix(github-actions): support ratchet comments for nested actions (#45210)
The `ratchet:` alternative in the pin-comment regex only allowed
`owner/repo`, so a ratchet marker for an action in a subdirectory
(`owner/repo/path@ref`) never matched. Such comments fell through to the
bare-token branch, which made `currentValue` the entire marker string,
e.g. `ratchet:actions/cache/restore@v4`. That is not version-like, so
the dep was switched to the `github-digest` datasource, which cannot
resolve the marker as a tag or branch and logs "Could not determine new
digest for update". The dep then gets no updates at all.

Allow further path segments after `owner/repo` so that nested actions
are extracted the same way as their top-level counterparts, with
`currentValue: v4` and the `github-tags` datasource.

Assisted-by: Claude:claude-opus-5
2026-08-12 22:15:52 +00:00
Sergei Zharinov 7c3a3eff21 fix(manager/terraform): stream-based H1 hashing (#45220)
* fix(manager/terraform): stream provider H1 hashing

* docs(manager/terraform): explain provider H1 semantics

* docs(manager/terraform): clarify provider H1 semantics
2026-08-12 22:09:45 +00:00
RahulGautamSingh d53ffc5633 test(bun): mock util/fs instead of fs-extra in artifacts spec (#45235) 2026-08-12 22:07:40 +00:00
RahulGautamSingh d678372061 fix(platform/azure): skip work item Markdown format on Azure DevOps Server (#45237) 2026-08-12 14:04:20 +00:00
Michael Kriese b2da209f26 fix(manager/npm): do not pass --recursive to pnpm dedupe (#45244)
`pnpm dedupe` does not support the `--recursive` flag, so strip it from
the shared args when building the dedupe command.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 12:58:51 +00:00
Sebastian Poxhofer e01b50c6ab refactor(linter): oxlint prefer partial typed casts for consts (#45239)
* refactor: flag all typed object literal casts in prefer-partial-in-specs

* refactor: type maven spec httpError helper against got response shape
2026-08-12 08:50:57 +00:00
Marcelo Estriga 3646307241 fix(manager/npm): pass correct arguments to pnpm dedupe (#42024)
* fix(manager/npm): pass correct arguments to pnpm dedupe

Run pnpm dedupe with the same options that pnpm install, to:
- suppress unecessary dependency download;
- respect Renovate allowScripts and ignoreScripts options.

* fix documentation table alignment

* Fix typo
2026-08-11 22:02:16 +00:00
Edward Klesel 2869cd3a8b fix(terraform): deduplicate provider lockfile hashes (#45226) 2026-08-11 16:01:22 +00:00
Jamie Tanna fba1a9de30 feat(manager/github-actions): add support for Actions Lockfiles (#45199)
* refactor(manager/github-actions): make `extractPackageFile` async

As part of follow-up changes we'll need to read `.github/workflows/actions.lock`
while extracting, which requires we are an async function.

To reduce the diff, we can prefactor this change first.

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

* feat(manager/github-actions): add support for Actions Lockfiles

In June, GitHub announced a public preview for the GitHub Actions
lockfile functionality[0].

To add support for this, we can extend our support for GitHub Actions to
handle the presence of an `actions.lock` file, and if so, update it
after updating other manager files.

Although our ideal case would be to have a pure Typescript-based parsing
and updating of the `actions.lock`, due to the early nature of the
Actions Lockfile syntax, and its lack of stability, we can invoke the
`gh actions-lock` extension when updating.

After the schema has reached a v1 release, we can then migrate to
Typescript.

To make sure that the version of the `actions-lock` extension is always
version pinned, we can expose a `constraints` to control the version,
but allow Renovate to keep the pinned default updated as needed.

This doesn't imply that we have support for `lockFileMaintenance`, as we
are only updating the lockfile when there is a dependency update, not
periodically recreating the lockfile from the current ranges.

`gh actions-lock` re-reads every workflow from disk and rewrites the
whole lockfile, so it does not fit `updateArtifacts`, which is called
once per updated package file.

We can instead follow the shape the `npm` manager uses for its
lock files, and have `processBranch` invoke this once per branch, after
every updated package file has been written to disk.

We skip workflows that aren't onboarded to the lockfile, but still run
for any other package file, as a local composite action can be a
transitive dependency of a workflow which is.

`gh actions-lock` rewrites the workflows it manages back to plain refs
when it regenerates them, which strips out any inline digest pin:

```diff
-        uses: actions/setup-java@1bcf9fb12c # v5.4.0
+        uses: actions/setup-java@v5.7.0
```

This would lead to a repository with `pinDigests` set "flip flopping",
and would cause a lot of erroneous noise for repository owners.

Instead, we can make sure that:

- we don't suggest a `pinDigest` for workflows that are managed by the
  lockfile
- digest pinning is still enabled for `docker://` references
- already-committed digests are updated when they're present - we only
  avoid suggesting /new/ digests to be pinned

Co-authored-by: Sebastian Poxhofer <secustor@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Fable 5 <jamie.tanna+claude-code@mend.io>

[0]: https://github.com/github/actions-lockfile

* coverage

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

* fixup! feat(manager/github-actions): add support for Actions Lockfiles

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

---------

Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
2026-08-11 11:55:06 +00:00
Birger Johan Nordølum 3823ef8742 docs: fix fenced blocks (#45206) 2026-08-11 10:29:08 +00:00
Jamie Tanna 15d541461b refactor(manager): add utility for creating Artifact Error messages (#45218)
* refactor(manager); add utility for creating Artifact Error messages

To prevent ignoring linting rules for nullish coalescing, as well as for
future changes that will use this helper, we can extract out a helper
function for this.

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

* fixup! refactor(manager); add utility for creating Artifact Error messages

---------

Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
2026-08-11 10:18:20 +00:00
Bartosz Dolewski d735b9b6b8 fix(swift): support Package Registry pins in Package.resolved (#44358)
* fix(swift): allow Package.resolved pins without a `revision`

The swift manager's Package.resolved Zod schema requires
`state.revision: z.string()` on every pin. That is correct for
source-control pins (`kind: "remoteSourceControl"`), which always
have a git commit SHA, but wrong for SwiftPM Package Registry pins
(`kind: "registry"`) introduced by SE-0292: registry packages are
identified by a version alone and have no revision. As a result,
any Package.resolved that mixes source-control and registry pins
fails `PackageResolvedJson.safeParse`, `updateArtifacts` logs
`swift: could not parse Package.resolved` and returns `null`, and
Renovate silently stops writing lockfile updates on that repository.

This makes `state.revision` optional in the pin schema. The existing
`updateArtifacts` logic already guards the revision-replacement
branch with `if (newRevision)`, so registry pins are still safely
left untouched during source-control dep bumps.

Adds a regression test with a mixed-pins fixture. Before this change
that test panicked at parse time; after the change it demonstrates
the source-control pin gets updated and the registry pin is preserved
without gaining a spurious revision field.

Refs: #41534 (initial Package.resolved support, tested with
source-control pins only), #42303 (from: prefix strip).

* test(manager/swift): address review feedback on mixed-pins test

Per review on the Package.resolved mixed source-control/registry pins
test: inline the fixture into the test body, trim the comment to a
concise regression note, and assert on the parsed JSON with
toMatchObject instead of substring matching.

Co-Authored-By: Claude (Cricut Security policy) <noreply@anthropic.com>

* test(manager/swift): assert full updateArtifacts result for mixed pins

Per review: replace the parse/find/toMatchObject assertions with a
single resolves.toEqual on the whole updateArtifacts result, comparing
against the expected Package.resolved output directly.

Co-Authored-By: Claude (Cricut Security policy) <noreply@anthropic.com>

* test(manager/swift): trim mixed-pins regression comment

Apply review suggestion to shorten the comment to a single line.

Co-Authored-By: Claude (Cricut Security policy) <noreply@anthropic.com>

---------

Co-authored-by: Claude (Cricut Security policy) <noreply@anthropic.com>
2026-08-11 06:26:37 +00:00
Sebastian Poxhofer 4adc8f3725 fix(cargo): support fetching crates from git monorepo (#45142) 2026-08-10 14:30:10 +00:00
Jamie Tanna 7f40d43179 refactor(workers/repository): allow managers to opt out of digest pinning (#45198)
As part of future changes in #45190, we have found that when using
GitHub Actions' dependency lockfile, the digest pinning is manged by the
lockfile, rather than being specified in the package file itself.

To avoid a "flip flop" where using the manager removes the digest from
the package file (relying on the lockfile itself) and then a `pinDigest`
update re-adds it to the package file, we can instead follow how
`digestOneAndOnly` works and add a means to note
`digestManagedExternally`.

This isn't currently used, but allows an opt out for github-actions in
the future.

Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
2026-08-10 13:56:23 +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
Sebastian Poxhofer 1f6546b7a9 fix(versioning/cargo): convert ranges to semver in subset and intersects (#45146)
`cargo2npm` exists because a bare `1.2.3` in Cargo means `^1.2.3` and
`0.4` means `^0.4`, since caret requirements are the default. Every
range-consuming function in this module converts through it: `isValid`,
`matches`, `isLessThanRange`, `getSatisfyingVersion`,
`minSatisfyingVersion` and `getNewValue`.

`subset` and `intersects` did not. The exported `api` is built from a
`...npm` spread and never overrode them, so they received Cargo syntax
and interpreted it as semver syntax. Read that way, `1.70` means
`1.70.x` rather than `^1.70`:

    subset('1.70', '1.63')      was false, is now true
    intersects('1.70', '1.63')  was false, is now true
    intersects('1.63', '1.70')  was false, is now true

`subset` is called by `applyConstraintsFiltering`, so repositories using
`constraintsFiltering: 'strict'` had crate releases dropped whenever the
release constraint differed from the configured one. `intersects` has no
caller in this repository today, but it is part of `VersioningApi` and
was wrong in the same way.

Both are now wrapped the way `composer` does it, including the
`try`/`catch`, because the underlying semver calls throw on ranges they
cannot parse.

The module had no tests for either function, which is why this was not
caught. Both are now covered, including the throwing path.
2026-08-10 11:03:19 +00:00
Sebastian Poxhofer a2d1b8cf0a fix(manager/asdf,mise,proto): use rust-version datasource for rust (#45143)
The `rust` tool was resolved via the `github-tags` datasource on
`rust-lang/rust` with the default (semver) versioning. That meant the
release channel values rustup actually accepts were not understood.

Switch all three managers to the `rust-version` datasource, which
declares `rust-release-channel` as its `defaultVersioning`, matching the
`rust-toolchain` manager and `lib/util/exec/containerbase.ts`.

`packageName` becomes `rust` rather than the `rust-lang/rust` owner/repo
slug, which is meaningless for this datasource. It is set rather than
omitted because mise would otherwise fall back to the backend-prefixed
depName, yielding `core:rust` / `asdf:rust` as the package name.

No explicit `versioning` is set: the datasource default already applies,
and the convention in these files is to set `versioning` only to
override a datasource default.

Behaviour change: `nightly-<date>` pins were previously skipped as
`invalid-value` and now update. `stable`, `beta` and `nightly` are now
recognised as ranges rather than flagged invalid, but still only resolve
to a concrete version under `rangeStrategy: pin`.
2026-08-10 07:54:37 +00:00
Sebastian Poxhofer 183ee9caac fix(manager/rust-toolchain): report skipReason instead of dropping deps (#45144)
The manager emitted `logger.warn` four times during extraction and
returned `null` for content that is valid but not updatable. A
`rust-toolchain.toml` using `path` instead of `channel` is a legitimate
file, yet it failed schema validation and produced a maintainer-facing
warning.

Per the logging guidance in `docs/development/best-practices.md`, WARN
is consumed by metrics and error catching services, so it should not
fire for user content Renovate simply cannot update. The manager guide
also asks for a `skipReason` rather than silently dropping a dependency.

The schema now accepts an optional `channel` and an optional `path`, and
extraction reports:

- `invalid-version` when a channel cannot be parsed
- `path-dependency` when the file points at a local toolchain
- `unspecified-version` when neither field is set

`channel` takes precedence when both are present, since rustup rejects
that combination and `channel` is the actionable field.

Files that are not toolchain files at all still return `null`: TOML that
does not parse, TOML without a `[toolchain]` table, and legacy plain
text files that are empty or hold more than one line. The file pattern
matches any file named `rust-toolchain`, so these are treated as false
matches. All remaining logs are DEBUG.
2026-08-10 07:52:31 +00:00
renovate[bot] 5ca534a0c8 docs: update references to python to 3a9d2dd (main) (#45179)
docs: update references to python to 3a9d2dd

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-10 00:26:08 +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 6d2fa815b7 fix(manager/npm): quote package spec in corepack command
To prevent the possibility of a npm package 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 Opus 5 <jamie.tanna+claude-code@mend.io>
2026-08-07 14:25:41 +01:00
Jamie Tanna 3793e3bab9 fix(manager/deno): quote allow-import host list in install command
A malicious Host Rule could be crafted to inject shell metacharacters
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:25:40 +01:00
Jamie Tanna 521d325afd fix(manager/nix): quote GitHub token in flake update command
A malicious Host Rule could be crafted to inject shell metacharacters
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
Jamie Tanna 7279744cd6 fix(manager/maven-wrapper): quote distribution type in wrapper command
To prevent the possibility of the `distributionType` in a given
repository including shell metacharacters, 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
Jamie Tanna b3f7846c16 fix(manager/gradle-wrapper): quote distribution URL in wrapper command
To prevent the possibility of the `distributionUrl` in a given
repository including shell metacharacters, 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
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
Jamie Tanna ff3e99ef53 fix(manager/mix): quote hex organization and token in auth command
To prevent the possibility of an `organization` or `token` including
shell metacharacters, 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
Jamie Tanna a28ecdc122 refactor(types): clarify ToolSettings has two levels of config (#45125)
As part of future changes, we'll add options that do not require the
Global option to take precedence and/or be used as an upper limit.

To make this clearer, we can split out the options into Global and Repo
variants.
2026-08-07 12:21:13 +00:00