Commit Graph

180 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
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
Jamie Tanna ea3b7acede test(util/git): add missing coverage of setGitAuthor (#45607)
As part of follow-up changes, we're removing the "bot" terminology.

While doing so, GitHub Copilot Code Review discovered that there was no
coverage of the defaults in this function.

Before we change this, we can add coverage of the defaults.

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-09-02 08:56:19 +00:00
Sebastian Poxhofer fbedd41e82 test: replace env operation with vi.stubEnv() (#45490)
* 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.
2026-08-28 09:26:20 +00:00
Jamie Tanna 65be1c5cee test(git): disable Git's maintenance in test repositories (#45310)
We periodically see test flakiness in the `git` functionality, where
we're trying to clean up our temporary directories, and see i.e. [0]:

```
FAIL  lib/util/git/index.spec.ts > util/git/index > ...
Error: ENOTEMPTY: directory not empty, rmdir '/tmp/tmp-2701-SIDrNnhWZmc7/.git/objects'
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/4]⎯

 FAIL  lib/util/git/index.spec.ts > util/git/index > ...
Error: ENOTEMPTY: directory not empty, rmdir '/tmp/tmp-2701-8p6HvIMqwS4k/.git/info'
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/4]⎯

 FAIL  lib/util/git/index.spec.ts > util/git/index > ...
Error: ENOTEMPTY: directory not empty, rmdir '/tmp/tmp-2701-Q6gACVUhHYu1/.git/objects/pack'
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/4]⎯

 FAIL  lib/util/git/index.spec.ts > util/git/index > ...
Error: ENOTEMPTY: directory not empty, rmdir '/tmp/tmp-2701-5VelWdq8M1Iy/.git/objects/pack'
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/4]⎯
```

Investigating this with Claude Sonnet, it appears that this /could be/
down to Git's automated garbage collection processes.

The infrequency of the failures makes this less straightforward to
investigate the issue, but it seems like this may be the likely culprit.

We had enabled this on `base` and `origin` repos, but never the `local`
client which runs against `tmpDir`.

We can make sure that this is applied, and this should reduce the
flakiness.

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

[0]: https://github.com/renovatebot/renovate/actions/runs/32008122699/job/95322113612
2026-08-17 09:28:50 +00:00
Sebastian Poxhofer 16ef1715e9 refactor(linters): add rules for @sindresorhus/is helpers (#45229)
* 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>
2026-08-13 14:22:03 +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
user_9090 65ee1f18b4 feat: add regex support for gitIgnoredAuthors configuration (#43938)
* feat: add regex support for gitIgnoredAuthors configuration

* feat: add tests for gitIgnoredAuthors regex handling in isBranchModified

* refactor: simplify ignored authors matching in isBranchModified function

* refactor: use for-of loop for ignored author filtering

* fix(git): treat non-regex gitIgnoredAuthors as exact strings

* fix(git): remove duplicate import of matchRegexOrGlobList

* fix(git): reorder import statements for consistency

* feat(git): enhance gitIgnoredAuthors handling with regex validation and logging

* feat(git): enhance gitIgnoredAuthors support for glob patterns and improve regex handling

* fix(git): add support for escaped glob patterns in matchRegexOrGlobList

* feat(git): update gitIgnoredAuthors documentation and improve regex handling for glob patterns

* fix(git): improve escaping of brackets and backslashes in glob pattern handling

* feat(git): normalize GitHub bot email addresses in ignored authors handling

* feat(tests): add custom author with brackets to file list in index.spec.ts

* feat(git): refactor ignored author handling to support regex normalization

* feat(git): enhance ignored authors handling to support regex patterns

* chore: retrigger ci
2026-08-10 21:41:40 +00:00
Sergei Zharinov cca6227dfa fix(git): resolve child env before adding authentication (#45184)
* fix(git): preserve approved runtime config with authentication

* test(git): remove redundant authentication cases

* test(git): update post-upgrade environment assertions

* test(hermit): cover uninstall setup failure

* refactor(git): clarify authentication host types

* refactor(git): coerce exec options

* refactor(git): coerce docker env vars

* refactor(exec): coerce docker env vars
2026-08-10 11:54:18 +00:00
Felipe Santos d32e38ec2b fix(github): include commitTrailers in platform-native commits (#44918)
* fix(github): include commitTrailers in platform-native commits

The GitHub platform-native commit path (platformCommit) recreates the
commit via the REST API using only message, so trailers from
commitTrailers / :gitSignOff were dropped even though prepareCommit
wrote them into the local commit.

* test: use codeBlock for multi-line commit trailer expectations

* Remove unnecessary comment

* refactor(gerrit): format commit message with shared helper

Use formatCommitMessage for Gerrit reserved trailers so the final
message is built the same way as the git and GitHub platform-native
paths, then clear trailers so prepareCommit does not append them twice.

* Revert "refactor(gerrit): format commit message with shared helper"

This reverts commit d230fa3802.

* refactor(git): fold commit trailers into the message before scm

Remove CommitFilesConfig.trailers so platforms only ever see a fully
formatted message. Workers call formatCommitMessage once; prepareCommit
and GitHub platform-native commits pass message through as-is. Gerrit
parses the existing trailer block to merge Renovate-Branch/Change-Id.

* refactor(git): drop formatCommitMessage helper

Trailers are already folded into message at the worker boundary, so the
shared formatter only re-joined strings. Inline that at the few call sites
and keep splitCommitMessage for Gerrit's reserved-trailer merge.

* revert: keep the minimal commitTrailers platform-native fix

Drop the later refactors (fold trailers into message, Gerrit changes,
splitCommitMessage). Keep formatCommitMessage shared by prepareCommit
and GitHub platform-native commits only; Gerrit is unchanged.
2026-07-29 06:16:44 +00:00
Jamie Tanna a44bbfadcf test(util/git): reference default branch (#44877)
Otherwise this sometimes fails when a repository uses
`init.defaultBranch=main`.
2026-07-27 10:45:06 +00:00
Felipe Santos ddbbb687f9 feat: add commitTrailers option (#44651)
* feat(config): add commitTrailers option

Renovate's only way to add git trailers today is `commitBody`, but it's
broken on Gerrit: Renovate appends its own `Renovate-Branch`/`Change-Id`
block after the body, so user trailers end up in a non-final message
block and are not real trailers per git-interpret-trailers rules.

This adds a `commitTrailers: string[]` option (each entry a full
`Key: value` line), standardizes Gerrit's own trailers through the same
mechanism so user trailers and platform trailers merge into one final
block, and verifies the result at runtime with `git interpret-trailers`
(commitlint's trailer-exists rule uses the same approach). The
`:gitSignOff` preset is migrated from `commitBody` to `commitTrailers`
so sign-off works correctly on Gerrit too.

* Simplify a bit

* Simplify docs even more

* Simplify another bit

* Add comment about rawExec

* Drop runtime commit trailer verification

Bypass simple-git only to emit a proactive warn log is not worth the
extra surface area. Config validation already enforces Key: value form.

* test(git): cover string commit message with trailers

Codecov patch failed on the partial ternary branch that normalizes a
string message before appending trailers.

* test(gerrit): fix trailers test after scm rework

Align the commitTrailers merge test with the post-rework Gerrit SCM:
use fakeSha helpers and drop the removed force flag.

* Improve wording on gitSignOff docs

* Validate compiled commitTrailers as well

* Improve trailers example

* Use isString instead

* Update lib/util/git/index.ts

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

* Update lib/workers/repository/onboarding/branch/create.ts

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

* Format code

* Fix type-check

* Fix tests

---------

Co-authored-by: Sebastian Poxhofer <secustor@users.noreply.github.com>
2026-07-27 06:49:09 +00:00
Jamie Tanna f932d52fbd feat(platform): get all branch update dates in a more performant manner (#44582)
* feat(platform): get all branch update dates in a more performant manner

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

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

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

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

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

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

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

---------

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-07-21 13:17:58 +00:00
Sebastian Poxhofer 2dbfd85506 refactor(linters): enable node/no-sync and migrate to async calls (#44693)
* ci(linter): add renovate/no-sync-io rule

Flags calls to a fixed list of Node.js sync I/O APIs (readFileSync,
writeFileSync, mkdirSync, rmSync, readdirSync, statSync, existsSync,
copyFileSync, execSync, spawnSync, execFileSync) in tools/** and
**/*.spec.ts only; production lib code is not targeted.

Set to "warn" instead of "error": the repo has 40 pre-existing
violations, exceeding the agreed fix threshold of 30, so violations
are left in place for follow-up rather than mass-fixed here.

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

* ci(linter): enforce renovate/no-sync-io at error

Promote the rule from warn to error now that the codebase has been
migrated off synchronous I/O in tools/ and spec files.

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

* refactor(tools): migrate synchronous fs calls to async equivalents

Replace *Sync fs calls with their async/promise-based counterparts in
tools/ scripts (generate-imports, check runner, utils, cwdchanged hook)
now that renovate/no-sync-io is enforced at error there.

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

* test: migrate synchronous fs calls in specs to async equivalents

Replace *Sync fs calls (readdirSync, writeFileSync, existsSync, etc.)
with their async/promise-based counterparts across affected spec
files, making the enclosing it()/module-scope initializers async as
needed, to satisfy renovate/no-sync-io now enforced at error.

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

* ci(linter): replace custom no-sync-io rule with built-in node/no-sync

The oxc built-in covers a superset of the custom fixed-name list.
Migrate the additionally flagged sites: async glob in test-shards,
async execa in prepare-deps, promisified gzip/generateKeyPair in
rpm/hex specs, and rename the misleading execSync mock alias
(it mocks the async rawExec).

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

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 14:28:26 +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
Felipe Santos 8e6a7fc2e6 fix(git): detect commits modified through rebase or amend (#44587)
* fix(config): make platformCommit global-only

* fix(git): reapply committer check for isBranchModified

Reapply #42975 (reverted in #43171): treat a different committer
(rebase/amend/Gerrit UI) as a branch modification.

* fix(git): ignore platformCommit committer from init-time list

Register noreply@${host} at GitHub initPlatform when platform commits
are active. isBranchModified only consumes the list — correct for
github.com, ghe.com, and self-hosted GHES.

Share isPlatformCommitEnabled() with GithubScm so commit path and
ignore-list registration use the same rule.

* refactor: stop threading platformCommit through commits

Decision is resolved once in GitHub initPlatform
(isPlatformCommitEnabled). Workers no longer pass the raw option on
CommitFilesConfig — it was unused after that change.

* refactor: simplify platformCommit / ignore-author wiring

Drop cached platformCommitEnabled flag — isPlatformCommitEnabled() is
a pure read of GlobalConfig + isGHApp. Trim redundant tests and
trace noise.

* Simplify env var setting

* revert: keep platformCommit packageRules-capable

Do not make platformCommit global-only. Restore CommitFilesConfig
threading and GithubScm reading commitConfig.platformCommit so rules
can still set platformCommit per package (see #44585 discussion).

* fix(github): always ignore platformCommit noreply committer

Do not gate noreply@host on isPlatformCommitEnabled (that needed
global platformCommit). Always register host noreply at init so
packageRules can still flip platformCommit per commit while
isBranchModified stays correct.

Remove isPlatformCommitEnabled; GithubScm again uses
commitConfig.platformCommit.

* Simplify some stuff

* Add one assertion

* Change some comments
2026-07-18 12:47:11 +00:00
Felipe Santos 18c9c9340e feat(gerrit): rework scm implementation (#38966)
* fix(gerrit): remove memCache to fix prNo coming as null when pr-created

* perf(gerrit): remove custom scm functions

* Fully remove login parameter from configureScm()

* Fetch refspecs in batches

* Remove unnecessary error handling

* Add tests

* Throw if branch init fails

* Simplify tests a little

* Reduce more the tests

* More test changes

* Reuse the existing test setup more

* Undo test import change

* Improve initializeBranchesFromRefspecs JSDoc

* The same for deleteBranchCreatedFromRefspec

* Reduce a log to trace level

* Abandon Code-Review -2 changes before initializing repository

* Simply initialize the branches after git.initRepo()

* Rework approach to be more generic

* Add TODO comment about commitAndPush()

* fix(gerrit): defer change creation to `createPr()`

Signed-off-by: Felipe Santos <felipe.santos@ericsson.com>

* Refactor hashtags handling

* Add prTitle to all missing commitAndPush()

* Fix type check

* Fix test issue

* Fix gerrit tests

* Add warning when prTitle is set in updatePr

* Remove now useless labels from commitAndPush

* Fix gerrit client coverage

* Fix gerrit scm coverage

* Fix rebase coverage

* Improve TODO about assignees

* Fix formatting

* Fix review comment

* Extract to a pushForReview function

* Fix after #41382

* Fix onboarding

* Cleanup code

* Fix ESLint

* Fix tests

* Restore gitRetry for git.merge

* Fix tests

* Simplify hashtags code

* Delete pendingChangeBranch in pushForReview()

* Fix test name

* Remove unnecessary test comments

* Improve test name again

* Fix another test name

* Delete local branch in Gerrit SCM

* Add test for deleting pending branch

* Add tests for pushForReview()

* Simplify/optimize commitAndPush

* Align jsdoc terminology on virtual branches

* Remove no longer relevant TODO

* Update virtal branch on push

* Simplify deleteVirtualBranch

* Fix test case name

* Improve another test name

* Restore test deleted by mistake

* Fix another small test inconsistency

* Fix coverage

* Fix Renovate not detecting modified commits

* Simplify Gerrit commitAndPush by leveraging git.commitFiles

* Fix some code style issues

* Revert "Simplify Gerrit commitAndPush by leveraging git.commitFiles"

This reverts commit d71edcc279.

* Fix another small code style issue

* Use isUndefined instead

* Fix one small test style issue

* Fix more code style issues

* Fix Gerrit mergeToLocal trying to fetch (and probably failing)

* Extract refs/remotes/origin to a function

* Rename virtualBranchRef to remoteBranchRef

* Fix remoteBranchRef tsc

* Consistently use currentRevision in Gerrit tests

* Remove unnecessary type assertion

* Instrument "fetch virtual branches"

* Remove pendingChangeBranches, avoid overriding deleteBranch and mergeToLocal

* Optimize virtual branches fetch (no longer requires update-ref), convert virtualBranches to Record, rename setVirtualBranch to registerVirtualBranch

* Combine registerVirtualBranch and updateVirtualBranch into a single setVirtualBranch, and update ref in virtual branch too

* Fix virtualBranches not being initialized

* Add some debug logs

* Simplify mergeToLocal for virtual branches

* Revert "Simplify mergeToLocal for virtual branches"

This reverts commit 375d57a474.

* Remove useless isVirtual const

* test(git): add toThrow message for virtualBranches fetch error

Satisfy vitest/require-to-throw-message so oxlint passes.

* Update lib/util/git/types.ts

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

* Address review feedback

---------

Signed-off-by: Felipe Santos <felipe.santos@ericsson.com>
Co-authored-by: RahulGautamSingh <rahultesnik@gmail.com>
2026-07-17 21:47:08 +00:00
Felipe Santos 636e888119 test(git): disable git maintenance to prevent test flakiness (#44670)
fix(git): disable git auto-maintenance in tests to prevent ENOTEMPTY flake

Background gc/maintenance can still be writing objects/pack when
unsafeCleanup removes the tmp dir, causing intermittent ENOTEMPTY errors.
2026-07-17 18:07:03 +00:00
Sergei Zharinov 19a38430eb fix(post-upgrade): preserve executable file modes (#44505)
* fix(post-upgrade): preserve executable file modes

* refactor(post-upgrade): clarify executable detection

* refactor(post-upgrade): use filesystem abstraction

* Clarify Git executable bit detection

* test(post-upgrade): use CI platform for mode coverage

* fix(post-upgrade): trust Git file mode setting

* perf(git): cache file mode setting

* test(post-upgrade): cover existing executable artifact

* test(post-upgrade): verify committed executable mode

* test(git): skip chmod regression without file mode support
2026-07-17 12:03:51 +00:00
Sebastian Poxhofer 9717259ffc refactor(oxlint): enable no-else-return and unicorn/no-lonely-if (#44553)
Enable no-else-return (with allowElseIf: false) and unicorn/no-lonely-if
as errors in .oxlintrc.json and fix all 131 pre-existing violations
(91 no-else-return, 40 unicorn/no-lonely-if) across 98 files.

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

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 12:11:21 +00:00
Sebastian Poxhofer ad0b59f8b7 refactor(oxlint): enable vitest/require-to-throw-message (#44421) 2026-07-07 17:47:04 +00:00
Michael Kriese 289e2d2028 fix(git): allow overriding GIT_ASKPASS (#44322)
* fix(git): allow overriding `GIT_ASKPASS`

* fix: drop experimental options

* test: fix tests
2026-07-02 08:22:40 +00:00
Sebastian Poxhofer 171a591d84 feat(git): validate commit shas (#43988)
* feat(git): validate length commit shas

* test: adapt test mocks

* chore: update import paths

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

* test: add fakeSha function for deterministic git commit shas in tests
2026-06-15 06:36:57 +00:00
Jiri Daněk def09c2661 fix(github): use base_tree in pushFiles to avoid org ruleset file-path restrictions (#42556)
* fix(github): use base_tree in pushFiles to avoid org ruleset file-path restrictions (#42554)

pushFiles sent the entire repo tree to POST /git/trees without base_tree.
GitHub validates all file paths against org rulesets, rejecting the tree
when it contains protected files (e.g. semgrep.yaml) — even if Renovate
only changed unrelated paths.

Use base_tree (parent commit's tree) with only the changed files from
git diff-tree, so unchanged protected files are inherited without
validation.

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

* test(git): add coverage for getCommitTreeSha and diffCommitTree

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

* fix(test): assert specific files instead of hardcoding diff count

The test fixture creates 2 known files between develop and
defaultBranch (master_file, file_to_delete), but CI produces 3
changed files — likely a .gitattributes from the CI environment.
Assert on the known files rather than the total count.

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

* fix(git): handle renames, copies, and submodules in diffCommitTree

- Regex now matches multi-char status codes (R100, C100) and
  tab-separated source/target paths for renames and copies.
- Renames emit a deletion for the source path + addition for target.
- Derive tree item type from mode: 160000→commit, 040000→tree,
  otherwise blob.

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

* refactor(git): address review comments in diffCommitTree

Keep git utility types centralized and make diff status handling easier to follow.

Made-with: Cursor

* test(git): cover rename handling in diffCommitTree

Verify that renamed files are emitted as a deletion for the old path and an addition for the new path, matching the tree delta expected by GitHub.

Made-with: Cursor

* fix(git): validate parsed tree SHA

Fail fast when commit output cannot be parsed into a tree SHA so pushFiles does not propagate an invalid base_tree, and cover the failure path in tests.

Made-with: Cursor

* fix(git): enable rename detection and cover remaining diffCommitTree branches

Add -M to diff-tree so Git emits R status for renames, exercising the
existing case 'R' handler. Add focused tests for rename parsing,
submodule mode (160000), and tree mode (040000).

Made-with: Cursor

* fix(git): clarify copy vs rename comment in diffCommitTree

R uses both tab-separated paths (delete old + add new), while C falls
through to default where only the target path matters.

Made-with: Cursor

* refactor(git): remove dead listCommitTree and TreeItem

Nothing imports listCommitTree after the switch to diffCommitTree with
base_tree. Remove the function, its regex, its test, and the TreeItem
interface.

Made-with: Cursor

* refactor(git): tighten DiffTreeItem.type to GitObjectType union

Define GitObjectType = 'blob' | 'tree' | 'commit' and use it in
DiffTreeItem and treeTypeFromMode instead of plain string.

Made-with: Cursor

* fix(git): remove unreachable nullish coalescing in getCommitTreeSha

split()[0] on a non-empty string is always defined, so the ?? ''
fallback was unreachable and caused an uncovered branch in Codecov.

Made-with: Cursor

* fix(git): add v8 ignore for partial branch on throw template literal

v8 reports template literal interpolations inside throw as partial
branch coverage even when the line is tested. Use the established
v8 ignore pattern to suppress the false positive.

Made-with: Cursor

* fix(github): guard pushFiles against empty diff from diffCommitTree

GitHub's POST /git/trees rejects an empty tree array with 422
"Invalid tree info". While prepareCommit already prevents no-op
commits from reaching pushFiles, add a defensive early return so
the failure mode is a clear log message instead of a swallowed 422.

Made-with: Cursor

* docs(github): document hybrid git/REST commit strategy in pushFiles

Restore architectural knowledge from PRs #13824 and #14271 that was
lost when the old "for reasons unknown" comments were replaced. The
push-then-recreate pattern exists because custom refs avoid CI triggers,
REST-created commits get GitHub signing, and GraphQL lacks force-push
and file mode support.

Made-with: Cursor

* fix(git): wrap bare regex literals in regEx() in tests

Use the project's regEx() helper instead of bare /pattern/ in
toMatch and stringMatching calls, consistent with repo conventions.

Made-with: Cursor

* fix(git): revert regEx() in expect.stringMatching (only accepts bare RegExp)

expect.stringMatching() is a Vitest/Jest API that requires a native
RegExp, not the wrapped object from Renovate's regEx() helper.

Made-with: Cursor

* fix(git): drop line count from v8 ignore next

Vitest uses ast-v8-to-istanbul which is AST-aware: it ignores the
entire next AST node (here the whole throw statement), making the
line count unnecessary.

Made-with: Cursor

* refactor(git): replace magic mode strings with GitTreeMode enum

Introduce a documented GitTreeMode enum in types.ts and use it in
treeTypeFromMode, replacing raw '160000'/'040000' literals with named
members linked to the git data model documentation.

Made-with: Cursor

* fix(git): use const object instead of enum for GitTreeMode

Node's TypeScript strip-only mode does not support enum syntax.
Use `as const` object pattern consistent with the rest of the codebase.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-09 09:08:20 +00:00
Sebastian Poxhofer 6f9411c7d4 test(git): increase timeout to 30s (#43704)
test(git): increae timeout to 30s
2026-05-31 19:21:08 +00:00
renovate[bot] 24154eb71a build(deps): update dependency simple-git to v3.36.0 [security] (main) (#43122)
* build(deps): update dependency simple-git to v3.36.0 [security]

| datasource | package    | from   | to     |
| ---------- | ---------- | ------ | ------ |
| npm        | simple-git | 3.35.2 | 3.36.0 |

* chore(utils): set unsafe flags for SimpleGit (#43268)

* Enabled some unsafe flags for SimpleGit.

* Removed allowUnsafePager

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Dave <reduckted@outlook.com>
Co-authored-by: Sebastian Poxhofer <secustor@users.noreply.github.com>
2026-05-26 21:48:49 +00:00
Sebastian Poxhofer 0793274b86 refactor: prefer templates rather than + in test files (#43441)
refactor: prefer templates rather than `+`
2026-05-19 09:52:28 +00:00
Qingyu Wang ae9fde1e07 fix(git): allow customEnvVariables to override GIT_SSH_COMMAND (#43293)
* fix(git): allow customEnvVariables to override GIT_SSH_COMMAND

* test: simplify env cleanup, rely on beforeEach reset

* refactor(git): use extraEnv for GIT_SSH_COMMAND default

Move GIT_SSH_COMMAND from forcedEnv to extraEnv (lowest priority)
so that both process.env and customEnvVariables override the default
naturally, without conditional logic.

Suggested-by: viceice
2026-05-13 15:02:43 +00:00
Dave e10a96bfd0 refactor: centralize SimpleGit creation (#43035)
* central function for creating SimpleGit instance

* Updated tests.

* Set the LANG and LC_ALL environment variables for all Git operations instead of just initRepo.

* Moved GIT_SSH_COMMAND to `createSimpleGit` function.

* Removed unnecessary custom env vars.
2026-05-11 15:05:08 +00:00
Jamie Tanna 2239c7536c fix(git): Revert "fix(git): not detecting commits modified through rebase or amend" (#43171)
Revert "fix(git): not detecting commits modified through rebase or amend (#42…"

This reverts commit ff2a83d979.
2026-05-08 10:41:43 +00:00
Felipe Santos ff2a83d979 fix(git): not detecting commits modified through rebase or amend (#42975)
* fix(git): not detecting commits modified with rebase or amend

* Fix being detected as modified when new commits in base branch
2026-05-07 19:11:39 +00:00
Michael Kriese 59c3dfdbae fix(git): pass only allowed child env (#43113)
* fix(git): pass only allowed child env

* test(git): cover filtered git env (#43125)

* Update lib/util/git/index.ts

Co-authored-by: Dave <reduckted@outlook.com>

---------

Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com>
Co-authored-by: Dave <reduckted@outlook.com>
2026-05-06 14:04:55 +00:00
Jamie Tanna ee61f1e1ce test(util/git): increase coverage ahead of simple-git upgrade (#42944)
* test

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

* sq

* chore: linting

---------

Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
2026-05-06 08:53:45 +00:00
Felipe Santos 45ba03e616 fix(git): implement caching for branch update dates (#42948)
* feat(update-date-cache): implement caching for branch update dates

* Try fix coverage

* Fix some test style inconsistencies

* Fix coverage

* Fix test

* Fix test testing the same path
2026-05-01 08:39:20 +00:00
Felipe Santos 1bbe82400e fix(gerrit): defer change creation to createPr() (#39250)
* fix(gerrit): defer change creation to `createPr()`

Signed-off-by: Felipe Santos <felipe.santos@ericsson.com>

* Refactor hashtags handling

* Add prTitle to all missing commitAndPush()

* Fix gerrit tests

* Add warning when prTitle is set in updatePr

* Remove now useless labels from commitAndPush

* Fix gerrit client coverage

* Fix gerrit scm coverage

* Fix rebase coverage

* Improve TODO about assignees

* Fix formatting

* Fix review comment

* Extract to a pushForReview function

* Fix after #41382

* Fix onboarding

* Cleanup code

* Fix ESLint

* Fix tests

* Restore gitRetry for git.merge

* Fix tests

* Simplify hashtags code

* Delete pendingChangeBranch in pushForReview()

* Fix test name

* Remove unnecessary test comments

* Improve test name again

* Fix another test name

* Delete local branch in Gerrit SCM

* Add test for deleting pending branch

* Add tests for pushForReview()

* Fix test case name

* Improve another test name

* Fix another small test inconsistency

* Fix some code style issues

* Use isUndefined instead

* Fix one small test style issue

---------

Signed-off-by: Felipe Santos <felipe.santos@ericsson.com>
2026-04-28 08:29:26 +00:00
Jamie Tanna ec921a69e0 fix(git): support repo cache with getBranchUpdateDate (#42852)
As noted in #41953, the introduction of `getBranchUpdateDate` did not
take into account the use of a repository cache.

When using a repository cache, the repo is not cloned until it is needed
(and various metadata is used from the cache instead).

However, when using a cache (with a repo not yet cloned) this results in
`getBranchUpdateDate` failing (and a debug log appearing).

We can instead handle this by performing a repo sync at this point.

Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
2026-04-24 07:15:06 +00:00
Felipe Santos f9bddb97a7 test(git): test failing when no git author is configured (#42676)
Fix test failing when no git author is configured locally
2026-04-16 09:02:24 +00:00
Johannes Feichtner 70fa9622bc fix(git): don't pass extraCloneOpts to ls-remote when local clone exists (#42491)
* fix(workers/repository): cleanup localDir before recursive retry after automerge

* add test for failed directory cleanup

* fix(git): don't pass extraCloneOpts to ls-remote when local clone exists
2026-04-15 09:56:04 +00:00
Jamie Tanna 33c1bf5d18 fix(util/git): allow setting config.hooksPath (#42630)
* test(util/git): add test coverage for `X_CLEAR_HOOKS`

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

* fix(util/git): allow setting `config.hooksPath`

Since simple-git 3.35.2's update in #42588, the setting of
`config.hooksPath` is marked as "unsafe", and does not allow setting
this configuration.

This only affects users who specify the experimental self-hosted config
option, `RENOVATE_X_CLEAR_HOOKS`.

However, the primary user of this is Mend-hosted Renovate which, as
noted in #42628, resulted in all jobs failing to run.

We can instead conditionally set the `allowUnsafeHooksPath`
configuration if we're running with `RENOVATE_X_CLEAR_HOOKS`.

We need to refactor our test to make sure that we're re-initialising
`git` at the point the `RENOVATE_X_CLEAR_HOOKS` is set.

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

---------

Co-authored-by: Claude Opus 4.6 <jamie.tanna+claude-code@mend.io>
2026-04-14 16:26:34 +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 fa1068721f test: fix flaky test (#42428) 2026-04-07 15:38:02 +01:00
Michael Kriese f8ef935840 fix(git): skip merge commits for semantic commit detection (#42419)
* fix(git): skip merge commits for semantic commit detection

* docs: update docs
2026-04-07 13:35:24 +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 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 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
Felipe Santos 7ebba26236 feat: add commitHourlyLimit (#36226)
* feat: add `commitHourlyLimit`

Signed-off-by: Felipe Santos <felipe.santos@ericsson.com>

* Update docs/usage/configuration-options.md

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

* Remove date optionality

* Fix lint comment

* Fix coverage

* Restore contents of commit.spec.ts

* Use ! somewhere else too

* Change optional parameter to nullish

* Refactor `!` to use proper check

* Fix set-branch-commit.spec.ts lint

* Fix test coverage

* Apply suggestions from code review

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

* Split commit-limit-reached into two

* Fix review comments

* Use toUTC() where applicable

* Simplify another test to utc()

---------

Signed-off-by: Felipe Santos <felipe.santos@ericsson.com>
Co-authored-by: RahulGautamSingh <rahultesnik@gmail.com>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
2026-02-19 18:00:32 +00:00
Sergei Zharinov b02897fab1 refactor(lint): Fix lint violations (#40965)
* refactor(lint): Fix lint violations

* Update lib/modules/versioning/versioning-metadata.spec.ts

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

---------

Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
2026-02-06 15:34:33 +00:00
Sergei Zharinov 9d857c1f68 refactor(lint): Organize imports with biome (#40966) 2026-02-06 13:40:01 +00:00
Michael Kriese 17a1bbad96 refactor: use named simpleGit imports (#40759) 2026-01-28 16:55:14 +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