* test(workers/repository): mark seven unreachable guards for v8
These are defensive paths that no input reaches, and the guards stay as
they are. What changes is that v8 now knows to skip them: the existing
`istanbul ignore` comments are inert under the v8 provider, so the
branches behind them were still being counted.
- `versioning/index`: a string input can only fail the schema with the
custom issue its own transform raises
- `versioning/conda`: pep440 always answers for a well-formed `==X.Y.*`
- `versioning/ruby`: callers only pass versions that have already parsed
- `repository/index`: only called when the repository logged a problem
- `config-migration/branch/rebase`: JSON5 output is always serializable
back to JSON
- `onboarding/pr/pr-list`: base branches are unique Record keys, so the
sort never compares one with itself
- `changelog/release-notes`: a matched release always carries its own url
- `changelog/source`: `getInRangeReleases` only returns null on paths it
already ignores
Two notes on the hints. They have to be a single-line comment directly
above the statement -- a two-line reason, or anything in between such as
an oxlint directive, breaks the association silently. And `v8 ignore
else` covers an `if` with no else, while `v8 ignore next` covers an
expression-level branch such as `??` or a ternary.
`versioning/index` also swaps `issue && issue.code` for `issue?.code`,
which is what the oxlint directive sitting in the way was suppressing.
Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io>
* test(workers/repository): cover the last five pr worker guards
None of these needed an ignore comment; each has a real input:
- `updatePrDebugData` gets a describe of its own. It is exported but was
only reached through a pr whose debug data already carried labels, so
the case where an existing pr has none went untaken.
- a `not-pending` branch whose status is no longer yellow
- a changelog error that is not a missing GitHub token
- an existing pr updated because a rebase was requested
- a platform that answers `createPr` with null, so assignees and
reviewers are skipped
With these, `update/pr/index.ts` is fully covered.
Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io>
* test(workers/repository): cover the last four branch update guards
- `bump-versions` reads the current version off disk when the pending
change for that file carries no contents. All three guards involved are
covered by one case where the file is pending in both the package file
and the artifact list with no contents on either entry. An earlier
attempt at this looked like it failed: the bump does happen, but the
result is appended to `updatedPackageFiles` rather than
`updatedArtifacts`, because the file is already pending there.
- `get-updated` keeps a package file another upgrade already wrote, for a
manager that is asked for a lockfile-only update but has no
`updateLockedDependency`.
With these, `lib/workers/repository` is fully covered.
Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io>
* ci: pin the branch coverage threshold at 100
A full run on this branch reports 100% on all four metrics: statements
(49435/49435), branches (25727/25727), functions (7414/7414) and lines
(48924/48924).
Branches joins the other three at 100 rather than taking another
rounding-down step. There is no longer a margin to leave: any new
uncovered branch is a regression, and the threshold should say so.
Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io>
---------
Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io>
* refactor(linters): add prefer-coerce-array rule
Refs #45217
`x ?? []` and `coerceArray(x)` say the same thing, but only the second
one is searchable and consistent. The rule flags a `??` whose default is
a bare `[]` literal; a non-empty default or an asserted `([] as Foo[])`
still passes.
Applying it across `lib/` surfaced three spots the helper cannot cover,
which keep `?? []` with a disable comment or a narrower fix:
- `package-files.ts` destructures a tuple, which `coerceArray()` widens
- `generate.spec.ts` defaults `matchAll()`, an iterator rather than an array
- `mise/upgradeable-tooling.ts` declares a `Record` return, so its
`?? []` fallback was wrong to begin with and becomes `coerceObject()`
* refactor(platform/github): hoist the GHE version header lookup
`Object.entries(...).find()` returns a tuple, and defaulting it with
`?? []` only to destructure the second element reads as an array
default when it is not one. Name the found entry instead, which drops
the `?? []` rather than routing a tuple through `coerceArray()`.
* 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>
Enable the unicorn/prefer-at rule as error in .oxlintrc.json and fix all
43 pre-existing violations (arr[arr.length - 1] -> arr.at(-1)) via oxlint
autofix. Where .at() widened the type to T | undefined, non-null
assertions were added at sites where surrounding logic guarantees the
element exists (length guards, split results), preserving the original
runtime behavior and typing.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Moves datasource, manager, platform and versioning code from lib/ into new lib/modules/
BREAKING CHANGE: External tools must update paths to datasource, manager, platform and versioning