Commit Graph

104 Commits

Author SHA1 Message Date
Michael Kriese 8e19aef903 test(util): cover remaining implicit else branches (#45840)
Two `if` statements had their implicit else path untested:

- deleteLocalFile: the no-localDir case never ran
- getMergeConfidenceLevel: the API returning an unrecognised confidence
  value never ran, so the 'neutral' fallback was untested

Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io>
2026-09-10 10:28:39 +00:00
Michael Kriese b5211d4944 test(util): cover remaining lib/util coverage gaps (#45832)
test(util): cover minimatchFilter and cachePathIsFile gaps

Brings lib/util to 100% coverage:

- minimatchFilter: the closure returned on the uncached path was never
  invoked, and the options-based cache key branch was never taken
- cachePathIsFile: only the "does not exist" path was tested, so
  stat().isFile() never ran

Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io>
2026-09-10 07:28:12 +00:00
Sebastian Poxhofer 05e1271376 test: use expect().resolves instead of awaiting inside expect (#45672)
Enables the vitest/prefer-expect-resolves oxlint rule and applies its
autofix across the spec suite.
2026-09-04 10:40:46 +00:00
Sebastian Poxhofer df8c4051ff test(core): replace file snapshots with explicit assertions (#45660)
* test(core): replace file snapshots with explicit assertions

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

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

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

* test(core): address review feedback

* test(core): use resolves instead of awaiting inside expect
2026-09-04 10:28:55 +00:00
Thinh Nguyen ab105e6e42 feat(gomod): add gomodTidyAll option for indirect dependency updates in Go monorepos (#37138)
* feat(gomod): add `gomodTidyAll` option for indirect dependency updates in Go monorepos

In Go monorepos it is common for one module to depend on another in the
same repo via a local `replace` directive (e.g. `replace example.com/shared
=> ../shared`). When Renovate updates the shared module, today `go mod
tidy` runs only in that module, leaving dependent `go.sum` files stale.

Add a new `gomodTidyAll` post-update option that:

- Discovers every `go.mod` in the repo and parses its local `replace`
  directives (both inline and block form).
- Builds a dependency graph with `graph-data-structure`, with edges from
  dependency → dependent, matching the existing NuGet convention.
- Runs `go mod tidy` on every transitive dependent in topological order,
  propagating any `gomodTidy1.17` / `gomodTidyE` flags to the dependent
  commands.
- Collects updated `go.mod` and `go.sum` files from each dependent
  directory into the artifact result.
- Implies `gomodTidy` so users only need to enable one option.

Supporting changes:

- Extract `getMatchingFiles` and `resolveRelativePathToRoot` into
  `lib/util/fs/util.ts` so NuGet and gomod can share them instead of
  each having its own glob/resolve helper.
- Refactor `lib/modules/manager/nuget/package-tree.ts` to use the
  shared `getMatchingFiles` helper and rename local variables for
  clarity (`deps` → `visited`, `dep` → `dependent`) per review feedback.

Docs and config:

- Register `gomodTidyAll` in `postUpdateOptions` `allowedValues`.
- Add a row for `gomodTidyAll` to the `postUpdateOptions` table in
  `docs/usage/configuration-options.md`.
- Add a "Monorepo tidying for local `replace` directives" subsection
  to `docs/usage/golang.md` describing when to use the option.

Tests and coverage:

- `lib/modules/manager/gomod/package-tree.spec.ts` — parse/graph/topo
  order, 100% line/branch/function coverage.
- `lib/modules/manager/gomod/artifacts-gomodtidyall.spec.ts` — six
  integration cases covering subshell commands, `tidyOpts` propagation,
  result collection, no-op with no dependents, error handling, and
  the disabled path.
- Full `lib/modules/manager/gomod` suite (151 tests) and NuGet
  package-tree suite (9 tests) pass; new code is fully covered.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor(gomod): use named capture groups and direct fs util imports

* fix(gomod): use `go -C` for dependent module tidy commands

A subshell only works in Docker mode, where all commands are concatenated
into a single `bash -l -c`. With `binarySource=install` or `global` each
command is split with shlex and run without a shell, so `(cd dir && ...)`
is treated as the name of a binary.

* refactor(gomod): simplify parsing of local `replace` directives

A single regex now covers both the single line form and the lines inside
a `replace (...)` block. The previous block pattern stopped at the first
`)`, so a block containing a comment with a bracket was skipped, and the
single line pattern did not allow a trailing comment.

Also keeps the NuGet package tree unchanged apart from the two helpers it
now shares.

* docs(gomod): warn against combining `gomodTidyAll` with `gomodMassage`

Massaging comments out the relative `replace` directives that
`gomodTidyAll` follows, so the two options work against each other.

* refactor(fs): use `matchRegexOrGlob` in `getMatchingFiles`

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-13 08:35:38 +00:00
Sebastian Poxhofer 716baf630b fix(linters): add rules for filesystem helpers and Date (#44685)
* 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>
2026-07-25 16:00:44 +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
Jamie Tanna ff6761ed23 fix(config/global): return default values for GlobalConfig.get (#42113)
* 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>
2026-05-15 17:10:38 +00:00
Dmytro Shteflyuk 3d9899058c refactor(datasource/rpm): extract xml metadata provider (#41910)
* refactor(datasource/rpm): extract xml metadata provider

* refactor(datasource/rpm): remove unnecessary error cast

* refactor(datasource/rpm): extract repomd helpers

* refactor(datasource/rpm): cache extracted metadata file

* test(datasource/rpm): cover cache helper error paths

* fix(datasource/rpm): preserve cached metadata on refresh failure
2026-05-13 14:29:40 +00:00
renovate[bot] 766db6fc6f build(deps): update dependency upath to v3 (main) (#43121)
* build(deps): update dependency upath to v3

| datasource | package | from  | to    |
| ---------- | ------- | ----- | ----- |
| npm        | upath   | 2.0.1 | 3.0.7 |

* chore: fix types

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
2026-05-06 12:09:33 +00:00
Jamie Tanna c985ca29dd fix(util): don't log "Hidden Unicode" warning when reading a binary file (#41470)
In the case that we are reading binary files in repositories, we should
not log a WARN that there are "hidden" characters in it, as it's a
binary file.

We can use a common heuristic (at least according to Claude Sonnet 4.5)
to look for null bytes at the beginning of our files, and not log the
warning in that case.

Co-authored-by: Claude Sonnet 4.5 <jamie.tanna+github-copilot@mend.io>
2026-02-25 08:36:16 +00:00
Jamie Tanna 165d88f4b3 fix(util): don't treat Zero Width Joiner as "hidden Unicode" (#41471)
As it's commonly found in emoji, and is less likely to be used for
hidden text attacks.

Co-authored-by: Claude Sonnet 4.5 <jamie.tanna+github-copilot@mend.io>
2026-02-24 22:10:24 +00:00
Jamie Tanna 8f16b4442e fix(util): don't log duplicate "hidden Unicode" characters (#41469)
* fix(util): don't log duplicate "hidden Unicode" characters

* test: update post-merge
2026-02-24 21:31:31 +00:00
Jamie Tanna 5949dd4aca fix(util): don't include filename in "Hidden Unicode" warning (#41468)
fix(logger): don't include filename in "Hidden Unicode" warning

As noted in #41467, if a repository has many files with these warnings,
the Dependency Dashboard can be flooded, which can reduce the utility,
especially if some of these may be false positives.

We can remove the filename from the WARN message, which will ensure that
only a single message is logged.

However, this will reduce the utility of the log message, as then users
need to check their logs to see the `file`.
2026-02-24 17:57:47 +00:00
Jamie Tanna 7c7330b162 fix(util): don't warn if a file contains only a Byte Order Mark (BOM) (#41416)
As noted in #41381, it's common for a Byte Order Mark (BOM) Unicode
character to exist in a codebase that's used on Windows.

If we only find a BOM, we will report a TRACE log instead of the WARN,
but if any other characters are found, we'll continue with our WARN.
2026-02-23 14:53:34 +00:00
Jamie Tanna 9dcd32dc72 feat(util): log warning if file(s) contain hidden Unicode characters (#41353)
feat(utilgit): log warning if file(s) contain hidden Unicode characters

With the rise of prompt injection, there is an increased number of
attacks occurring using hidden Unicode characters.

These hidden characters can also confuse other tools, so it's best for
Renovate to surface these to repository owners, as we read files that
may be problematic.

To avoid multiple reads of files, we can do this every time our
`readLocalFile` function is called, as we already have the file content.

An alternate option would be that in `workers/repository` we could check
the read package files, but given `extractAllPackageFiles` may be used
by a Manager, we can't inject the logic in, without Managers needing to
implement the logic themselves.

This should be performant, and not introduce too many false-positives,
but this will also depend on how (package) files are set up in
repositories.

The list of suspicious characters has been largely compiled by Claude
Sonnet 4.5.

Co-authored-by: Claude Sonnet 4.5 <jamie.tanna+github-copilot@mend.io>
2026-02-20 14:15:45 +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
Michael Kriese 9fe353adb4 test: add coverage (part1) (#40636) 2026-01-23 15:09:01 +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
Sergei Zharinov 7c79c11285 fix: Always use default import from upath and semver-stable (#37325) 2025-08-05 11:01:45 +00:00
renovate[bot] 856f5dc5f7 build(deps): update dependency find-up to v7 (main) (#35752)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
2025-05-06 09:42:33 +00:00
Michael Kriese 19c115c813 test: cleanup (#34785) 2025-03-13 17:52:09 +00:00
Michael Kriese 997c23502e test: migrate to vitest (#34475)
Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com>
2025-02-26 09:35:54 +00:00
renovate[bot] e9ce240459 build(deps): update dependency node to v22.14.0 (#33947)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
2025-02-19 11:31:33 +00:00
Sebastian Poxhofer 3681b2a945 chore: eslint to enforce for typed imports (#30844) 2024-08-19 13:15:27 +00:00
renovate[bot] eb8c08079e chore(deps): update typescript-eslint monorepo to v8 (major) (#30750)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
2024-08-14 10:33:02 +00:00
oxdev03 5bdb8210ef chore(utils): extend fs utils with createCacheReadStream and statCach… (#30600) 2024-08-05 16:57:21 +00:00
Sebastian Poxhofer a1cad20a42 fix(manager/terraform): fix hash generation with directory (#28326) 2024-04-13 15:51:19 +00:00
Sebastian Poxhofer 481aa216b2 feat(instrumentation/reporting): add report option (#26087)
Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
2024-03-17 09:22:42 +00:00
Rhys Arkins 60a7de5032 chore: avoid use of confusing base dir term in log (#27659) 2024-03-01 10:57:30 +00:00
Sergei Zharinov b69416ce17 refactor(prettier): Force trailing commas (#25631) 2023-11-07 15:50:29 +00:00
Sergei Zharinov 11c05fc837 refactor: Default values for GlobalConfig.get (#22967) 2023-06-25 19:34:42 +00:00
Rhys Arkins 93052ec917 feat: platform=local (#22010)
Co-authored-by: Jamie Magee <jamie.magee@gmail.com>
2023-05-10 04:30:12 +00:00
Michael Kriese 9f01274911 fix(fs): remove regex path validation (#21871) 2023-04-28 12:31:32 +00:00
RahulGautamSingh 938a36801e refactor: replace test.each with it.each (#21859) 2023-04-28 04:33:15 +00:00
Rob Hannay b853af2c7d fix(fs): permit square brackets [] in file paths (#21625)
Co-authored-by: Sebastian Poxhofer <secustor@users.noreply.github.com>
2023-04-21 15:51:12 +00:00
Michael Kriese 09e43acdf6 fix(fs): allow {} inside paths (#21530) 2023-04-15 18:09:43 +00:00
Michael Kriese 3d23793237 fix(fs): allow +$ inside paths (#21482) 2023-04-13 13:09:01 +00:00
Michael Kriese 2ff75fb8e2 fix(fs): allow @ inside paths (#21476) 2023-04-13 08:57:39 +00:00
Michael Kriese 2de1b29c1f feat(fs): add isValidLocalPath function (#21433) 2023-04-12 15:13:34 +00:00
Jamie Magee 176282e65f chore: use node: protocol imports (#21181) 2023-03-28 21:05:36 +00:00
renovate[bot] 84df0c0ca7 chore(deps): update dependency @types/fs-extra to v11 (#19755)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
2023-01-24 11:46:08 +00:00
Michael Kriese e78048dfc1 fix: no cycles (#19982) 2023-01-23 21:20:54 +00:00
Rhys Arkins 4c88498544 fix: debug not warn for file access errors 2022-09-27 12:05:07 +02:00
Johannes Feichtner aaaa6a1cfe refactor: extract getLockFileContentMap() into fs utils (#17962) 2022-09-25 16:31:11 +02:00
Michael Kriese 10fd0f2827 fix(cache/repository): don't log error for non-existant files (#17427) 2022-08-26 12:25:35 +00:00
Michael Kriese 0316a5e62d test: use jest v29 (#17151) 2022-08-16 14:22:29 +02:00
Yun Lai f1bcafc584 feat(fs): add localPathIsSymbolicLink and readLocalSymlink (#16673)
* fix: add localPathIsSymbolicLink and readLocalSymlink to fs module

* Update lib/util/fs/index.ts

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

* Update lib/util/fs/index.ts

* Apply suggestions from code review

Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com>

Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
Co-authored-by: Rhys Arkins <rhys@arkins.net>
Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com>
2022-07-26 08:19:20 +00:00
Michael Kriese ad70360fda fix(utils/fs): make assertions windows compatible (#16583)
Co-authored-by: Rhys Arkins <rhys@arkins.net>
2022-07-14 17:33:28 +02:00