Renovate deployments that are deployed across multiple organisations may
take advantage of Inherited Config as a means to decentralise some
decisions and/or preferences that their organisations would like to use
for some self-hosted configuration.
Similarly, the decision of which hosts to allowlist may be something
that a self-hosted administrator /may/ want to allow their organisation
admins to decide.
We can make this an opt-in capability to indicate that the self-hosted
administrator trusts the Inherited Config moreso, and allows someone who
can write to it the ability to allowlist access to internal hosts that
may not be intended.
If a self-hosted administrator sets `allowInternal: false`, this takes
precedence, allowing a "veto", and a self-hosted admin's `headers` are
still preferred, too.
It's not possible for Inherited Config to set grants for `extends`, as
config resolution has already occurred, so this still needs to be
performed at the self-hosted config level.
This trust is transitive: `hostRules` defined in presets the
inherited config `extends` are registered at the same inherited
tier once resolved, so this option must only be enabled when those
preset sources are trusted too.
Co-authored-by: Claude Fable 5 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
To harden Renovate from being able to access internal hosts, we can add
a level of enforcement on all outgoing requests.
We can split this into two types of traffic:
- where the response becomes configuration (i.e. `extends`)
- where the response does not become configuration (i.e.
`customDatasources`)
To harden this, we enforce on every outbound HTTP request:
- check the resolved URL before anything, including cache lookups, can
proceed
- catching IP-literal hosts in every spelling the WHATWG URL parser normalizes
- blocking known Cloud metadata IPs, too
- a `dnsLookup` wrapper validates every address a hostname resolves to,
on every new connection, which also defeats DNS rebinding
- a `beforeRedirect` hook re-runs the URL check on each redirect
target, with the new host getting its own grant lookup rather than
inheriting the original host's verdict
We default this enforcement to `warn`, to not break existing deployments
and instead give them visibility into required configuration before a
future major version (major+1) enables `block` by default.
We'll also remove allow in a future major version (major+2), to give
time for admins to migrate over.
When a request is blocked, this degrades like an unreachable registry,
so a Renovate run isn't aborted by a blocked request.
As part of this, we can also provide a worked example of the different
cases that do/do not need allowing via `hostRules`.
Requests through an admin-configured proxy resolve DNS at the proxy, so
`dnsLookup` never runs for them, so we can resolve the hostname locally
and validate every address before the request instead.
This doesn't catch everything, especially as the proxy may resolve the
name to a different result, and if we can't resolve the name - possible
in locked-down corporate environments - we fail open.
Child processes aren't currently able to route traffic through
Renovate's HTTP layer, so are unrestricted.
Co-authored-by: Claude Fable 5 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
* refactor(lint): enable oxlint prefer-named-capture-group at error
Numbered capture groups (m[1], $1) break silently when a regex is
edited and group order shifts. Named groups (?<name>...) make intent
explicit and accesses (m.groups.name) resilient to reordering.
This enables the built-in eslint rule prefer-named-capture-group,
surfacing 321 pre-existing unnamed-group violations across ~121
files to be burned down incrementally in follow-up commits.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
* refactor(versioning): name capture groups for prefer-named-capture-group
Burns down all prefer-named-capture-group violations in
lib/modules/versioning/. Unused capture groups (only reachable via
.test() or whole-match) become non-capturing (?:...); groups whose
value is read become named (?<name>...), with accesses rewritten to
match.groups!.<name> (or destructured from .groups!) instead of
positional match[n]/$n so a future edit that reorders groups cannot
silently break the reader.
Two cases needed extra care to preserve behavior:
- semver/common.ts and poetry/patterns.ts split() on a regex whose
capture group is relied upon by String.prototype.split to keep the
separator in the output array; the group is kept capturing and
named, not converted to non-capturing.
- hashicorp/convertor.ts's semverRegex is only ever embedded via
.source into a named `(?<version>...)` group elsewhere and never
matched directly, so its internal groups are safe to make
non-capturing.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
* refactor(datasource): name capture groups for prefer-named-capture-group
Burns down all prefer-named-capture-group violations under
lib/modules/datasource/. Same treatment as the versioning module:
unused groups become non-capturing, used groups get names, and
positional match[n] reads move to match.groups!.<name>.
docker/ecr.ts and pypi/common.ts keep their positional destructuring
(`const [, region] = ...`, `!!m &&`) working unchanged since a named
capture group is still addressable by its numeric index in
JavaScript — only pypi/common.ts's access was rewritten to
m.groups!.owner for clarity since it read a single group directly.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
* refactor(platform): name capture groups for prefer-named-capture-group
Burns down all prefer-named-capture-group violations under
lib/modules/platform/. Uses the repo's established idiom of
`match.groups?.<name>` after an optional-chained exec()/match() (see
bitbucket/index.ts hostnameWithoutApiPrefix, gerrit/utils.ts
extractSourceBranch) and `$<name>` in String.replace replacement
strings. Unused groups (markdown/HTML massaging regexes matched only
to be stripped) become non-capturing.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
* refactor(manager): name capture groups in ansible-galaxy for prefer-named-capture-group
Burns down prefer-named-capture-group violations in
lib/modules/manager/ansible-galaxy/. newBlockRegEx and blockLineRegEx
dropped their unused outer wrapping group (only the inner key/value
groups were ever read) and named the key/value groups; nameMatchRegex's
remaining unused groups (protocol/user-info/port alternatives) become
non-capturing since only source/hostname/depName/version are read via
.groups. Accesses in collections.ts and roles.ts move from
lineMatch[2]/lineMatch[3] to lineMatch.groups!.key/value.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
* refactor(manager): name capture groups for prefer-named-capture-group (batch 1)
Burns down prefer-named-capture-group violations across the first
alphabetical slice of lib/modules/manager/ (ansible through mix).
Used groups get names with accesses rewritten to match.groups!.<name>
(or $<name> in replacement strings); groups whose value is never read
become non-capturing (?:...). Two String.split() call sites
(git-submodules/extract.ts, meteor/extract.ts) keep the established
"named group still readable positionally from the split() result
array" idiom instead of restructuring the destructuring.
bazel/rules/go.ts and buildpacks/extract.ts dockerRef verified
byte-for-byte equivalent before/after via a quick node script since
several nested groups collapsed to non-capturing at once.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
* refactor(manager): name capture groups for prefer-named-capture-group (batch 2)
Burns down prefer-named-capture-group violations across the remaining
alphabetical slice of lib/modules/manager/ (npm through terragrunt).
Same treatment as batch 1: used groups get names with accesses moved
to match.groups!.<name> or $<name> replacement strings; unused groups
(wrapping alternations, quantifier repetition groups only consumed via
.test(), or values never read from a match) become non-capturing.
terraform/extractors/others/modules.ts and terragrunt/modules.ts share
near-identical URL-parsing regexes (github/bitbucket/git/azure-devops
ref matchers) — the same set of always-unused `depth=`/`&depth=`
query-string groups is converted to non-capturing in both files.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
* refactor(config): name capture groups for prefer-named-capture-group
Burns down prefer-named-capture-group violations in lib/config/.
Used groups get names with replacement strings switched from $1/$2 to
$<name>; the unused separator group in schedule-migration.ts's
afterBeforeRegex becomes non-capturing. presets/parse.ts keeps
assigning through the already-declared `repo` variable rather than
array-destructuring the exec() result, matching this file's existing
style for the other named-group regexes just above it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
* refactor(util): name capture groups for prefer-named-capture-group
Burns down prefer-named-capture-group violations across lib/util/ and
lib/logger/. Same treatment as previous batches: named groups for
values that are read (via $<name> replacement strings, .groups!.<name>,
or destructured from .groups), non-capturing groups where nothing reads
the captured value (e.g. semantic.ts's angular-commit .test()-only
regex). www-authenticate.ts's tokenizer entries each get their own
named group but keep accessing the match generically via match[1],
since a positionally-indexed named group is still readable by index.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
* refactor(workers): name capture groups for prefer-named-capture-group
Burns down prefer-named-capture-group violations in lib/workers/.
Used groups get names with $<name> replacement strings; unused
wrapper/alternation groups (e.g. semantic-commit-message.ts's optional
scope/issue wrappers, release-notes.ts's date-heading and
horizontal-rule matchers that are only probed with .search()/replaced
wholesale) become non-capturing.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
* refactor(test,tools): name capture groups for prefer-named-capture-group
Finishes the prefer-named-capture-group burndown: test/, tools/, and
vitest.config.mts. Groups whose value is read get names ($<name>
replacement strings or .groups.<name> access); groups only used via
.test()/.search() or that feed a .match(/…/g) call (whose return value
is the array of whole matches, not captured groups) become
non-capturing.
This is the last remaining slice of pre-existing violations, so the
rule (already enabled at error repo-wide) now passes with zero
findings across the whole codebase.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
* fix prettier failure
* refactor(lint): use a named capture group in `v8-ignore-no-count`
New rule from main trips the newly enabled `prefer-named-capture-group` oxlint rule.
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
As they shouldn't be allowed, and we should therefore - loudly - block
them.
This migrates them to being a "security" error, given it's a config
option that is blocked for security reasons.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
As they shouldn't be allowed, and we should therefore - loudly - block
them.
This migrates them to being a "security" error, given it's a config
option that is blocked for security reasons.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
As an additional defence-in-depth, we can make sure that when applying
the `headers` configuration (from repo config, or presets) we
re-validate it.
We allow any admin-supplied configuration regardless, and then any
user-supplied settings are re-filtered according to `allowedHeaders`.
Due to the existing way that header merging incorrectly merges the repo
(or preset) `headers` over the admin config, we don't currently handle
this explicitly, unlike `filterAllowedEnv`.
If a user-supplied setting is filtered, we log a WARN message to inform
the user - and the admin - that this is ignored.
At this point, we don't try and explain which preset(s) this may have
come from, only that there is an issue.
Co-authored-by: Claude Opus 4.8 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
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>
* 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()`.
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.
When reporting config validation issues, we generally use the same
constants for our validation errors/warnings.
Instead of having these strings duplicated everywhere, we can refactor
these into constants, making it clearer when reading the code.
We can retain a "soft" union for cases where we use a dynamically
generated topic, which we won't know ahead of time.
Co-authored-by: Claude Opus 4.8 <jamie.tanna+claude-code@mend.io>
* feat(presets): support relative `extends` references inside presets
Presets which are fetched from a repository can now reference sibling
presets relatively, instead of repeating their own source, repository and
tag:
- `./x` resolves against the directory of the preset file with the
reference
- `../x` resolves against the parent directory of that file
- `/x` resolves against the root of the preset repository
The source, repository and tag of the preset which holds the reference are
inherited, so `./system/registries` inside `github>org/repo#v2.0.0`
resolves to `github>org/repo//system/registries#v2.0.0`. A reference which
resolves to the `default` preset at the repository root is emitted in the
plain repository form, so `github>org/repo#v2.0.0`, which keeps it
deduplicated against the way consumers spell the very same preset.
A reference must stay inside its repository, its final path segment must
name a preset file rather than a directory, and it can carry parameters
but neither its own `#tag` nor a `:subPreset`. Parameters may contain a
Handlebars template, including a sub-expression such as
`./group({{ lower (env.TEAM) }})`, while a templated path cannot be
resolved and is left alone. A reference must also not carry a source
prefix, so strings such as `local>./x` or `github>../x` are rejected as
invalid.
References are canonicalized lazily, while the preset which holds them is
fetched in `getPreset()`, after migration and massaging. Only presets from
a repository hosted source, so `github`, `gitlab`, `gitea`, `forgejo` and
`local`, are walked. A relative reference which has no parent preset, for
example in a repository config, an inherited config or in `globalExtends`,
is reported as a validation error for that entry.
Relative entries of a preset's `ignorePresets` are resolved in the same
way, so a preset can neutralize a preset which it references relatively,
as long as the consuming repository does not set `ignorePresets` itself.
A reference which cannot be resolved is kept raw and logged, which lets
consumers neutralize it with `ignorePresets`, and it only fails per entry.
Because relative references cannot be resolved while a config is
validated, they are stripped from a `packageRules` entry before its
presets are resolved. A rule which is then left without any selector is
reported as a warning rather than as an error, since the stripped preset
may still provide the missing selectors. Rules without relative references
keep failing hard as before.
The `renovate-config` manager reports relative and unparsable `extends`
entries with a skipReason, instead of dropping them, and ignores templated
entries which can only be resolved at runtime.
Behavior change: an `extends` string which starts with `./`, `../` or `/`,
such as `./x`, `../x` or `/x`, is now read as a relative reference. Before
it was parsed as a local repository name, which in rare cases could
accidentally resolve through the dot segment normalization of the request
URL. For the same reason a source prefixed relative looking string, such
as `local>/org/repo`, `github>./x` or `npm>./x`, is now rejected as an
invalid preset.
* fix(presets): parse scoped npm presets with explicit `npm>` prefix
`npm>@scope/name` was parsed as a local preset, because the heuristic for
local presets matched before the `npm>` prefix was stripped.
Every other use of `npm>` keeps its current behavior, so `npm>foo` still
falls back to the npm package `renovate-config-foo`, `npm>owner/repo` is
still resolved as a local preset and nested prefixes such as
`local>npm>foo` keep working.
* refactor: remove duplicated preset source
* docs: streamline new docs
* add more docs for skipReason and add requested changes
* Apply suggestions from code review
Co-authored-by: Jamie Tanna <github@jamietanna.co.uk>
* test(presets): drop object literal type casts in relative preset spec
---------
Co-authored-by: Jamie Tanna <github@jamietanna.co.uk>
* feat(config-validator): validate object entries in the `repositories` array
* Allow global configs in the repository object entry
* Simplify tests by combining them
* Allow `enabled` inside the repository entry
* Address review feedback
* Align type with #43295
* Skip validation for 'repositories' key in global config arrays
* refactor: flatten repositories array validation nesting
Address review feedback by combining the isArray and key checks
to avoid an extra nesting level.
* fix(schema): allow object entries in repositories array
Align renovate-global-schema with runtime: entries may be a string or
an object with required `repository` plus full global/repo config.
* Revert "fix(schema): allow object entries in repositories array"
This reverts commit 9aca8dcde8.
* fixups
* fix(config/validation): handle `allowedEnv` and `allowedHeaders` in `repositories`
Co-authored-by: Claude Opus 4.8 <jamie.tanna+claude-code@mend.io>
---------
Co-authored-by: Jamie Tanna <jamie.tanna@mend.io>
Co-authored-by: Claude Opus 4.8 <jamie.tanna+claude-code@mend.io>
* 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>
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>
* feat: add generic statusCheckWhen option to control any renovate status check
Replace the artifacts-specific `artifactsCheckWhen` option with a generic
`statusCheckWhen` object that can control when ANY Renovate status check is
emitted. Keys mirror `statusCheckNames`: `artifactError`, `configValidation`,
`mergeConfidence`, `minimumReleaseAge`.
Each key accepts: "always" | "never" | "failed"
- always: set check on every commit (green on success, red on failure)
- never: skip the check entirely
- failed: only set the check when there is a failure (silent on success)
Default values preserve existing behavior:
- artifactError: "failed" (only report failures, as before)
- configValidation: "always"
- mergeConfidence: "always"
- minimumReleaseAge: "always"
The defaults table in docs is autogenerated from the option's `default`
field via `tools/docs` so the docs cannot drift from the source of truth.
Logging is gated so that "skipping" debug lines only fire when there is
something to skip (errors / status set), keeping logs quiet on every
branch run when a check is set to "never".
Example configuration:
```json
{
"statusCheckWhen": {
"artifactError": "always",
"mergeConfidence": "never"
}
}
```
Signed-off-by: Pierluigi Lenoci <pierluigilenoci@gmail.com>
* refactor(docs): address viceice review — single replace marker, coerceObject, simplify replaceContent call
- Use single replace marker instead of begin/end pair in docs and config.ts
- Use coerceObject from lib/util/object.ts instead of manual (val ?? {}) as Type
- Refactor replaceContent call to match upstream API signature (string, not object)
Signed-off-by: Pierluigi Lenoci <pierluigilenoci@gmail.com>
* fix: fix test for never mode with no errors and format docs
- Add missing config.artifactErrors = [] in test that checks
'skips status entirely when mode is never with no errors' (beforeEach
sets artifactErrors to [{fileName: 'some'}], test needs no errors)
- Reformat note block in docs from 4-space to 2-space indent to match
prettier formatting (custom mkdocs-admonitions plugin expectation)
Signed-off-by: Pierluigi Lenoci <pierluigilenoci@gmail.com>
---------
Signed-off-by: Pierluigi Lenoci <pierluigilenoci@gmail.com>
* test(config/validation): document existing lack of coverage
So when we change it in the future, we have a failing test.
* fix(config/validation): validate children of arrays in global config
As we previously weren't doing so.
This was a regression as part of
321965a7fa, which inadvertently made the
validation too strict.
We can make sure that we use the example config we use in our
documentation to indicate what should be possible.
When we change configuration for what namespaces are possible to
override, there's no way for a self-hosted administrator to know this.
This leads to cases where an override can be left in configuration,
giving a false sense of security for caching.
Instead, we should inform self-hosted administrators when this happens,
using a config validation error, which will fail
`renovate-config-validator`, and add a WARN to the logs when failing.
* fix(config/global): return default values for `GlobalConfig.get`
As noted in #39949, it can be awkward working with in `GlobalConfig.get`, where
we would previously need to specify the default value when calling `.get`,
which could lead to drift with the defaults for a given config option.
To reduce this risk, we can rely on a given `default` for a configuration
option, providing that as a default.
Because this now definitely returns a value that matches the config option, it
now allows us to remove `!` assertions.
* fixup! fix(config/global): return default values for `GlobalConfig.get`
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
* fixup! fix(config/global): return default values for `GlobalConfig.get`
* test(presets): remove impossible test
As it's now not possible to set a value as `undefined` (as
`GlobalConfig` will then use the default), this test no longer validates
anything.
* test(workers/repository): add mock
Now `platform` defaults to `github`, we need to mock out the call to
fetch config.
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
* test: coverage
* test: coverage
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
* supportsTemplating field
* fix ci issue
* fix ci issue
* move tip below table
* apply suggestions
* docs: show list of options that support templating
* jsodc explanations for internal fields
* add test to ensure no option that applies template.compile() missed supportsTemplating=true
* apply review suggestions
* fix bad merge
* add filePatterns and commands to the list
* feat: allow separate versioning for constraints
As noted in #31831, there are times where it can be useful to override
the version that a given datasource uses, when performing
`constraintsFiltering=strict.`
This should only be applicable to the "additional" constraints, so we
make sure to validate this.
As this is new functionality, any misconfiguration should be marked as
an error.
We can make sure to provide a real-world usecase for this (taking
inspiration from `rails`' versioning of the `rubygems` constraint).
This will be used in the future by the extraction of the `go` directive,
which requires a different versioning to the default `semver`.
* fixup! feat: allow separate versioning for constraints
* fixup! feat: allow separate versioning for constraints
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
* extra-log-context
---------
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
* fix(validation): validate `constraints`
To provide better coverage for our users of what is a valid option for a
`constraints` value, we can validate the overall format of the
`constraints` block, as well as the given names of constraints.
Where we have a Tool defined, we can use the default versioning for that
Tool to validate the constraint's value.
For now, both the validation of the `constraints`' value, and the
validation of `constraints`' names will be a warning, but in the future
may be made an error.
* chore(validation): remove check for `compatibility`
As this was renamed in #7308. It's been long enough since then that we
can remove this check.
* chore(validation): add logger in `else` case
For coverage fix, and also to provide insight when this does happen
* fixup! chore(validation): add logger in `else` case
* fixup! chore(validation): add logger in `else` case
* key
* coverage
* Remove duplicate function
As it's been pulled in via another PR.
* fixup! docs(constraints): document the possible `constraints` and `installTools` (#42837)
As it can't be `undefined`.
* test: coverage
And more whitespace to make it clearer they're two separate `if` blocks.
* typo
* typo
---------
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
* test(validation): validate `installTools` aren't validated
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
* fix(validation): validate `installTools`
As we have a strong type for our `ToolName`s, we should make sure that
we now validate the `installTools`.
We'll start with a warning for now, and at some point promote it to an
error in the future.
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
---------
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
As noted in #40747, we have now explicitly deprecated
`binarySource=docker`.
This has been not recommended since 2023-07, and now we're noting that
it shouldn't be used any more.
We can make sure to mark any Docker-related self-hosted configuration as
deprecated, and add a custom deprecation warning (and URL for feedback)
to usages of `binarySource=docker`, so config validation flags these
deprecated usages.
fix(validation): show `deprecationMsg` as a warning if present
Although we specify the `deprecationMsg`, we don't always display this
to the user through `renovate-config-validator` or through regular repo
config validation.
The `deprecationMsg` has previously been made visible in the
documentation site, but that isn't as actionable as it appearing during
validation.
We can surface this by extending the `getDeprecationMessage`, using the
existing custom messages if using an option with deprecation, and
otherwise using the `deprecationMsg` on the option itself.
The only option we have available for testing the deprecation - right
now - is the `dnsCache` option under `hostRules`.
Noticed while making changes in the JSON Schema generation, but we're
currently returning a mutable reference to all of our options, which
means that it might be possible to (accidentally) change configuration
options that then affects all of the running Renovate process.
To handle this, we can make sure to `Object.freeze` the options, as well
as making sure our types clarify this is read-only.
This isn't something that should be user-facing, but makes sure that
we're keeping these immutable.
We also need to make sure any modifications now return a new config
option.
When we return a default value, we need to return a clone, so it's not
the frozen default value, as that then means it can't be modified (i.e.
in tests).
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
As part of future changes, we want to log the shallow configuration (the
full resolved configuration, but without any internal Renovate
configuration presets), where we'll want to note which presets have not
been merged in.
Before that, we can start with an initial refactor to indicate which
have been merged, and return them.
Right now, the `global:safeEnv` preset is the only "global" preset we
have, which allows providing a means to share common used global
self-hosting configuration.
In the future, we will introduce some new global presets, which will
have more (possibly dangerous) configuration that administrators will
need to make sure they are informed of the pros and cons before
enabling.
Before we make this available, we should make sure that there is no
possibility for a repo configuration to extend from `global:`, ensuring
that this can only be set in global configuration's `extends` or
`globalExtends`.
There is currently no gap in security allowing this to be bypassed, or a
way to leverage this right now without making a number of code changes
(to remove other sets of validation).
We mark this as an error to make sure that the repo cannot proceed.