As a further level of defence-in-depth for fixes on top of `allowedEnv`
and `allowedHeaders` enforcement, we can also make sure that we're
performing full config validation for the resolved configuration.
This allows us to report any configuration errors/warnings when we
include the full resolved configuration, without necessarily blocking
the full Renovate run, unless using `configValidationError`.
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>
This change was broken out of another commit, but it is unclear which AI
model was used to make the change, so we need to note both.
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>
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 a means to catch options setting `requiresCheckAtTrustBoundary`, we can add a test that is more of a reminder
than an enforcement.
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>
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>
As an additional defence-in-depth, we can make sure that when applying
the `env` 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 `allowedEnv`.
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>
As noticed while working on this branch, we currently do not merge an
admin's `hostRules` settings, if a user has (in repo or preset config)
specified `hostRules` themselves, when targeting the same `matchHost`.
To cover the existing (broken) functionality, we can document this with
a test.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
As part of follow-up changes, we'll be better enforcing the
`allowedHeaders` validation.
Before we do this, we should make sure that we have relevant test cases
to cover the existing (broken) behaviour.
We should cover this across both Config Validation and how config is merged.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
As part of follow-up changes, we'll be better enforcing the `allowedEnv`
validation.
Before we do this, we should make sure that we have relevant test cases
to cover the existing (broken) behaviour.
We should cover this across both Config Validation and how config is merged.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
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've previously been incorrectly caching the error responses from the
Go proxy occurs, which leads to a lot of "flapping" of PRs on
Mend-hosted apps, and can be rather frustrating as a user (and a service
owner).
Per the Go proxy protocol[0], a `,` fallback strategy should only
continue to the next entry on 404/410, and otherwise propagate the
error.
However, we currently break out of the loop and return `result` (which
may be `null` if no successful requests have been performed yet).
This `null` would be cached, leading to a "no releases found"
(`no-result`), stored in the "hard TTL" cache, which could lead to many
days without an update for given packages.
To fix this, we can make sure that we propagate errors, which would
mean that on an error:
- if we've previously successfully retrieved the package, serve the
"last good" result
- if we haven't, it's a full error, and the datasource can retry
[0]: https://go.dev/ref/mod#goproxy-protocol
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
As part of follow-up changes, we'll fix a bug with how the caching of
error responses from the Go proxy occurs, which leads to a lot of
"flapping" of PRs on Mend-hosted apps, and can be rather frustrating as
a user (and a service owner).
Per the Go proxy protocol[0], a `,` fallback strategy should only
continue to the next entry on 404/410, and otherwise propagate the
error.
However, we currently break out of the loop and return `result` (which
may be `null` if no successful requests have been performed yet).
Before we fix our behaviour, we need to clarify what our current
behaviour is.
[0]: https://go.dev/ref/mod#goproxy-protocol
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
Lock file maintenance deletes package-lock.json and regenerates it from
scratch, and a single npm install pass can produce a lock file that is out
of sync with package.json, so npm ci rejects the branch. Always run the
install command a second time for lock file maintenance, mirroring the
existing double run for remediations, instead of relying on users opting
in to the npmInstallTwice postUpdateOption. Because branch creation and
rebase share the same lock file generation path, this covers both.
A registry host never appears in a Git tag, so a host-qualified name
such as an OCI chart `<registry>/<org>/<repo>/<chart>` can never match
the tag that publishes it, which is scoped by the chart name alone:
`<chart>-<version>`. Match those names against their host-stripped form
and against their trailing path segment as well. Names that are not
host-qualified, such as scoped npm packages, keep matching in full only.
Escape the interpolated names and version too, so a `.` in a registry
host no longer acts as a wildcard and a name containing regex
metacharacters cannot throw out of `regEx()`.
Signed-off-by: Dennis Witt <dennis@derwitt.de>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* feat(manager): add apm manager for Agent Package Manager
Add a new `apm` manager that updates git-pinned dependencies in APM
(Agent Package Manager) `apm.yml` manifests, as requested in
renovatebot/renovate#42507.
The manager parses the string entries under `dependencies.apm` and
`devDependencies.apm` (`[host/]owner/repo[/subpath]#<ref>`) and selects
the datasource dynamically from the git host, reusing the existing
github-tags, gitlab-tags and git-tags datasources. MCP entries carry no
pinnable version and are ignored.
When an `apm.lock.yaml` lockfile is present, it is refreshed by running
`apm install` via a new `apm` tool constraint (pypi `apm-cli`).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vfjt3BpqDriiVsvwqVe9M9
* fix(manager/apm): resolve apm tool from github releases
APM ships self-contained binaries as GitHub release assets
(apm-linux-<arch>.tar.gz under vX.Y.Z tags), not as the PyPI apm-cli
wheel. Point the apm tool constraint at the github-releases datasource so
the version Renovate resolves matches the artifact that actually gets
installed, stripping the leading `v` from the tag.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vfjt3BpqDriiVsvwqVe9M9
* docs(manager/apm): point to canonical microsoft/apm repository
The APM project's canonical home is github.com/microsoft/apm (originally
danielmeppiel/apm). Update the manager URL and readme accordingly.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vfjt3BpqDriiVsvwqVe9M9
* refactor(manager/apm): validate manifest with zod schema
Address review feedback on the apm manager:
- parse `apm.yml` with a dedicated zod schema via
`parseSingleYaml(content, { customSchema })` instead of casting the
parsed YAML to `ApmManifest`
- `LooseArray(z.string())` keeps only the string dependency entries, so
MCP objects and other non-string values are dropped by the schema and
the manual `Array.isArray`/`is.string` guards are no longer needed
- drop the `as SkipReason` casts now that the literals are inferred
- remove the now-unused `types.ts`
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UbMAQBiMRNkCNxc8EGQw1C
* Update schema.ts
Co-authored-by: Sebastian Poxhofer <secustor@users.noreply.github.com>
* Update readme.md
Co-authored-by: Sebastian Poxhofer <secustor@users.noreply.github.com>
* Update readme.md
Co-authored-by: Sebastian Poxhofer <secustor@users.noreply.github.com>
* refactor(manager/apm): simplify manifest schema and host detection
Address review feedback:
- default the `apm` array to `[]` in the schema (`LooseArray(...).catch([])`)
since LooseArray already discards non-string entries, so downstream code
no longer needs to handle `undefined`
- use `coerceArray` when mapping the optional dependency sections
- drop the redundant `host === 'github.com'` / `host === 'gitlab.com'`
checks in datasource selection; `detectPlatform` already resolves those
hosts (the explicit host comparison is only kept to decide registryUrls
for self-hosted instances)
- document that APM only supports remote git references and that dots in
repo names / subpaths are handled, with a regression test
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UbMAQBiMRNkCNxc8EGQw1C
* docs(manager/apm): fix readme trailing newline
Remove the trailing blank line left after the readme edits so it passes
`prettier` and `markdown-lint`.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UbMAQBiMRNkCNxc8EGQw1C
* refactor(manager/apm): parse dependency path with named capture groups
Replace the manual host/owner/repo splitting (and the standalone dot
regex) with a single named-capture regex, as suggested in review. `owner`
excludes dots so the optional hostname segment is unambiguous, while repo
names and subpaths may still contain dots.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UbMAQBiMRNkCNxc8EGQw1C
* test(manager/apm): align admin config with InternalGlobalConfigOptions
`localDir` moved out of `RepoGlobalConfig` into `InternalGlobalConfigOptions`
on main, so annotate the test admin config as
`RepoGlobalConfig & InternalGlobalConfigOptions`, matching the other
manager artifacts specs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UbMAQBiMRNkCNxc8EGQw1C
* fix(manager/apm): resolve GitLab nested groups and recognize SHA-pinned refs
- resolve nested GitLab project slugs (e.g. `group/subgroup/project`)
instead of capping at `owner/repo`, splitting the project from any
virtual-package subpath using APM's primitive-dir / virtual-file markers
- recognize the documented SHA-pinned form and skip it
(`unversioned-reference`) rather than treating the SHA as a version or
rewriting it
* feat(manager/apm): support digest pinning for SHA-pinned deps
Recover the release tag from the trailing YAML comment of a SHA-pinned
entry (`owner/repo#<sha> # v2.0.0`) - which the structured parse strips -
so it extracts as a digest (`currentDigest` + `currentValue`) and updates
both via `pinDigests`, mirroring the github-actions manager. A bare SHA
with no tag comment (or a quoted form we can't rewrite verbatim) is left
skipped.
* fix(manager/apm): map SHA-pin tag recovery per line to handle duplicates
The raw-manifest scan matched the first line for the entry regardless of
section, so the same `owner/repo#<sha>` pinned in both `dependencies` and
`devDependencies` resolved to the first line's tag/replaceString. Consume
each line at most once (in file order) so duplicate pins map to distinct
lines.
* fix(manager/apm): recognize `.chatmode.md` virtual files
APM's VIRTUAL_FILE_EXTENSIONS includes `.chatmode.md`; add it to the
subpath-boundary regex so a `*.chatmode.md` virtual dependency on a
nested-group host (GitLab, Azure DevOps) is not folded into the repo path.
* test(manager/apm): cover SHA-pin digest updates on git-tags hosts
Lock in that a SHA-pinned dep on a non-github/gitlab host resolves via the
git-tags datasource (which supports `getDigest` through `git ls-remote`),
so the commit is preserved on a bump rather than dropped.
* fix(manager/apm): commit regenerated harness files, not just the lockfile
`apm install` re-deploys the harness directories APM consumers commit
(`.github/`, `.claude/`, ...), but updateArtifacts only returned
`apm.lock.yaml`, leaving instruction files stale after a bump. Capture
every file the install changed via `getRepoStatus` (additions +
deletions); the gitignored `apm_modules/` cache is excluded, and the
manifest stays with `updatedPackageFiles`.
* fix(manager/apm): declare lockFileMaintenanceIsDelegatedToPackageManager
main now requires managers with `supportsLockFileMaintenance` to set this
field. apm regenerates the lockfile via `apm install`, so it delegates to
the package manager (`true`).
* refactor(manager/apm): reuse shared regex and git-sha helpers
Adopt the shared utilities per review:
- use the exported `newlineRegex` from `util/regex` instead of a local copy
- use `isLongCommitSha` from `util/schema-utils/git` instead of a bespoke
SHA regex
- filter path segments with `isTruthy` instead of `Boolean`
* test(manager/apm): align docker exec snapshot with current base-image wrapper
The shared `util/exec` docker wrapper now injects `-e CI` and single-quotes
the `bash -l -c` payload. Update the docker-mode expectation to match, so the
snapshot tracks the current wrapper output.
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Sebastian Poxhofer <secustor@users.noreply.github.com>
* fix(bitbucket): use effective-branching-mode endpoint for bbUseDevelopmentBranch
Signed-off-by: Fernando Fernández <ferferga@hotmail.com>
* refactor(bitbucket): add more logging around BitBucket's branching model
Signed-off-by: Fernando Fernández <ferferga@hotmail.com>
* test(bitbucket): update mock for effective-branching-model
Signed-off-by: Fernando Fernández <ferferga@hotmail.com>
* test(bitbucket): fix forgotten test mock
Signed-off-by: Fernando Fernández <ferferga@hotmail.com>
* chore: address review comments
Signed-off-by: Fernando Fernández <ferferga@hotmail.com>
* fix(bitbucket): tests and types
Signed-off-by: Fernando Fernández <ferferga@hotmail.com>
---------
Signed-off-by: Fernando Fernández <ferferga@hotmail.com>
* fix: honour dashboard rebase for edited branch with no open PR
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* test: drop unconsumed findPr mocks from dashboard rebase test
The new guard short-circuits before platform.findPr, so the mocks were
never reached and the two tests were identical; collapse into one.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* test: assert commitSha loosely in dashboard rebase test
main replaced the shared `'123test'` mock value with `fakeSha('123test')`,
so the literal no longer matches on the merge ref.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
fix(git-submodules): init nested submodules in updateDependency
The cloneSubmodules function already uses --init --recursive, but
updateDependency only uses --checkout --init, losing nested submodule
content after updates. This breaks postUpgradeTasks that depend on
files inside nested submodules.
For repos without nested submodules, --recursive is a no-op.
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>
As part of follow-up changes, we're removing the "bot" terminology.
While doing so, GitHub Copilot Code Review discovered that there was no
coverage of the defaults in this function.
Before we change this, we can add coverage of the defaults.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
The conda datasource has returned `releaseTimestamp` since it was added,
for both the Anaconda.org API (`upload_time`) and prefix.dev
(`createdAt`), but never declared `releaseTimestampSupport`. The docs
therefore listed it as unsupported in both the datasource table and the
`minimumReleaseAge` support table.
Due to a long-standing issue with `semantic-release` not checking if
`#...` reference is for a Discussion or Issue, if a contributor says
`Closes #<discussion>`, then our release process fails.
We can extend our existing checks to try and catch this in the PR
itself, as users may not read the big warning that says "don't add a
Discussion here".
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
As per request in #45462, we can perform a prefactor to ensure that our
scripts for CI-related functionality are part of `tools`, so they're
linted appropriately.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
refactor(pnpm): rename managerData.pnpmShrinkwrap to pnpmLockFile
The field holds the path to pnpm-lock.yaml, and pnpm has not called that file
a shrinkwrap since v5, so the old name reads as a different artifact than the
one it points at.
Co-authored-by: Jamie Tanna <jamie.tanna@mend.io>