Via #35777, we have cases where a self-hosted user who doesn't run against
github.com leads to cases where they can't update the builtin Actions
when they're referenced by an `https://` URL.
As we already handle this for community actions, we can also handle this
for the builtin ones.
Co-Authored-By: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
Where we are able to support Java distributions that follow a
straightforward release cadence, we opt these distributions in, and skip
others as `unsupported`.
As the Temurin/Adopt distributions can be reliably tracked by the
`java-version` Datasource, backed by Adoptium, we can support them.
We can also use the `java-package` key to look up whether we want a JRE
or JDK.
Co-Authored-By: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
In the case a multi-line `dotnet-version` is specified to install
multiple SDKs at once, we skip it as `invalid-version`, as we don't
currently have a way to update multiple values in the field.
Co-Authored-By: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
Similar to how we already generate a list of the community actions we
support, we should also generate which first-party Actions from GitHub
are supported, and simplify some of the wording in the docs.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
As part of future changes, we'll be using this type more, but it's not
immediately clear that this is for the inbuilt/first-party GitHub
Actions.
Co-Authored-By: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
While looking at [0], I noticed that we didn't have support for our own
GitHub Action's configuration.
We can make sure that we support upgrading the `renovate-image` for
folks specifying an image (with optional digest) for the Renovate CLI
version to upgrade.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
While looking at [0], I noticed that we didn't have support for our own
GitHub Action's configuration.
We can make sure that we support upgrading the `renovate-version` for
the CLI version in use, whether it's quoted or unquoted (which YAML
parses as a number).
Co-Authored-By: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
[0]: https://github.com/renovatebot/github-action/issues/1035
* added support for extracting integrity and tarball from npm datasource
* test(datasource/npm): keep integrity and tarball in packument shape assertions
The packument-trimming tests on main pinned a cached shape that dropped
`dist.tarball`, so they broke once the schema started retaining
`integrity` and `tarball`. Update both expectations to the new shape and
cover `integrity` alongside `tarball`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* test(workers/lookup): expect integrity and tarball on npm updates
`generateUpdate` copies `downloadUrl` and `newDigest` from the release
onto the update, so every npm lookup in these tests now carries the
tarball URL and, where the packument fixture has one, the integrity
hash. Pin and rollback updates are built without those release fields,
so their expectations are unchanged.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Michael Kriese <michael.kriese@mend.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* feat(manager/mise): support gitlab backend
Maps the mise `gitlab` backend (e.g. `gitlab:gitlab-org/cli`) to the gitlab-releases datasource, mirroring the github backend including version_prefix support.
* refactor(manager/mise): use optional instead of Nullish for tool options
TOML has no null type, so MiseToolOptions values are only ever a string or absent. .optional() models that exactly; Nullish only adds value for sources that can emit explicit null.
* fix(manager/mise): use RegExp.escape in gitlab backend
Main switched `createGithubToolConfig` from the `escapeRegExp` util to
`RegExp.escape` and dropped the import, which left the newly added
`createGitlabToolConfig` referencing an undefined symbol after the merge.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Michael Kriese <michael.kriese@mend.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* test: close remaining line coverage gaps
A full coverage run reported three uncovered lines:
- `rez` versioning: `rez2pep440()` was never called with a plain version,
because `getNewValue()` short-circuits via `matchVersionPrecision()`
whenever the new version is valid for npm. A four-component rez version
is not, so it reaches the pep440 path.
- `nuget` v3: only the inner nuspec 404 was covered, never a 404 escaping
from the `.nupkg` download into the outer catch.
- `github` platform: the statement after `await` in the GitHub App branch
is a v8/source-map false negative - it runs, but is counted zero. The
branch used to carry the `v8 ignore` comment, which moved away with the
`ghHostname` block in #44587.
Co-Authored-By: Claude Opus 5 <michael.kriese+claude-code@mend.io>
* build: ratchet coverage thresholds
A full run now reports 100% statements (49776/49776), 100% lines
(49256/49256), 100% functions and 98.72% branches (25756/26089), so the
thresholds move up accordingly. Branches keep the same rounding-down
margin as before.
Co-Authored-By: Claude Opus 5 <michael.kriese+claude-code@mend.io>
---------
Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io>
* fix(datasource/gitlab-tags): replace getJsonUnchecked with validated getJson
The go datasource embeds GitlabTagsDatasource, so its test mocks are
updated to satisfy the stricter GitlabTag schema (commit.id/created_at).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* test: fixup tests
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Renovate deployments that are deployed across multiple organisations may
take advantage of Inherited Config as a means to decentralise some
decisions and/or preferences that their organisations would like to use
for some self-hosted configuration.
Similarly, the decision of which hosts to allowlist may be something
that a self-hosted administrator /may/ want to allow their organisation
admins to decide.
We can make this an opt-in capability to indicate that the self-hosted
administrator trusts the Inherited Config moreso, and allows someone who
can write to it the ability to allowlist access to internal hosts that
may not be intended.
If a self-hosted administrator sets `allowInternal: false`, this takes
precedence, allowing a "veto", and a self-hosted admin's `headers` are
still preferred, too.
It's not possible for Inherited Config to set grants for `extends`, as
config resolution has already occurred, so this still needs to be
performed at the self-hosted config level.
This trust is transitive: `hostRules` defined in presets the
inherited config `extends` are registered at the same inherited
tier once resolved, so this option must only be enabled when those
preset sources are trusted too.
Co-authored-by: Claude Fable 5 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
Indirectly related to our changes to Host Rules, it was noticed that we
previously did not provide as helpful an error when a config validation
error occurs with Inherited Config.
Instead of throwing a `CONFIG_VALIDATION`, without a `validationSource`,
`validationError` or `validationMessage`, we can instead throw it
accordingly.
Co-authored-by: Claude Fable 5 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
As part of looking to allow Inherit Config to manage Host Rules' grants,
we need to perform a prefactor to create an additional trust tier
between the global self-hosted administrator's config, and presets/repo
config.
The `find()` method already resolves sensitive fields - `headers`,
`enabled`, and the computed internal-host grant - a "trust tier" at a
time, so that the outcome cannot depend on how specific a rule from a
less trusted tier makes itself. The new `inherit` tier slots in between
the two we had:
- `headers` are applied untrusted first, then inherited, then the
administrator's, so theirs still win outright
- `enabled` is taken from the administrator's rules, falling back to
inherited config's, then a repository's
- an administrator's `allowInternal: false` acts as a veto: it is
resolved before inherited config's rules, and clears the scoped
and implicit grants too, so inherited config cannot re-grant the
host in any shape by out-scoping it. Meanwhile any inherited rule
naming a host in its `matchHost` - credentialed or not - now
implicitly permits it, like the admin's own rules do
We introduce a separate field than `trusted` to avoid Inherit Config
gaining the same precedence as the admin themselves.
Co-authored-by: Claude Fable 5 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
As part of recent changes to harden Host Rules, a test case was noticed
to be missing - we assume that a preset string doesn't include something
that looks like a host, but we didn't previously have a test to enforce
this.
This wasn't exploitable before our recent changes, but this test is here
to ensure we have a test covering this existing functionality.
Co-authored-by: Claude Fable 5 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
With the new hardening on blocking internal hosts with outbound HTTP
calls, we should build on top of this to ensure that the UX is better
when a preset is blocked.
We can do this by making sure that when `HOST_BLOCKED`, we report a more
targeted config validation error.
We can also make sure to pass around our `internalGrants`, similar to
how we currently allow an admin's `headers` are handled.
Co-authored-by: Claude Fable 5 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
To harden Renovate from being able to access internal hosts, we can add
a level of enforcement on all outgoing requests.
We can split this into two types of traffic:
- where the response becomes configuration (i.e. `extends`)
- where the response does not become configuration (i.e.
`customDatasources`)
To harden this, we enforce on every outbound HTTP request:
- check the resolved URL before anything, including cache lookups, can
proceed
- catching IP-literal hosts in every spelling the WHATWG URL parser normalizes
- blocking known Cloud metadata IPs, too
- a `dnsLookup` wrapper validates every address a hostname resolves to,
on every new connection, which also defeats DNS rebinding
- a `beforeRedirect` hook re-runs the URL check on each redirect
target, with the new host getting its own grant lookup rather than
inheriting the original host's verdict
We default this enforcement to `warn`, to not break existing deployments
and instead give them visibility into required configuration before a
future major version (major+1) enables `block` by default.
We'll also remove allow in a future major version (major+2), to give
time for admins to migrate over.
When a request is blocked, this degrades like an unreachable registry,
so a Renovate run isn't aborted by a blocked request.
As part of this, we can also provide a worked example of the different
cases that do/do not need allowing via `hostRules`.
Requests through an admin-configured proxy resolve DNS at the proxy, so
`dnsLookup` never runs for them, so we can resolve the hostname locally
and validate every address before the request instead.
This doesn't catch everything, especially as the proxy may resolve the
name to a different result, and if we can't resolve the name - possible
in locked-down corporate environments - we fail open.
Child processes aren't currently able to route traffic through
Renovate's HTTP layer, so are unrestricted.
Co-authored-by: Claude Fable 5 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
As part of follow-up changes, we're looking to tighten the way that
Renovate handles outgoing HTTP traffic.
Before we do this, we can introduce a new config option,
`hostRules[].allowInternal`, that allows a self-hosted administrator to
mark an internal host as "trusted" for access.
This wires in the new global-only config option, `allowInternal`, which
implies a new internal field `internalHostGrant`.
We'll add full documentation in a future commit, when the full
enforcement is in place, as there are some wider changes to enforce it
fully.
Co-authored-by: Claude Fable 5 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
As part of follow-up changes, we're looking to tighten the way that
Renovate handles outgoing HTTP traffic, and a self-hosted administrator
disabling a host needs to be something a repository cannot undo.
In a similar change to
4732da7d2b, we can resolve `enabled` per
trust tier, so that a repository or preset rule can no longer re-enable
- or disable - a host the administrator's own rules set, which was
previously possible with a longer `matchHost`.
Within a tier nothing changes: the most specific rule still wins, so a
repository disabling a host of its own keeps working, as does an
administrator masking their own broad rule with a narrower one.
This is a behaviour change for repository config that previously relied
on overriding an admin rule's `enabled`.
Co-authored-by: Claude Fable 5 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
As part of follow-up changes, we're looking to tighten the way that
Renovate handles outgoing HTTP traffic.
Before we do this, we can add helper methods to manage classification of
outgoing traffic to three "trust tiers":
- the public Internet - which is generally OK
- `internal` traffic - which should be carefully configured by a
self-hosted administrator based on their risk tolerance, and includes
loopback, RFC1918, link-local, CGNAT, multicast, unique-local and
unspecified addresses
- `metadata` traffic (i.e. to the AWS EC2 Metadata API) which should
/NEVER/ be allowed.
By splitting `metadata` out, we can always block access to them, while
allowing `internal` hosts to be accessed.
We use Node's built-in `net.BlockList` rather than adding a dependency,
which also transparently classifies IPv4-mapped IPv6 addresses (in all
their spellings) against the IPv4 rules.
Co-authored-by: Claude Fable 5 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
As part of follow-up changes, we need to have a single enforcement point
for outbound HTTP requests.
Before we do this, we can prefactor `stream()` to use the same options
preparation as `request()`.
This does lead to a slight behaviour change, wehre:
- host rule lookups for streams now use the resolved URL, whereas
previously a `baseUrl`-relative URL was passed as-is, so rules could
fail to match
- stream options are now deep-merged with the instance options, rather
than a shallow spread, matching `request()`
- a disabled host now logs a debug line on the stream path too
Co-authored-by: Claude Fable 5 <jamie.tanna+claude-code@mend.io>
* feat(config): add experimental exitCodeForErrors option
* feat(config): give unknown-error its own exit code
* docs: restore exit codes 1 and 2 to the table
Two `if` statements had their implicit else path untested:
- deleteLocalFile: the no-localDir case never ran
- getMergeConfidenceLevel: the API returning an unrecognised confidence
value never ran, so the 'neutral' fallback was untested
Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io>
pnpm v11.23 reshaped the `registries` setting in `pnpm-workspace.yaml`: it
is now keyed by the registry URL, with the scopes routed to it listed in the
entry. Renovate only accepted the older `<scope>: <url>` shape, so parsing of
the whole workspace file failed and its catalogs and overrides were no longer
extracted at all.
Accept both shapes and flatten the new one into the old one, where the bare
`@` scope is the scope-less default registry. URL keys which interpolate an
env var, embed credentials, or are unparseable are skipped, matching what
pnpm itself ignores or refuses. A `registries` value which is neither shape
now falls back to `undefined` instead of taking the file's catalogs with it.
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
test(util): cover minimatchFilter and cachePathIsFile gaps
Brings lib/util to 100% coverage:
- minimatchFilter: the closure returned on the uncached path was never
invoked, and the options-based cache key branch was never taken
- cachePathIsFile: only the "does not exist" path was tested, so
stat().isFile() never ran
Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io>
* build(deps): update dependency @redis/client to v6
| datasource | package | from | to |
| ---------- | ------------- | ------ | ----- |
| npm | @redis/client | 5.12.1 | 6.2.1 |
* fix(cache): keep RESP 2 protocol with @redis/client v6
@redis/client v6 defaults to RESP 3, which requires Redis server 6.0 or
newer and changed the default type parameters, breaking the RedisClient
type alias. Pin RESP 2 explicitly and type the client accordingly. The
switch to RESP 3 is deferred to the next major release.
---------
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: secustor <sebastian@poxhofer.at>
* feat(presets): vale package versions custom manager
Co-Authored-By: Claude Code
* fix(presets): fix lint and type errors in valeVersions tests
Co-Authored-By: Claude Code
* fix(presets): fix vale.ini file pattern to use regex delimiter syntax
Co-Authored-By: Claude Code
* test(presets): update valeVersions examples and add non-pinned case
Co-Authored-By: Claude Code
* feat(automerge): attempt branch automerge before falling back to a PR on merge queue rejection
* refactor(automerge): ask the platform instead of parsing merge queue rejection messages
* feat(gitlab): merge MRs through merge trains via the platform merge queue API
* feat(gitlab): report MRs waiting on a merge train through isPrInMergeQueue
* test(gitlab): drop targetBranch from mergePr calls
* Apply suggestion from @secustor
* refactor(gitlab): validate the merge train car response with a Zod schema
* feat(github): add experimental support for using merge queues without auto merge
* test(github): use vi.stubEnv for merge queue env flag
* fix(github): do not re-enqueue PRs already waiting in the merge queue
* refactor(github): reuse merge queue detection from #45252 for isBranchMergeQueueEnabled
* refactor(github): read the base branch from the PR instead of extending MergePRConfig
* feat(github): enable merge queue support without the RENOVATE_X_GITHUB_MERGE_QUEUE flag
* Apply suggestion from @secustor
* fix(merge-confidence): don't require auth in `platform=local`
When dry-running Renovate against a repository to validate it[0], if a
repository is using `matchConfidence`, the whole Renovate run is aborted
due to missing API credentials.
This can be frustrating, and the workaround available is to temporarily
remove all package rules use `matchConfidence`, which isn't the best
experience.
Instead, we should follow the existing pattern to return `null` when
loading a Package Rule with `matchConfidence`, as well as DEBUG logging
to inform the user why this is happening.
[0]: https://www.jvt.me/posts/2026/03/08/renovate-test-config/
* fixup! fix(merge-confidence): don't validate auth in a
With debugging from Claude to work out how to get the test to pass.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
---------
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
* feat(manager): share OCI Helm chart resolution across managers
Add getOciChartDep() to helmv3/oci.ts and use it in argocd, fleet, flux,
helmfile, helmsman, helmv3, kustomize, sveltos, terraform and vendir.
- set pinDigests: false for OCI charts in all of them
- apply registryAliases to OCI charts in argocd, helmfile and helmsman
- keep the registry port in terraform helm_release repositories
- skip fleet OCI charts without a version instead of using 'undefined'
* docs(manager/helmv3): correct the OCI chart pinDigests rationale
* refactor(manager/helmfile): drop redundant OCI repository url guard
The repository schema already requires url to be a string, so the falsy
branch could not be reached by parsed input and left the patch partially
covered.