* feat(datasource/go): look up modules from a `go-import` `mod` proxy
When interacting with a Go module, a host can advertise that a module is
served by a Go module proxy, instead of a Version Control System (VCS),
by noting the following in the `go-import` HTML meta tag:
<meta name="go-import" content="bsr.example.com/gen/go mod https://bsr.example.com/gen/go">
Previously, we only handled the `git` protocol, which would lead to
users integrating with a (private) Buf Schema Registry (BSR) not being
able to download generated Go modules.
When interacting with public Go modules on `buf.build`, these are served
successfully through `proxy.golang.org`, but a private BSR can't be
routed through the public proxy, and therefore fail to be looked up.
We should instead follow how `go` does it[0] and add support for
directly calling a `mod` proxy.
We leverage `getDirectReleases()`s' checks to make sure we don't
try and follow this flow when we're on a "known" host, i.e. if we're
pulling a module called `github.com/...` or a vanity domain package name
that resolves to `gitlab.com`.
The `?go-get=1` will keep the in-memory HTTP cache's result.
[0]: https://go.dev/ref/mod#serving-from-proxy
Co-Authored-By: Claude Opus 5.5 <jamie.tanna+claude-code@mend.io>
* fixup! feat(datasource/go): look up modules from a `go-import` `mod` proxy
fixup! feat(datasource/go): look up modules from a `go-import` `mod` proxy
Co-Authored-By: Claude Sonnet 5.5 <jamie.tanna+claude-code@mend.io>
* fixup! feat(datasource/go): look up modules from a `go-import` `mod` proxy
* fixup! feat(datasource/go): look up modules from a `go-import` `mod` proxy
---------
Co-authored-by: Claude Opus 5.5 <jamie.tanna+claude-code@mend.io>
* fix(workers/global): apply `hostRules` and `internalHostAccess` when resolving `globalExtends`
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(workers/global): resolve admin hostRules per rule for globalExtends and share the HTTP GlobalConfig keys
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Single env variables for mergeable options now combine with the value in
`RENOVATE_CONFIG` instead of replacing it: lists are appended and objects
are shallow-merged, with the env variable winning for shared keys.
Non-mergeable options are still replaced. This extends the `hostRules`
and `customManagers` handling to every mergeable option, e.g.
`packageRules`, `addLabels` and `registryAliases`.
Co-authored-by: Claude Opus 5.5 <michael.kriese+claude-code@mend.io>
* refactor(manager/gradle): add helper for matching `group:artifact` strings
As part of follow-up changes, we'll extract dependencies whose version
is declared separately from their coordinates, so we need a way to
validate a bare `group:artifact` notation. `isDependencyString` can't
be used, as it requires a version to be present.
This isn't currently used.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
* feat(manager/gradle): support rich version constraints in the Groovy/Kotlin DSL
As noted in discussion #45481, Renovate doesn't extract dependencies
whose version comes from a Gradle rich version constraint[0], so a
`strictly` pin never receives updates - not even for a security fix:
```groovy
dependencies {
implementation('org.slf4j:slf4j-api') {
version {
strictly '[1.7, 1.8['
}
}
}
```
The version catalog extractor already handles rich versions, so the
missing piece is the `version { ... }` block in the Groovy and Kotlin
DSLs.
Renovate can only rewrite a single version literal per dependency, so
we pick one constraint to update and record which one in
`managerData.versionConstraint`:
- `strictly` -> bump `strictly`
- `strictly` (single version) + `prefer` -> bump `strictly`, as `prefer`
is inert when there's nothing to choose between
- `require`, optionally with `prefer` -> bump `require`, as `prefer` is
only a hint and may not be what gets resolved
- `prefer` alone -> bump `prefer`
- `require` + `strictly` -> skip as `multiple-constraint-dep`, as Gradle
applies `require()` before `strictly()`, so bumping only `strictly`
would leave the `require` literal behind as stale text
- `strictly` range + `prefer` -> skip as `multiple-constraint-dep`, as
`prefer` has to keep pointing inside the range and we can't move both
- anything with `reject`/`rejectAll` -> skip as `unsupported-version`,
matching what the version catalog extractor already does
As `strictly` and `prefer` pin a version on purpose, updating them by
default would be surprising, so those deps are extracted with
`enabled: false` - meaning they only receive updates for vulnerability
alerts, which force through. Users who want regular updates can opt in
with a package rule matching `managerData.versionConstraint`, similar to
how `manager/gomod` handles `depType: indirect`. A `require` constraint
means the same thing as a plain version declaration, so it is updated
like any other dependency.
This doesn't unify behaviour with version catalogs, which extract a
single `require`/`prefer`/`strictly` and update it without disabling it.
Aligning them would take away updates users get today, so that's left as
a separate decision.
The `!!` shorthand (i.e. `foo:bar:1.7.25!!`) is untouched - it already
extracts as an opaque version string. Rich versions declared in the
Groovy/Kotlin `versionCatalogs { }` builder, as opposed to TOML, are
still dropped silently.
[0]: https://docs.gradle.org/current/userguide/dependency_versions.html#sec:rich-version-constraints
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
* fix(vulnerabilities): raise fixes for deps their manager disables by default
* test(workers/fetch): set packageName on disabled-dep fixtures
* test(manager/gradle): assert enabled is not set
---------
Co-authored-by: Jamie Tanna <jamie.tanna@mend.io>
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
* feat(npm): extract devEngines.runtime and devEngines.packageManager
Adds extraction for the npm devEngines field
(https://docs.npmjs.com/cli/v11/configuring-npm/package-json#devengines)
covering both single-object and array forms. Uses dot-notated depTypes
("devEngines.runtime", "devEngines.packageManager") consistent with
"pnpm.overrides", and reuses the existing engines/packageManager
datasource resolution. Items without a version are skipped.
Refs #38067.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(npm): update devEngines.runtime and devEngines.packageManager versions
Adds an update path for the new devEngines depTypes. Handles both the
single-object form and the array form (the array element is identified
via managerData.devEnginesIndex set at extraction time). Uses the same
anchored search-and-verify approach as the existing replaceAsString
(indexOf("devEngines") + dequal check), so unrelated occurrences of the
same version string elsewhere in the file are not touched.
Refs #38067.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(npm): skip lockedVersion and apply @yarnpkg/cli for devEngines deps
Extends the locked-versions post-extract step to cover the new
devEngines depTypes:
- devEngines.runtime and devEngines.packageManager are added to the
npm-lock skip list (mirrors the engines/packageManager/volta handling
added in #38598)
- devEngines.packageManager with depName "yarn" gets the @yarnpkg/cli
packageName fallback when the project is on Yarn 2+, matching the
existing behavior for engines / packageManager
Refs #38067.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(npm): harden devEngines handling against malformed input
- Register devEngines.runtime and devEngines.packageManager in
knownDepTypes (matches the existing pnpm.overrides pattern)
- Guard against null/non-object array elements in devEngines.* during
extraction so malformed JSON does not throw
- Use JSON.stringify when interpolating versions into the source search
string, so any future versions containing JSON-escaped characters are
matched correctly
- Add an extraction test for a mixed array containing a null item, a
valid entry, and a version-less entry
Refs #38067.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(npm): set hasPackageManager when devEngines.packageManager is an array
The previous hasPackageManager check used isNonEmptyObject which returns
false for arrays. Now that the array form of devEngines.packageManager
is actually extractable and updatable, the corepack post-update step
needs to be triggered for those users as well. Introduces a shared
hasDevEnginesPackageManager helper and uses it from both
extractPackageJson and extractPackageFile.
Refs #38067.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(npm): require at least one non-empty array item for hasPackageManager
Align the array branch of hasDevEnginesPackageManager with the
single-object branch by requiring at least one non-empty object item.
Previously, an array containing only null/empty entries would set
hasPackageManager to true and trigger corepack post-update even though
no usable item exists. Add coverage for the empty-array and
only-invalid-items cases.
Refs #38067.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test(npm): document hasPackageManager semantics for stray-key array items
Make the chosen semantic explicit: an array element with arbitrary keys
but no `name` (e.g. `[{ foo: 'bar' }]`) still sets hasPackageManager to
true, mirroring the pre-existing single-object behavior. The extract
step independently filters out items lacking `name`/`version`.
Refs #38067.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test(npm): cover dequal rejection in devEngines array update
Adds a test where two devEngines.packageManager array items share the
same version string. The first source-level match belongs to the wrong
index, so the dequal verification rejects it and the loop continues to
the correct occurrence. This exercises the false branch of the dequal
check in updateDevEnginesDependency.
Refs #38067.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(node): list devEngines.runtime as a supported field for Node.js
The npm manager now updates the version inside devEngines.runtime in
package.json, so include it in the file-support list alongside engines
and volta.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Apply the comment changes suggested in the code review
Co-authored-by: Michael Kriese <michael.kriese@gmx.de>
* test(npm): cover devEngines update error path instead of ignoring it
Remove the v8 ignore on the updateDevEnginesDependency catch and add a
test that reaches it with invalid JSON, matching how the main
updateDependency catch is covered.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(npm): drop unnecessary spread fallback in devEngines managerData
Object spread ignores null/undefined, so the `?? {}` fallback is
redundant. Removing it satisfies the oxlint no-unnecessary-spread-fallback
rule that now runs in CI.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(npm): type devEnginesIndex on NpmManagerData
Declare devEnginesIndex on NpmManagerData so the value no longer needs a
`as number | undefined` cast when reading it back during update.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(node): document package manager version fields
List packageManager and devEngines.packageManager separately from the Node.js runtime file support entries.
Co-authored-by: Codex <noreply@openai.com>
* feat(npm): support Bun and Deno devEngines runtimes
* fix(npm): preserve Corepack hashes in devEngines
* test(npm): use partial helper for devEngines fixture
Co-authored-by: Codex <noreply@openai.com>
* fix(npm): warn on invalid devEngines update state
Co-authored-by: Codex <noreply@openai.com>
* fix(npm): include devEngines in extracted tool constraints
Co-authored-by: Codex <noreply@openai.com>
* fix(npm): prefer devEngines over volta for package manager versions
Co-authored-by: Codex <noreply@openai.com>
* fix(npm): update Yarn binaries for devEngines package manager upgrades
Co-authored-by: Codex <noreply@openai.com>
* fix(npm): recognize devEngines package managers for Yarn catalogs
Co-authored-by: Codex <noreply@openai.com>
* fix(npm): exclude devEngines from Yarn locked versions
Co-authored-by: Codex <noreply@openai.com>
* refactor(npm): reuse Bun extraction for devEngines runtime
Co-authored-by: Codex <noreply@openai.com>
* test(npm): cover Yarn devEngines manifest preservation and grouped updates
Co-authored-by: Codex <noreply@openai.com>
* refactor(npm): pass packageJsonResult directly to hasDevEnginesPackageManager
Co-authored-by: Michael Kriese <michael.kriese@gmx.de>
* test(npm): simplify malformed devEngines fixture
Co-authored-by: Codex <noreply@openai.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Codex <noreply@openai.com>
In a similar way to how `allowedEnv` works, we should allow a
self-hosted admin to specify whichever headers they wish in their
`hostRules` - whether in their global config, a `repositories[]` entry,
or a preset a `repositories[]` entry extends.
Previously, this would require a self-hosted admin to add any header
they wished to set to `allowedHeaders`, which would also allow any of
their users' repositories to set that same header.
We can align this behaviour with `allowedEnv`, which makes sure that
the admin's own `headers` are always applied regardless of
`allowedHeaders`, while a repository's own `hostRules` - and those of
any preset it extends - remain constrained by it as before.
We make sure to use an explicit `[]` to make it clear when there are no
headers to allow, opposed to using something less clear like
`undefined`.
We do not currently allow an `extends` (without a `repositories[]`
entry) to bypass, and they'll be followed-up with in #45670.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
Exposes the isBreaking flag that lookup already computes per upgrade as a
native packageRules matcher, so it can be combined with matchJsonata
selectors from extended presets instead of being inlined into them.
Exposes Renovate's string pattern matching (globs, regex, negation) to
matchJsonata expressions, so a single expression can OR conditions on
different fields such as packageName and registryUrls.
To make sure this is more readable in our dark mode theme, we can add a
dark variant, which is automagically shown.
As it's an `<object>` not an `<img>`, we need to add a specific CSS
rule, as we can't use Material for MkDocs' `img#only-light` or
`img#only-dark`.
This also requires that we set `color-scheme: and `background-color:
transparent` to ensure that it blends into the background, otherwise we
see white edges in dark mode.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
To make sure that we're more consistent in our colour branding with
Mend Renovate's colour scheme, we can override our theme to use the
correct blues.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
* docs: fix images rendered as code inside figure blocks
The docs build forces tab_length 2, so content indented by two spaces
inside a <figure markdown> block is parsed as an indented code block.
Six images were printed as literal markdown instead of being rendered.
De-indent the six figure blocks and add a test that fails if indented
content reappears inside one.
* chore: add markdownlint rule for indented figure content
Replace the vitest check with a markdownlint custom rule. It runs with
pnpm markdown-lint, reports file and line like any other markdown
violation, and uses the micromark tokens so a <figure markdown> block
inside a fenced code sample is not flagged.
* Revert "chore: add markdownlint rule for indented figure content"
This reverts commit b853804501.
* chore: remove test
As part of follow-up changes in #45706, we want the `apk` / `apt`
parsing in the `dockerfile` manager to attempt to determine which
distribution - and therefore registry - to look up dependencies for.
When there is an image that we don't know how to resolve, we want to
treat them as a `skipReason: unknown-registry`.
However, this doesn't provide any way for the user to say "I know which
registry you should look up updates for".
To handle this, we can treat `unknown-registry` differently, allowing it
to un-skip itself when there are any `registryUrls`s defined.
This allows for general usage, where if Renovate doesn't know how to
interact with a given registry, but a user does, then the user can
override the registry with a `packageRules` entry.
We continue skipping a dependency when `unknown-registry` is set
alongside a dependency's `registryUrl`.
We add this un-skipping logic into `applyPackageRules()`, but need to
make sure that we also gate it inside `lookup()`, so a dependency that's
passed through `applyPackageRules()` is re-checked to ensure that the
check is enforced.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
As noted in #45839, we're currently out-of-sync with the current list,
so should get this automagically updated.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
With help from Claude to correctly render it as an SVG (that can have
URLs that are clickable) and render it so it's more responsive.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
* feat(config): add minimumReleaseAgeBuffer option
Adds a new config option which extends the time Renovate waits before
suggesting an update by a percentage of minimumReleaseAge. This gives
companion packages that are published after the main package (e.g.
platform-specific binaries) time to pass the package manager's own
release age cooldown, avoiding lock file artifact errors.
* feat(config): make minimumReleaseAgeBuffer a duration with 10 minutes default
* feat(config): raise minimumReleaseAgeBuffer default to 30 minutes
fix(github): attempt direct merge before falling back to the merge queue
PR automerge against a merge-queue-protected base branch could no longer
merge directly when the authenticated actor is allowed to bypass the
queue: mergePr() enqueues the PR unconditionally once the base branch has
a merge queue, and the enqueuePullRequest mutation evaluates queue-entry
requirements (e.g. required code-owner review) without honoring ruleset
bypass, leaving bypass-enabled installs unable to merge at all.
Attempt the direct REST merge first and enqueue only when that merge is
refused, mirroring the try-first design #45724 shipped for branch
automerge. Repositories without a bypass actor pay one refused REST merge
call per automerge attempt before the queue fallback, and up to four when
an unrecognized refusal message triggers method guessing.
Docs: describe the direct-merge-first behavior in the GitHub merge queue
section of the automerge documentation.