* 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
* 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>
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>
* 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
* 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>
* 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>
* chore(logger): serialize `DateTime` to ISO strings
As an alternative to 2228a79015, we can
instead serialize any `DateTime` objects that are present in our logging
fields.
Co-authored-by: Claude Sonnet 4.5 <jamie.tanna+github-copilot@mend.io>
* Revert "fix(util/git): log date as string (#41360)"
This reverts commit 2228a79015.
* test(logger): clarify Luxon dates
As we'll follow-up with native dates in the future.
---------
Co-authored-by: Claude Sonnet 4.5 <jamie.tanna+github-copilot@mend.io>
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>
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`.
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>
fix: don't sign commits made in submodules created by test suite
The 'commit.gpgsign=false' configuration was already in place for some
tests in this file, but not all of them. I'm pretty sure that with this
change in place, there's no more commit signing happening in this test
suite.
Now we have instrumented our Git operations with tracing, we can make
sure that users who are not using OpenTelemetry still get insights into
their Git operation usage using a debug log output.
Following how other insights are produced, we can introduce a new type
in `lib/util/stats` for `GitOperationStats`, which will track the
overall execution for each operation type, and output them in the same
style as we use for other timing reports.
At the end of a Renovate run, we'll then make sure that this is logged
into a debug log for further investigation.
To create the report, we can make sure that we introduce a new
OpenTelemetry `SpanProcessor`, which will run when we end our Run, and
store any Git operations in `GitOperationStats`.
This adapts code from GPT-4.1 and code from [0].
Co-authored-by: gpt-4.1 <jamie.tanna+github-copilot@mend.io>
[0]: https://github.com/yurisouza/monitoria-sdk/blob/ca9d751fa7c3a785a04f87b8966bb782b4617021/src/adapters/nestjs/span-duration-tracker.ts#L18-L27
* fix(git): instrument `SimpleGit` operations
Now we have the basis for instrumentation for SimpleGit, we can now
fully integrate it.
This creates a wrapper, `InstrumentedSimpleGit`, which has a simplified
interface for `SimpleGit` to allow us to focus on the important parts of
the interface for what we need, instead of trying to correctly extend /
implement SimpleGit's interface (and slightly complex types).
In each of our methods, we then make sure we instrument it with the
relevant Git subcommand being invoked.
Co-authored-by: gpt-4.1 <jamie.tanna+github-copilot@mend.io>
* test(instrumentation): remove unused path
Currently, SimpleGit's `getRemotes` function being passed a `verbose:
false` is the same as not providing a `verbose`.
This fixes the code coverage failures, as we do not call this.
---------
Co-authored-by: gpt-4.1 <jamie.tanna+github-copilot@mend.io>
As part of being able to fully instrument our Git operations - using
SimpleGit - we can introduce some Git-specific instrumentation helpers.
These helpers will be used as part of a future change, where we will
instrument methods of SimpleGit that we're using.
This provides a set of types which will be used as OpenTelemetry
Attributes to categorise command types.
A number of subcommands that aren't currently deemed to be too important
are bucketed into an `other` category.