Commit Graph

811 Commits

Author SHA1 Message Date
RahulGautamSingh 96ad4beb6a fix(versioning): use BigInt to avoid integer precision loss in gradle, maven and loose (#43901)
* fix(versioning): use BigInt to avoid integer precision loss in gradle, maven and loose

* fix(versioning): preserve exact update types

* Update lib/modules/versioning/maven/index.ts

* fix(versioning): satisfy func-style and prefer-at lint rules

* treat missing loose version section as zero in isSame

* fix coverage

* revert unrelated custom-manager rangeStrategy change

---------

Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com>
2026-09-22 17:41:11 +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 d89d8e513e refactor(workers/lookup): share the release classification between getBucket and getUpdateType (#46144)
`getUpdateType()` never read its `config` argument and `UpdateTypeConfig` was a
field-for-field copy of `BucketConfig`, while `getBucket()` and
`getUpdateType()` each ran their own major/minor comparison. Both now call a
single `classifyRelease(versioningApi, currentVersion, newVersion)`, which asks
`isSame()` for the minor as well as the major and falls back to comparing
`getMajor()`/`getMinor()` when the versioning does not implement it.
`getUpdateType()` and `UpdateTypeConfig` are gone; the two callers use
`classifyRelease()` directly.

Behaviour changes:

- `getBucket()` now honours `isSame('major')`, so `pvp` no longer buckets
  1.1.x -> 1.10.x as non-major just because `getMajor()` squashes both into the
  float 1.1.
- The update type now reports a difference rather than an increase, matching
  what `getBucket()` has always done. Epoch-aware versionings (deb, debian,
  pep440, rpm) can produce a greater version with a lower major or minor
  number; those updates were bucketed as major/minor but labelled `patch`, and
  are now labelled to match their bucket.
2026-09-18 10:12:40 +00:00
Sebastian Poxhofer 20015e4894 refactor(workers/lookup): resolve the current version from one release list (#46143)
`resolveCurrentVersion()` took an `allVersions: string[]` and a separate
`nonDeprecatedVersions: string[]`. The caller built the first from the
releases filtered by `isVersion()` and `followTag`, but the second from the
unfiltered `dependency.releases`, so the "prefer non-deprecated, fall back to
all" passes searched different sets of releases.

It now takes the filtered `Release[]` and derives both lists from it, the same
way `getNewestMatchingVersion()` already did. The shared pair of passes moved
into a private `getCurrentVersionFromReleases()` helper used by both.

No behaviour change in practice: the non-deprecated pass no longer sees
releases that are not versions or that `followTag` excluded, but a non-version
release could only have been picked if `versioningApi.matches()` accepted it,
and the whole lookup spec (including every `followTag` case) is unchanged.
2026-09-18 10:12:39 +00:00
Sebastian Poxhofer bf848fa6c7 refactor(workers/repository/lookup): split lookupUpdates into testable stages (#46142)
`lookupUpdates()` was a single ~840-line function whose stages could only be
reached end-to-end through the datasource layer, which is why its spec had
grown to 6700 lines. Move seven of those stages into separately testable
functions, leaving `lookupUpdates()` as a linear orchestrator:

- `matchVersionCompatibility()` / `restoreVersionCompatibility()` in the new
  `version-compatibility.ts`
- `resolveRangeStrategy()` in the new `range-strategy.ts`
- `resolveCurrentVersion()` and `getNewestMatchingVersion()` in `current.ts`
- `applyVulnerabilityFixFilter()` in the new `vulnerability.ts`
- `groupReleasesIntoBuckets()` in `bucket.ts`
- `resolveUpdateDigests()` in the new `digest.ts`, which also takes over
  `couldApplyMinimumReleaseAgeToDigest()`, `applyMinimumReleaseAgeToDigestUpdate()`
  and `DigestLikeUpdate` from `index.ts`
- `stripNoopUpdates()` in `utils.ts`

`lookupUpdates()` keeps its signature and `index.ts` drops from 1020 to 665
lines. Each new stage gets a focused spec; the end-to-end specs are unchanged.

No behaviour change.
2026-09-18 10:12:38 +00:00
Sebastian Poxhofer f5db0217f1 refactor(workers/repository/lookup): share the update-type config resolution (#46141)
`applyMinimumReleaseAgeToDigestUpdate()` and `filterInternalChecks()` both
resolved the config their `minimumReleaseAge` check runs against by merging
the `updateType`-scoped sub-config and then applying `packageRules` matching
on `update-type`, and both carried a comment asking the other to be kept in
sync by hand.

Extract that sequence as `resolveUpdateTypeConfig()` in `filter-checks.ts`
and use it from both, and share the `timestamp-optional` warning text as
`missingReleaseTimestampWarning`. The warning stays a constant rather than a
helper function so that each caller keeps its own `logger.once` call site.
Both sync comments are gone.

No behaviour change.
2026-09-18 10:12:38 +00:00
Sebastian Poxhofer c303a282a1 test(workers/repository/lookup): enforce http mocks in the lookup spec (#46140)
The spec's `afterEach` called `httpMock.clear(false)`, which skipped both
the missing-request and the unused-mock checks for every test in the file.
That kept nine tests green while they performed unmocked requests or left
mocks unused, including two tests whose mocks were crossed: `handles github
404` mocked PyPI and `handles pypi 404` mocked the GitHub API, so neither
ever exercised a 404.

Drop the opt-out and fix the tests it was hiding: swap the two crossed 404
mocks, mock the GitHub GraphQL calls made by the digest lookups, add the
missing packagist `~dev` metadata, gomod `?go-get=1` and PyPI requests, let
the Maven `postprocessRelease` spy handle every call, and delete the dead
`@types/helmet` mock in a test that returns before any release is fetched.

`httpMock.clear(false)` remains in other specs, so the `check` parameter of
`clear()` is kept.
2026-09-18 10:12:37 +00:00
Michael Kriese f7e8104511 test(workers/repository): close more branch coverage gaps (#46259)
* test(workers/repository): cover five pr body and warning guards

- an upgrade with no release notes of its own, which gets no summary
  title while the branch as a whole has notes
- an upgrade with no homepage, source or dependency url, whose name is
  therefore left unlinked
- an upgrade that defines no pr body columns
- an assignee list that filtering empties out
- a second warned dependency in a package file that is already listed,
  so the file is not recorded twice

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

* test(workers/repository): cover four changelog guards

- `massageName` gets a describe of its own: it is exported but was only
  ever reached through a release that carried a tag, so the no-version
  path and the empty-result path went untaken
- a lone in-range release with no earlier one to prepend
- a bitbucket tree holding exactly one changelog candidate, so nothing is
  logged about choosing between several
- a bitbucket-server source url that parses but matches neither the git
  nor the web repository pattern

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

* test(workers/repository): cover both extract failure paths

- a manager whose `extractAllPackageFiles` returns null, so there is
  nothing to massage dep names in
- a file whose `extractPackageFile` returns nothing, so it contributes no
  package file

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

* ci: ratchet the branch coverage threshold

A full run on this branch reports 100% statements (49491/49491), 100%
functions (7384/7384), 100% lines (48981/48981) and 99.86% branches
(25726/25761), up from 99.82% on the branch below. The threshold moves to
99.84, keeping the same rounding-down margin as before.

Statements, functions and lines are already pinned at 100 and stay
there.

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

* test(workers/repository): cover four process guards

- a libyear update released before the version currently in use, which
  yields a negative age and is therefore not counted
- a pr that is closed, and one raised from the onboarding branch, neither
  of which counts towards the concurrent pr limit
- a second base branch whose package files do not displace the first
  one's, on a platform that cannot sync a fork with its upstream

The fork case redefines `syncForkWithUpstream` rather than deleting it,
the same way the migration branch spec handles `refreshPr`.

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

* test(workers/repository): cover the extract cache guards

- a cached extract whose manager fingerprints all still match, so the
  cache is reusable; the test reads the expected fingerprint out of
  `hashMap` rather than hard-coding a hash that regenerates
- an extract that is told not to overwrite the cache
- a cached scan for a branch that is still a configured base branch, so
  it survives the clean-up that drops the others

With these, `lib/workers/repository/process` is fully covered.

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

* test(workers/repository): cover the branchPrefixOld miss

`prAlreadyExisted` retries the lookup under the old branch prefix, but
every test either hit on the first lookup or on the second, so the case
where both miss went untaken.

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

* ci: ratchet the branch coverage threshold to 99.87

The tests added after the earlier bump in this branch close eight more
branches. A full run now reports 100% statements (49491/49491), 100%
functions (7384/7384), 100% lines (48981/48981) and 99.89% branches
(25734/25761). The threshold moves from 99.84 to 99.87, keeping the same
rounding-down margin as before.

Statements, functions and lines are already pinned at 100 and stay
there.

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

* test(workers/repository): cover three changelog embedding guards

The pr worker copies release notes off each upgrade's changelog result.
Three of its guards were never taken because every test supplied a
complete result for a distinct repository:

- a changelog with no project, so no repo name is recorded
- a changelog with a project but no versions, so no releases are copied
- a second upgrade for a repository whose notes were already committed,
  which is skipped rather than repeated

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-17 07:08:46 +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 7aedcb24d2 test(workers/lookup): cover untested branches under lookup/ (#45930)
* test(workers/lookup): cover the remaining generateUpdate branches

Adds a unit spec for `generateUpdate()` exercising the branches that the
surrounding lookup tests never reached: a release carrying `checksumUrl`,
`downloadUrl` and `newDigest`, a versioning api whose `getNewValue`
throws, and an update with no current version.

With those covered, the last istanbul ignores in the file can go, so
`generate.ts` now reports full statement and branch coverage with
nothing suppressed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test(workers/lookup): cover two untested lookup branches

Adds tests for two paths flagged by the `TODO: add test #40625` markers
that no existing test reached:

- `filterInternalChecks()` with a release that has no `releaseTimestamp`
  while `minimumReleaseAgeBehaviour` is unset. The existing tests only
  cover `timestamp-required` and `timestamp-optional`, so the release is
  now checked to be accepted without being reported under either.
- `lookupUpdates()` when no current version can be resolved but a
  `lockedVersion` is set, which must return without marking the
  dependency `invalid-value`.

The ignore comments are left in place, so these branches stay excluded
from the coverage report; each test instead asserts an outcome that only
holds on the intended path.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test(workers/lookup): cover error paths in bucket, current and rollback

Adds unit specs for three exported helpers whose guard clauses no test
reached: `getBucket()` when the versioning api cannot determine a major
or a minor, `getCurrentVersion()` when the current value is not a string,
and `getRollbackUpdate()` when the versioning api lacks
`isLessThanRange()`, when `isLessThanRange()` throws, and when there is
nothing older to roll back to.

The ignore comments on those branches are left in place, so the coverage
report is unchanged; each test asserts the return value that is only
produced by the guard it targets.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test(workers/lookup): cover filter and rollback guards

Covers three more guards that no test reached: `filterVersions()` with
no current version, and `filterByMaxMajorIncrement()` when the versioning
api cannot determine the current major or a release's major. Adds a
`lookupUpdates()` test for the case where rollbacks are enabled but
nothing older exists to roll back to, which warns instead of updating.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test(workers/lookup): cover the vulnerability alert range strategy fallback

A vulnerability alert configured with `rangeStrategy=update-lockfile` but
no locked version falls back to `bump`, which no test covered. The new
test asserts the range is widened and the update is marked as a bump,
which only happens once the fallback has been applied.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs(workers/lookup): explain the remaining coverage ignores

Each ignore left under `lookup/` now records why the branch it hides is
not reached, instead of pointing at a TODO with no detail. No ignore is
added or removed, and the coverage report is unchanged.

The explanation goes above the hint rather than after it: a hint only
applies to the statement on the line immediately below, so trailing
comment lines silently stop it from suppressing anything.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test(workers/lookup): cover three more unreached lookup branches

Covers the guards behind three of the remaining ignore hints:

- `getRollbackUpdate()` when the release it falls back to carries an
  empty version, so there is nothing to roll back to after all
- `filterVersions()` coercing a release version that the configured
  versioning accepts but semver cannot parse, which happens once
  `allowedVersions` falls back to semver range syntax
- `lookupUpdates()` when the datasource rejects every candidate release
  during postprocessing, leaving a bucket with no release to update to

The ignore comments stay in place, so the coverage report is unchanged;
each test asserts an outcome that only holds on the intended path.

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

* docs(workers/lookup): correct the ignore reasons this branch disproves

Three of the reasons added alongside the previous batch of tests claimed
their branch was unreachable, which the tests in this branch disprove:
`getRollbackUpdate()` can pop a versionless release, `filterVersions()`
does coerce a version semver cannot parse, and `filterInternalChecks()`
yields no release when a datasource rejects every candidate. Each now
describes what actually reaches it.

Also sharpens two of the reasons that still stand. The `getBucket()`
else contradicts the `isVersion()` filter every release has already
passed, so it reads as unreachable rather than untested; and a lookup
whose releases are all unversioned tags never reaches the empty-version
block, because a configured digest routes it to the digest-only path
first.

No ignore is added or removed, and the coverage report is unchanged.

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

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io>
2026-09-14 12:29:39 +00:00
Michael Kriese ec4ba7b381 refactor(workers/lookup): drop stale istanbul ignores in generateUpdate (#45929)
Vitest uses the v8 coverage provider, and v8-to-istanbul still honours
istanbul hints, so these comments suppress real branch coverage rather
than being inert. The `releaseTimestamp` and `registryUrl` branches are
both exercised by the existing lookup tests, so their ignores only hid
coverage that was already there.

The remaining ignores in this file stay: no datasource used in these
tests reports a checksum url, and the `getNewValue` catch block and the
missing-currentVersion guard are still unreachable.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-14 12:29:38 +00:00
Michael Kriese 874060f7ee refactor(lookup): remove redundant currentValue check (#45933)
* refactor(lookup): remove redundant currentValue check

The inner `if (config.currentValue)` was already guaranteed by the
enclosing condition, so the `v8 ignore else` comment was hiding an
unreachable branch rather than an untested one. Drop both; the
`invalid-value` path remains fully covered by existing tests.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Update lib/workers/repository/process/lookup/index.ts

Co-authored-by: Jamie Tanna <jamie.tanna@mend.io>

* refactor(lookup): use safeStringify for invalid currentValue log

Template interpolation of a non-string `currentValue` yields
`[object Object]`, which hides the value that made it invalid. Use
`safeStringify` so objects and arrays are logged readably.

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

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Jamie Tanna <jamie.tanna@mend.io>
Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io>
2026-09-14 09:59:37 +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
Sebastian Poxhofer 05e1271376 test: use expect().resolves instead of awaiting inside expect (#45672)
Enables the vitest/prefer-expect-resolves oxlint rule and applies its
autofix across the spec suite.
2026-09-04 10:40:46 +00:00
Sergei Zharinov 09ff8d22b6 test: Validate minimumReleaseAge is ignored for security updates (#44272)
* test: validate minimumReleaseAge does not apply to security updates

* test: add end-to-end coverage for security-update minimumReleaseAge bypass

Drive the real vulnerability flow (appendVulnerabilityPackageRules) through the
real lookupUpdates, instead of only simulating the generated packageRule. Also
reword the inline comment and use luxon/asTimestamp for timestamps.

* test: fix type-check on e2e lookup config

Cast the spread config to satisfy partial() overload resolution, matching the
existing `getConfig() as never` idiom in the lookup spec.

* test: drop redundant inline lookup test in favor of end-to-end coverage

The simulated lookup test hand-built the security packageRule; the end-to-end
test plus the generated-rule assertion in vulnerabilities.spec.ts cover the same
behavior against the real flow, so the inline test added no unique coverage.

* test(vulnerability): align lookup config types
2026-09-04 09:31:58 +00:00
Birger Johan Nordølum 19e4cdc47f fix(lookup): preserve current compatibility (#45171)
* fix: preserve current compatibility after lookup

* fix: expose current compatibility in lookup result

* test: preserve current compatibility after lookup

* test: preserve compatibility through fetch

* test: isolate current compatibility regression

* test: isolate current compatibility regression

* test: isolate current compatibility regression

* test: isolate current compatibility regression
2026-09-03 14:29:15 +00:00
RahulGautamSingh 3b699b3698 feat: configure limiting security updates (#45574)
* configure limiting security updates

* separate security limit from other limits

* rename type

* fix coverage

* add comments

* add test
2026-09-03 06:08:37 +00:00
Sebastian Poxhofer 8d08b51db0 refactor: return a RepositoryResult while onboarding (#45531)
* refactor(onboarding): return repository result from ensureOnboarding

Rename ensureOnboardingPr to ensureOnboarding and have it return a new
'onboarding' RepositoryResult. renovateRepository now branches on
repoIsOnboarded, so exactly one of ensureOnboarding/updateRepo produces
the repository result and the non-null assertion on the update result
(TODO #22198) is no longer needed. updateRepo/update no longer return
undefined for non-onboarded repositories.

* refactor(onboarding): keep ensureOnboardingPr name
2026-08-28 11:50:28 +00:00
Sebastian Poxhofer 97327c3d28 refactor(linters): add prefer-coerce-array rule (#45492)
* refactor(linters): add prefer-coerce-array rule

Refs #45217

`x ?? []` and `coerceArray(x)` say the same thing, but only the second
one is searchable and consistent. The rule flags a `??` whose default is
a bare `[]` literal; a non-empty default or an asserted `([] as Foo[])`
still passes.

Applying it across `lib/` surfaced three spots the helper cannot cover,
which keep `?? []` with a disable comment or a narrower fix:

- `package-files.ts` destructures a tuple, which `coerceArray()` widens
- `generate.spec.ts` defaults `matchAll()`, an iterator rather than an array
- `mise/upgradeable-tooling.ts` declares a `Record` return, so its
  `?? []` fallback was wrong to begin with and becomes `coerceObject()`

* refactor(platform/github): hoist the GHE version header lookup

`Object.entries(...).find()` returns a tuple, and defaulting it with
`?? []` only to destructure the second element reads as an array
default when it is not one. Name the found entry instead, which drops
the `?? []` rather than routing a tuple through `coerceArray()`.
2026-08-28 09:27:58 +00:00
Sebastian Poxhofer a473e73b3e fix(linters): forbid inert counts in v8 coverage-ignore comments (#45287)
Adds a custom oxlint rule renovate/v8-ignore-no-count that flags the
count form '/* v8 ignore next <N> */'. The count is not honored by
vitest's ast-v8-to-istanbul hint parser, which captures only the
keyword (if/else/next/file); 'next' always exempts exactly the next
AST node. Trailing counts therefore suggest a line range that is never
applied and mislead readers.

The rule is autofixable (drops the count, preserving actual behavior)
and has been applied to all existing occurrences.
2026-08-22 11:25:31 +00:00
Jameel Al-Aziz 6c7d345057 fix(vulnerabilities): scope Go stdlib OSV remediation to the toolchain directive (#45334)
* fix(vulnerabilities): scope Go stdlib OSV remediation to the `toolchain` directive

The module `go` directive was already excluded from OSV alerts, but the toolchain
rule still matched it via shared datasource/packageName and go-mod-directive ranges.

* fix(vulnerabilities): scope OSV remediation rules to the vulnerable depType

Remediation rules are generated per dependency. When that dep has a depType,
constrain the rule so it cannot match another dep that shares datasource and
packageName.

* fix(vulnerabilities): set matchDepTypes only for Go toolchain OSV rules

A generic matchDepTypes would stop an npm `dependencies` rule from also
matching `overrides` of the same package. Only the existing toolchain path
sets depType on the generated rule.
2026-08-21 08:56:12 +00:00
Sebastian Poxhofer e01b50c6ab refactor(linter): oxlint prefer partial typed casts for consts (#45239)
* refactor: flag all typed object literal casts in prefer-partial-in-specs

* refactor: type maven spec httpError helper against got response shape
2026-08-12 08:50:57 +00:00
Beto Aveiga a84e007f46 feat(vulnerabilities): match OSV Packagist sub-ecosystems (#45203)
Allow osvVulnerabilityAlerts to match OSV sub-ecosystems such as
Packagist:https://packages.drupal.org/8, based on #40004. Adds a
negative test so unrelated prefixes like PackagistSomething do not match.

Co-authored-by: Stephan Zeidler <stephan@ramsalt.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-10 16:28:55 +00:00
Jamie Tanna 7f40d43179 refactor(workers/repository): allow managers to opt out of digest pinning (#45198)
As part of future changes in #45190, we have found that when using
GitHub Actions' dependency lockfile, the digest pinning is manged by the
lockfile, rather than being specified in the package file itself.

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

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

Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
2026-08-10 13:56:23 +00:00
Wade Carpenter a16858be0d refactor(workers): allow extractedConstraints on PackageDependency (#43252)
* refactor(workers): allow extractedConstraints on PackageDependency

Mirror the existing PackageFileContent.extractedConstraints field on
PackageDependency so managers can attach per-dep constraints (e.g.
python_version markers from PEP 508 dependencies) without overloading
the user-facing constraints field. In fetch.ts these dep-level
constraints are merged on top of the file/global constraints before
lookup, so the most specific source wins while user packageRules can
still override afterwards.

Extracted from #42701 at the reviewer's request so the type-level
change can land independently of the pep621/poetry feature work that
consumes it.

* fix(workers): prefer configured constraints over extracted values

Preserve configured constraints when extraction provides values for
the same names.

User configuration must take precedence over metadata discovered during
package extraction so users retain control over dependency lookup
behavior.

---------

Co-authored-by: wwade <wwade@users.noreply.github.com>
2026-08-03 18:08:26 +00:00
Jamie Tanna 33f51391f0 fix(workers/repository): apply minimumReleaseAge to pinDigest updates (#44968)
As per #44820, `pinDigest` updates currently don't get
`minimumReleaseAge` checks applied to them.

We can extend the recent support for `digest`s being handled by also
introducing support for `pinDigest`s to receive `minimumReleaseAge`
enforcement.

This will:

- enforce `minimumReleaseAge` on all updates that `pinDigest`s has
  pending
- consider the newest resolved version's timestamp, ignoring
  `rangeStrategy`-related logic
- allow unversioned releases like `latest` to /not/ be bound by
  `minimumReleaseAge`, as they'll potentially not have a release
  timestamp and will be unpinned forever, which is less safe (and
  reduces reproducibility)

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-07-30 16:00:12 +00:00
Jamie Tanna 1247df7fc4 fix(workers/repository): apply minimumReleaseAge to digest updates (#44965)
In some cases, we hadn't correctly wired in the `minimumReleaseAge`
checks for `digest`, due to the `currentValue` not changing.

To handle this, we need to:

- use our helper methods for calculating whether the `minimumReleaseAge`
  has passed
- handle a new digest's new `releaseTimestamp`
  the current timestamp
- intentionally not gate `minimumConfidence`, as this is only computed
  per-release, not at the digest level
- note the fixed behaviour, and clarify when it will/will not work
- add coverage for all generated updates for `digest`s, including when
  remapping a Go Modules update as a `digest`
- clarify that `filterInternalChecks` and
  `applyMinimumReleaseAgeToDigestUpdate` should stay in sync

Co-authored-by: Claude Fable 5 <jamie.tanna+claude-code@mend.io>
2026-07-30 12:06:25 +00:00
Jamie Tanna 12f5fde66e refactor(types): make currentVersionTimestamp a Timestamp (#44917)
To more strongly type it for other usages.
2026-07-28 13:03:28 +00:00
Arnaud Dezandee 5173de026b refactor: move checkMinimumReleaseAge to lib/util/minimum-release-age.ts (#44904) 2026-07-28 08:11:05 +00:00
renovate[bot] 196101a6bb chore(deps): update dependency oxlint-tsgolint to v0.25.0 (main) (#44424)
* chore(deps): update dependency oxlint-tsgolint to v0.25.0

| datasource | package         | from   | to     |
| ---------- | --------------- | ------ | ------ |
| npm        | oxlint-tsgolint | 0.23.0 | 0.25.0 |

* chore: fix new no-unnecessary-type-assertion findings

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

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Sebastian Poxhofer <sebastian.poxhofer@stedi.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-28 07:04:21 +00:00
Jamie Tanna 927b094344 refactor(workers/repository): extract minimumReleaseAge/minimumConfidence checks (#44825)
As part of follow-up changes, we'll need to call the checks in multiple
places, so should prefactor these into helper methods.

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-07-25 16:00:26 +00:00
Jamie Tanna f1cd516513 refactor(workers/repository): add isMinimumReleaseAgeApplicable/isMinimumConfidenceApplicable (#44824)
As part of follow-up changes, we'll use these functions to centrally
determine as to whether to execute `minimumReleaseAge` or
`minimumConfidence` checks against a given updateType.

For now, we can wire this into our documentation tests, to make sure
that this stays in sync with `isMinimumReleaseAgeApplicable`.

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-07-24 16:22:00 +00:00
Jamie Tanna f932d52fbd feat(platform): get all branch update dates in a more performant manner (#44582)
* feat(platform): get all branch update dates in a more performant manner

When Renovate is working on a repository with many /potential/ branches,
as well as some actually created branches, it's possible for the
calculation for `commitHourlyLimit` to end up taking significant time.

This can lead to a less performant job generally, but can sometimes lead
to the Renovate job failing to complete, and then timing out when
executed by a job runner.

To handle this, we can instead use use `git for-each-ref` to look up
each Git ref (remotely) and request the commit date, which leads to a
much more performant lookup.

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

* fixup! feat(platform): get all branch update dates in a more performant manner

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

* fixup! Merge remote-tracking branch 'origin/HEAD' into wip/commit-hourly-slow

---------

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-07-21 13:17:58 +00:00
Sebastian Poxhofer 1e03699cd6 test: add linter for as LongCommitSha in test files (#44681)
* test: add linter for `as LongCommitSha` in test files

Adds a custom oxlint rule `renovate/prefer-fake-sha-in-specs` that flags
`as LongCommitSha` casts in spec files and suggests the deterministic
`fakeSha()` helper from `test/util` instead. Enabled at error level for
`**/*.spec.ts` and `test/**`; all 131 pre-existing casts across 22 spec
files replaced.

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

* Update lib/modules/platform/bitbucket-server/index.spec.ts

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 10:08:09 +00:00
Sebastian Poxhofer c41b46bac3 feat(logging): do not use dynamic fields in log messages with severity WARN or higher (#44560)
* ci(linter): add renovate/logger-static-message rule

Adds a custom oxlint rule that enforces a static msg component for
logger.warn/error/fatal calls (including logger.once variants) so the
messages can be grouped in metrics and error catching services, per
docs/development/best-practices.md. It also flags metadata properties
named 'error' that hold error-ish values, because the bunyan serializer
only handles the 'err' key.

The rule is enabled as an error for lib/ production code and disabled
for spec files. All 33 pre-existing violations are fixed by moving
interpolated values into the metadata object, making messages static,
and renaming 'error' metadata keys to 'err'. Affected log-message
assertions in co-located specs are updated accordingly.

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

* ci: ignore validator output

* fixup new merged in log messages

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 06:53:37 +00:00
Jamie Tanna df7aa7b687 chore(workers/repository): instrument calculation of limits (#44581)
As part of an investigation around `commitHourlyLimit` performing slowly
on a repository with many branches, we can introduce more
instrumentation to be able to debug further.
2026-07-14 16:09:22 +00:00
Jamie Tanna 121f5df81d chore: log how many branches commitHourlyLimit is being calculated against (#44575)
As it can be useful to know on large repositories.
2026-07-14 13:55:42 +00:00
Sebastian Poxhofer d57843c60d refactor(oxlint): enable typescript/no-unnecessary-type-arguments (#44555)
Enable the type-aware typescript/no-unnecessary-type-arguments rule as
error and remove all 44 pre-existing redundant type arguments (type
arguments identical to the type parameter default), e.g.
HttpResponse<string>, ZodError<unknown>,
PackageDependency<Record<string, any>>.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 12:33:42 +00:00
Sebastian Poxhofer 9717259ffc refactor(oxlint): enable no-else-return and unicorn/no-lonely-if (#44553)
Enable no-else-return (with allowElseIf: false) and unicorn/no-lonely-if
as errors in .oxlintrc.json and fix all 131 pre-existing violations
(91 no-else-return, 40 unicorn/no-lonely-if) across 98 files.

The no-else-return violations were fixed with the oxlint autofix
(iterated to a fixpoint, plus two else-if chains that required
--fix-dangerously) followed by Prettier formatting. One comment dropped
by the autofix in lib/modules/manager/pub/artifacts.ts was restored
manually. The unicorn/no-lonely-if violations were merged by hand,
preserving comments and coverage-ignore hints.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 12:11:21 +00:00
Sebastian Poxhofer 7436b80cda test(linter): add renovate/no-redundant-mock-reset rule (#44557)
ci(linter): add renovate/no-redundant-mock-reset rule

Vitest sets mockReset: true globally in vitest.config.mts, which resets
all mocks before each test. This makes vi.resetAllMocks() /
vi.clearAllMocks() and per-mock .mockReset() / .mockClear() calls inside
beforeEach/afterEach hooks redundant. Add a custom oxlint rule (enabled
for **/*.spec.ts and test/**) flagging such calls, and remove the 40
redundant calls it found. restoreAllMocks/mockRestore are not flagged
because restoreMocks is not enabled globally.

Two sites keep an inline disable with a reason: nested beforeEach hooks
in filter-checks.spec.ts and onboarding/pr/index.spec.ts intentionally
call mockReset() to discard once-values queued by an outer beforeEach.

Requested by maintainer review feedback (review comment 3052324877).

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 11:26:20 +00:00
Sebastian Poxhofer ad0b59f8b7 refactor(oxlint): enable vitest/require-to-throw-message (#44421) 2026-07-07 17:47:04 +00:00
Sebastian Poxhofer 171a591d84 feat(git): validate commit shas (#43988)
* feat(git): validate length commit shas

* test: adapt test mocks

* chore: update import paths

* feat(git): make the validation more strict and support repositories using sha256

* test: add fakeSha function for deterministic git commit shas in tests
2026-06-15 06:36:57 +00:00
Jérémy Fauvel 5646cbae8c fix: use lockedVersion for currentVersionTimestamp lookup (#42476)
break line
2026-06-09 09:28:35 +00:00
Michael Kriese 058faaa872 fix(worker/lookup): don't use a range as current version (#43737) 2026-06-02 12:46:05 +00:00
Sebastian Poxhofer 914c64afbd test(linter): zod schema and infered type naming rule (#43736)
* ci: add linting rule for schema and infered types

* refactor: remove usages of Schema and differently named types
2026-06-02 12:07:35 +00:00
Sebastian Poxhofer 15f4bd8eff chore: migrate from zod/v3 to zod/v4 (#43691)
* chore: migrate from zod/v3 to zod/v4

This commit contains the logic changes

* chore: migrate imports from zod/v3 to zod/v4

This contains import updates and adds explicit record keys as zod/v4 requires these now

* ci: enforce usage of zod/v4
2026-05-30 16:01:58 +00:00
Björn Kautler 950f9a40a7 fix(lookup): try to find a release for changelog by newVersion if not found by newValue (#38894)
* fix(lookup): try to find a release for changelog by newVersion if not found by newValue

* Review Feedback Vol. 1

* Review Feedback Vol. 2
2026-05-27 11:31:56 +00:00
Sebastian Poxhofer 73b90e958b refactor: remove string concetation for production code (#43442)
refactor: prefer templates rather than `+`
2026-05-19 13:31:27 +00:00
Sebastian Poxhofer 0793274b86 refactor: prefer templates rather than + in test files (#43441)
refactor: prefer templates rather than `+`
2026-05-19 09:52:28 +00:00
Johannes Feichtner b05b21802d feat(vulnerabilities): support golang-version toolchain directive for OSV vulnerability alerts (#43333) 2026-05-14 06:05:17 +00:00