Commit Graph

158 Commits

Author SHA1 Message Date
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
Sebastian Poxhofer 762ac01133 test(platform): replace file snapshots with explicit assertions (#45684)
* test(manager): replace file snapshots with explicit assertions

* test(manager): replace inline snapshots with explicit assertions

* test(manager): assert on relevant sections instead of full bodies

* test(manager): drop assertions implied by full equality

* test(manager): address review feedback

* test(manager): assert depType and versioning in the regex matcher

* test(bundler): replace file snapshots with explicit assertions

* test(bundler): replace inline snapshots with explicit assertions

* test(bundler): drop assertions implied by full equality

* test(bundler): address review feedback

* test(npm): replace file snapshots with explicit assertions

* test(npm): replace inline snapshots with explicit assertions

* test(platform): replace file snapshots with explicit assertions

* test(platform): replace inline snapshots with explicit assertions

* test(platform): assert on relevant sections instead of full bodies

* test(platform): address review feedback

* test(platform): use resolves instead of awaiting inside expect
2026-09-04 10:28:54 +00:00
Sebastian Poxhofer 3412de84ce refactor(linters): enable oxlint rule prefer-named-capture-group (#44714)
* refactor(lint): enable oxlint prefer-named-capture-group at error

Numbered capture groups (m[1], $1) break silently when a regex is
edited and group order shifts. Named groups (?<name>...) make intent
explicit and accesses (m.groups.name) resilient to reordering.

This enables the built-in eslint rule prefer-named-capture-group,
surfacing 321 pre-existing unnamed-group violations across ~121
files to be burned down incrementally in follow-up commits.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk

* refactor(versioning): name capture groups for prefer-named-capture-group

Burns down all prefer-named-capture-group violations in
lib/modules/versioning/. Unused capture groups (only reachable via
.test() or whole-match) become non-capturing (?:...); groups whose
value is read become named (?<name>...), with accesses rewritten to
match.groups!.<name> (or destructured from .groups!) instead of
positional match[n]/$n so a future edit that reorders groups cannot
silently break the reader.

Two cases needed extra care to preserve behavior:
- semver/common.ts and poetry/patterns.ts split() on a regex whose
  capture group is relied upon by String.prototype.split to keep the
  separator in the output array; the group is kept capturing and
  named, not converted to non-capturing.
- hashicorp/convertor.ts's semverRegex is only ever embedded via
  .source into a named `(?<version>...)` group elsewhere and never
  matched directly, so its internal groups are safe to make
  non-capturing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk

* refactor(datasource): name capture groups for prefer-named-capture-group

Burns down all prefer-named-capture-group violations under
lib/modules/datasource/. Same treatment as the versioning module:
unused groups become non-capturing, used groups get names, and
positional match[n] reads move to match.groups!.<name>.

docker/ecr.ts and pypi/common.ts keep their positional destructuring
(`const [, region] = ...`, `!!m &&`) working unchanged since a named
capture group is still addressable by its numeric index in
JavaScript — only pypi/common.ts's access was rewritten to
m.groups!.owner for clarity since it read a single group directly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk

* refactor(platform): name capture groups for prefer-named-capture-group

Burns down all prefer-named-capture-group violations under
lib/modules/platform/. Uses the repo's established idiom of
`match.groups?.<name>` after an optional-chained exec()/match() (see
bitbucket/index.ts hostnameWithoutApiPrefix, gerrit/utils.ts
extractSourceBranch) and `$<name>` in String.replace replacement
strings. Unused groups (markdown/HTML massaging regexes matched only
to be stripped) become non-capturing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk

* refactor(manager): name capture groups in ansible-galaxy for prefer-named-capture-group

Burns down prefer-named-capture-group violations in
lib/modules/manager/ansible-galaxy/. newBlockRegEx and blockLineRegEx
dropped their unused outer wrapping group (only the inner key/value
groups were ever read) and named the key/value groups; nameMatchRegex's
remaining unused groups (protocol/user-info/port alternatives) become
non-capturing since only source/hostname/depName/version are read via
.groups. Accesses in collections.ts and roles.ts move from
lineMatch[2]/lineMatch[3] to lineMatch.groups!.key/value.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk

* refactor(manager): name capture groups for prefer-named-capture-group (batch 1)

Burns down prefer-named-capture-group violations across the first
alphabetical slice of lib/modules/manager/ (ansible through mix).
Used groups get names with accesses rewritten to match.groups!.<name>
(or $<name> in replacement strings); groups whose value is never read
become non-capturing (?:...). Two String.split() call sites
(git-submodules/extract.ts, meteor/extract.ts) keep the established
"named group still readable positionally from the split() result
array" idiom instead of restructuring the destructuring.

bazel/rules/go.ts and buildpacks/extract.ts dockerRef verified
byte-for-byte equivalent before/after via a quick node script since
several nested groups collapsed to non-capturing at once.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk

* refactor(manager): name capture groups for prefer-named-capture-group (batch 2)

Burns down prefer-named-capture-group violations across the remaining
alphabetical slice of lib/modules/manager/ (npm through terragrunt).
Same treatment as batch 1: used groups get names with accesses moved
to match.groups!.<name> or $<name> replacement strings; unused groups
(wrapping alternations, quantifier repetition groups only consumed via
.test(), or values never read from a match) become non-capturing.

terraform/extractors/others/modules.ts and terragrunt/modules.ts share
near-identical URL-parsing regexes (github/bitbucket/git/azure-devops
ref matchers) — the same set of always-unused `depth=`/`&depth=`
query-string groups is converted to non-capturing in both files.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk

* refactor(config): name capture groups for prefer-named-capture-group

Burns down prefer-named-capture-group violations in lib/config/.
Used groups get names with replacement strings switched from $1/$2 to
$<name>; the unused separator group in schedule-migration.ts's
afterBeforeRegex becomes non-capturing. presets/parse.ts keeps
assigning through the already-declared `repo` variable rather than
array-destructuring the exec() result, matching this file's existing
style for the other named-group regexes just above it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk

* refactor(util): name capture groups for prefer-named-capture-group

Burns down prefer-named-capture-group violations across lib/util/ and
lib/logger/. Same treatment as previous batches: named groups for
values that are read (via $<name> replacement strings, .groups!.<name>,
or destructured from .groups), non-capturing groups where nothing reads
the captured value (e.g. semantic.ts's angular-commit .test()-only
regex). www-authenticate.ts's tokenizer entries each get their own
named group but keep accessing the match generically via match[1],
since a positionally-indexed named group is still readable by index.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk

* refactor(workers): name capture groups for prefer-named-capture-group

Burns down prefer-named-capture-group violations in lib/workers/.
Used groups get names with $<name> replacement strings; unused
wrapper/alternation groups (e.g. semantic-commit-message.ts's optional
scope/issue wrappers, release-notes.ts's date-heading and
horizontal-rule matchers that are only probed with .search()/replaced
wholesale) become non-capturing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk

* refactor(test,tools): name capture groups for prefer-named-capture-group

Finishes the prefer-named-capture-group burndown: test/, tools/, and
vitest.config.mts. Groups whose value is read get names ($<name>
replacement strings or .groups.<name> access); groups only used via
.test()/.search() or that feed a .match(/…/g) call (whose return value
is the array of whole matches, not captured groups) become
non-capturing.

This is the last remaining slice of pre-existing violations, so the
rule (already enabled at error repo-wide) now passes with zero
findings across the whole codebase.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk

* fix prettier failure

* refactor(lint): use a named capture group in `v8-ignore-no-count`

New rule from main trips the newly enabled `prefer-named-capture-group` oxlint rule.

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-09-03 09:54:40 +00:00
Abizer 7a6e7b2880 fix(azure): filter pull request queries by Renovate author (#45359)
* implement plan

* add tests

* fix initialization order

* cast contexts to WebApi for type safety in authHandler checks

* fix(azure): scope PR filtering to effective credentials (#1)

* fix(azure): scope PR filtering to effective credentials

* fix(azure): address authentication review feedback

* fix: reorder import statements

* Address review comments

* fetch renovate user id in initPlatform

---------

Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com>
2026-09-03 08:26:18 +00:00
Jamie Tanna b62fe59594 fix: remove references to "bot" (#39305)
We dropped the "bot" from our terminology long ago, but it looks like
we've got some outdated docs + code that reference it.

We should remove this to keep things consistent.

A `fix`, as we're changing the commit author's name, and log lines.

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-09-02 08:56:20 +00:00
Sebastian Poxhofer e0cec3dc95 refactor(lint): add types-location rule and enable it for lib/modules (#45497)
feat(lint): add `types-location` rule and enable it for `lib/modules`

Reviewers consistently ask for exported types to be moved into a
colocated `types.ts`. Add a `renovate/types-location` oxlint rule that
reports `export interface` / `export type` declarations outside such a
file, and turn it on across `lib/modules`.

Re-exports (`export type { X }`, `export type *`), file-local types, and
values (enums, classes, functions) are left alone. `schema.ts` files and
`schema/` directories are excluded via config, matching how
`zod-schema-location` is configured — inferred types belong next to the
schema they are derived from.

Relocating the 87 existing violations means:

- new `types.ts` files for the modules that had none
- `terragrunt/common.ts` folded into its `types.ts`, as it held nothing
  else
- `RangeBound` in `versioning/gradle/compare.ts` un-exported, since only
  a file-local interface referenced it
- `bazel-module/parser/fragments.ts` split from its inferred types, which
  now live in `parser/types.ts` and infer through a namespace import so
  each schema keeps its merged name
2026-08-27 19:52:09 +00:00
RahulGautamSingh 694410d4bb fix(platform/azure): detect hosted deployment when deploymentType is a string (#45440) 2026-08-25 10:35:24 +00:00
Sebastian Poxhofer a1971afa78 fix(linters): add linting rule to enforce usage of our regEx utility (#44690)
* 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>
2026-08-14 14:30:46 +00:00
RahulGautamSingh d678372061 fix(platform/azure): skip work item Markdown format on Azure DevOps Server (#45237) 2026-08-12 14:04:20 +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
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
RahulGautamSingh e0714e0d23 feat(azure): make issue work item type configurable (#44736)
* feat(azure): make issue work item type configurable

* move azureWorkItemType to Config

* fix type

* add docs url using productLinks

* apply suggestions

* Update lib/modules/platform/azure/issue.ts

Co-authored-by: Sebastian Poxhofer <secustor@users.noreply.github.com>

* fix ci + doc addition

* fix docs lint

---------

Co-authored-by: Sebastian Poxhofer <secustor@users.noreply.github.com>
2026-07-24 09:19:11 +00:00
Sebastian Poxhofer 91e068f1fd test(linters): add linting rule to enforce v8 ignore reason declaration (#44726)
* 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>
2026-07-20 13:01:39 +00:00
Jamie Tanna 7ac677dc9b fix(platform/azure): evaluate policies before attempting to merge PR (#44631)
When a PR created on Azure is inside a project or repository that has
additional policy evaluations that need to be fulfilled for a given PR,
we should not attempt to perform a manual `mergePr` unless the policies
allow us to.

Previously, we would attempt to `mergePr` and would result in

    DEBUG: Failed to set the PR as completed.

Platform-native auto-merge functionality would still work as expected,
as once the evaluations had succeeded (for instance, a PR is approved by
a human) Azure will auto-merge it.

However, the failure in attempting to merge it is noisy, and should be
avoided by evaluating the policies before attempting to merge.

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-07-20 09:21:55 +00:00
Jonathan Hill 0f06e635df feat(platform-azure): initial bearer token auth support for Azure DevOps (#43888)
* 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>
2026-07-19 23:01:52 +00:00
Sebastian Poxhofer 58771bb183 refactor(linters): enabled oxlints func-style (#44691)
* 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>
2026-07-19 11:14:22 +00:00
Sebastian Poxhofer 5ad36a2387 test(linters): add linting rule to enforce usage of host rules test util (#44692)
* ci(linter): add renovate/no-host-rules-mock rule

Flags vi.mock()/vi.doMock() calls whose module specifier contains
"host-rules" in spec files. Tests should configure real rules via
hostRules.add() instead of mocking the host-rules module.

Enabled at "warn" severity instead of "error": the repo currently has
35 pre-existing violations across 34 spec files, which exceeds the
agreed fix threshold of 12 files. No violation fixes are included;
migrating each spec to real hostRules.add()/clear() setup is a
semantic test rewrite that should be done incrementally, after which
the rule can be promoted to "error".

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

* ci(linter): enforce renovate/no-host-rules-mock at error

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

* test(datasource): use real host-rules instead of mocking

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

* test(manager): use real host-rules instead of mocking

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

* test(platform): use real host-rules instead of mocking

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

* test(util,workers): use real host-rules instead of mocking

Also narrow renovate/no-host-rules-mock to the host-rules module itself so that mocking e.g. host-rules-from-env is not flagged.

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

* ci(linter): mention '~test/host-rules.ts' util in no-host-rules-mock message

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

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 10:36:12 +00:00
Sebastian Poxhofer 4add67e86e test: add linter for as any in test files (#44658)
* ci(linter): add prefer-partial-in-specs oxlint rule

Flags object literals cast to `any` (`{...} as any`) in spec/test files and steers toward `partial<T>()` from `test/util`. Enabled at error in the spec-files override so CI blocks new occurrences.

Closes #44646

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test: drop unnecessary object-literal `as any` casts

The casts masked values already assignable to the expected type (migration configs accepted as Record<string, unknown>, all-optional param types, etc.); removing them restores real type checking.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test: replace object-literal `as any` casts with partial<T>()

Uses partial<T>() from test/util so incomplete mock/config objects keep proper typing. Azure API mocks switch to mockResolvedValue(partial<T>()) and their inner method mocks to mockResolvedValue(), matching the sibling-file idiom.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test: suppress prefer-partial-in-specs for intentionally-invalid inputs

Some tests deliberately pass malformed or legacy data to exercise validation/error paths, where no real type fits; keep the cast with a reasoned oxlint-disable-next-line.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 10:47:30 +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
Emanuel Besliu 2d431ea7a7 fix(platform/azure): don't create Dependency Dashboard for projects without an Issue type (#44592)
* fix(platform/azure): guard against null work item on issue creation

The Azure DevOps REST client resolves createWorkItem to null (instead of
throwing) on a 404 or any 2xx response with an empty/non-JSON body, such
as a 203 sign-in page returned by an expired token or an SSO/proxy in
front of the instance. ensureIssue then dereferenced newWorkItem.id
unconditionally, crashing the dependency dashboard run with
"Cannot read properties of null (reading 'id')".

Guard the result and skip the issue with a warning instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(platform/azure): detect missing Issue work item type

Check that the project's process defines the 'Issue' work item type
before attempting to create one. Processes such as Scrum do not define
it, so createWorkItem returned a 404 that the REST client surfaces as
null, producing a cryptic crash. Log an actionable warning instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* test(platform/azure): mock getWorkItemTypes in ensureIssue create test

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-15 09:57:02 +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
Emanuel Besliu 483890a8f1 fix(platform/azure): resolve work item states from process (#44412)
* fix(platform/azure): resolve work item states from process

Renovate hardcoded the Azure Boards work item state to `New` on
create/reopen and `Closed` on close. Processes that don't have those
states (Basic uses To Do/Done; custom inherited processes vary) reject
the request with "The field 'State' contains the value 'New' that is not
in the list of supported values", so the Dependency Dashboard (and any
issue) could not be created or closed.

Resolve the concrete open/closed state names for the `Issue` work item
type from its process via `getWorkItemTypeStates`, grouped by state
category (Proposed/InProgress = open, Completed/Resolved/Removed =
closed). Omit `System.State` on create so Azure DevOps applies the work
item type's default initial state. Classify issues open/closed by state
category rather than the literal `Closed`. Fall back to the previous
`New`/`Closed` names when the states cannot be read (e.g. older ADO
Server). Result is cached per repository.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(platform/azure): prefer Completed state as close target

Address review: closedNames[0] picked the first state across the
Completed/Resolved/Removed categories in workflow order, so processes that
order a Resolved-category state before the Completed one (e.g. a custom
inherited Agile process) would close work items to `Resolved` instead of
`Closed`, changing prior behavior.

Resolve the close target from the `Completed` category first, falling back to
the wider closed set only when no Completed state exists. The full closed set
is still used to classify already-closed items.

Add tests covering a process where `Resolved` is ordered before `Closed`.

* fix(platform/azure): address review feedback on state resolution

- Extract namesByCategory into a module-level function declaration instead
  of an arrow function assigned to a variable.
- Add a test where the Issue type exposes a closed-category state but no
  Completed state, exercising the completedNames[0] ?? closedNames[0]
  fallback (restores 100% patch coverage).
- Reword the readme to avoid possessives per the style guide.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* refactor(platform/azure): simplify state resolution per review

- use stateColors.find for the Completed close target instead of an
  extra namesByCategory pass over a single-element array
- document that the open-state fallback may pick a closed state when a
  process exposes only closed states (intentional, not a bug)
- reuse the workItemType const instead of repeating the 'Issue' literal

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(platform/azure): resolve work item states via Lazy

getWorkItemStates was async with a plain null-check cache guard, so two
concurrent callers could both pass the guard and each fire a duplicate
getWorkItemTypeStates request. Wrap resolution in `Lazy<Promise<...>>`
so the executor runs once and all callers share the same promise.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-14 11:49:32 +00:00
Sebastian Poxhofer ad0b59f8b7 refactor(oxlint): enable vitest/require-to-throw-message (#44421) 2026-07-07 17:47:04 +00:00
Sebastian Poxhofer aac8365dd6 refactor(oxlint): enable vitest/prefer-snapshot-hint (#44420)
Add distinct hints to the multi-snapshot tests flagged by the rule
and regenerate the affected snapshot files, then re-enable the rule.

Part of #43845

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 16:35:22 +00:00
Illia Mazuriak fed1eb1066 fix(platform/azure): avoid corrupting HTML entities and URL anchors in massageMarkdown (#44131)
The `#(\d+)` -> `!$1` replacement added in #42758 over-matched any `#`
followed by digits, corrupting HTML entities such as `&#8203;` (becomes
`&!8203;`) and changelog URL anchors such as `CHANGELOG.md#4780` (becomes
`!4780`) in Azure DevOps PR bodies.

Only convert a standalone reference preceded by start-of-string, whitespace
or `(`, matching the boundary already used in util/markdown.ts.
2026-06-23 14:43:59 +00:00
RahulGautamSingh eaa2cea3e1 feat(platform/azure): add dependency dashboard support (#42758)
* Add support for Azure DevOps in dependency dashboards feature

related #9592

* Add missing test for got wrapper

* Apply all current CR suggestions

* fix: resolve eslint and tsx issues in Azure platform code

* test: add coverage for issue.number undefined cases

Add test cases to ensure proper handling when:
- Trying to reopen an issue without a number
- Trying to update an issue without a number

This improves code coverage for the null checks added in previous commit.

* test: fix and add tests of azure/issue.ts to up coverage

there was mismatch in mock resulting in testing of different code branch

* refactor: address review feedback

* fix: type-check

* refactor: address review feedback round 2

* apply suggestions

* Apply suggestions from code review

Co-authored-by: Sebastian Poxhofer <secustor@users.noreply.github.com>

* refactor: use partial helper and remove host-rules mock in issue.spec.ts

* more changes from suggestions

* Update lib/modules/platform/azure/issue.spec.ts

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

---------

Co-authored-by: Viktorie Novotná <viktorie.novotna@drmax.eu>
Co-authored-by: Sebastian Poxhofer <secustor@users.noreply.github.com>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
2026-06-03 15:56:14 +00:00
Jamie Tanna 128f446e08 docs: ensure that config in documentation is error and warning free (#43727)
* docs: skip validation on JSON files that aren't Renovate config

As part of future changes, we'll enable validation on all JSON code
snippets to run Config Validation.

Before we do that, we should opt-out JSON snippets that aren't anything
related to Renovate config.

* docs: don't validate invalid Renovate config

As it's intentionally referencing a manager that doesn't exist.

* docs: don't validate partial Renovate config

As part of future changes, we'll enable validation on all JSON code
snippets to run Config Validation.

There are several code snippets we have that are part of a Renovate JSON,
but it doesn't make sense to convert these to a fully passing config, as
it'd reduce clarity on what we're trying to explain.

* docs: convert `baseBranchPatterns` snippets to code blocks

So we can validate them.

* docs: make sure that `datasourceTemplate` is set

So this passes validation.

* docs: clarify that `force` is global config

As it may not be clear, so we can make it extra clear with a `.js` file,
and note that it's global self-hosted config.

* docs: make sure `packageRules` is an array

* docs: `matchBaseBranches` needs `baseBranchPatterns` to be set

* docs: correct typo for `prBodyColumns`

* docs: mark global config snippets as such

As part of future changes, we'll use this to detect whether it's global
self-hosted configuration.

* docs: make sure `packageRules` wraps its children

* docs: add `allowedHeaders`

* docs: ignore deprecation warnings

As part of future changes, we'll use this to note that we don't care
about the validation warnings.

* docs: make sure `customManagers` wraps its children

* docs: make sure `fleet` wraps its children

* docs: validate JSON snippets are valid Renovate config

To make sure that we're always presenting valid JSON configuration to
our users, we can validate them as part of `check-fenced-code`.

As well as configuration errors we can warn for warnings, but allow code
blocks to opt-out, for instance when there's a known deprecation
affecting the code block.

We need to make sure to set `allowedEnv` for various code snippets that
reference environment variables.

* docs(development): document fenced code block checks

* docs: wrap `configType` and `ignoreConfigWarnings` in `{ ... }`

As otherwise we see build failures i.e.

    WARNING -  Doc file 'modules/platform/gitlab/index.md' contains a link
       '../../../self-hosted-configuration.md#autodiscoverrepoorder', but the doc
       'self-hosted-configuration.md' does not contain an anchor '#autodiscoverrepoorder'.

This needs to be wrapped alongside all other options like `title`.

* fixup! docs: wrap `configType` and `ignoreConfigWarnings` in `{ ... }`
2026-06-02 13:29:48 +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
Felipe Santos 392105b7c6 chore(oxlint): enable unicorn plugin and prefer-node-protocol (#43283)
chore(oxlint): enable unicorn plugin and prefer-node-protocol
2026-05-29 06:55:58 +00:00
Sebastian Poxhofer 9a27d7aa78 ci(prettier): add prettier plugin for admonitions (#43615)
* ci: add local mkdocs-admonitions plugin for prettier to allow admonition preservation

* docs: remove uses of `prettier-ignore` for admonitions

* test: rather use await expect

* chore: use named group exclusively
2026-05-27 09:39:52 +00:00
Jamie Tanna 33e857e04a docs: migrate all admonitions and lists to using 2-space indents (#43607)
* docs: ensure 2 spaces used for generated admonitions

As a follow-up to 4b0146ab7b and
1844916259b6dc17f532e491eb93f6116327c324., this correctly renders
admonitions with 2 spaces (1 indent).

* fixup! docs: use 2-space indentation for Markdown (#43537)

Plus using 3-space for mixed-style `<ul>` and `<ol>`s.

* fixup! docs: use 2-space indentation for Markdown (#43537)

As otherwise it breaks the rendering of the table.
2026-05-26 20:03:23 +00:00
Jamie Tanna 6fb038bb59 chore(azure): simplify calculation for getMergeMethod (#42849)
* chore(azure): simplify calculation for `getMergeMethod`

Instead of the complicated check we were previously performing which:

- recovered from errors if `policyConfigurations` wasn't undefined, or
  other errors occurred
- trimmed the field names and checked if they were one of the
  `GitPullRequestMergeStrategy` options

We can instead rewrite this with stronger types and compile time checks
to confirm that the mapping from a policy configuration matches the
different `GitPullRequestMergeStrategy`s.

This provides a clearer intent for what this code is doing.

This changes behaviour slightly - previously, the first JSON key defined
that was a `GitPullRequestMergeStrategy` would be used (which is JSON
implementation specific), whereas now it is a defined order.

We also add coverage for the new behaviour.

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

* fixup! chore(azure): simplify calculation for `getMergeMethod`

---------

Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
2026-04-24 06:18:01 +00:00
Jamie Tanna b81a6add44 chore(azure): log the resolved MergeMethod for a given branch (#42847)
To aid with debugging, it would be useful to confirm what the resulting
method is, in both paths.

With help from GPT-4.1 to craft the enum-to-string conversion.

Co-authored-by: gpt-4.1 <jamie.tanna+github-copilot@mend.io>
2026-04-23 15:02:09 +00:00
Sergei Zharinov 7df11ed734 chore(lint): add enforce-ts-extension oxlint rule (#42389)
* refactor(lint): extract custom oxlint rules into separate files

Split `tools/lint/rules.js` into one file per rule under
`tools/lint/rules/`. Also simplify `test-root-describe` with
early-exit guard clauses.

* feat(lint): add `enforce-ts-extension` oxlint rule

Add a custom JS-based oxlint rule that enforces `.ts` extensions on
local imports. The rule catches two problems:

- `.js` extension used instead of `.ts` (auto-fixable)
- missing file extension entirely (report only)

Checked locations:
- static import/export declarations
- dynamic `import()` expressions
- vitest module APIs: `vi.mock`, `vi.doMock`, `vi.unmock`,
  `vi.doUnmock`, `vi.importActual`, `vi.importMock`

Both relative paths (`./`, `../`) and path aliases (`~test/`)
are treated as local. Package imports are ignored.

Also fixes 26 pre-existing violations across 18 spec files.

* Update tools/lint/rules/enforce-ts-extension.js

Co-authored-by: Anne Stellingwerf <1637358+astellingwerf@users.noreply.github.com>

---------

Co-authored-by: Anne Stellingwerf <1637358+astellingwerf@users.noreply.github.com>
2026-04-07 15:36:16 +00:00
Michael Kriese 440e353145 chore: use ts extension (#42300) 2026-04-01 07:46:34 +00:00
Jamie Tanna c04e7b19b5 chore(azure): remove JSON.stringify'd message (#42241)
As objects should be added as additional context, rather than in the
string body.
2026-03-30 21:35:26 +00:00
Jamie Tanna 450e08634c chore(azure): log more context when updating PRs (#42242)
As a means to improve debuggability of Azure's `platformAutomerge` and
`autoApprove`, we can provide a log line to provide more context of what
we're changing.
2026-03-30 17:34:32 +00:00
Jamie Tanna 2eb1e1e706 chore(platforms): correct typo in "up-to-date" (#41460) 2026-02-24 16:13:17 +00:00
Michael Kriese 912c623d60 test: full coverage for platforms (#41318)
chore: full coverage for platforms
2026-02-19 11:05:15 +00:00
renovate[bot] 4a2578d18d build(deps): update dependency zod to v4 (main) (#41225)
* build(deps): update dependency zod to v4

| datasource | package | from    | to    |
| ---------- | ------- | ------- | ----- |
| npm        | zod     | 3.25.76 | 4.3.6 |

* fix: zod migration

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
2026-02-18 07:37:50 +00:00
Sergei Zharinov 9d857c1f68 refactor(lint): Organize imports with biome (#40966) 2026-02-06 13:40:01 +00:00
Sergei Zharinov 2b0e80b884 feat!: Switch to ESM modules (#40756) 2026-01-29 14:21:41 +00:00
Michael Kriese e36d080d22 chore: add proper imports from azure-devops-node-api (#40762) 2026-01-28 17:01:15 +00:00
Sergei Zharinov 930cf6633c refactor: Rewrite imports with .ts extensions (#40700)
fix: Additional vi.mock path corrections and prettier formatting
2026-01-26 22:48:17 +00:00
renovate[bot] acacad57c6 chore(deps): update linters (main) (#40277)
* chore(deps): update linters

| datasource | package              | from   | to     |
| ---------- | -------------------- | ------ | ------ |
| npm        | eslint-plugin-oxlint | 1.36.0 | 1.38.0 |
| npm        | typescript-eslint    | 8.50.1 | 8.52.0 |

* chore: enable oxlint gha format

* chore: fix lint

* chore: fix lint

* chore: fix lint

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
2026-01-14 15:32:48 +00:00
Michael Kriese 050ac8d23b chore: better code coverage (#39518) 2025-11-25 15:01:54 +00:00
RahulGautamSingh 76f911041a refactor: use named exports (#39196)
* use named exports

* fix test

* add missing imnport

* fix prettier
2025-11-10 12:00:35 +00:00
renovate[bot] 1280fe4dc7 chore(deps): update dependency @vitest/eslint-plugin to v1.3.16 (main) (#38502)
* chore(deps): update dependency @vitest/eslint-plugin to v1.3.16

| datasource | package               | from   | to     |
| ---------- | --------------------- | ------ | ------ |
| npm        | @vitest/eslint-plugin | 1.3.13 | 1.3.16 |

* fix linting errors

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: secustor <sebastian@poxhofer.at>
2025-10-13 09:24:15 +00:00
Anne Stellingwerf 9fae0192a1 docs: introduce JSON schema validation and migration checks (#38145)
* docs: introduce JSON schema validation and migration checks

* refactor(tools): enhance code clarity with additional typings, comments, and optional chaining

* ci(workflows): add build steps to lint and type-check jobs

* Update tools/check-fenced-code.mjs

Co-authored-by: RahulGautamSingh <rahultesnik@gmail.com>

* Partial revert

* docs(jsonata): fix wording in code block title in readme

* ci(workflows): remove redundant build steps from workflows

* ci(workflows): remove redundant build steps from workflows

* refactor(tools): simplify error reporting

* Incorporate feedback

* Incorporate feedback

* Incorporate feedback

---------

Co-authored-by: RahulGautamSingh <rahultesnik@gmail.com>
Co-authored-by: Jamie Tanna <jamie.tanna@mend.io>
2025-10-07 10:54:48 +00:00
Michael Kriese 3211d56e21 refactor(zod): rename schema to match our best practices guide (#37499) 2025-08-14 10:35:03 +00:00