* fix(github): treat graphql_rate_limit as rate limiting
GitHub answers a spent app-installation budget with a GraphQL error carrying
code graphql_rate_limit, which neither call site recognised: the repository
query reported platform-unknown-error, and app authentication reported
Init: Authentication failure. Both readings send the user looking for a
problem that is not there, and neither is retried the way rate limiting is.
The two shapes are now recognised in one place and both call sites use it.
* fix(github): propagate GraphQL rate limits
* fix(github): preserve GraphQL response contract
---------
Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com>
Refs #45216
The object counterpart to `prefer-coerce-array`: `x ?? {}` becomes
`coerceObject(x)`. The rule flags a `??` whose default is a bare `{}`
literal, so a populated default or an asserted `({} as Foo)` still
passes; a `x ?? y ?? {}` chain maps onto `coerceObject(x, y)`.
Every hit across `lib/` converted cleanly, so no disable comments were
needed.
* test: replace manual process.env mutation with vi.stubEnv
Enable Vitest's `unstubEnvs` so env stubs are reverted automatically
before every test, and convert the manual `process.env.X = ...` /
`delete process.env.X` pairs in specs to `vi.stubEnv()`.
This removes the hand-written `afterEach` cleanup blocks and the
`const OLD_ENV = process.env` / `process.env = { ...OLD_ENV }`
save-restore dance, which silently leaked state between tests when a
test set a variable without a matching delete.
Left as-is (incompatible with `unstubEnvs`, which unstubs before each
test, not after):
- module top-level env writes (cocoapods, gomod, post-update, pip-compile
and bundler artifacts specs)
- `beforeAll` env writes -- the two in `util/http` moved to `beforeEach`
* test: stop asserting on ambient environment variables
Three specs asserted on values that the surrounding environment can
override, so they only passed on a machine that happened not to set them:
- `util/exec/env`: `getChildProcessEnv()` forwards every entry of
`basicEnvVars`, but the spec only seeded a subset. Any other forwarded
variable that was set ambiently (e.g. a lowercase `http_proxy`) leaked
into the `toEqual` assertion. Clear all of them first.
- `util/git/index`: `process.env.GIT_SSH_COMMAND` deliberately overrides
the default that the two env-inheritance tests assert on. Clear it.
- `logger/pretty-stdout`: the colorized level strings are built at import
time, so the `beforeEach` setting `FORCE_COLOR` could never affect them
-- it was dead code, and the test silently assumed a terminal without
colour support. Derive the expectation the same way the module does.
* test(datasource/nuget): use a throwaway cache dir for nupkg downloads
The `determine source URL from nupkg` tests do not mock the filesystem,
so they really wrote downloaded packages into a fixed `/tmp/cache` path.
That fails wherever the system tmpdir is not writable, and two checkouts
running the suite at once would share the same directory.
Use `tmp.dir({ unsafeCleanup: true })` and clean it up afterwards, which
is the pattern the other specs that touch disk already use.
* feat(lint): add renovate/prefer-stub-env rule
Enforces in specs what the migration to `vi.stubEnv` established:
- assigning to or deleting `process.env.X` inside `beforeEach`, `afterEach`,
`it` or `test` is reported, with a fixer that rewrites it to `vi.stubEnv()`
- module scope, `describe` bodies and `beforeAll` / `afterAll` are left alone:
`unstubEnvs` reverts stubs *before* each test, so a stub created there is
gone by the time the first test runs, and those must keep assigning directly
- replacing the `process.env` object is reported everywhere and never fixed.
`vi.stubEnv()` captures the original object when the worker starts, so after
a reassignment its deletes silently target the old object
The rule found 28 further violations in specs the earlier sweep missed, since
that one was anchored on `delete process.env`. Twelve were auto-fixed; the
rest replaced `process.env` wholesale and are now `clearEnv()` from test/util.
`util/exec/index.spec.ts` opts out with a comment: it asserts on the whole
child env, and `vi.stubEnv()` cannot express that because it maps `PROD`,
`DEV` and `SSR` onto '' instead of deleting them.
* feat(http/bitbucket): warn when an endpoint announces a deprecation
To highlight to a self-hosted administrator when they are using
deprecated/removed functionality, we can look for i.e.
sunset: Fri, 21 Aug 2026 00:00:00 UTC
deprecation: @1771545600
link: <https://developer.atlassian.com/cloud/bitbucket/changelog#CHANGE-3071>; rel="deprecation"; type="text/html"
This provides visibility into a soon-to-be-removed piece of
functionality, and should allow us to catch these deprecations more
centrally.
We make sure to log them - as a WARN - once, and with ISO8601 dates for
readability.
If we can't parse either `sunset` or `deprecation`, we log them as-is,
so we don't accidentally remove any necessary context.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
* fixup! feat(http/bitbucket): warn when an endpoint announces a deprecation
* fixup! feat(http/bitbucket): warn when an endpoint announces a deprecation
Co-Authored-By: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
---------
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
As part of follow-up changes, we'll want to check the response's
headers, which requires we have an additional hook that we can use.
By default, this is a no-op.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
To surface the deprecation or removal of features by Bitbucket Cloud,
there may be an error body such as:
{
"type": "error",
"error": {
"message": "CHANGE-3071 - Functionality has been deprecated",
"detail": "Please read the changelog entry for more details.",
"data": {
"announcement_url": "https://developer.atlassian.com/cloud/bitbucket/changelog#CHANGE-3071"
}
}
}
To make it more visible to a self-hosted administrator that they're
using deprecated/removed functionality, we can elevate this to a WARN
log line, if there is an `announcement_url`.
We make sure to handle both parsed JSON response bodies and a raw string
body used for other requests.
To reduce noise to a self-hosted administrator, we can log this once per
run.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
* ci(linter): add renovate/require-regex-util rule
Adds a custom oxlint rule that flags raw RegExp usage in lib/
production code: any `new RegExp(...)` call and any regex literal
that is not the direct first argument of `regEx(...)`. The regEx()
helper from lib/util/regex.ts uses the RE2 engine for ReDoS-safe
matching and caches compiled patterns. lib/util/regex.ts itself is
exempt.
The rule is disabled for **/*.spec.ts, test/**, and tools/** via
config overrides, because vitest APIs such as expect.stringMatching
need bare RegExp instances (a past commit reverted regEx() there).
Severity is set to "warn" instead of "error": the repo currently has
197 pre-existing violations (above the agreed mechanical-fix
threshold of 80), and a number of them are deliberately
RE2-incompatible patterns (lookahead/lookbehind/named backreferences,
see TODO #12872/#12875 markers in e.g. lib/modules/versioning/rez/
pattern.ts and lib/modules/manager/dockerfile/extract.ts) that need
per-site judgment before they can be wrapped in regEx() or suppressed
with a justified disable comment. No violation fixes are included in
this commit.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* ci(linter): enforce renovate/require-regex-util at error
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor: use regEx() for regex literals and RegExp construction in lib
Burn down all renovate/require-regex-util violations (197):
- wrap RE2-compatible regex literals and RegExp constructions in regEx()
- rewrite lookaround patterns where behavior is provably preserved:
goproxy separator split, sbt-package link extraction, leiningen
comment stripping and keyword search, npm GitHub owner validation
(unit-count bound replaced by an explicit length check)
- keep native RegExp with disable comments where RE2 cannot be used:
moo / good-enough-parser lexer patterns (moo rejects RE2 instances),
MigrationsService propertyName (matched via isRegExp, which RE2
instances fail), rez named backreferences and lookaheads, GitHub
markdown link negative lookbehind, emoji astral-plane matching
- drop stale TODO #12875 comments for patterns current re2 handles
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor: reduce require-regex-util disable comments
Rewrite the github massage-markdown-links URL regex to capture an
optional `api.` prefix in a named group (skipped in code) instead of
relying on a negative lookbehind, so both the base and global variants
can use regEx()/RE2 and their two disable comments are removed. Add
spec cases for api-prefixed URLs that match the URL shape.
Consolidate the four related line disables in rez/pattern.ts (bound and
range patterns emulating Python conditional patterns via named
backreferences and lookaheads, which RE2 cannot express) into a single
block disable/enable pair, matching the treatment of the lexer files.
Disable comment count drops from 13 to 8.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor(datasource/sbt-package): use named capture group in link regex
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor(manager/cake): restore original multiLineComment regex spelling
The [^] -> [\\s\\S] rewrite was only needed for an RE2 wrap that was
later reverted; keep the diff minimal.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(datasource/go): skip empty GOPROXY segments
The switch from a lookahead split to a capture-group split (needed because
RE2 has no lookahead support) changed how empty GOPROXY segments parse:
`a|,b` yielded `{ url: ',', fallback: '|' }` before and
`{ url: '', fallback: ',' }` after. The comma fallback only continues on
404/410, so a failing proxy ahead of an empty segment silently stopped the
lookup instead of falling through to the remaining proxies.
Empty segments carry no url to query, so drop them.
* refactor(datasource/go): use isTruthy for empty segment filter
* fix(datasource/go): filter empty segments before mapping
Filtering after the map broke the contextual typing from the
GoproxyItem[] annotation, widening fallback to string.
* refactor(platform/github): use regEx() for merge queue query stripping
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat(lint): add renovate/prefer-is-helpers and renovate/prefer-is-object rules
Flag ad-hoc type checks that have @sindresorhus/is equivalents:
- .filter(Boolean) -> .filter(isTruthy)
- typeof x === 'string' -> isString(x)
- x === null || x === undefined -> isNullOrUndefined(x) (and negation)
The typeof x === 'object' shape lives in a separate suggestion-only rule
(renovate/prefer-is-object, kept at warn) because isObject()/isPlainObject()
are not drop-in equivalents: null, arrays and functions behave differently.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor: fix renovate/prefer-is-helpers violations
Replace ad-hoc type checks with @sindresorhus/is helpers across lib/:
- 13x .filter(Boolean) -> .filter(isTruthy)
- 36x typeof x ==/!== 'string' -> isString(x) / !isString(x)
- 6x x === null || x === undefined -> isNullOrUndefined(x) (and negation)
Promote renovate/prefer-is-helpers to error now that the codebase is clean.
renovate/prefer-is-object stays at warn: its 15 remaining sites guard
parsed YAML/JSON or unknown values where isObject()/isPlainObject() are
not provably equivalent (null/array/function semantics).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor: enforce renovate/prefer-is-object at error level
Resolve the 15 remaining warnings and raise the rule from warn to error:
- Migrate 10 sites to isObject() where the guarded value provably cannot
be a function (parsed YAML/JSON, typed exec command arguments, or
test-controlled fixtures): helm-values, woodpecker, bun, pre-commit
managers, exec utils, file package cache, and the github http spec.
In the bun manager this also fixes a latent crash where a null
`workspaces` value would throw on the `in` operator.
- Keep 5 sites as reasoned oxlint-disable comments where excluding
functions is load-bearing: the byte-exact fingerprint canonicalizer
(2), the circularity walker, the zod result guard, and the generic
hasKey helper.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
To prevent potential SSRF attempts, we can ignore a
misconfigured/malicious `next` link, and log a warning.
Co-authored-by: Claude Opus 4.8 <jamie.tanna+claude-code@mend.io>
To prevent potential SSRF attempts, we can ignore a
misconfigured/malicious `next` link, and log a warning.
Co-authored-by: Claude Opus 4.8 <jamie.tanna+claude-code@mend.io>
As noted in #44756, this would allow templates across Renovate's
different usages to be able to use the `renovateVersion` string as a
template variable.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
fix(platform/gitlab): retry MR creation on transient source_branch race
GitLab occasionally rejects a merge request POST with
`400 {"message":{"source_branch":["does not exist"]}}` immediately after
a branch push succeeds, because the freshly pushed ref is not yet visible
to the API due to Gitaly eventual consistency. The request was not
retried, leaving an orphaned branch until the next run.
Extend the existing `calculateRetryDelay` hook (which already retries
transient `409 Resource lock` POST errors) to also retry this
`400 source_branch does not exist` case, reusing got's bounded
exponential backoff.
* feat(lint): add renovate/prefer-fs-util and renovate/prefer-luxon rules
Two shared-util substitution rules, both at warn level:
- renovate/prefer-fs-util flags value imports of fs, node:fs,
fs/promises, node:fs/promises, fs-extra and fs-extra/esm in lib/
source files outside lib/util/fs/, pointing to the scoped helpers
from lib/util/fs. Spec files and type-only imports are exempt.
A config-only change via no-restricted-imports was considered but
rejected: that rule is at error severity globally and per-path warn
severity is not expressible, so the 13 existing call sites would
break the baseline.
- renovate/prefer-luxon flags new Date(...) and Date.now() in lib/
source files, pointing to Luxon per best-practices. Date/time
utility modules (lib/util/date, lib/util/pretty-time,
lib/util/timestamp) and spec files (vi.setSystemTime etc.) are
exempt.
Baseline: 13 prefer-fs-util and 45 prefer-luxon warnings, zero errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor: use Luxon instead of new Date() at remaining call sites
Fixes all renovate/prefer-luxon violations for `new Date(...)`:
- `new Date().toISOString()` -> `DateTime.utc().toISO()` (byte-identical
output) in the http cache provider, schedule logging and PR cache.
- `new Date()` -> `DateTime.now().toJSDate()` for the git commit-date
fallback and the rubygems `syncedAt` markers (same `Date` values).
- rust-release-channel now computes the Rust 1.0 release date and nightly
version dates via `DateTime.utc(...)`; previously `new Date(y, m, d)`
used the local timezone while the epoch used UTC, so the comparison was
timezone-dependent at the boundary date. Tests run with TZ=UTC, where
behavior is unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor: use lib/util/fs helpers in repository worker
Fixes renovate/prefer-fs-util violations outside bootstrap code:
- `fs.ensureDir()` -> `ensureDir()` from lib/util/fs (same fs-extra call
underneath; it no-ops on an empty dir name, so the repository worker
spec now simulates the init failure via a rejected `initRepo` instead
of relying on `fs.ensureDir('')` throwing).
- `fs.remove(privateCacheDir())` -> `cachePathExists()` + `rmCache()`,
keeping the remove-if-present semantics while asserting cacheDir
containment.
Two call sites keep raw imports with reasoned disable comments:
- lib/util/modules.ts synchronously enumerates Renovate's own installed
module directories at import time.
- lib/util/cache/package/impl/sqlite.ts receives cacheDir as an explicit
argument during global initialization, before GlobalConfig (which the
scoped cache helpers resolve against) contains cacheDir.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(lint): promote prefer-fs-util and prefer-luxon to error
Both rules are narrowed to what is actually accepted practice before
being promoted:
prefer-luxon no longer flags `Date.now()`: it returns UTC-based epoch
milliseconds used for elapsed-time measurement and TTL arithmetic, which
is timezone-independent by construction. The mined reviewer feedback
behind this rule ("use Luxon for date arithmetic outside util") targets
timezone-dependent date construction/formatting, which cannot occur with
a raw millis number; the rule keeps flagging `new Date(...)`.
prefer-fs-util exempts code that legitimately needs raw fs access
because the scoped lib/util/fs helpers resolve against GlobalConfig
localDir/cacheDir, which does not exist yet or does not apply there:
- lib/logger/: log-file streams at user-configured system paths during
bootstrap; lib/util/fs also depends on the logger (import cycle).
- lib/workers/global/: creates baseDir/cacheDir themselves and
reads/writes user-supplied paths before GlobalConfig is seeded.
- lib/config-validator.ts: standalone CLI without GlobalConfig.
- lib/util/git/: owns the localDir lifecycle (clone, emptyDir, symlinks)
and private-key files with sync cleanup on process exit.
Also fixes a pre-existing tsc error in prefer-fs-util.js: `importKind`
is a TypeScript-ESTree extension missing from eslint's base AST types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor(fs): make rmCache ignore missing paths
All rmCache callers use it for cleanup, where a missing path is a
no-op, so bake force: true in instead of guarding call sites with
an existence check.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor(linters): exempt lib/instrumentation from prefer-fs-util
`lib/instrumentation/file-exporter.ts` landed on main while this branch
was open and imports `node:fs/promises` directly.
The exporter writes to a user-configured system path
(`RENOVATE_TRACING_FILE_EXPORTER_PATH`) outside `localDir`/`cacheDir`,
so the scoped helpers do not apply. `lib/instrumentation` is also
deliberately kept out of the module graph of instrumented libraries
(see the `⚠️` note in `lib/renovate.ts`), so it must not pull in
`lib/util/fs` and its config/logger dependencies. Exempt the directory,
as is already done for `lib/logger`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: shorten doc
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* ci(linter): add renovate/v8-ignore-reason rule
Flag coverage-ignore comments ("v8 ignore") that carry no justification.
Accepted forms: "-- reason" / "--- reason" (recommended) and the legacy
colon form "v8 ignore <kind>[ <count>]: reason", which is already
widespread in the codebase (29 sites). Bare "v8 ignore stop" markers are
exempt because the justification lives on the paired "start" marker. The
"v8 ignore next <N>" count form remains allowed; this rule only requires
a justification.
Registered as "warn" instead of "error": the repo currently has 119
reason-less v8 ignore comments, too many to fix mechanically in one PR,
so existing sites are left untouched and can be fixed incrementally.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* ci(linter): promote renovate/v8-ignore-reason to error
Record the empirical verdict on the contested "v8 ignore next <N>" count
semantics in the rule doc: verified against vitest 4 with
ast-v8-to-istanbul that the count is not honored - the ignore hint always
exempts exactly the next AST node regardless of N. Counts are therefore
inert and stay allowed; the rule keeps requiring only a justification.
Promoting to error so all remaining reason-less coverage-ignore comments
must be fixed; the burndown follows in subsequent commits.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
* refactor: add justifications to coverage-ignore comments (batch 1)
Give every reason-less "v8 ignore" comment outside the large platform
index files a site-specific justification explaining why the exempted
branch is untestable or defensive, as now required by the
renovate/v8-ignore-reason rule.
Also guard against a nullish comment.loc in the rule itself; the
merged-in stricter tools typechecking flagged the unguarded access.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
* refactor: add justifications to coverage-ignore comments (batch 2)
Cover the five large platform index files (github, bitbucket,
bitbucket-server, codecommit, gitlab) with site-specific reasons on
every "v8 ignore" comment, completing the renovate/v8-ignore-reason
burndown. Two meaningless ignore hints inside commented-out CodeCommit
mergePr code are dropped instead of annotated.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
* Apply suggestions from code review
Co-authored-by: Michael Kriese <michael.kriese@gmx.de>
* Update lib/util/regex.ts
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
* feat(platform/azure): support bearer token auth (auto-detect token type)
* refactor(platform/azure): use isPlainObject for JWT header check
Replace manual typeof/null check with isPlainObject() from
@sindresorhus/is in isProbablyJwt(). Remove unused _GlobalConfig
import from test file.
* refactor(platform/azure): use parseJsonc to parse JWT header
* test(platform/azure): use a real JWT in the set bearer token/endpoint test
* feat(platform/azure): log detected token type
* refactor(platform/azure): guard token before JWT check; remove outdated todo comment
* docs(platform/azure): restore TODO note about possibly-undefined token (#22198)
* refactor(platform/azure): move isProbablyJwt() and tests to new files lib/util/http/jwt.ts and lib/util/http/jwt.spec.ts
* refactor(platform/azure): use Json.safeParse() instead of parseJsonc() in isProbablyJwt()
* refactor(platform/azure): accept undefined token in isProbablyJwt and add guard to drop non-null assertions
* test(platform/azure): extract shared buildTestJwt helper and dedupe
* docs(platform/azure): reword the Entra ID token instructions
* chore(platform/azure): remove irrelevant lines from docstring
* refactor(platform/azure): export buildTestJwt() from new test/jwt-util.ts
* docs(platform/azure): use 1 for numbered lists
* refactor(test): extract arrow function from buildTestJwt
---------
Co-authored-by: Bastian Wenske <bastianwenske@outlook.de>
* refactor(oxlint): enable func-style
Enable the built-in func-style rule as ["warn", "declaration"] so that
named functions are written as function declarations instead of arrow or
function expressions assigned to variables, matching the convention in
docs/development/best-practices.md (Functions section). Inline arrow
callbacks are unaffected; prefer-arrow-callback continues to cover the
callback direction.
Severity is "warn" instead of "error" as a fallback: a repo-wide run
found 196 pre-existing violations (70 in spec files, 126 in production
code), exceeding the 80-violation fix threshold for this change, so no
violations were fixed here. Follow-up work can convert the offenders
(largest clusters: lib/modules/versioning/ruby, lib/util/cache/package,
lib/modules/versioning/maven, lib/modules/versioning/gradle) and then
raise the rule to "error". Note oxlint 1.72 also supports an
allowTypeAnnotation option if typed consts should remain arrows.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* ci(linter): enforce func-style at error
* refactor(func-style): convert const-arrow functions to declarations in with-cache spec and ruby versioning
* refactor(func-style): convert const-arrow functions to declarations in maven/gradle modules
* refactor(func-style): convert const-arrow functions to declarations in remaining versioning modules
* refactor(func-style): convert const-arrow functions to declarations in platform modules
Discriminated-union closures (ensureCommentRemoval byTopic/byContent
helpers in github, gitlab, bitbucket, bitbucket-server) needed the
narrowed field passed explicitly as a parameter, since function
declarations are hoisted and lose the outer if-narrowing that inline
arrow-function closures previously relied on.
* refactor(func-style): convert const-arrow functions to declarations across util/manager/datasource modules
One case (logger/renovate-logger.ts logOnceFn) is kept as an arrow
function with a documented oxlint-disable: it is stored on
this.logger.once[level] and relies on lexically-bound this, which a
hoisted function declaration would not preserve.
* refactor(func-style): convert remaining const-arrow test helpers to declarations
get-updated.spec.ts: hoisted expectPipCompilePackageAndLockFile to
module scope (it only closes over the module-level pipCompile mock)
and added a documented oxlint-disable for vitest/expect-expect on its
caller test, since oxlint's expect-expect check does not trace
assertions through an externally-defined helper function.
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* 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>
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>
refactor(oxlint): enable vitest/consistent-test-it
Enforce `it` over `test` in spec files via
vitest/consistent-test-it (fn: "it"), matching repo convention.
Renamed all 52 pre-existing `test(`/`test.each` usages across
13 spec files to `it(`/`it.each` using oxlint --fix.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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>
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>
* fix(datasource/npm): require public Cache-Control to cache responses
The npm datasource opts out of the authorization-header privacy check
(checkAuthorizationHeader: false) and relies on Cache-Control alone to
classify responses. Previously, when a registry omitted Cache-Control
entirely, cacheAllowed fell through to "cache it" — so private packages
served by GitHub Packages (which sends no Cache-Control header) were
cached in the shared package cache.
Flip the semantic of checkCacheControlHeader: true to require an
affirmative Cache-Control: public signal. Missing or non-public headers
now disallow caching. registry.npmjs.org is unaffected because it
already sends Cache-Control: public, max-age=...
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(cache): avoid renewing disallowed package cache on 304
* Revert "fix(cache): avoid renewing disallowed package cache on 304"
This reverts commit 64801bb036269352465aac580b9861c5b7716cc1.
- Convert `param: T | undefined = undefined` to optional `param?: T`.
- Drop dead `= false` defaults on the required cache-provider options.
- Make `GraphqlPaginatedContent.nodes/edges` optional so the `= []`
fallbacks (load-bearing for partial GraphQL connections) are valid.
- Type the unchecked `default_branch` response field as optional so
the `'HEAD'` fallback is retained.
- Drop `tag = undefined` from the Forgejo/Gitea/GitLab preset configs.
Part of #43845
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
As a follow-up to e1e5c398e0, we can make
sure that we remove references to hardcoded docs site URLs, by wiring in
the `GlobalConfig.get(...)` call.
To do this, we need to make sure that `productLinks` exists to be called
by `GlobalConfig.get`.
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
* chore: ensure we use `productLinks` for docs site links where possible
Where possible, we should be making sure that we're using the
`productLinks`' configuration for the documentation site, especially
where self-hosted users may create a mirror of their docs[0].
To make sure we catch this in the future, we can introduce a custom
linting rule with Oxlint to enforce this.
Where we (currently) can't wire in the config, we can disable it against
that line.
[0]: https://www.jvt.me/posts/2024/11/19/renovate-private-docs/
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
* fixup! chore: ensure we use `productLinks` for docs site links where possible
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
* fixup! chore: ensure we use `productLinks` for docs site links where possible
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
---------
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
* fix(util/http): remove workaround for `onCancel`
As we're now past the necessary verison of Got, we can remove this
workaround.
* fixup! fix(util/http): remove workaround for `onCancel`
* 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
* feat(self-hosted): make `user-agent` templatable
For Mend-hosted apps, it would be useful to provide a little bit more
information for where a Renovate HTTP request is coming from.
To provide more control over the generated field, we can make it
templatable, with the option to specify the `renovateVersion`.
As this now exposes Handlebars syntax to the user, we should be clear
that this `supportsTemplating`, and document with tests what this
allows.
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
* fixup! feat(self-hosted): make `user-agent` templatable
* fixup! feat(self-hosted): make `user-agent` templatable
As we're now returning the defaults in `GlobalConfig.get` calls.
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
---------
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
* fix(config/global): return default values for `GlobalConfig.get`
As noted in #39949, it can be awkward working with in `GlobalConfig.get`, where
we would previously need to specify the default value when calling `.get`,
which could lead to drift with the defaults for a given config option.
To reduce this risk, we can rely on a given `default` for a configuration
option, providing that as a default.
Because this now definitely returns a value that matches the config option, it
now allows us to remove `!` assertions.
* fixup! fix(config/global): return default values for `GlobalConfig.get`
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
* fixup! fix(config/global): return default values for `GlobalConfig.get`
* test(presets): remove impossible test
As it's now not possible to set a value as `undefined` (as
`GlobalConfig` will then use the default), this test no longer validates
anything.
* test(workers/repository): add mock
Now `platform` defaults to `github`, we need to mock out the call to
fetch config.
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
* test: coverage
* test: coverage
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
* test(noNewURL): add new rule enforcing parseUrl() from 'lib/util/url.ts'
* replace newURL with parseUrl
* remove non-null assertions marks if appropiate
* test: add additional tests
* test: add additional tests and ignore where it makes sense
* implement suggestions
* test: further improve coverage
* apply suggestion
* fix(http): fallback to github hostType for GHE platform endpoint
When running against GitHub Enterprise Server, datasources not listed
in GITHUB_API_USING_HOST_TYPES (e.g. github-digest) fail to authenticate
because the existing fallback only covers api.github.com URLs.
This adds a host-matching fallback: when the active platform is github
and the request URL targets the same host as the configured endpoint,
credentials from the github hostType rule are applied.
* Refactor
* Fix
* fix: Add `github-digest` to `GITHUB_API_USING_HOST_TYPES` list
* fix(http): detect x-access-token prefix before hostType-based auth branching
Moves GitHub App installation token detection (`x-access-token:` prefix)
before the hostType-based authorization chain in `applyAuthorization`.
This ensures correct `token` scheme auth for any GitHub-related hostType,
not only those listed in `GITHUB_API_USING_HOST_TYPES`.
* test(http/auth): add regression test for GitHub App token with non-listed hostType
* Fixes
* Fix tests
* - Added Renovate support for the [SCM-Manager](https://scm-manager.org/)
- SCM-Manager is a repository management tool like GitHub
- It is maintained as an open source project by the company [Cloudogu](https://cloudogu.com/en/)
- The SCM-Manager support is not feature complete yet, features like auto merging are still missing
- The SCM-Manager also got added to the documentation as another platform
author Thomas Zerr <thomas.zerr@cloudogu.com> 1690877165 +0200
committer Eduard Heimbuch <eduard.heimbuch@cloudogu.com> 1706264263 +0100
* Reverted numbering change in markdown docs
* Changed from type to interface, if possible
* Removed axios dependency and using the http layer of renovate instead
* Fixed not using scmm specific mime types for accept header
* Use git from test/util instead
* Add dummy tests for no ops
* Fix some phrasing and spelling issues
* Change scmm to scm-manager and fix SCM-Manager specific content type
* Add supported major versions, review plugin requirement, write permissions is needed
* Change using actual host rules instead of mocking it
* Change use http mocks for testing
* Update docs/usage/getting-started/running.md
Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com>
* Update lib/modules/platform/scm-manager/index.ts
Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com>
* Update lib/modules/platform/scm-manager/mapper.spec.ts
Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com>
* Update lib/modules/platform/scm-manager/readme.md
Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com>
* Update lib/modules/platform/scm-manager/readme.md
Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com>
* Update lib/modules/platform/scm-manager/readme.md
Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com>
* Update lib/modules/platform/scm-manager/readme.md
Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com>
* Update lib/modules/platform/scm-manager/readme.md
Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com>
* Fix scm-manager docs link
* Fix linting
* Fix linting
* Throw errors if username or token is not provided by the host rules
* Replace NO-OP with Not implemented
* Remove objects from log messages
* Fix linting
* Fix path to platform config options
* Fix link to self-host-configuration docs
* Fix link to self-host-configuration docs
* Remove the link to the platform config option, because the tests keep failing
* Fix link to self-host-configuration docs
* Remove not needed type cast
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
* Fix type check of protocol links
* Move scm-manager into util http folder
* Apply linting
* Add maxBodyLength function and its test
* Add test case if protocol links are not an array of links
* Use zod schema for pagination
* Apply linting
* Refactor typing with zod schema
* Fix test description
Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com>
* Fix test description
Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com>
* Fix test description
Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com>
* Fix test description
Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com>
* Update readme
Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com>
* Add try catch around fetching the current user
* Switch log statement from info to debug
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
* Switch log statement from info to trace
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
* Switch log statement from debug to trace
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
* Switch log statement from info to trace
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
* Switch log statement from info to trace
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
* Switch log statement from info to trace
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
* Fix linting errors
* Remove credentials check in initRepo
* Fix imports
* Fix zod schema for repositories
* Fix zod schema for pull requests
* Fix 500 error after attempting to update an pr
* Fix wrong typing
* Refactor parameterized tests for better readability
* Refactor SCM HTTP API
* Add setToken functionality
* Remove not needed type definition
Co-authored-by: Michael Kriese <michael.kriese@gmx.de>
* Fix assertion
* Fix istanbul comment
* Change log statement
* Remove type rename
* Move inferred types close to corresponding schemas
* Add platform is experimental
* Remove type renaming
* Fix type imports
* Fix test suite description
* Remove debug log statement
Co-authored-by: Michael Kriese <michael.kriese@gmx.de>
* Fix warning
* Fix paremeterized unit tests with string templates
* Fix spelling
Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com>
* Fix eslint error
* Convert trace logs to debug logs
* Convert info logs to debug
* Replace manual null and undefinded check with is util
* Rephrase instruction in readme
* Use ensureTrailingSlash instead
* Fix linting
* Keep type and schema together
* Simplify hasAssignees check
* Simplify reviewer mapping
* Remove istanbul comments
* Replace custom scmm header option with renovate native http headers option
* Let the token be passed in initPlatform
* Add description which permissions are needed
* Add support for ignorePrAuthor filter
* Add notes about automerge feature within platform readme
* Add support for fast_forward_only
* Change supported versions due to merge strategy change
* Remove commented code
* Fix import
* Use email schema
* Heed review advice
* Fix import and empty array assertions
* Fix linting issue
* Fix import errors
* Fix removed ignorePrAuthor parameter from initRepo function
* Fix failing unit tests by setting/reseting the global config
* Mark scm-manager as experimental
* Fix zod import path
* Change endpoint configuration, so that user only needs to define origin, but not also the path
* Fix warning of redundant backslash
---------
Co-authored-by: Eduard Heimbuch <eduard.heimbuch@cloudogu.com>
Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
Co-authored-by: René Pfeuffer <rene@pfeuffer-web.de>
Co-authored-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: René Pfeuffer <rene.pfeuffer@cloudogu.com>