Commit Graph

3942 Commits

Author SHA1 Message Date
Jamie Tanna 7b8ac17c36 feat(manager/github-actions): support GitTools/actions/gitversion/setup's versionSpec
Co-Authored-By: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-09-15 09:27:54 +01:00
Jamie Tanna e227af992e feat(manager/github-actions): support subosito/flutter-action's flutter-version
Co-Authored-By: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-09-15 09:27:54 +01:00
Jamie Tanna 6687887bb8 feat(manager/github-actions): support aquaproj/aqua-installer's aqua_version
Co-Authored-By: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-09-15 09:27:54 +01:00
Jamie Tanna e8a17adefe feat(manager/github-actions): support cycjimmy/semantic-release-action semantic_version
Co-Authored-By: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-09-15 09:27:54 +01:00
Jamie Tanna 347c642f1d feat(manager/github-actions): support cloudflare/wrangler-action wranglerVersion
Co-Authored-By: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-09-15 09:27:53 +01:00
Jamie Tanna 9b7dfb9d8b feat(manager/github-actions): support peaceiris/actions-hugo's hugo-version
Co-Authored-By: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-09-15 09:27:53 +01:00
Jamie Tanna f417e2004f feat(manager/github-actions): support jfrog/setup-jfrog-cli's version
Co-Authored-By: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-09-15 09:27:53 +01:00
Jamie Tanna 84be57eadd feat(manager/github-actions): support helm/chart-releaser-action's version
Co-Authored-By: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-09-15 09:27:53 +01:00
Jamie Tanna 9266b6d05e feat(manager/github-actions): support azure/setup-kubectl's version
Co-Authored-By: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-09-15 09:27:52 +01:00
Jamie Tanna b4f9d9d607 feat(manager/github-actions): support snok/install-poetry's version
Co-Authored-By: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-09-15 09:27:52 +01:00
Jamie Tanna d27e967632 feat(manager/github-actions): support terraform-linters/setup-tflint's tflint_version (#46034)
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-09-15 07:53:32 +00:00
Jamie Tanna 6c7e9faa7e feat(manager/github-actions): support extractions/setup-just's just-version (#46033)
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-09-15 07:53:31 +00:00
Jamie Tanna 3de36a8e43 feat(manager/github-actions): support gradle/actions/setup-gradle's gradle-version (#46032)
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-09-15 07:53:30 +00:00
Jamie Tanna 608b47ea2a feat(manager/github-actions): support hashicorp/setup-terraform's terraform_version (#46031)
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-09-15 07:53:29 +00:00
Michael Kriese 55a7341be2 test(manager): close long-tail branch coverage gaps (#45954)
* test(manager): close azure-pipelines, bundler and cocoapods gaps

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

---------

Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io>
2026-09-15 07:10:10 +00:00
Michael Kriese dec41b697e test(manager/terraform): close branch coverage gaps (#45948)
test(manager/terraform): close the terraform family coverage gaps

Adds two terraform extractions that no test covered: a lock file that
cannot be read, and one that holds no locks. Both leave the deps without
a locked version.

Marks three guards. The lockfile update path needs a change that also
satisfies the recorded constraints, `extractTFLintPlugin()` never
returns null, and only terragrunt's already-ignored default case leaves
its result unset.

Two implicit elses stay counted, in the terraform module extractor and
the tflint key parser: a coverage-ignore hint does not attach to an
`else if`, so they carry a plain note.

Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io>
2026-09-15 07:10:10 +00:00
Michael Kriese 44a9f5283b test(manager/sbt,swift): close branch coverage gaps (#45946)
test(manager/sbt,swift): close the sbt and swift coverage gaps

sbt is now fully covered by tests: a build definition referencing
symbols that were never defined, a resolver whose location is not a url,
a package file that yields nothing during a multi-file extract, and two
scala version strings that normalization leaves alone - a range and a
version with no patch part.

swift keeps two marks. `artifacts.ts` falls back to an empty depName
that extract always sets, and the null state in `extract.ts` is only
re-entered at a deps boundary. Its two `.package(` transitions stay
counted, since a coverage-ignore hint does not attach to an `else if`.

Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io>
2026-09-15 07:10:09 +00:00
Michael Kriese 351201cac6 test(manager/bazel): close branch coverage gaps (#45944)
test(manager/bazel): close the bazel branch coverage gaps

Adds two extractions that no test covered: a `go_repository` carrying
both a tag and a commit, which must not be marked digest-only, and a
`maven_install` artifact whose coordinate is not group:artifact:version.

Marks the rest. `parser.ts` guards are type narrowing over the parsed
fragment tree, where the else only happens if the parser hands back a
shape it never produces. In `artifacts.ts` only http rules reach
updateArtifacts, and the empty url list already returned earlier.

The digest branch in `rules/http.ts` stays counted: a coverage-ignore
hint does not attach to an `else if`, so it carries a plain note.

Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io>
2026-09-15 07:10:08 +00:00
Jamie Tanna 826541b266 fix(datasource/go): don't cache private modules (#45949)
Previously, we were caching private Go modules' information, even when
`cachePrivatePackages=false`.

This leads to the module path, versions, and possibly the `go`
directive being cached unintentionally.

Instead of doing so, we should make sure that we're intentionally
caching packages.

To do this, we can use a mix of the `GOPRIVATE`/`GONOPROXY` to determine
which packages shouldn't be fetched in the public Go proxy, given
they're private, following how the Go toolchain itself does this.

When interacting with the public Go proxy, we treat these packages as
public (as the public Go proxy has no means to authenticate) and so
anything outside of this should be treated as private.

When `GOPROXY` contains `direct`, we only treat a package as public only
when the public proxy is in the list too, the way Go's own default is
written. This is used to imply that `direct` is the fallback for
whatever the public proxy doesn't have.

When thre is no Go proxy set, `GOPROXY=direct` means everything comes
from source, which tells us nothing about who is allowed to read it.

This doesn't catch everything: with the default `GOPROXY`, a private
package the public proxy doesn't have falls through to `direct` and is
still cached by Renovate, unless `GOPRIVATE` says otherwise. We only
learn that no proxy served it after we've fetched it, which is after
`cacheable` is determined.

When using Renovate with a private Go proxy mirror, such as Artifactory,
this will result in no cached packages until `cachePrivatePackages:
true` is set.

This is a similar change to #45348.

Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
2026-09-14 16:39:36 +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
Michael Kriese ed285cc4c1 perf(manager/maven-wrapper): avoid matching each line twice (#46027)
refactor(maven-wrapper): avoid matching each line twice

`extractLineInfo` ran `line.match(regex)` only to re-run `regex.exec(line)`
on the same line immediately afterwards. None of the regexes are global,
so `exec` alone is equivalent and halves the regex work per line.

Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io>
2026-09-14 15:11:01 +00:00
Jamie Tanna 3e099dd645 feat(manager/github-actions): support aws-actions/amazon-ecs-render-task-definition's image (#45940)
* feat(manager/github-actions): support aws-actions/amazon-ecs-render-task-definition's `image`

Per #43038, and following the existing pattern for Docker image
extraction.

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

* fixup! feat(manager/github-actions): support aws-actions/amazon-ecs-render-task-definition's `image`

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-09-14 14:42:54 +00:00
Michael Kriese 3a723b7891 test(datasource): close branch coverage gaps (#45943)
* test(versioning/aws-machine-image): cover the empty version guard

`_parse()` returns null for a falsy version before it tries the AMI id
regex, and no test passed one. Checking that an empty string is not
valid closes the only branch the module was missing.

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

* test(datasource/buildpacks-registry): cover a response without a homepage

`latest.homepage` is optional in the registry response, but every test
supplied one, so the release result was never built without it. A
buildpack whose latest entry carries no homepage now checks that the
releases still come back and no source url is derived.

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

* test(datasource): cover optional-field branches in four datasources

Each of these datasources builds its release result by attaching fields
only when the registry supplies them, and the "not supplied" path was
never exercised:

- cdnjs: a library with neither homepage nor repository
- cpan: a search result where no release is marked latest, so no tag
- dart: a latest release carrying no pubspec
- ruby-version: a release table row whose first column is not a version

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

* test(datasource): cover missing-metadata branches in hex and pypi

Two more datasources only attached fields when the registry supplied
them, and the absent case was untested: a hex package with neither an
html_url nor a github link in its meta, and a pypi response carrying no
releases at all.

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

* test(datasource): cover galaxy and repology fallbacks, mark unreachable guards

Adds a galaxy role with empty github fields, so no source url is
derived, and a repology lookup where the api fallback after a 403 finds
no matching package.

Marks four guards that are not worth a test: cpan and dart both check a
variable that is only null when the request threw, and
`handleGenericErrors()` always rethrows; conan's registry url is always
supplied by the datasource layer; and repology's resolver either returns
a body or throws.

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

* test(datasource): cover pod CDN branches, mark the sbt listing guards

Adds two pod lookups: an empty CDN body, and a CDN index that lists no
matching pod.

Marks the guards whose tests would need multi-level directory listing
fixtures: both sbt datasources walk nested index pages, and pod's github
helper checks a body that an empty json response never produces because
parsing throws first.

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

* test(datasource): cover maven metadata without a latest tag

Adds maven metadata carrying a release but no latest, so respectLatest
is left alone. Marks the three deb guards, which would each need a
crafted package index: a block missing a required key, a repeated
package in the final block, and two component indexes whose meta agrees.

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

* test(datasource): cover npmrc registry fallback, mark cache-bound guards

Adds a resolveRegistryUrl lookup for a package no npmrc rule matches.

Marks the guards whose tests would need a primed cache or a specific
blob shape: nuget's services index, deno's release cache, the docker hub
cache window, docker's manifest and config handling, go's pseudo-version
fallback, and both rubygems cache layers.

Three implicit elses are left counted: a coverage-ignore hint does not
attach to an `else if`, so the registry strategy chain, the npmrc reset
and docker's digest-header branch carry a plain note instead.

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

* fix(datasource/repology): pass the mock body as a string

`ResponseMock.body` is typed as a string, and every other call in the
spec passes `'[]'`. The new api fallback test passed an array literal,
which tsc rejected.

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-14 12:11:52 +00:00
Sebastian Poxhofer 4b4d14ec00 feat(manager): pass extracted constraints to updateArtifacts (#45826)
* feat(manager): pass extracted constraints to updateArtifacts

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* refactor(manager): inline thin resolveToolConstraint wrappers

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

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

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

composer only runs extractConstraints() when a user constraint is missing,
via Lazy. UpdateArtifactsConfig no longer re-declares constraints and
extractedConstraints, which ToolConstraintsConfig already provides.
2026-09-14 11:09:07 +00:00
MFietze 96e72f6a93 fix(platform/gitlab): skip projects marked for deletion (#45928) 2026-09-14 10:40:41 +00:00
Sebastian Poxhofer 44160755f9 feat(platform): validate gitea responses with schemas and share the implementation with forgejo (#45825)
* refactor(platform): share one implementation between gitea and forgejo

The `forgejo` platform was copied from `gitea` in #37075 and the two have
drifted since: fixes landed on one side only (zod validation #43900, empty
email #44068, null issues #44048, team reviewers #39533, merge-style fallback
#37768 vs #38040), and lint sweeps had to be applied to both copies by hand.

Both platforms now build on `lib/modules/platform/gitea-common/`, which holds
the zod schemas, API helpers, utils, PR cache and the platform object itself.
`createPlatform()` closes over its own state, so `gitea` and `forgejo` keep
separate config, caches and host types. `gitea/index.ts` and `forgejo/index.ts`
are thin wrappers that supply the platform id, default endpoint, http client
and the version gates that genuinely differ.

Reconciliations, forgejo's behaviour adopted for gitea:

- Responses are validated with zod instead of `getJsonUnchecked` casts. Gitea
  therefore tolerates empty emails, null PRs in list responses and lenient
  repo/issue payloads the same way Forgejo already did.
- `getRepoContents` returns a discriminated union, so `getRawFile` returns null
  for dir/symlink/submodule entries instead of reading a missing field. The
  gitea preset resolver now throws PRESET_INVALID for non-file entries, like
  the forgejo one.
- An unknown `default_merge_style` (e.g. `manually-merged`) is caught by the
  schema and skipped, instead of aborting the repository with
  REPOSITORY_BLOCKED from `isAllowed()`.
- `initRepo()` resolves whether the repo owner is an org and only fetches org
  labels when it is, adding one `/orgs/{owner}` request and an `orgs` entry in
  the gitea repository cache.
- Reviewers prefixed with `team:` are sent as `team_reviewers`. Gitea keeps its
  `v1.14.0` guard for requesting reviewers at all.
- `getBranchStatusCheck()` maps unknown commit status values through the
  schema's `unknown` fallback rather than warning and returning yellow.

Gitea's behaviour is kept where it is deliberately different: the Forgejo
instance detection and its deprecation notice, the `1.24.0` (or `10.0.0` for a
detected Forgejo) native automerge gate, and the reviewer version guard are
passed in as options.

Two shared log messages became static so they can be grouped in metrics:
`{platform}-native automerge: fail` is now `Platform-native automerge: fail`
and `{Platform} getRepos() error` is now `Error auto-discovering repositories`,
both with the platform id in the metadata. The dead `defaults.hostType` field
is gone.

* refactor(platform): keep the shared gitea implementation under gitea/

Drop the `gitea-common/` folder. The zod schemas, API helpers, utils, PR
cache and `createPlatform()` live in `lib/modules/platform/gitea/` under
their original file names, and `forgejo/` imports them from there.

The preset resolvers pass `giteaHttp` and `forgejoHttp` to
`getRepoContents()` directly, which removes the two bound wrappers. The
gitea changelog source uses the shared `RepoContents` type like the
forgejo one already does.

* refactor(http): derive ForgejoHttp from GiteaHttp

The two clients were identical apart from the default `hostType`.
`ForgejoHttp` now extends `GiteaHttp` and only keeps its own base url,
so the pagination logic exists once. The platform helpers accept
`GiteaHttp` directly instead of the `HttpBase` alias.

Also covers the `updatePr()` branch where the updated pull request
cannot be converted and therefore is not cached.

* refactor(platform): create the gitea and forgejo http clients in index.ts

`forgejo-helper.ts` only held the `ForgejoHttp` instance, so it is gone
and `forgejo/index.ts` creates the client next to the platform. Gitea
does the same for symmetry, which leaves `gitea-helper.ts` with only the
shared API helpers.

* refactor(platform): fetch gitea labels and issues with await

`getLabelList()` and `getIssueList()` still memoize the in-flight
promise, but build it from small async functions instead of `.then()`
and `.catch()` chains.

* refactor(platform): keep declaration order of gitea/index.ts

Order the module the way it was before `createPlatform()` so the diff
against main aligns: platform id and http client after the repo config
interface, pure helpers before the factory, and `maxBodyLength()` after
the platform object.

* refactor(platform): move gitea label fetching to labels.ts

`fetchLabelList()` takes the http client and the repository details
instead of closing over the platform state, and gets its own spec. The
factory only keeps the memoizing `getLabelList()`.

* refactor(platform): move gitea label lookup to labels.ts

* refactor(platform): create the gitea pr cache per platform

`GiteaPrCache` is now created once per platform with its http client and
platform id, and `initRepo()` records the repository. The per-repository
state moves to a private `RepoPrCache` which is bound to the repository
cache on first use and reused until the next `initRepo()`, instead of
being rebuilt on every lookup.
2026-09-14 08:45:04 +00:00
Jamie Tanna 58cd82c060 feat(manager/github-actions): support actions/setup-java's java-version (#45878)
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>
2026-09-14 08:07:26 +00:00
Jamie Tanna e6c6f2914a feat(manager/github-actions): support actions/setup-dotnet's dotnet-version (#45877)
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>
2026-09-14 08:07:25 +00:00
Jamie Tanna 343fed8955 docs(manager/github-actions): generate one combined first-party and community table (#45875)
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.

Instead of duplicating this, we can instead move them into a single
section in the documentation.

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-09-14 08:07:25 +00:00
Jamie Tanna 03906a7cbf refactor(manager/github-actions): don't duplicate parsing logic for first-party Actions (#45887)
* refactor(manager/github-actions): don't duplicate parsing logic for first-party Actions

Instead of having a separate set of Action parsing and their
configuration between first-party GitHub-owned Actions and those of
third-party Actions, we can merge them into a single collection.

This also leads to `https://<host>/` handling noted in #35777 now being
handled out-of-the-box, as it was already supported on third-party
actions.

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

* fixup! refactor(manager/github-actions): don't duplicate parsing logic for first-party Actions

---------

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-09-14 08:07:24 +00:00
RahulGautamSingh 405c32b88e docs: clarify extractVersion and add artifactory example (#45926) 2026-09-14 06:44:03 +00:00
Jan Vollmer 26903f4324 fix(managers/pep621): use lowest locked version from uv (#40208)
* fix(managers/pep621): use lowest locked version from uv

* reduce diff

* add file extension to import

* use correct file path in import

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

---------

Co-authored-by: Michael Kriese <michael.kriese@gmx.de>
2026-09-14 06:36:16 +00:00
renovate[bot] b6ffadc70c docs: update references to astral-sh/setup-uv to v10.1.0 (main) (#45921)
docs: update references to astral-sh/setup-uv to v10.1.0

| datasource  | package            | from    | to      |
| ----------- | ------------------ | ------- | ------- |
| github-tags | astral-sh/setup-uv | v10.0.1 | v10.1.0 |

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-14 01:25:43 +00:00
renovate[bot] fa393c49d0 docs: update references to python to e06cc11 (main) (#45918)
docs: update references to python to e06cc11

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-14 00:25:02 +00:00
Jamie Tanna 6580ef4f97 feat(manager/github-actions): support renovatebot/github-action renovate-image (#45873)
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>
2026-09-11 10:47:21 +00:00
Jamie Tanna e4307d526a feat(manager/github-actions): support renovatebot/github-action's renovate-version (#45872)
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
2026-09-11 10:47:21 +00:00
Matthew Nitschke ac22678812 feat(datasource/npm): integrity and tarball extraction (#44315)
* 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>
2026-09-11 10:09:59 +00:00
Pieter Willekens 141e136869 feat(manager/mise): support gitlab backend (#44116)
* 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>
2026-09-11 10:04:37 +00:00
Michael Kriese c23e9f0fe5 test: close remaining line coverage gaps (#45870)
* 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>
2026-09-11 10:03:46 +00:00
Sebastian Poxhofer e5ef25bbba feat(datasource/gitlab-tags): replace getJsonUnchecked with validated getJson (#44144)
* 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>
2026-09-11 08:54:01 +00:00
Sebastian Poxhofer da4cbf6d80 feat(datasource/gitlab-releases): replace getJsonUnchecked with validated getJson (#44145)
fix(datasource/gitlab-releases): replace getJsonUnchecked with validated getJson

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-11 08:53:20 +00:00
Jamie Tanna 29a7b9c5f5 fix(util/http): allow blocking requests to internal hosts
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>
2026-09-10 14:52:01 +01:00
Adam Setch 6d67f70cd2 feat(manager/github-actions): extract expo GitHub actions' eas-version (#45846)
feat: github actions for expo cli version

Signed-off-by: Adam Setch <adam.setch@outlook.com>
2026-09-10 12:29:02 +00:00
Adam Setch c387bc11e4 refactor(platform/utils/pr-body): treat truncation as an "Important" callout (#45645)
* refactor: pr body important note

Signed-off-by: Adam Setch <adam.setch@outlook.com>

* refactor: pr body important note

Signed-off-by: Adam Setch <adam.setch@outlook.com>

* Merge branch 'main' into refactor/important-note

Signed-off-by: Adam Setch <adam.setch@outlook.com>

---------

Signed-off-by: Adam Setch <adam.setch@outlook.com>
2026-09-10 12:27:37 +00:00
RahulGautamSingh 76d55bf3e6 fix(manager/npm): keep workspace entries when massaging lockstep siblings (#45786) 2026-09-10 12:11:36 +00:00
Michael Kriese a4a5efa8c2 feat(manager/npm): support pnpm v11.23 url-keyed registries (#45844)
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>
2026-09-10 10:27:20 +00:00
Sebastian Poxhofer 5f91549447 feat(gitlab): merge MRs through merge trains via the platform merge queue API (#45722)
* 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
2026-09-09 15:21:46 +00:00
Sebastian Poxhofer 7b25e97ba3 feat(github): add support for using merge queues without auto merge (#45721)
* 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
2026-09-09 15:21:45 +00:00
Sebastian Poxhofer b2d3b64c48 refactor(lint): enforce err key for errors in logger metadata (#45759)
* refactor(lint): enforce err key for errors in logger metadata

* refactor(lint): flag error message and stack strings in logger-err-key
2026-09-09 13:55:14 +00:00
Sebastian Poxhofer be13c9f5f7 feat(manager): share OCI Helm chart resolution across managers (#45760)
* 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.
2026-09-09 13:51:30 +00:00