Although we document that the `hostRules[].hostType` are
Platform/Datasource names, we don't currently provide a means to suggest
to the user what the values should be.
As there is currently no validation for these, we can provide them as a
suggestion, rather than an enum of all possible values, so we don't
introduce config validation mismatches.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
* refactor(config): require an option to document where it can be used
Now we have coverage of all of our repo config's `scopes` we can
refactor our types to make sure that:
- global self-hosted config could include `scopes`
- repo config must include `scopes`
This now allows us to relax the error checking in JSON schema
generation, as `scope` now will be required per the types.
To do this, we need to extract out a base type for global-only config.
As noted in #43020, an option which declares neither `parents` nor
`scopes` is treated as valid anywhere, which means a new option can
silently join that group by saying nothing.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
* fixup! refactor(config): require an option to document where it can be used
---------
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
* feat(json-schema): suggest the managers, datasources and categories we know
As per #40450, and similar to how we provide suggestions for `extends`
presets, we can suggest to an editor which values a `match*` option
usually takes, so they can be completed.
As these options allow a regex or a glob pattern, we can't use an
`enum`.
Instead, we give them `suggestedValues`:
- `matchManagers`, from the managers we support, with our custom
managers under the `custom.` prefix they're matched by
- `matchDatasources`, from the datasources we support
- `matchCategories`, from the categories a manager can be in
A pattern, or a value we don't know about, is still accepted.
We don't include these in the docs table, as it's unnecessary noise.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
Co-Authored-By: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
* fixup! feat(json-schema): suggest the managers, datasources and categories we know
---------
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
As part of follow-up changes, we'll want to suggest values for options
other than `extends` - such as the managers, datasources and
categories a `match*` option takes, and the host types a `hostRules`
entry's `hostType` takes - which need the same `anyOf: [{enum}, items]`
shape we already build for suggesting presets.
We can first prefactor the way that we propose suggested values for
`extends` into a shape that we can re-use for other types, extracting a
`suggestValues` helper function, and building both the array and scalar
cases generically in `createSingleConfig`.
The scalar case isn't exercised by any option yet - the next two
commits each introduce one - so it's marked as such for coverage.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
As part of #43020, we have a few options that can be found at any level
of configuration.
We can introduce an `any` scope for these, so we can reduce duplication
and make it clearer when it's used anywhere.
Objects which aren't a scope of their own are now listed once, in
`namedParents`, which `AllowedParents` is derived from so the two can't
drift.
We can now remove the hand-rolled `description` and
`overrideDescription` in the JSON schema, as it's now a known config
option.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
We currently allow an option to be set to `null` when it defaults to it,
which means that our JSON schema's additional validation will reject the
two nullable options:
- `semanticCommitScope`, which the `default:semanticCommitScopeDisabled` preset sets to `null`
- `minimumReleaseAgeBuffer`
Instead, we should mark them as `nullable: true`, so we report the
correct types for our JSON schema, which then allows us to mark
`default:semanticCommitScopeDisabled` as well-formed against our JSON
schema.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
To have greater confidence in changes to our JSON schema will result in
the correct validation rules, we can test all internal presets against
the JSON schema.
This does lead to `default:semanticCommitScopeDisabled` failing
validation, as it is technically valid but our JSON schema reports it as
invalid, due to a type mismatch.
We'll fix this in a follow-up commit.
As `global:` presets are used in `globalExtends`, they need to be
validated against the global self-hosted config schema.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
As noted in #43020, an option which doesn't declare its `parents` is
treated as valid anywhere, which means we can't currently i.e. tell
`automerge` - which is valid at the top level, in a package rule, in a
manager's config and in an update type's config - apart from
`baseBranchPatterns`, which is only valid at the top level.
Instead of making the `parents` explicit - which would require an
exhaustive list of all Managers and `updateType`s that could be used -
we can instead abstract this into a new "scope" type:
- `repo`, for the top level of a config
- `packageRule`, for a `packageRules` entry
- `manager`, for every manager's config object
- `updateType`, for every update type's config object
An option which is only valid in a specific object, like the children of
`hostRules`, will retain the `parents`.
In the future, this will be used to aid config validation and our
generated JSON Schema.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
When an option declares its `parents`, we add it to the `items` of each
of those parents, which only works for the parents which are an array of
configs, like `packageRules` or `hostRules`.
For the other parents which aren't - every manager, every update type,
`postUpgradeTasks`, `toolSettings`, `vulnerabilityAlerts` and
`customDatasources` - `items` is ignored, so none of their children are
validated:
```yaml
postUpgradeTasks:
# not reported, although it must be an array
commands: echo hi
# not reported, although it's not an allowed value
executionMode: bogus
```
We should instead declare the children on the schema being validated,
which differs depending on whether the parent is an array of configs, a
map of configs, or a config itself.
As `customDatasources` is a map of maps, we need to declare the children
on the values, rather than on the map.
This also means that we will reject a misconfigured custom datasource
which contains other Renovate config.
The option metadata is frozen, so we need to copy any
`additionalProperties` we're given before declaring children on it.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
* fix(json-schema): restrict all known object properties keys
As noted when declaring the values of our maps of values, we didn't have
our JSON schema restrict the keys of `statusCheckNames` and
`statusCheckWhen` to the status checks we know about in, although config
validation does correctly error on i.e.
```json
{
"statusCheckNames": {
"bogusCheck": "renovate/bogus"
}
}
```
We already generated the keys of an object for `constraints`,
`constraintsVersioning` and `installTools`, which was generated
specifically in the JSON Schema generation.
Rather than add another hardcoded case, we can add a new `properties`
type to config options, which the generator copies as it does the rest
of an option's metadata.
The keys are hidden from the docs tables, as the generated JSON is noise
next to a description which already says the keys match
`statusCheckNames`.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
* fixup! fix(json-schema): restrict all known object properties keys
getSupportedToolNames() returns Object.keys(allToolConfig), so every
name it yields is guaranteed to be a key of allToolConfig - meaning
getToolConfig(toolName) can never return undefined for it. The `if
(!toolConfig) continue;` guards in toolConstraintProperties() and
installToolProperties() were therefore dead code, which 100% coverage
enforcement was flagging as uncovered lines.
We can just remove them, and the now-unused toolConfig variable and
getToolConfig import along with them.
Co-Authored-By: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
* fixup! fix(json-schema): restrict all known object properties keys
Every entry in `additionalConstraintDefinitions` currently has a
`description`, so the `??` fallback in `additionalConstraintProperties`
is unreachable, which 100% branch coverage enforcement was flagging.
As the type still allows an entry without one, we should keep the
fallback rather than delete it - we can instead document why it's
currently unreachable with a `v8 ignore` comment, per
docs/development/best-practices.md.
Co-Authored-By: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
---------
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
As a follow-up to the previous change, we should make sure that these
config options have their `additionalProperties` defined explicitly.
As `statusCheckWhen`'s allowed values are now needed in two places, we
can share them from `config/types`, rather than redeclaring them in the
validation.
In a follow-up commit, we'll ensure that only valid key names can be
used for `StatusCheckWhen`'s object keys.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
* chore(util/exec): add a strong type for Containerbase's known tools
As noted in #41849, we currently don't have a way of enforcing the usage
of a `ContainerbaseToolName` being a tool that Containerbase actually
knows.
To handle this, we can use the new `@containerbase/base` and
`@renovatebot/base-image` packages to see what Tools we currently have
support for, and make sure that our types use the tools supported by
`@renovatebot/base-image` (and therefore `@containerbase/base`).
As well as the Typescript compilation error a user will receive, we can
add a test that provides a better note to the user about how to add a
new tool.
Co-Authored-By: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
* fixup! chore(util/exec): add a strong type for Containerbase's known tools
* fixup! chore(util/exec): add a strong type for Containerbase's known tools
So we can get better confidence that we're not clashing with type names
between Containerbase tools and non-tool constraints.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
---------
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
Options like `secrets`, `registryAliases` and `productLinks` are a map
of user-chosen keys to simple values, but when we generate the JSON
Schema, we use a `$ref` to the root schema, in a similar way to options
that do have a nested Renovate config, like `force` or
`onboardingConfig`.
That means the keys of the map are validated as if they were config
options, so a perfectly valid config is reported as an error:
```yaml
secrets:
# must be boolean
enabled: a-secret
registryAliases:
# must be array
labels: https://example.com
```
As we already have `additionalProperties` defined, we can use these to
document the format of the body, instead of treating it as a Renovate
schema.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
As part of follow-up changes we'll fix how our JSON schema treats the
options which are an object. Before we do this, we should document how
we currently generate them.
Currently, if an object option:
- is not `freeChoice`
- nests a Renovate config i.e. `force`
- is a map of simple types i.e. `secrets`, `env`
then the JSON schema indicates that this is can take any root-level
options, which isn't correct.
Also, the children an option declares through its `parents` are
generated into `items`, which is only validated for the parents which
are an array.
This means that we error for valid config i.e.
```yaml
env:
automerge: "true" # incorrectly reports this must be boolean
```
but do not error for an invalid config i.e.
```yaml
postUpgradeTasks:
commands: echo hi # incorrectly does not report that this must be an array
```
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
As part of follow-up changes to make our JSON schema representative of
where each option can be used, we'll want to assert that the generated
schema accepts and rejects the configs we expect it to, which we can't
currently do without writing the schema to disk first.
We can prefactor these changes by extracting this function so it can be
used in tests.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
As part of #43020, we're making an option's `parents` explicit, which
isn't possible without breaking the docs links that our JSON Schema
contains.
We previously incorrectly generated the `See also` link for an option,
by taking the first of its `parents` which isn't `.`, and assume the
option is documented under that parent, which isn't true for options
that can be valid in multiple places.
To fix this, we track which headings are output, and then linking to
them accordingly.
By fixing this, we see the following diffs:
```diff
-#packagerulesenabled
+#enabled
-#packagerulesfetchchangelogs
+#fetchchangelogs
-#ansiblemanagerfilepatterns
+#managerfilepatterns
```
We can also add a test to catch this breakage in the future.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
As part of follow-up changes, we want to fix how these links are
generated. Before we do this, we should cover how they're generated, so
there's a clearer diff.
When generating an option's `See also` link, we take the first of its
`parents` which isn't `.`, and assume the option is documented under
that parent, which isn't true for options that can be valid in multiple
places, which means we have 3 links that don't match anything.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
* feat(datasource): add GraalVM version datasource with support for JDK and JRE releases
* feat(datasource): add GraalVM version datasource with support for JDK and JRE releases
* feat(datasource): add GraalVM version datasource with support for JDK and JRE releases
* feat(datasource): add GraalVM version datasource with support for JDK and JRE releases
* feat(datasource): add GraalVM version datasource with support for JDK and JRE releases
* add coverage
* fix
* fix
* fix
* code cov
* code cov
* code cov
* refactor(datasource): integrate GraalVM into java-version datasource
Merges graalvm-version datasource into java-version as a unified multi-vendor
Java distribution datasource. Implements vendor-based modular architecture with
routing layer for Adoptium (Eclipse Temurin) and Oracle GraalVM.
Architecture:
- Vendor-specific handlers (adoptium.ts, graalvm.ts) with routing in index.ts
- Vendor-aware system detection with different arch/os mappings per vendor
- Custom registry support for GraalVM's mise-java API
- Adoptium remains the default registry for backwards compatibility
Package names:
- New explicit: adoptium-jdk, adoptium-jre, oracle-graalvm-jdk, oracle-graalvm-jre
- Legacy (map to Adoptium): java, java-jdk, java-jre
Changes:
- Created adoptium.ts and graalvm.ts vendor handlers
- Enhanced common.ts with vendor detection and vendor-specific system mappings
- Updated index.ts with routing layer and custom registry support
- Merged test suites with comprehensive coverage for both vendors
- Updated mise manager integration to use JavaVersionDatasource
- Removed graalvm-version datasource directory
All 65 datasource tests and 93 mise manager tests passing.
* fix
* test(datasource): add coverage for non-HttpError paths in java-version
* fix(datasource): remove dead code and add coverage for java-version
Remove unreachable HttpError handling from _getReleases catch block
since both getAdoptiumReleases and getGraalvmReleases handle HttpError
internally. Add test for the graalvmRegistryUrl fallback when
registryUrl is undefined.
* fix(datasource): address review comments for GraalVM datasource
- Remove unused 'datasource-graalvm-version' cache namespace
- Convert MiseJavaRelease interface to Zod schema and derive type from it
- Use http.getJson() with the Zod schema in getGraalvmReleases instead
of getJsonUnchecked, letting the schema handle invalid/empty responses
- Update getGraalvmReleases test mock to use getJson
* docs: remove unused datasource-graalvm-version from cacheTtlOverride docs
* fix(datasource): preserve Adoptium config typing
* fix(datasource): harden GraalVM release parsing
* fix(datasource): address GraalVM review feedback
* test: cover GraalVM mise package mapping
* test(datasource): cover default GraalVM registry fallback
* test(datasource): cover legacy registry resolution
* test(datasource): type legacy datasource mocks
* fix(datasource): harden GraalVM defaults and responses
* refactor(datasource): use function-only registry accessors
* test(datasource): cover registry accessor functions
* test: restore coverage exclusions
* chore: retrigger CI checks
As noted in #45839, we're currently out-of-sync with the current list,
so should get this automagically updated.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
Although I'd implemented this a couple of days ago, this surprised me
when I went to read the page.
We can make it clearer that this is the default, and reference the
footnote.
Similar to how we already generate a list of the community actions we
support, we should also generate which first-party Actions from GitHub
are supported, and simplify some of the wording in the docs.
Instead of duplicating this, we can instead move them into a single
section in the documentation.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
* refactor(manager/github-actions): don't duplicate parsing logic for first-party Actions
Instead of having a separate set of Action parsing and their
configuration between first-party GitHub-owned Actions and those of
third-party Actions, we can merge them into a single collection.
This also leads to `https://<host>/` handling noted in #35777 now being
handled out-of-the-box, as it was already supported on third-party
actions.
Co-Authored-By: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
* fixup! refactor(manager/github-actions): don't duplicate parsing logic for first-party Actions
---------
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 part of follow-up changes, we'll introduce stricter validation for
config options that need to be re-validated before use.
We can prefactor by adding a new field to the config options, and making
sure it doesn't appear in the generated docs.
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>
feat(lint): add `types-location` rule and enable it for `lib/modules`
Reviewers consistently ask for exported types to be moved into a
colocated `types.ts`. Add a `renovate/types-location` oxlint rule that
reports `export interface` / `export type` declarations outside such a
file, and turn it on across `lib/modules`.
Re-exports (`export type { X }`, `export type *`), file-local types, and
values (enums, classes, functions) are left alone. `schema.ts` files and
`schema/` directories are excluded via config, matching how
`zod-schema-location` is configured — inferred types belong next to the
schema they are derived from.
Relocating the 87 existing violations means:
- new `types.ts` files for the modules that had none
- `terragrunt/common.ts` folded into its `types.ts`, as it held nothing
else
- `RangeBound` in `versioning/gradle/compare.ts` un-exported, since only
a file-local interface referenced it
- `bazel-module/parser/fragments.ts` split from its inferred types, which
now live in `parser/types.ts` and infer through a namespace import so
each schema keeps its merged name
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>
* feat(config): add `overrideDescription` option
Presets which extend many other presets used an `ignoreDeps: []` sentinel
to keep their own one-line summary in the onboarding PR instead of one line
per extended preset. Replace that hack with an explicit `overrideDescription`
option, which is consumed and removed while presets are resolved.
The resolved descriptions are unchanged. Repositories which set
`ignoreDeps: []` in their own config no longer lose all preset descriptions
in their onboarding PR.
* fixup! feat(config): add `overrideDescription` option
* fixup! feat(config): add `overrideDescription` option
* fixup! feat(config): add `overrideDescription` option
As found with recent changes to the Terraform manager, although we
generally have `lockFileMaintenance` being executed by an external
package manager being invoked by `exec(...)`, there are a few package
managers that do not do so.
To make it very clear how this happens, we can add a new field to the
Manager API, which will provide a means to document this.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
As noted in #30714, and to make the Minimum Release Age page a
"one-stop-shop", we can generate the documentation accordingly.
Using an orange "maybe" for support helps nudge folks to checking which
registry they're using, and noting that it still doesn't necessarily
work, even if the Datasource supports it.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
* feat(lint): add renovate/zod-schema-location and renovate/prefer-json-pipe rules
Backlog item #23: reviewers repeatedly ask for consistent Zod schema
structure. Two new oxlint JS-plugin rules, both at "warn":
- renovate/zod-schema-location flags `export const X = <zod schema>` at
module scope in lib/modules/**/ files that aren't schema.ts (or a
colocated schema/ directory), reusing the leftmost-identifier schema
detection from zod-schema-naming.js / prefer-nullish-util.js. Only
exported top-level schemas are flagged — non-exported ones are treated
as intentionally local/trivial (e.g. tightly coupled to file-local
helpers), which keeps the rule's signal high.
- renovate/prefer-json-pipe flags `Schema.parse(JSON.parse(x))` /
`Schema.safeParse(JSON.parse(x))` and suggests `Json.pipe(Schema)` from
lib/util/schema-utils instead.
A third mined slice (require a matching `z.infer` type export for every
exported schema) was evaluated and skipped: ~275+ exported schema-like
consts in schema.ts files vs. 231 existing z.infer exports repo-wide is
too high a mismatch to flag mechanically without heavy per-site
judgment, so it would be mostly false positives.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor: fix a clean subset of renovate/zod-schema-location and renovate/prefer-json-pipe violations
renovate/prefer-json-pipe: fixed all 5 safe `.parse(JSON.parse(...))`
call sites (bazel datasource, generate-mise-registry script, a hook
spec) by switching to `Json.pipe(Schema).parse(...)`. Left the 2
`.safeParse(JSON.parse(...))` sites (pretooluse-check.ts,
github-query-items.ts) unfixed: JSON.parse throwing before safeParse is
reached today crashes the script, whereas Json.pipe folds the bad-JSON
case into a graceful `{ success: false }`, which is an observable
behavior change, not just a mechanical rewrite.
renovate/zod-schema-location: fixed the one clean, self-contained
violation (platform/github's GithubIssue schema, moved into the
already-existing platform/github/schema.ts) as a representative
example. Left the other 20: they require moving exported schemas out of
files where they're built from local helper functions/config tables
(manager/github-actions/community.ts) or restructuring an entire
directory into a new schema.ts with import-graph updates across many
files (manager/bazel/rules/*.ts, manager/bazel-module/parser/*.ts) —
real refactors needing per-site judgment, not mechanical fixes.
Both rules stay at "warn": renovate/prefer-json-pipe has 2 remaining
violations that shouldn't be auto-fixed, and renovate/zod-schema-location
has 20.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor: resolve remaining prefer-json-pipe and zod-schema-location findings
- github-actions: move the derived `CommunityActions` union into the
existing colocated `schema.ts`; the action config table and the
`actionSchema` builder stay in `community.ts` and are now exported.
- tools/docs: fold `JSON.parse` + `safeParse`/rethrow of the `gh` CLI
output into `Json.pipe(...)`. Invalid JSON now surfaces as a ZodError
instead of a SyntaxError; the only consumer catches generically, so
behavior is preserved.
- tools/agents/hooks: keep `JSON.parse` + `safeParse` with a reasoned
disable comment — hook scripts must stay dependency-light, and the
`Json` helper lives in lib/util/schema-utils, which drags in the full
lib import graph (logger, yaml, toml).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(lint): enforce zod-schema-location and prefer-json-pipe as errors
Narrow `renovate/zod-schema-location` to files whose directory already
contains a colocated `schema.ts`. The mined reviewer feedback ("move
this to schema.ts") presumes the module follows that convention and the
schema leaked into a logic file. Modules that deliberately export
schemas from differently-named schema-only files — bazel `rules/*.ts`
Target schemas, bazel-module `parser/fragments.ts` — are a different,
accepted layout, not "schema mixed into logic", and are no longer
flagged.
With that narrowing and the preceding migrations, both rules are clean
repo-wide, so promote them from "warn" to "error".
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor: drop GithubIssue re-export from issue.ts
Consumers now import the schema directly from schema.ts.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(lint): register zod-schema-location rule
The rule registration was lost while merging main, so oxlint failed to
parse .oxlintrc.json with "Rule 'zod-schema-location' not found in plugin
'renovate'". Re-add the import and rules entry, and restore alphabetical
ordering for prefer-json-pipe.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(lint): allow sync fs in zod-schema-location rule
ESLint rules execute synchronously, so the sibling `schema.ts` lookup
cannot use async fs. Silence `no-sync` with a justification.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* docs(manager): make sure that Supported Datasources are de-duped and sorted
As noted in #44764, we otherwise end up with a lot of duplicated
entries for `renovate-config`.
We can also sort them to make ti a slightly more readable list.
* chore(manager/renovate-config): dedupe `supportedDatasources`
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>
- Convert `param: T | undefined = undefined` to optional `param?: T`.
- Drop dead `= false` defaults on the required cache-provider options.
- Make `GraphqlPaginatedContent.nodes/edges` optional so the `= []`
fallbacks (load-bearing for partial GraphQL connections) are valid.
- Type the unchecked `default_branch` response field as optional so
the `'HEAD'` fallback is retained.
- Drop `tag = undefined` from the Forgejo/Gitea/GitLab preset configs.
Part of #43845
Co-authored-by: Claude Opus 4.8 <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>
* docs(manger/github-actions): reword "community actions" section
As some follow-ups to 27a3f5871f, we
can slightly reword the intro to add some more information about what
these target.
* docs(manager/github-actions): document why there may not be a `packageName`
* docs(manager/github-actions): generate a table for Actions and their `with`s
To provide further clarity on how each of the Actions' `with`s are used,
we can make this more explicit in our autogenerated docs, providing:
- which field(s) are extracted, taken from their Zod schema (with help
from Claude Opus to extract this)
- note the dependency updating, and where it may be determined from the
given `withSchema`
Co-authored-by: Claude Opus 4.7 <jamie.tanna+claude-code@mend.io>
---------
Co-authored-by: Claude Opus 4.7 <jamie.tanna+claude-code@mend.io>
In the case of a config option that has both `allowedValues` and is
templateable - such as `bumpVersions.bumpType` - we should relax the
generated JSON schema to not restrict the exact value.
As part of recent work around environment variable handling, it's clear
we should provide more user-facing documentation on how environment
variables are handled, and which are passed to child processes by
default.
We can create a "deep dive" page for this, with an autogenerated list of
the environment variables in `basicEnvVars` that are always passed to
child processes, if they're set.
We can also point self-hosted administrators and users alike to the
options they have to control this, too.
With help from GPT-4.1 for case-insensitive sorting.
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
Co-authored-by: gpt-4.1 <jamie.tanna+github-copilot@mend.io>
* docs(config): don't trim newline after generated config filenames
Otherwise there's no newline before the next sentence.
* docs(config): correct usage of JSON5 presets
* docs(config): rewrite overview section
- introduce a linkable section for "what filenames are supported"
- correct the usage of "config help" discussions
- keep precedence/ordering in a single paragraph
* fixup! docs(config): rewrite overview section