2087 Commits

Author SHA1 Message Date
Michael Kriese 4ebd20edc9 feat(util/exec): look up jb versions from containerbase/jb-prebuild (#47303)
Co-authored-by: Claude Opus 5.5 <michael.kriese+claude-code@mend.io>
2026-10-23 11:28:22 +00:00
Jamie Tanna 1deb80ecaa chore(util/exec): correct typo in constraints (#47304) 2026-10-22 14:45:43 +00:00
renovate[bot] 1a80c538f8 build(deps): update dependency got to v16.1.0 (main) (#47214)
* build(deps): update dependency got to v16.1.0

| datasource | package | from   | to     |
| ---------- | ------- | ------ | ------ |
| npm        | got     | 16.0.0 | 16.1.0 |

* fix(util/http): adapt to got 16.1 types

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

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Kriese <michael.kriese@mend.io>
Co-authored-by: Claude Opus 5.5 <michael.kriese+claude-code@mend.io>
2026-10-22 11:30:06 +00:00
Michael Kriese dff2bd5068 refactor(util/exec): use isContainerbase from the base image package directly (#47247)
* refactor(util/exec): use isContainerbase from the base image package

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

* refactor(util/exec): read CONTAINERBASE from the process environment only

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

* refactor(util/exec): use isContainerbase from the base image package directly

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

---------

Co-authored-by: Claude Opus 5.5 <michael.kriese+claude-code@mend.io>
2026-10-21 11:07:04 +00:00
Michael Kriese 320f770c36 fix(cache): hash URL credentials in cache keys
Co-Authored-By: Claude Fable 5.1 <michael.kriese+claude-code@mend.io>
Co-Authored-By: Claude Opus 5 <michael.kriese+claude-code@mend.io>
Co-Authored-By: Claude Opus 5.5 <michael.kriese+claude-code@mend.io>
2026-10-20 09:05:00 +01:00
Michael Kriese 9e46e31f32 fix(http): persist only an allow-list of response headers in the http caches
Co-Authored-By: Claude Fable 5.1 <michael.kriese+claude-code@mend.io>
Co-Authored-By: Claude Opus 5.5 <michael.kriese+claude-code@mend.io>
2026-10-20 09:05:00 +01:00
Sebastian Poxhofer 0070fc5e6a refactor: remove unused exports and types (#47130)
Found with knip.
2026-10-17 09:10:12 +00:00
RahulGautamSingh df201a98ff fix(util/exec): pick tool releases compatible with their parent tool version (#47090)
* fix(util/exec): pick tool releases compatible with resolved node version

* refactor(util/exec): pass resolved runtimes as an object

* refactor(util/exec): match tools against their containerbase parent

* test(util/exec): run real constraints filtering for parent versions
2026-10-16 08:13:04 +00:00
Michael Kriese 969b3cb162 fix(util/git): use non-empty passwords for token credentials on more platforms (#47085)
* fix(util/git): use non-empty passwords for token credentials on more platforms

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

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

* docs: update git token host rule notes

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

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

---------

Co-authored-by: Claude Sonnet 5.5 <michael.kriese+claude-code@mend.io>
2026-10-15 13:42:10 +00:00
Michael Kriese a9677c36f4 fix(util/git): use a non-empty password for token-only git credentials (#47077)
* fix(util/git): use a non-empty password for token-only git credentials

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

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

* fix(util/git): pick token credentials from the host platform for manager host rules

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

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

---------

Co-authored-by: Claude Sonnet 5.5 <michael.kriese+claude-code@mend.io>
2026-10-15 12:06:10 +00:00
Jamie Tanna 1dce2f8ed0 feat(util/http): fall back to go host rules for go-proxy requests (#47043)
* fix(util/http): fall back to `go` host rules for `go-proxy` requests

Prior to 5665570f0b, all requests made by
the `go` Datasource - including those to a Go module proxy - used the
`go` host type.

When we refactored them into classes, this introduced the ability to
specify a `go-proxy` host type, which would only be used for direct
access to the Go module proxy.

As this isn't documented - and may change in the future - we can add a
fallback to the credentials for `hostType: go`, similar to how i.e.
`gitea-tags` and `gitea` do the same.

Co-Authored-By: Claude Opus 5.5 <jamie.tanna+claude-code@mend.io>

* fixup! fix(util/http): fall back to `go` host rules for `go-proxy` requests

Co-Authored-By: Claude Sonnet 5.5 <jamie.tanna+claude-code@mend.io>

* fixup! fix(util/http): fall back to `go` host rules for `go-proxy` requests

---------

Co-authored-by: Claude Opus 5.5 <jamie.tanna+claude-code@mend.io>
2026-10-15 09:48:27 +00:00
Michael Kriese 4dc30ea9bc fix(http): share concurrent identical cache provider requests (#46627)
* fix(http): share concurrent identical cache provider requests

Identical requests that use a cache provider and run at the same time now
share one in-flight request instead of each fetching from the server.
Callers that join an in-flight request get a deep copy of the response.

This replaces the per-URL mutex, which only covered the cache check and
was released before the fetch finished.

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

* fix(http): reuse cache providers for npm and typst lookups

The npm and typst datasources now use one module-level cache provider, so
concurrent lookups of the same package share one request. The request key
is only hashed for GET and HEAD requests and includes `throwHttpErrors`.

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

* fix(http): don't share requests that differ in response type

Add `responseType` and `responseBecomesConfig` to the key of shared
requests, and test that requests with different headers aren't shared
and that a shared response is copied for every caller.

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

* fix(http): keep in-flight requests per Http class and copy binary bodies

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

---------

Co-authored-by: Claude Opus 5.5 <michael.kriese+claude-code@mend.io>
2026-10-13 15:38:10 +00:00
Aleksandr Mezin 911b681cc5 feat(datasource/rpm): support zstd compressed "primary" files (#46372)
* feat(datasource/rpm): support zstd compressed "primary" files

* Improve util tests

* Improve tests, remove unnecessary .destroy() call
2026-10-12 15:46:43 +00:00
Michael Kriese f64ec3975a fix(cache): build all cache keys with a shared helper (#46811)
* refactor(datasource): separate registry URLs in cache keys with a colon

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

* fix(datasource/go): separate the remaining cache key parts with a colon

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

* refactor(datasource): build cache keys with a shared colon-joining helper

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

* refactor: build all cache keys with buildCacheKey

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

* refactor(http): keep GET package cache keys as the bare URL

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

* refactor(cache): extend cache key helper to memory cache keys

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

* refactor(datasource/go): prefix the goproxy cache keys with their purpose

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

---------

Co-authored-by: Claude Opus 5.5 <michael.kriese+claude-code@mend.io>
2026-10-10 10:46:09 +00:00
Jamie Tanna 7027ee5ced fix(util/exec): add a strong type for Containerbase's known tools (#46580)
* chore(util/exec): add a strong type for Containerbase's known tools

As noted in #41849, we currently don't have a way of enforcing the usage
of a `ContainerbaseToolName` being a tool that Containerbase actually
knows.

To handle this, we can use the new `@containerbase/base` and
`@renovatebot/base-image` packages to see what Tools we currently have
support for, and make sure that our types use the tools supported by
`@renovatebot/base-image` (and therefore `@containerbase/base`).

As well as the Typescript compilation error a user will receive, we can
add a test that provides a better note to the user about how to add a
new tool.

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

* fixup! chore(util/exec): add a strong type for Containerbase's known tools

* fixup! chore(util/exec): add a strong type for Containerbase's known tools

So we can get better confidence that we're not clashing with type names
between Containerbase tools and non-tool constraints.

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-10-09 12:12:53 +00:00
renovate[bot] d1fd5df4bc build(deps): update dependency simple-git to v4 [security] (main) (#46781)
* build(deps): update dependency simple-git to v4 [security]

| datasource | package    | from   | to    |
| ---------- | ---------- | ------ | ----- |
| npm        | simple-git | 3.36.0 | 4.0.1 |

* fix(git): adapt to simple-git v4 environment guard

Allow the environment Renovate passes explicitly, use a dedicated instance for
authenticated submodule updates and allow url.insteadOf rewrites used by host
rules authentication.

* fix(deps): override @simple-git/argv-parser to v2.0.1

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: secustor <sebastian@poxhofer.at>
2026-10-08 07:51:45 +00:00
Michael Kriese 2ca2bc0ba0 fix(exec): re-run install-tool when switching back to an earlier tool version (#46823)
`install-tool` installs a version and also makes it the active one. The
memo skipped `install-tool` for any tool version already installed in the
run, so after A -> B -> A the last command ran on B. Track the active
version per tool instead and skip only when the requested version is
already active.

Co-authored-by: Claude Opus 5.5 <michael.kriese+claude-code@mend.io>
2026-10-07 16:15:34 +00:00
Sebastian Poxhofer 101cb08b4e feat(datasource): report the datasource which served a lookup (#46808)
* feat(datasource): report the datasource which served a lookup

A datasource which delegates a lookup to another one, such as the go datasource to github-tags, returns the delegate's id as effectiveDatasource. The lookup copies it onto the update result, so that templates, matchJsonata and logs can tell which path answered.

* Update lib/util/template/index.ts

* style(template): format the effectiveDatasource description
2026-10-07 14:57:25 +00:00
Jamie Tanna 4a0935d711 fix(util/exec): remove java-maven tool (#46587)
As it's not an official tool Renovate supports, and was added for
Mend-internal usage.

However, as we work towards #41849, we should make sure that we don't
document a tool that isn't used by Renovate.
2026-10-07 12:02:27 +00:00
Sebastian Poxhofer 42805afe66 refactor(datasource): share the GitLab URL helpers across the GitLab datasources (#46188) 2026-10-07 07:07:08 +00:00
Michael Kriese 9788f3698d refactor(manager): type manager data of the remaining managers (#46639)
* refactor(manager): type manager data of the remaining managers

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

* refactor(manager): type flux deps from shared helpers and require ansible collection names

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

---------

Co-authored-by: Claude Fable 5.1 <michael.kriese+claude-code@mend.io>
2026-10-07 06:31:47 +00:00
RahulGautamSingh 215433f311 fix(vulnerabilities): raise fixes for deps their manager disables by default (#46761) 2026-10-05 12:46:38 +00:00
Michael Kriese a58b413742 fix(http): deep copy buffer bodies in copyResponse (#46752)
A deep copy of a `Uint8Array` body used `subarray()`, which returns a view
of the same memory, so changing the original also changed the copy. Use
`slice()`, which copies the bytes.

Co-authored-by: Claude Opus 5.5 <michael.kriese+claude-code@mend.io>
2026-10-05 10:16:51 +00:00
Michael Kriese c503e44adc fix(cache): handle redis client connection errors (#46754)
The Redis package cache client had no `error` listener. node-redis emits
connection errors, such as an idle socket closed by the server, as
`error` events and reconnects on its own, but an unhandled `error` event
exits the process. Log them instead: once as a warning, every time at
debug level.

Co-authored-by: Claude Opus 5.5 <michael.kriese+claude-code@mend.io>
2026-10-05 09:42:23 +00:00
Michael Kriese f3ec5e6b51 fix(http): skip throttle and queue for cached responses (#46622)
Responses served by the cache provider's `bypassServer` no longer wait
for a `maxRequestsPerSecond` throttle slot or a concurrency queue slot.
Only requests that reach the server are throttled and queued.

Co-authored-by: Claude Opus 5.5 <michael.kriese+claude-code@mend.io>
2026-10-01 08:43:58 +00:00
Jamie Tanna 8b3a066756 test: remove redundant hostRules.clear() calls (#46584)
As we're now managing them via a `afterEach` in `test/setup.ts`, we can
remove any entries in tests themselves.

We don't update overrides of an outer hook or cases where there are more
explicit `clear()`s.

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-09-30 11:22:18 +00:00
Jamie Tanna a2704ed3f1 test: always clear hostRules after each test (#46582)
Instead of needing to always make sure that we've cleared host rules in
tests that use them - or knowing when they're touched indirectly - we
can make sure that we have an `afterEach` that will clear our Host
Rules.

We can do this by making sure that we have a top-level `afterEach` that
handles this, which needs a dynamic import to avoid eagerly importing
and caching it, which would leave stale unmocked bindings for a given
file's test run.

We also need to make sure that `private-key.spec.ts`'s `sanitize.ts`
mock is updated to also stub `clearRepoSanitizedSecretsList`, since
`hostRules.clear()` now calls.

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-09-30 11:22:18 +00:00
Jamie Tanna af055eba22 feat(config): allow self-hosted admins to bypass allowedHeaders (#45654)
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>
2026-09-29 10:37:15 +00:00
renovate[bot] 1909c2ef22 build(deps): update dependency execa to v10 (main) (#45834)
* build(deps): update dependency execa to v10

| datasource | package | from  | to     |
| ---------- | ------- | ----- | ------ |
| npm        | execa   | 8.0.1 | 10.0.1 |

* fix(exec): adapt to execa v10 types and subprocess API

* fix(tools): type execa v10 results in hook exec and mkdocs

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: secustor <sebastian@poxhofer.at>
2026-09-25 09:00:52 +00:00
Sebastian Poxhofer 18eb38c2bd feat(config): add matchIsBreaking package rule option (#46449)
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.
2026-09-24 20:09:29 +00:00
Sebastian Poxhofer df021966a5 feat(jsonata): add $matchRegexOrGlob custom function (#46448)
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.
2026-09-24 20:03:35 +00:00
Michael Kriese 0efc05f025 fix(reconfigure): cache a flag instead of the unused extract result (#46441)
* fix(reconfigure): cache a flag instead of the unused extract result

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

* fix(reconfigure): migrate a cached extract result to the new flag

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

---------

Co-authored-by: Claude Opus 5.5 <michael.kriese+claude-code@mend.io>
2026-09-24 12:47:57 +00:00
Michael Kriese facc6423f7 fix(cache): clean up the HEAD http cache like the GET one (#46436)
Co-authored-by: Claude Fable 5.1 <michael.kriese+claude-code@mend.io>
2026-09-24 08:52:34 +00:00
Michael Kriese e144d8dbc1 fix(http): validate the cached response shape in the http cache schema (#46417)
refactor(http): validate the cached response shape in the http cache schema

Co-authored-by: Claude Fable 5.1 <michael.kriese+claude-code@mend.io>
2026-09-23 14:12:16 +00:00
Sergei Zharinov ac2fc77641 refactor(http-mock): Remove request tracing (#44482)
* refactor(http-mock): remove request tracing

* test: replace remaining HTTP trace assertions
2026-09-23 09:01:01 +00:00
Sebastian Poxhofer 1e6ffa8171 refactor(datasource): add cached() helper to the Datasource base class (#46102)
Every datasource that caches its releases hand-wrote the same
`withCache({ namespace: `datasource-${id}`, ... }, () => this._getReleases(config))`
wrapper, repeating the namespace literal and using underscore-prefixed
method names that `docs/development/best-practices.md` discourages.

Add `Datasource.cacheNamespace` (derived from the datasource id) and a
protected `Datasource.cached()` helper that defaults `namespace` to it,
exporting `CachedOptions` from `with-cache.ts`. Migrate 29 datasources
onto the helper, dropping their namespace literals, the static
`cacheNamespace` field in `github-digest`, and renaming the wrapped
`_getX` methods to `fetchX`.

Behaviour change: `golang-version` used the constant cache key `'all'`
while declaring `customRegistrySupport = true`, so a custom registryUrl
shared the cache entry with the default one. The key is now
`${config.registryUrl}`, which invalidates existing entries once.
2026-09-22 19:30:25 +00:00
Jamie Tanna 3b70d5ffe2 test(utill/git): add 30s timeout to beforeAll (#46386)
So we don't have tests exiting early when on i.e. a slower GitHub
Actions machine.
2026-09-22 15:03:15 +00:00
Sebastian Poxhofer 853290db9c refactor(http): read platform families instead of the host type aliases (#46347)
`lib/util/http/auth.ts` and `lib/util/http/host-rules.ts` were the last
readers of the `*_API_USING_HOST_TYPES` constants, which the previous
commits left as aliases of `PLATFORM_FAMILIES`. Both now read the table
directly and the aliases are deleted, so each family's host types are
declared in exactly one place.

Also covers the `forgejo` fallback in `findMatchingRule()`, which had no
test: the shared setup only registers a `gitea` host rule, so the
forgejo branch was never entered.

Behaviour changes: none. The aliases pointed at the same arrays.
2026-09-21 15:27:53 +00:00
Sebastian Poxhofer 0583e54718 refactor(constants): add a platform family capability table (#46191)
* refactor(constants): add a platform family capability table

Every consumer of `detectPlatform` carried its own mapping from the
detected platform to a tags datasource or a web UI path, and the seven
`*_API_USING_HOST_TYPES` arrays were checked one by one to produce that
platform in the first place.

Introduce `PLATFORM_FAMILIES`, one record keyed by family holding the
host types, the hostnames which identify the family outright, the tags
datasource, the API base URL derivation and the web UI path to a
directory at the default branch. A family is a group of platforms, so
the ids are checked against `PlatformId`: a family which is not a
platform is a compile error. Not every platform is a family, because
codecommit, gerrit, local and scm-manager are never recognized from a
URL.

`detectPlatform` loops the table for both its hostname and its hostType
matching, and the consumers look their answers up:

- `github-actions` and `pre-commit` read `tagsDatasource` instead of
  importing the tags datasource classes.
- The PR body reads `webDirPath` instead of special-casing Bitbucket and
  Bitbucket Server.

`apiBaseUrl` has no consumer yet; the changelog sources pick it up in
the next commit.

`lib/util/http/auth.ts` and `lib/util/http/host-rules.ts` still read six
of the old arrays by name, so those stay as aliases of the table and are
migrated in a follow-up. `AZURE_API_USING_HOST_TYPES` had no other
consumer and is dropped.

Behaviour changes: none. `detectPlatform` now tests every known hostname
before its name heuristics instead of interleaving the two, which is
equivalent because the hostname lists are pairwise disjoint and no known
hostname contains the name of another family.

* Apply suggestion from @secustor
2026-09-21 15:27:50 +00:00
Sebastian Poxhofer 8f5f238b8f fix(datasource/crate): skip the web API of registries that do not implement it (#46329)
* fix(datasource/crate): only query the crates.io web API for crates.io

Private sparse registries such as Artifactory or CodeArtifact advertise an
`api` URL in their `config.json` for publishing, but do not implement the
crates.io-only read endpoints `api/v1/crates/<name>` and
`api/v1/crates/<name>/<version>`. Since #41536 Renovate called both for
every registry with an `api` field, producing 404s and a
"Release interceptor failed" warning on each run.

Restore the crates.io flavor guard for the crate metadata lookup and the
release timestamp lookup. Reading `config.json` from a cloned registry is
now unreachable, so drop that branch.

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

* docs(datasource/crate): cite the registry web API specification in the guards

* fix(datasource/crate): probe the registry web API once instead of guarding on flavor

Keep the crates.io read endpoints for registries that implement them.
Registries whose config.json points `api` at crates.io, such as index
mirrors, are used without probing. Any other registry is probed on the
first crate; a 404 for a crate that the index just returned means the
endpoint does not exist, so the registry is remembered as unsupported in
the memory cache and, for a day, in the package cache. The release
timestamp lookup handles a 404 the same way instead of surfacing the
generic "Release interceptor failed" warning.

Restores the cloned config.json branch, since cloned registries can now
advertise an API again.

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

* fix(datasource/crate): key the unsupported web API marker by the api URL

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 07:29:50 +00:00
Jamie Tanna 8dc06640a7 feat(workers/repository): allow users to bypass registryUrl when unknown-registry (#46323)
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>
2026-09-18 15:59:57 +00:00
Sebastian Poxhofer 17466ceb32 fix(host-rules): ignore URL credentials when matching matchHost (#46128)
feat(host-rules): ignore URL credentials when matching matchHost

`matchesHost()` compared the raw href of the searched URL against
`matchHost`, so a URL carrying `user:pass@` userinfo (often a literal
placeholder such as `${USER}:${PASS}@`) never matched a `matchHost`
without credentials, including path-scoped ones. Callers worked around
this by stripping `username`/`password` off the URL by hand before
calling `hostRules.find()`.

- Add `stripUrlCredentials()` to `lib/util/url.ts`, returning the URL's
  `href` without userinfo (or `null` if unparseable), covered by
  `lib/util/url.spec.ts`.
- `matchesHost()` in `lib/util/host-rules.ts` now strips credentials
  from the searched URL before comparing it against an HTTP(S)
  `matchHost`, so `hostRules.find()` ignores userinfo on every caller's
  URL. Covered by new cases in `lib/util/host-rules.spec.ts` (a
  `matchHost` rule matches a URL carrying `user:pass@`, including a
  path-scoped `matchHost`).
- Remove the hand-rolled strip in
  `lib/modules/datasource/pypi/host-rules.ts`'s
  `findPypiIndexCredentials()`, now redundant since `find()` does it.
  `lib/modules/datasource/pypi/host-rules.spec.ts` already covers this
  behaviour and needed no changes.

This is strictly additive: more URLs match `matchHost` than before,
and nothing that matched before stops matching.
2026-09-18 10:53:12 +00:00
Michael Kriese 654431d69f test(util/git): share one clone across the read-only tests (#46287)
* test(util/git): skip the per-test clone for tests that need no repo

The spec's `beforeEach` rebuilds a bare clone and calls `initRepo()`
before every test, which costs about 0.7s each. Eight tests never touch
a repository at all -- `createSimpleGit`, `gitRetry`, `validateGitVersion`
and `getUrl` -- yet each paid for that clone. They now sit in a second
root describe with no clone in it, so the file drops from about 129s to
about 121s with the same 144 tests.

The two blocks that are pure functions are marked `describe.concurrent`.
The other two stay sequential: `createSimpleGit` spies on a prototype and
sets the custom env, and `gitRetry` stubs `NODE_ENV`.

This was the outcome of trying `it.concurrent` across the file. It cannot
help there, for two reasons stacked on each other. Vitest still runs
`beforeEach` for every concurrent test, so concurrency does not remove
the clone, it only interleaves several of them. And those interleaved
clones all write the same module singleton (`config`, `git`,
`gitInitialized`) and `GlobalConfig.localDir`, so one test's `initRepo()`
is overwritten by another's before its body runs. The only lever that
works is not running the clone for tests that do not need it.

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

* test(util/git): share one clone across the read-only tests

The spec now has one root describe with three nested groups, split by how
much git setup a test needs:

- `without a repository`: pure functions, no setup at all.
- `shared clone`: 32 read-only tests. One bare clone of `base` and one
  `initRepo()` in `beforeAll`, so each test costs only the git commands
  it runs itself.
- `clone per test`: the tests that commit, push, check out or re-init.
  They keep the fresh clone and `initRepo()` per test.

The `base` repository moves up to the root describe so both clone groups
can use it. Groups run in file order, and some of the writing tests change
`base` without restoring it, so the shared-clone group has to stay ahead.

`isBranchModified()` stays with the writing tests although it never touches
the repository: it caches per-branch results in `config.branchIsModified`,
which only `initRepo()` clears, and its tests query the same branch with
different ignored authors.

Three describes are split by test: `getFileList`, `getBranchUpdateDate`
and `diffCommitTree` each have one test that writes, which stays behind
under the same describe name with a pointer to the read-only half.

Same 144 tests; the file drops from about 121s to about 100s.

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

* test(util/git): keep the 30s test timeout for every test

The `{ timeout: 30000 }` option used to sit on the single root describe
and so covered every test in the file. The split left it on the
`clone per test` group only, which put the 32 shared-clone tests on the
5s default even though they still run real git commands. CI is a lot
slower than a local machine, so the option moves up to the root describe
again; nested describes inherit it.

Hooks are unaffected either way: they run under `hookTimeout`, not the
suite option, and the shared `beforeAll` does the same work the old
`beforeEach` did.

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

* test(util/git): reuse one clone for the local-only writers

A fourth nested group, `reused clone`, holds the 36 tests that write to
the local checkout but never to `origin` or `base`: `checkoutBranch`,
`isBranchModified`, `mergeToLocal`, `isFileModeEnabled`,
`getCommitMessages`, `setGitAuthor`, `getRepoStatus`, `fetchRevSpec` and
single tests of `getBranchUpdateDate`, `mergeBranch`, `deleteBranch` and
`diffCommitTree`.

The group clones once, but `initRepo()` and `syncGit()` run again before
every test. On an existing checkout `syncGit()` takes its fetch path:
`fetch --prune`, `reset --hard`, `checkout` of the default branch,
`clean -fd` and deletion of every other local branch. With the fresh
`config` from `initRepo()` that undoes everything such a test can do to
the repository or the module singleton, including the per-branch
`branchIsModified` cache that kept `isBranchModified()` out of the
shared-clone group. Local git config is the one thing it leaves alone, so
the `beforeEach` re-sets the author that `setGitAuthor()` writes.

That reset costs about 0.35s per test against about 0.87s for a clone, so
the file drops from about 100s to about 87s. Same 144 tests.

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

* test(util/git): trim the describe comments to the essentials

Review feedback: the block comments read more like a narration of how
the layout came to be than like documentation. Each now states only
what a group's setup is, what a test may or may not do to belong there,
and the ordering constraint about `base`. The explanation of the
`isBranchModified()` cache is gone too, since that test now runs with a
fresh `initRepo()` in the reused-clone group.

Comments only, no test changes.

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

* test(util/git): move isBranchModified() into the shared-clone group

`isBranchModified()` only reads the repository, but it stores results in
`config.branchIsModified`, which only `initRepo()` cleared. That kept its
16 tests in the reused-clone group at about 0.35s each.

A new `clearBranchIsModifiedCache()` helper, marked `@internal`, clears
that store. The shared-clone `beforeEach` calls it along with the cheap
config setters (`setUserRepoConfig`, `setGitAuthor`,
`setPlatformIgnoredAuthors`), so those tests now share one `initRepo()`
and cost a few milliseconds each. The file drops from about 87s to about
83s.

A dynamic import with `vi.resetModules()` was considered instead: a fresh
module instance has no `config` and `gitInitialized = false`, so every
test would need its own `initRepo()` and `syncGit()` on it, which is the
reused-clone cost again plus re-importing the module graph.

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

---------

Co-authored-by: Claude Fable 5.1 <michael.kriese+claude-code@mend.io>
2026-09-18 10:28:42 +00:00
Sebastian Poxhofer 4215f35059 feat(config): add minimumReleaseAgeBuffer option (#45577)
* 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
2026-09-17 07:08:00 +00:00
Menco Bolt 3abfaacabc feat(util/template): Add uppercase helper (#46205)
Add uppercase to template

Co-authored-by: Menco Bolt <133383+macmenco@users.noreply.github.com>
2026-09-16 13:27:56 +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 312c380926 test(manager): cover the pre-commit warning switch and drop unreachable fallbacks (#46221)
* fix(util/http): make the legacy `headers` getter configurable

Every other property defined on `HttpError.prototype` in this file is
`configurable`, but `headers` was not. That makes the module fail with
`TypeError: Cannot redefine property: headers` whenever a test resets the
module registry and re-imports anything that pulls in `got.ts`.

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

* test(manager/pre-commit): cover the suppress-warning env var

`defaultConfig.prBodyNotes` drops the unsupported-manager warning when
`RENOVATE_X_SUPPRESS_PRE_COMMIT_WARNING` is set. Since the value is
computed at module load, the new spec resets the module registry and
re-imports the manager with the variable stubbed.

The `istanbul ignore next` on that arm is dropped because the branch is
now exercised.

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

* refactor(manager): remove unreachable fallbacks

Drop three defensive fallbacks that can never be taken:

- `docker-compose`: `config.services ?? config` always yields an object,
  so the `|| {}` guard behind it is dead
- `git-submodules`: `git.raw()` resolves to a string, so the `?? ''`
  never applies
- `maven`: the only site that builds a `MavenProp` always passes a
  `packageFile` string, so narrow the type and drop the `?? undefined`

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:02 +00:00
Jamie Tanna aae889a285 fix(datasource/go): cache the publication time of each version (#45951)
* fix(datasource/go): cache the publication time of each version

The Go proxy defines that the `.info` API call is for a specific release
version of a module, this file should never be modified after it's been
created.

However, because we previously had a 30m TTL on these entries, a
repository that runs infrequently can lead to re-fetching data that
doesn't ever update.

We can fix this by introducing a separate cache namespace for the
module's creation timestamp (`Time` in the `.info` API call).

We can make sure that:

- we always merge, not replace, the entries, as the `major < 2` filter
  in `_getReleases` means a run may only see a subset of a module's
  versions, and writing back only what we saw would evict the rest
- we re-read immediately before writing, as `foo` and `foo/v2` are
  separate lookups which both walk the `v2` module, so one can overwrite
  the other's timestamps
- the key is the proxy which served the data, minus any credentials,
  since a private Artifactory `GOPROXY` is a different universe of
  timestamps to `proxy.golang.org`
- only the timestamps we successfully fetched are stored, so a proxy
  which serves no `Time` doesn't have that recorded for 100 days
- it uses its own namespace, so that a `cacheTtlOverride` on the release
  cache doesn't drag the immutable data down with it

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

* fixup! fix(datasource/go): cache the publication time of each version

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

* fixup! fixup! fix(datasource/go): cache the publication time of each version

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

---------

Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
2026-09-15 16:02:16 +00:00
Jamie Tanna b2135e41b7 fix(exec): memoise which install-tools we've run (#46084)
When running Renovate with `binarySource=install` on a repository with
many branches, the amount of time running `install-tool` - on already
installed tools - can take a significant percentage of the overall run.

For instance, on one repository we have instrumented with OpenTelemetry,
we see:

- initial `install-tool golang`: 8.7s
- follow-up `install-tool golang`: median 635ms, max 2.4s

However, because we run `install-tool golang` 640 times, this adds up to
24.8/29.2m (85%) of the repo's run time, which is an overwhelming
percentage when we're not even re-installing the tool.

To handle this more effectively, we can add an in-memory cache of all
the tools (and resolved versions) that we've installed in a given run.

We can't do this with `binarySource=docker`, as it has a fresh container
each time.

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-09-14 20:33:10 +00:00
Gregor Zeitlinger 2e951d2254 feat(mise): support selector lockfile updates (#44615)
* mise: support selector lockfile updates

* fix(mise): handle empty lockfile AST

* test(mise): use valid empty TOML AST fixture

* fix(mise): support current regex utility

* fix: clarify lockfile-only lookup handling

* fix(mise): handle selector lockfile updates correctly

* test(mise): cover selector lockfile review fixes

* fix(mise): scope selector artifact refresh

* chore: retrigger CI

* fix(mise): remove unreachable lockfile guard

* refactor(lookup): clarify lockfile-only value handling

* refactor(mise): use shared TOML utilities

* fix(mise): handle selector lockfile edge cases

* fix(mise): satisfy selector CI coverage

* fix(mise): require dependency names

* fix(mise): preserve configured dependency names

* fix(mise): address selector lockfile review feedback

* test(mise): cover major selector lockfile updates

* chore(static-data): auto-update Java LTS versions

So we don't have a hardcoded set of data in the mise manager.

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

* fix(mise): address selector lockfile feedback

* test(manager/mise): cover nonnumeric current version prefix

formatLockedVersion()'s currentPrefix fallback to '' only runs when
the current version has no leading numeric match, which no existing
test reached.

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

---------

Co-authored-by: Jamie Tanna <jamie.tanna@mend.io>
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-09-14 15:57:22 +00:00