* fix: misleading log message when updatePr is called due to autoApprove
* Log "PR body changed" only if PR body changed
* Revert "Log "PR body changed" only if PR body changed"
This reverts commit b4bd3de3d2.
* Add log assertion ot test
Enable the unicorn/prefer-at rule as error in .oxlintrc.json and fix all
43 pre-existing violations (arr[arr.length - 1] -> arr.at(-1)) via oxlint
autofix. Where .at() widened the type to T | undefined, non-null
assertions were added at sites where surrounding logic guarantees the
element exists (length guards, split results), preserving the original
runtime behavior and typing.
Co-authored-by: Claude Fable 5 <noreply@anthropic.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>
ci(linter): add renovate/no-redundant-mock-reset rule
Vitest sets mockReset: true globally in vitest.config.mts, which resets
all mocks before each test. This makes vi.resetAllMocks() /
vi.clearAllMocks() and per-mock .mockReset() / .mockClear() calls inside
beforeEach/afterEach hooks redundant. Add a custom oxlint rule (enabled
for **/*.spec.ts and test/**) flagging such calls, and remove the 40
redundant calls it found. restoreAllMocks/mockRestore are not flagged
because restoreMocks is not enabled globally.
Two sites keep an inline disable with a reason: nested beforeEach hooks
in filter-checks.spec.ts and onboarding/pr/index.spec.ts intentionally
call mockReset() to discard once-values queued by an outer beforeEach.
Requested by maintainer review feedback (review comment 3052324877).
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>
* fix(workers/repository): use GlobalConfig for productLinks
PR #44098 added productLinks to GlobalConfig.OPTIONS, which moves it into
GlobalConfig and deletes it from the per-repo config. Several readers
were not migrated and now receive undefined from config.productLinks.
Most visibly, setStability and setConfidence build the status check
target_url from config.productLinks?.documentation. With it now empty the
URL becomes scheme-relative (e.g. "key-concepts/minimum-release-age/"),
which GitLab rejects with HTTP 400. That throws in setBranchStatus and
aborts the branch before its merge request is created.
Migrate the remaining readers to GlobalConfig.get('productLinks'),
matching #44098, and drop the now-redundant coerceString calls and
non-null assertions.
* refactor(config): drop productLinks from RenovateSharedConfig
productLinks is globalOnly and is now read via GlobalConfig.get. Leaving
it on the per-repo RenovateSharedConfig let callers read the (always
empty) config.productLinks, which is the footgun this PR fixes. Remove it
from the shared interface so it only exists on RepoGlobalConfig, and the
type now prevents reintroducing config.productLinks.
* chore: ensure we use `productLinks` for docs site links where possible
Where possible, we should be making sure that we're using the
`productLinks`' configuration for the documentation site, especially
where self-hosted users may create a mirror of their docs[0].
To make sure we catch this in the future, we can introduce a custom
linting rule with Oxlint to enforce this.
Where we (currently) can't wire in the config, we can disable it against
that line.
[0]: https://www.jvt.me/posts/2024/11/19/renovate-private-docs/
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
* fixup! chore: ensure we use `productLinks` for docs site links where possible
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
* fixup! chore: ensure we use `productLinks` for docs site links where possible
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>
* fix(platform/forgejo): replace getJsonUnchecked with validated getJson
Migrate all getJsonUnchecked calls in the Forgejo platform module to use
getJson with Zod schemas for response validation. Add comprehensive Zod
schemas to schema.ts and update test mocks to use proper data formats.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* simplify by using infered types
* first pass on reducing duplications
* move PrStatus and CommitStatus to schema
* remove code handling BranchStatus values now ensured by schema
* remove now unreachable code
* fix coverage
* use forgejo schemas instead gitea for changelog fetching
* feat: do not abort repo on unrecognized default merge style
* refactor: instead of usages of `?? {}` with a default parameter
* tighten required parameters and move contentString generation to schema
* refactor: merge both content schemas and use a discriminated union
* refactor: move patchJson and postJson to schema validation
* Make body field required
* make schema more strict
* use DeepNullish
* simplify catch
* revert the gitea Content type change
* unify User
* log more nicely if accidentally not a file has been referenced
* Use fakeSha and LongCommitSha schema
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(release-notes): include gitRef in release notes cache key
Append the release gitRef to the changelog cache key so that releases
sharing a version but pointing at different git refs are cached and
matched independently.
* chore: remove global resets
* feat(git): validate length commit shas
* test: adapt test mocks
* chore: update import paths
* feat(git): make the validation more strict and support repositories using sha256
* test: add fakeSha function for deterministic git commit shas in tests
* 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(workers/repository): use more explicit test case
Otherwise this could pass unnecessarily if either `schedule` or
`automergeScheudle` renders to this.
* test(workers/repository): document `force` doesn't apply in this function
As it should've been performed higher up in the configuration merging.
* fix(workers/repository): correctly render `schedule` for vulnerability alerts
Otherwise we see i.e.
- Branch creation
- ""
- Automerge
- At any time (no schedule defined)
`checkForPendingVersions` (introduced in #41629) previously threw
`WORKER_FILE_UPDATE_FAILED` when the re-extracted dep had none of
`lockedVersion`, `newVersion`, `currentVersion`, or `currentValue`
populated. That aborts the entire `getUpdatedPackageFiles` flow for a
single dep we cannot verify, which is disproportionate to the intent of
the check (flag artifact updates that introduced a pending version).
Demote the abort to a warn-and-continue: if we cannot determine the
resolved version for a single dep, skip the pending-version check for
that dep only and let the rest of the update proceed. The remaining
deps in the same file can still be verified normally, and a
`logger.warn` makes the skip visible without taking down the update.
* 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>
* test(noNewURL): add new rule enforcing parseUrl() from 'lib/util/url.ts'
* replace newURL with parseUrl
* remove non-null assertions marks if appropiate
* test: add additional tests
* test: add additional tests and ignore where it makes sense
* implement suggestions
* test: further improve coverage
* apply suggestion
* fix(github): set commit message explicitly for platform automerge
When GitHub's "Use PR title and body as commit message" setting is
enabled, the verbose Renovate PR description gets used as the squash
commit body. Pass `commitHeadline` and `commitBody` to the
`enablePullRequestAutoMerge` GraphQL mutation so the actual commit
message is used instead.
* add REBASE test
* pr feedback
* fix(gerrit): defer change creation to `createPr()`
Signed-off-by: Felipe Santos <felipe.santos@ericsson.com>
* Refactor hashtags handling
* Add prTitle to all missing commitAndPush()
* Fix gerrit tests
* Add warning when prTitle is set in updatePr
* Remove now useless labels from commitAndPush
* Fix gerrit client coverage
* Fix gerrit scm coverage
* Fix rebase coverage
* Improve TODO about assignees
* Fix formatting
* Fix review comment
* Extract to a pushForReview function
* Fix after #41382
* Fix onboarding
* Cleanup code
* Fix ESLint
* Fix tests
* Restore gitRetry for git.merge
* Fix tests
* Simplify hashtags code
* Delete pendingChangeBranch in pushForReview()
* Fix test name
* Remove unnecessary test comments
* Improve test name again
* Fix another test name
* Delete local branch in Gerrit SCM
* Add test for deleting pending branch
* Add tests for pushForReview()
* Fix test case name
* Improve another test name
* Fix another small test inconsistency
* Fix some code style issues
* Use isUndefined instead
* Fix one small test style issue
---------
Signed-off-by: Felipe Santos <felipe.santos@ericsson.com>
* chore(types): add a strong type for `ToolName`s
Until #41849, we can use our local definitions of the tool names that
Containerbase supports by extracting out a `ToolName` type.
* fixup! chore(types): add a strong type for `ToolName`s
Co-authored-by: Claude Opus 4.6 <jamie.tanna+claude-code@mend.io>
Co-authored-by: gpt-4.1 <jamie.tanna+github-copilot@mend.io>
* fixup! fixup! chore(types): add a strong type for `ToolName`s
* no-never
* simplify
* coverage
* sq
* warn
* sq
* fixup! sq
* sq
* fixup! sq
---------
Co-authored-by: Claude Opus 4.6 <jamie.tanna+claude-code@mend.io>
Co-authored-by: gpt-4.1 <jamie.tanna+github-copilot@mend.io>
* test(pr): add test coverage for `automergeSchedule`
* test(pr): validate full `Schedule` text
As part of a future change, we'll be modifying this, so we should
clarify the exact behaviour.
* feat(pr): break `Schedule` definition over multiple lines
To provide a more readable set of `schedule` and `automergeSchedule`
configuration options, we can break these over multiple lines, which
makes it clearer where there are multiple schedules that may apply at
a given time, as well as making it clearer between branch creation vs
automerge, which isn't necessarily clear.
* feat(pr): show cron syntax in code blocks
As it can make it clearer, as well as avoiding potential interpretation
as Markdown.
* fix(pr): ensure enough whitespace between elements
Although it's unlikely to hit our currently used Platforms, it's worth
making sure we do it right.
* test: add additional case for attestation changes
* fix: correctly warn when an attestation is missing
As noted in #37258, when a package registry had previously seen an
attestation for authenticity of a given package release, Renovate should
warn if future updates then lose authenticity.
Our previous attempt at this didn't quite pass around the current
package's attestation, which results in no warnings.
Given recent supply chain attacks where an attestation was removed (such
as Axios in MSC-2026-3522), we should make sure that this logic does
work correctly, and flags to our users.
In the future, we'll add more checks and a failing status check.
By introducing `hasAttestation` in the `LookupUpdate`, this can now be
matched on with `matchJsonata`, as well as providing visibility in the
`packageFiles with updates` log line.
* fixup! fix: correctly warn when an attestation is missing
> Run `pnpm run jest
> lib/workers/repository/process/lookup/index.spec.ts` and handle any test
> failures - the implementation is correct, so update the tests
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
* test: clarify that we don't check for intermediate releases
Which we'll look to improve as part of future changes.
* chore: fix typo
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
---------
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
As a means to make the dry-run functionality a little more useful, we
can log out what commit(s) a given Renovate run would have created
outside of Dry Run.
Because the meta key `contents` is automagically replaced with
`[contents]`, we need to move this into a new field, `rawContents`.
This can also lead to longer lines being output, but provides additional
utility that we've had requests for before.
As `fileName` makes more sense (as it's not always a lock file we're
updating).
Also, if you set `fileName`, it would never actually output the
filename.
This renames the usages of `lockFile` to `fileName`.
Co-authored-by: Claude Sonnet 4.5 <jamie.tanna+github-copilot@mend.io>
As noted in #41716, there are cases where a `depName` may be absent, but
a `packageName` is present.
We should handle this accordingly, and check for the `packageName`, and
only error if neither of these are set.
* feat(workers/repository): raise artifact error if `pending` version used in an update
When using Minimum Release Age, and a package manager that doesn't
support being told an explicit version to update to (#41624) it is
possible that an artifact update leads to a different version of a
dependency being used compared to what Renovate is expecting.
This can lead to, at best, a surprising PR update, and at worst, a
supply chain attack.
We should report these cases more explicitly with an Artifact Error, to
allow the reviewers to decide what to do with the changes.
To do this, we need to re-extract package files after an update, and
determine if any of the version(s) of that dependency are using any of
the `pendingVersions`.
This may be slightly breaking to users, which is why this is a `feat`
not a `fix`, but isn't so breaking that it's worth leaving until the
next breaking change .
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+github-copilot@mend.io>
* fixup! feat(workers/repository): raise artifact error if `pending` version used in an update
* fixup! fixup! feat(workers/repository): raise artifact error if `pending` version used in an update
* Update lib/workers/repository/update/branch/get-updated.ts
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
---------
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+github-copilot@mend.io>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
* feat(postUpgradeTasks): allow specifying `installTools`
As noted in #8111 and #41569, it is possible that when using
`binarySource=install`, you can execute a `postUpgradeTasks`' given
command without Renovate having the right tools installed, dependent on
the Manager used for the update.
To make it possible for users to indicate that they explicitly need
given tools (at a given `constraint`), we can introduce a new
`installTools` option which will allow specifying which tools +
constraints to use when invoking the `postUpgradeTasks`'s command.
Right now, we're not defining what the `installTools'` interior type is,
but leaving it open to extension.
Co-authored-by: gpt-4.1 <jamie.tanna+github-copilot@mend.io>
* docs: add examples for `toolVersions`
---------
Co-authored-by: gpt-4.1 <jamie.tanna+github-copilot@mend.io>