Commit Graph

2005 Commits

Author SHA1 Message Date
mithil cfb2a76354 fix(util/markdown): preserve at signs in URLs (#45555) 2026-09-01 09:41:53 +00:00
Dharma Teja Thoutam a3a00ce574 fix(exec): supress unhandled promise rehection from execa timeout (#45335)
* fix(exec): supress unhandled promise rehection from execa timeout

* fix: Use isFunction from @sindresorhus/is, fix v8 ignore comment

* fix: log suppressed rejection, add catch to mock per review

* fix: add type annotation for catch mock parameter
2026-08-28 16:30:18 +00:00
Pham Manh Luc 2e89151d7e fix(github): treat graphql_rate_limit as rate limiting (#45396)
* fix(github): treat graphql_rate_limit as rate limiting

GitHub answers a spent app-installation budget with a GraphQL error carrying
code graphql_rate_limit, which neither call site recognised: the repository
query reported platform-unknown-error, and app authentication reported
Init: Authentication failure. Both readings send the user looking for a
problem that is not there, and neither is retried the way rate limiting is.

The two shapes are now recognised in one place and both call sites use it.

* fix(github): propagate GraphQL rate limits

* fix(github): preserve GraphQL response contract

---------

Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com>
2026-08-28 09:28:57 +00:00
Sebastian Poxhofer c32e2391a0 refactor(linters): add prefer-coerce-object rule (#45493)
Refs #45216

The object counterpart to `prefer-coerce-array`: `x ?? {}` becomes
`coerceObject(x)`. The rule flags a `??` whose default is a bare `{}`
literal, so a populated default or an asserted `({} as Foo)` still
passes; a `x ?? y ?? {}` chain maps onto `coerceObject(x, y)`.

Every hit across `lib/` converted cleanly, so no disable comments were
needed.
2026-08-28 09:27:59 +00:00
Sebastian Poxhofer 97327c3d28 refactor(linters): add prefer-coerce-array rule (#45492)
* 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()`.
2026-08-28 09:27:58 +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 021612414c fix(lint): use parseInt over Number (#45472)
* fix(lint): use `parseInt` over `Number`

As a code review comment that comes up every so often, we can add a
linting rule to enforce this check.

This also fixes any existing usages.

As this could be breaking, we can release it as a `fix`.

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

* fixup! fix(lint): use `parseInt` over `Number`

* fixup! fix(lint): use `parseInt` over `Number`

---------

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-08-26 13:02:26 +00:00
Jamie Tanna a9c8f7431f fix(lint): extend prefer-is-helpers to catch more cases (#45474)
This now covers everything that isn't `isObject` or `typeof x === 'number'`.

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-08-26 10:48:40 +00:00
Nikos Angelopoulos d4c29b1cfd fix(github-graphql): lower shrinkPageSize floor from 25 to 5 (#45460) 2026-08-25 23:02:27 +00:00
Jamie Tanna a4b5c1878c feat(http/bitbucket): warn when an endpoint announces a deprecation (#45461)
* feat(http/bitbucket): warn when an endpoint announces a deprecation

To highlight to a self-hosted administrator when they are using
deprecated/removed functionality, we can look for i.e.

    sunset: Fri, 21 Aug 2026 00:00:00 UTC
    deprecation: @1771545600
    link: <https://developer.atlassian.com/cloud/bitbucket/changelog#CHANGE-3071>; rel="deprecation"; type="text/html"

This provides visibility into a soon-to-be-removed piece of
functionality, and should allow us to catch these deprecations more
centrally.

We make sure to log them - as a WARN - once, and with ISO8601 dates for
readability.

If we can't parse either `sunset` or `deprecation`, we log them as-is,
so we don't accidentally remove any necessary context.

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

* fixup! feat(http/bitbucket): warn when an endpoint announces a deprecation

* fixup! feat(http/bitbucket): warn when an endpoint announces a deprecation

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

---------

Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
2026-08-25 20:06:55 +00:00
Jamie Tanna 3861bdab30 refactor(http): add a handleResponse hook (#45449)
As part of follow-up changes, we'll want to check the response's
headers, which requires we have an additional hook that we can use.

By default, this is a no-op.

Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
2026-08-25 15:40:07 +00:00
Jamie Tanna 4eee9a4683 feat(http/bitbucket): surface deprecated and removed API functionality (#45446)
To surface the deprecation or removal of features by Bitbucket Cloud,
there may be an error body such as:

    {
      "type": "error",
      "error": {
        "message": "CHANGE-3071 - Functionality has been deprecated",
        "detail": "Please read the changelog entry for more details.",
        "data": {
          "announcement_url": "https://developer.atlassian.com/cloud/bitbucket/changelog#CHANGE-3071"
        }
      }
    }

To make it more visible to a self-hosted administrator that they're
using deprecated/removed functionality, we can elevate this to a WARN
log line, if there is an `announcement_url`.

We make sure to handle both parsed JSON response bodies and a raw string
body used for other requests.

To reduce noise to a self-hosted administrator, we can log this once per
run.

Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
2026-08-25 15:40:06 +00:00
Jamie Tanna 43d63f9b31 feat: always set CI=true for subprocesses
As noted in #43761, we had recently set `CI=true` for the Renovate and
Containerbase orgs on Mend-hosted apps due to a pnpm v11 requirement:

    ERR_PNPM_ABORTED_REMOVE_MODULES_DIR_NO_TTY  Aborted removal of
      modules directory due to no TTY

    If you are running pnpm in CI, set the CI environment variable to
      "true", or set "confirmModulesPurge" to "false".

Similarly in #43606, it was noted that we should do this for `mise lock`
to mark the workspace as "trusted".

Although we went with a different situation, there will be cases where
this is useful for tools being executed, for instance when we invoke `yarn`.

We also make sure to keep our documentation up-to-date as we add to the
specific overrides.
2026-08-24 17:27:41 +01:00
Jamie Tanna 5b1749983c feat: always set CI=true for subprocesses
As noted in #43761, we had recently set `CI=true` for the Renovate and
Containerbase orgs on Mend-hosted apps due to a pnpm v11 requirement:

    ERR_PNPM_ABORTED_REMOVE_MODULES_DIR_NO_TTY  Aborted removal of
      modules directory due to no TTY

    If you are running pnpm in CI, set the CI environment variable to
      "true", or set "confirmModulesPurge" to "false".

Similarly in #43606, it was noted that we should do this for `mise lock`
to mark the workspace as "trusted".

Although we went with a different situation, there will be cases where
this is useful for tools being executed, for instance when we invoke `yarn`.

We also make sure to keep our documentation up-to-date as we add to the
specific overrides.

With help from Claude Sonnet and Opus to:

- perform some of the mechanical updates as part of this change
- ensure that the Docker sidecar always has `hardcodedProcessEnv` passed
  into it
- catch a needed change to `exposeAllEnv` handling

Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-08-24 17:21:24 +01:00
Jamie Tanna 0d920f17d2 test(util/exec): be more strict in expected value
As part of future changes, we'll introduce additional values, and we
want to make sure that this is strictly catching that addition.

However, this drifts between CI and local builds, as in CI, `CI=true` is
set, so we can explicitly set it for now.

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-08-24 17:21:24 +01:00
goda6565 9cc1ab0df6 fix(http/github): support cursor pagination (#45241)
* fix(http/github): support cursor pagination

* fix(http/github): harden cursor pagination

* fix(http/github): log pagination mode
2026-08-24 14:24:25 +00:00
Sebastian Poxhofer a473e73b3e fix(linters): forbid inert counts in v8 coverage-ignore comments (#45287)
Adds a custom oxlint rule renovate/v8-ignore-no-count that flags the
count form '/* v8 ignore next <N> */'. The count is not honored by
vitest's ast-v8-to-istanbul hint parser, which captures only the
keyword (if/else/next/file); 'next' always exempts exactly the next
AST node. Trailing counts therefore suggest a line range that is never
applied and mislead readers.

The rule is autofixable (drops the count, preserving actual behavior)
and has been applied to all existing occurrences.
2026-08-22 11:25:31 +00:00
Sebastian Poxhofer 41da033756 refactor: remove escapeRegExp and replace with RegExp.escape (#45322) 2026-08-18 06:24:47 +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 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
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
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 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
Lucas Colley 848ef4a88e feat: parse TOML files by default with TOML 1.1 (#45231)
feat: support TOML 1.1
2026-08-12 05:46:31 +00:00
Jamie Tanna fba1a9de30 feat(manager/github-actions): add support for Actions Lockfiles (#45199)
* refactor(manager/github-actions): make `extractPackageFile` async

As part of follow-up changes we'll need to read `.github/workflows/actions.lock`
while extracting, which requires we are an async function.

To reduce the diff, we can prefactor this change first.

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

* feat(manager/github-actions): add support for Actions Lockfiles

In June, GitHub announced a public preview for the GitHub Actions
lockfile functionality[0].

To add support for this, we can extend our support for GitHub Actions to
handle the presence of an `actions.lock` file, and if so, update it
after updating other manager files.

Although our ideal case would be to have a pure Typescript-based parsing
and updating of the `actions.lock`, due to the early nature of the
Actions Lockfile syntax, and its lack of stability, we can invoke the
`gh actions-lock` extension when updating.

After the schema has reached a v1 release, we can then migrate to
Typescript.

To make sure that the version of the `actions-lock` extension is always
version pinned, we can expose a `constraints` to control the version,
but allow Renovate to keep the pinned default updated as needed.

This doesn't imply that we have support for `lockFileMaintenance`, as we
are only updating the lockfile when there is a dependency update, not
periodically recreating the lockfile from the current ranges.

`gh actions-lock` re-reads every workflow from disk and rewrites the
whole lockfile, so it does not fit `updateArtifacts`, which is called
once per updated package file.

We can instead follow the shape the `npm` manager uses for its
lock files, and have `processBranch` invoke this once per branch, after
every updated package file has been written to disk.

We skip workflows that aren't onboarded to the lockfile, but still run
for any other package file, as a local composite action can be a
transitive dependency of a workflow which is.

`gh actions-lock` rewrites the workflows it manages back to plain refs
when it regenerates them, which strips out any inline digest pin:

```diff
-        uses: actions/setup-java@1bcf9fb12c # v5.4.0
+        uses: actions/setup-java@v5.7.0
```

This would lead to a repository with `pinDigests` set "flip flopping",
and would cause a lot of erroneous noise for repository owners.

Instead, we can make sure that:

- we don't suggest a `pinDigest` for workflows that are managed by the
  lockfile
- digest pinning is still enabled for `docker://` references
- already-committed digests are updated when they're present - we only
  avoid suggesting /new/ digests to be pinned

Co-authored-by: Sebastian Poxhofer <secustor@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Fable 5 <jamie.tanna+claude-code@mend.io>

[0]: https://github.com/github/actions-lockfile

* coverage

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

* fixup! feat(manager/github-actions): add support for Actions Lockfiles

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

---------

Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
2026-08-11 11:55:06 +00:00
palakkhinvasara 728ce9752e fix: keep HTTPS when resolving same origin URLs (#45157)
* pushing

* pushing

* pushing

* pushing

* pushing
2026-08-11 06:14:50 +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
Jamie Tanna 45372476c8 feat(util/exec): add support for gh tool (#45192)
* feat(deps): update ghcr.io/renovatebot/base-image docker tag to v13.84.0

| datasource | package                        | from    | to      |
| ---------- | ------------------------------ | ------- | ------- |
| docker     | ghcr.io/renovatebot/base-image | 13.83.0 | 13.84.0 |

* feat(util/exec): add support for `gh` tool

As a prerequisite for #44753 and #45190, we need to support the `gh`
CLI.

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-10 13:55:09 +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
Jamie Tanna c92c7e2d3a refactor(types): make return type for getToolSettingsOptions stricter (#45133)
As part of future changes, it makes it easier to work with the resulting
types, because it's clear when they are optional/required.

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-08-07 17:33:17 +00:00
Jamie Tanna b017c7548a fix(exec/docker): single-quote the sidecar bash command
When executing commands for `binarySource=docker`, we have two areas
that a command could have shell expansion/injection:

- on the host (when constructing the `bash -l -c`)
- in the container (when running a manager-specific command)

When constructing the host's command, we previously would escape the
`"`, which allows Bash syntax for `${VAR}` and `$(...)` syntax inside
it.

While managers use `quote()` to make the inputs safer, the use of `"`
around that would not provide any protection, and lead to cases where
the `quote()` could be expanded on the host, before `docker run`
executes.

After recent changes to each manager - and removal of `shell: true` -
this doesn't seem to be exploitable, but this hardens it further.

Additionally, we never escaped `\`, so a value containing `\"` produces
a command that `shlex.split` rejects, and the update fails rather than
running.

Instead, we can quote the whole `-c` argument with `quote()`, which
round-trips through both `shlex.split` - the default, no-shell path - and
a real shell.

This removes the `lgtm [js/incomplete-sanitization]` suppression as
we're now correctly sanitising this.

Note this doesn't remove the need for the managers to quote their own
values, as the second area above is still a real shell.

Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
2026-08-07 14:25:42 +01:00
Jamie Tanna a28ecdc122 refactor(types): clarify ToolSettings has two levels of config (#45125)
As part of future changes, we'll add options that do not require the
Global option to take precedence and/or be used as an upper limit.

To make this clearer, we can split out the options into Global and Repo
variants.
2026-08-07 12:21:13 +00:00
Jamie Tanna 54384ff3e5 fix(util/host-rules): sanitise TLS credential fields in hostRules (#45119)
* chore(util): note that `httpsCertificate` and `httpsCertificateAuthority` aren't secret

Although we're currently treating them as such, they're not technically
unsafe to appear in the logs, as a Certificate (and the authority) are
public.

* fix(util/host-rules): sanitise TLS credential fields in hostRules

We previously noted that the `httpsPrivateKey`, `httpsCertificate`, and
`httpsCertificateAuthority` fields would be marked as confidential, but
we weren't correctly sanitising them.

We can make sure that these fields are correctly flagged as secret
("confidential") and that they need to be sanitised when referenced.

Although the `httpsCertificate` and `httpsCertificateAuthority` aren't
secret, we can keep them sanitised for consistency with how we've
currently documented them as being sanitised.

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

* test(util/host-rules): ensure that all secret fields are marked as secret

As a way to make sure that new fields being added `HostRule`s are
considered as to whether the field should be marked as secret
("confidential") or not, we can add a test (and a compile-time
exhaustive check) to validate that `redactedFields` and
`confidentialFields` are kept in sync.

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

---------

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-08-06 15:15:54 +00:00
Jamie Tanna 8108714fc3 docs: validate JSONC and Javascript code blocks (#45063)
* docs: correct `onboardingConfig` example

As we'll be enforcing this as valid Global config in future commits.

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

* docs: correct `module.exports` syntax

As we'll be enforcing this as valid Global config in future commits.

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

* docs: completely skip `doc-fence-check` on code blocks only used for synatx highlighting

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

* docs: skip schema validation on non-config snippets

As we'll be enforcing this as valid Global config in future commits.

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

* chore(tools/doc-fence-check): validate JSONC and Javascript code blocks

To further ensure that our documentation is well-formed, we can validate
that JSONC and Javascript code blocks are well-formed syntactically, and
are valid Renovate configuration.

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

* chore(tools/doc-fence-check): allow opting out of syntax validation

On top of schema validation wanting to be disabled, we should also
support disabling the syntax validation, in the case that we're using
`json` code blocks for syntax highlighting, but they're not necessarily
well-formed JSON.

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

* docs: use `json` syntax highlighting

As `jsonc` doesn't seem to exist in Material for MkDocs.

As it's only for syntax highlighting, we need to opt out of validation.

* tsc

---------

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-08-04 13:18:08 +00:00
Jamie Tanna a160e39c7a fix(platform/gitlab): don't follow Link headers with different hosts
To prevent potential SSRF attempts, we can ignore a
misconfigured/malicious `next` link, and log a warning.

Co-authored-by: Claude Opus 4.8 <jamie.tanna+claude-code@mend.io>
2026-08-04 09:09:26 +01:00
Jamie Tanna edb2217952 fix(platform/github): don't follow Link headers with different hosts
To prevent potential SSRF attempts, we can ignore a
misconfigured/malicious `next` link, and log a warning.

Co-authored-by: Claude Opus 4.8 <jamie.tanna+claude-code@mend.io>
2026-08-04 09:09:26 +01:00
Jamie Tanna 7f7b039559 refactor(util): add a helper method for resolveSameOriginUrl
As part of future changes, it would be useful to have a helper method to
handle the correct resolution for `Link` header parsing, where we want
to avoid the risk of a registry/platform providing a link to a different
hostname, which could lead to SSRF.

Co-authored-by: Claude Opus 4.8 <jamie.tanna+claude-code@mend.io>
2026-08-04 08:06:57 +01:00
Jamie Tanna 69a629031b feat(templates): always expose renovateVersion (#44969)
As noted in #44756, this would allow templates across Renovate's
different usages to be able to use the `renovateVersion` string as a
template variable.

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-07-30 16:01:51 +00:00
Adam Setch 14c81bb298 fix(util/markdown): undo zero-width space chars when used inside codeblocks (#44933)
* fix(changelog): undo zero-width space chars when used inside codeblocks

Signed-off-by: Adam Setch <adam.setch@outlook.com>

* fix: undo zero-width space chars when used inside codeblocks

Signed-off-by: Adam Setch <adam.setch@outlook.com>

* use codeblock

Signed-off-by: Adam Setch <adam.setch@outlook.com>

* fix test

Signed-off-by: Adam Setch <adam.setch@outlook.com>

* fix test

Signed-off-by: Adam Setch <adam.setch@outlook.com>

---------

Signed-off-by: Adam Setch <adam.setch@outlook.com>
Co-authored-by: Jamie Tanna <jamie.tanna@mend.io>
2026-07-30 15:48:23 +00:00
Jamie Tanna 29243d0559 chore(util/exec): fix typo (#44946)
Surfaced in https://togithub.com/SchemaStore/schemastore/pull/6142
2026-07-30 15:41:27 +00:00
Gabriel-Ladzaretti 5ff2229e27 feat(exec): support custom stream output writers (#44910) 2026-07-29 07:10:32 +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
Arnaud Dezandee 5173de026b refactor: move checkMinimumReleaseAge to lib/util/minimum-release-age.ts (#44904) 2026-07-28 08:11:05 +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
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
Vincent Pizzo 12b2f4f405 fix(platform/gitlab): retry MR creation on transient source_branch race. (#44502)
fix(platform/gitlab): retry MR creation on transient source_branch race

GitLab occasionally rejects a merge request POST with
`400 {"message":{"source_branch":["does not exist"]}}` immediately after
a branch push succeeds, because the freshly pushed ref is not yet visible
to the API due to Gitaly eventual consistency. The request was not
retried, leaving an orphaned branch until the next run.

Extend the existing `calculateRetryDelay` hook (which already retries
transient `409 Resource lock` POST errors) to also retry this
`400 source_branch does not exist` case, reusing got's bounded
exponential backoff.
2026-07-25 18:42:41 +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
Anand Kumria 3cba608bb1 fix(git): surface GitHub GH013 ruleset rejections as config errors (#44819)
When GitHub returns 'GH013: Repository rule violations found' during
a push, the failure is currently silently swallowed by handleCommitError
whenever the changeset touches a file under .github/workflows/. The
existing swallow was intended for the narrow case of an App token
missing the 'workflows' scope, but it also masks unrelated ruleset
violations such as:

  - GITHUB PUSH PROTECTION 'File path is restricted'
  - Secret scanning push protection
  - Signed commit / branch-naming / tag-deletion rulesets

Self-hosted operators cannot see these failures in aggregated log
reports because Renovate logs at info level, marks the branch as
aborted, and continues. Repositories that are effectively 100%
blocked by a ruleset appear healthy.

Detect the 'GH013' token before the workflow-files silent-swallow and
throw a CONFIG_VALIDATION error - mirroring the treatment already
applied to GH003 (force-push denied) and 'protected branch hook
declined'. This flags the repository as failing, populates
validationError / validationMessage so the failure reason is visible
in the repository summary, and lets any downstream reporting pick it
up as a real failure instead of an info-level abort.

Adds tests to lib/util/git/errors.spec.ts covering:

  1. A GH013 Push Protection error whose changeset is entirely under
     .github/workflows/ is thrown as CONFIG_VALIDATION with the
     expected validationSource / validationError / validationMessage.

  2. A generic non-GH013 workflow-file remote rejection still returns
     null (existing swallow behaviour preserved).
2026-07-24 09:08:04 +00:00
Jamie Tanna a72dc7e823 test(util/exec): remove deprecated reference to trust level (#44244)
test(util/exec): remove deprecated reference to `trustlevel`
2026-07-22 16:21:35 +00:00