Files
renovate/lib/config/presets/internal/default.preset.ts
Felipe Santos ddbbb687f9 feat: add commitTrailers option (#44651)
* feat(config): add commitTrailers option

Renovate's only way to add git trailers today is `commitBody`, but it's
broken on Gerrit: Renovate appends its own `Renovate-Branch`/`Change-Id`
block after the body, so user trailers end up in a non-final message
block and are not real trailers per git-interpret-trailers rules.

This adds a `commitTrailers: string[]` option (each entry a full
`Key: value` line), standardizes Gerrit's own trailers through the same
mechanism so user trailers and platform trailers merge into one final
block, and verifies the result at runtime with `git interpret-trailers`
(commitlint's trailer-exists rule uses the same approach). The
`:gitSignOff` preset is migrated from `commitBody` to `commitTrailers`
so sign-off works correctly on Gerrit too.

* Simplify a bit

* Simplify docs even more

* Simplify another bit

* Add comment about rawExec

* Drop runtime commit trailer verification

Bypass simple-git only to emit a proactive warn log is not worth the
extra surface area. Config validation already enforces Key: value form.

* test(git): cover string commit message with trailers

Codecov patch failed on the partial ternary branch that normalizes a
string message before appending trailers.

* test(gerrit): fix trailers test after scm rework

Align the commitTrailers merge test with the post-rework Gerrit SCM:
use fakeSha helpers and drop the removed force flag.

* Improve wording on gitSignOff docs

* Validate compiled commitTrailers as well

* Improve trailers example

* Use isString instead

* Update lib/util/git/index.ts

Co-authored-by: Sebastian Poxhofer <secustor@users.noreply.github.com>

* Update lib/workers/repository/onboarding/branch/create.ts

Co-authored-by: Sebastian Poxhofer <secustor@users.noreply.github.com>

* Format code

* Fix type-check

* Fix tests

---------

Co-authored-by: Sebastian Poxhofer <secustor@users.noreply.github.com>
2026-07-27 06:49:09 +00:00

652 lines
17 KiB
TypeScript

import type { Preset } from '../types.ts';
export const presets: Record<string, Preset> = {
approveMajorUpdates: {
description: 'Require Dependency Dashboard approval for `major` updates.',
packageRules: [
{
dependencyDashboardApproval: true,
matchUpdateTypes: ['major'],
},
],
},
assignAndReview: {
description: 'Set `{{arg0}}` as assignee and reviewer of PRs.',
extends: [':assignee({{arg0}})', ':reviewer({{arg0}})'],
},
assignee: {
assignees: ['{{arg0}}'],
description: 'Assign PRs to `{{arg0}}`.',
},
automergeAll: {
automerge: true,
description:
'Automerge all upgrades (including `major`) if they pass tests.',
},
automergeBranch: {
automergeType: 'branch',
description:
'If automerging, push the new commit directly to the base branch (no PR).',
},
automergeDigest: {
description: 'Automerge `digest` upgrades if they pass tests.',
digest: {
automerge: true,
},
},
automergeDisabled: {
automerge: false,
description:
'Disable automerging feature - wait for humans to merge all PRs.',
},
automergeLinters: {
description: 'Update lint packages automatically if tests pass.',
packageRules: [
{
automerge: true,
extends: ['packages:linters'],
},
],
},
automergeMajor: {
automerge: true,
description:
'Automerge all upgrades (including `major`) if they pass tests.',
},
automergeMinor: {
description: 'Automerge `patch` and `minor` upgrades if they pass tests.',
lockFileMaintenance: {
automerge: true,
},
minor: {
automerge: true,
},
patch: {
automerge: true,
},
pin: {
automerge: true,
},
},
automergePatch: {
description: 'Automerge `patch` upgrades if they pass tests.',
lockFileMaintenance: {
automerge: true,
},
patch: {
automerge: true,
},
pin: {
automerge: true,
},
separateMinorPatch: true,
},
automergePr: {
automergeType: 'pr',
description: 'Raise a PR first before any automerging.',
},
automergeRequireAllStatusChecks: {
description: 'Require all status checks to pass before any automerging.',
ignoreTests: false,
},
automergeStableNonMajor: {
description:
'Automerge non-major upgrades for semver stable packages if they pass tests.',
packageRules: [
{
automerge: true,
matchCurrentVersion: '!/^0/',
matchUpdateTypes: ['minor', 'patch'],
},
],
},
automergeTesters: {
description: 'Update testing packages automatically if tests pass.',
packageRules: [
{
automerge: true,
extends: ['packages:test'],
},
],
},
automergeTypes: {
description: 'Update `@types/*` packages automatically if tests pass.',
packageRules: [
{
automerge: true,
matchPackageNames: ['@types/**'],
},
],
},
combinePatchMinorReleases: {
description:
'Do not separate `patch` and `minor` upgrades into separate PRs for the same dependency.',
separateMinorPatch: false,
},
configMigration: {
configMigration: true,
description: 'Enable Renovate configuration migration PRs when needed.',
},
dependencyDashboard: {
dependencyDashboard: true,
description: 'Enable Renovate Dependency Dashboard creation.',
},
dependencyDashboardApproval: {
dependencyDashboardApproval: true,
description: 'Enable Renovate Dependency Dashboard approval workflow.',
},
disableDependencyDashboard: {
dependencyDashboard: false,
description: 'Disable Renovate Dependency Dashboard creation.',
},
disableDevDependencies: {
description: 'Do not update development dependencies.',
packageRules: [
{
enabled: false,
matchDepTypes: ['devDependencies', 'dev-dependencies', 'dev'],
},
],
},
disableDigestUpdates: {
description: 'Disable `digest` and Git hash updates.',
digest: {
enabled: false,
},
},
disableDomain: {
description: 'Disable requests to a particular domain.',
hostRules: [
{
enabled: false,
matchHost: '{{arg0}}',
},
],
},
disableHost: {
description: 'Disable requests to a particular host.',
hostRules: [
{
enabled: false,
matchHost: 'https://{{arg0}}',
},
],
},
disableMajorUpdates: {
description: 'Disable `major` updates.',
major: {
enabled: false,
},
},
disablePeerDependencies: {
description: 'Do not update `peerDependencies` versions/ranges.',
packageRules: [
{
enabled: false,
matchDepTypes: ['peerDependencies'],
},
],
},
disablePrControls: {
description: 'Remove the checkbox controls from PRs.',
prBodyTemplate:
'{{{header}}}{{{table}}}{{{notes}}}{{{changelogs}}}{{{configDescription}}}{{{footer}}}',
},
disableRateLimiting: {
commitHourlyLimit: 0,
description: 'Remove hourly and concurrent rate limits.',
prConcurrentLimit: 0,
prHourlyLimit: 0,
},
disableRenovate: {
description: 'Disable Renovate.',
enabled: false,
},
disableVulnerabilityAlerts: {
description: 'Disable vulnerability alerts completely.',
vulnerabilityAlerts: {
enabled: false,
},
},
docker: {
description: 'Keep Dockerfile `FROM` sources updated.',
'docker-compose': {
enabled: true,
},
dockerfile: {
enabled: true,
},
},
doNotPinPackage: {
description: 'Disable version pinning for `{{arg0}}`.',
packageRules: [
{
matchPackageNames: ['{{arg0}}'],
rangeStrategy: 'replace',
},
],
},
enablePreCommit: {
description: 'Enable the pre-commit manager.',
'pre-commit': {
enabled: true,
},
},
enableRenovate: {
description: 'Enable Renovate.',
enabled: true,
},
enableVulnerabilityAlerts: {
description: 'Raise PR when vulnerability alerts are detected.',
vulnerabilityAlerts: {
enabled: true,
},
},
enableVulnerabilityAlertsWithAdditionalLabel: {
description:
'Raise PR when vulnerability alerts are detected with label `{{arg0}}`, in addition to any existing list of PR labels.',
vulnerabilityAlerts: {
addLabels: ['{{arg0}}'],
enabled: true,
},
},
enableVulnerabilityAlertsWithLabel: {
description:
'Raise PR when vulnerability alerts are detected with label `{{arg0}}`, replacing any existing list of PR labels.',
vulnerabilityAlerts: {
enabled: true,
labels: ['{{arg0}}'],
},
},
followTag: {
description:
'For package `{{arg0}}`, strictly follow release tag `{{arg1}}`.',
packageRules: [
{
followTag: '{{arg1}}',
matchPackageNames: ['{{arg0}}'],
},
],
},
githubComToken: {
description:
'Use provided token for `github.com` lookups. Do not configure this if you are already running on `github.com`.',
hostRules: [
{
encrypted: {
token: '{{arg0}}',
},
hostType: 'github',
matchHost: 'github.com',
},
],
},
gitSignOff: {
commitTrailers: ['Signed-off-by: {{{gitAuthor}}}'],
description: 'Append `Signed-off-by:` to signoff Git commits.',
},
gomod: {
description: 'Enable Go modules support.',
gomod: {
enabled: true,
},
},
group: {
description: 'Group `{{arg1}}` packages into same branch/PR.',
packageRules: [
{
extends: ['{{arg0}}'],
groupName: '{{arg1}}',
},
],
},
ignoreModulesAndTests: {
description:
'Ignore `node_modules`, `bower_components`, `vendor` and various test/tests (except for nuget) directories.',
ignorePaths: [
'**/node_modules/**',
'**/bower_components/**',
'**/vendor/**',
'**/examples/**',
'**/__tests__/**',
'**/test/**',
'**/tests/**',
'**/__fixtures__/**',
],
nuget: {
ignorePaths: [
'**/node_modules/**',
'**/bower_components/**',
'**/vendor/**',
'**/examples/**',
'**/__fixtures__/**',
],
},
},
ignoreUnstable: {
description:
'Upgrade to unstable versions only if the existing version is unstable.',
ignoreUnstable: true,
},
includeNodeModules: {
description:
'Include `package.json` files found within `node_modules` folders or `bower_components`.',
ignorePaths: [],
},
label: {
description: 'Apply label `{{arg0}}` to PRs.',
labels: ['{{arg0}}'],
},
labels: {
description: 'Apply labels `{{arg0}}` and `{{arg1}}` to PRs.',
labels: ['{{arg0}}', '{{arg1}}'],
},
maintainLockFilesDisabled: {
description:
'Update existing lock files only when `package.json` is modified.',
lockFileMaintenance: {
enabled: false,
},
},
maintainLockFilesMonthly: {
description:
'Run lock file maintenance (updates) on the first day of each month.',
lockFileMaintenance: {
enabled: true,
extends: ['schedule:monthly'],
},
},
maintainLockFilesWeekly: {
description: 'Run lock file maintenance (updates) early Monday mornings.',
lockFileMaintenance: {
enabled: true,
extends: ['schedule:weekly'],
},
},
meteor: {
description: 'Keep Meteor Npm.depends packages updated.',
meteor: {
enabled: true,
},
},
noUnscheduledUpdates: {
description: 'Only update branches when scheduled.',
updateNotScheduled: false,
},
npm: {
description: 'Keep `package.json` npm dependencies updated.',
npm: {
enabled: true,
},
},
pathSemanticCommitType: {
description:
'Use semanticCommitType `{{arg1}}` for all package files matching path `{{arg0}}`.',
packageRules: [
{
matchFileNames: ['{{arg0}}'],
semanticCommitType: '{{arg1}}',
},
],
},
pinAllExceptPeerDependencies: {
description: 'Pin all dependency versions except `peerDependencies`.',
packageRules: [
{
matchPackageNames: ['*'],
rangeStrategy: 'pin',
},
{
matchDepTypes: ['engines', 'peerDependencies'],
rangeStrategy: 'auto',
},
],
},
pinDependencies: {
description:
'Pin dependency versions where `depType=dependencies`. Usually applies only to non-dev dependencies in `package.json`.',
packageRules: [
{
matchDepTypes: ['dependencies'],
rangeStrategy: 'pin',
},
],
},
pinDevDependencies: {
description: 'Pin dependency versions for development dependencies.',
packageRules: [
{
matchDepTypes: ['devDependencies', 'dev-dependencies', 'dev'],
rangeStrategy: 'pin',
},
],
},
pinDigestsDisabled: {
description: `Disable pinning of dependency digests.
Note: This preset does not revert the digest pinning set from within the packageRules, when set at root level or via extends).
See [Docker - Disable digest pinning](./docker.md#disable-digest-pinning) for more details.`,
pinDigests: false,
},
pinOnlyDevDependencies: {
description:
'Pin dependency versions for development dependencies and retain SemVer ranges for others.',
packageRules: [
{
matchPackageNames: ['*'],
rangeStrategy: 'replace',
},
{
matchDepTypes: ['devDependencies', 'dev-dependencies', 'dev'],
rangeStrategy: 'pin',
},
{
matchDepTypes: ['peerDependencies'],
rangeStrategy: 'widen',
},
],
},
pinSkipCi: {
description: 'Add `[skip ci]` to commit message body whenever pinning.',
pin: {
commitBody: '[skip ci]',
},
},
pinVersions: {
description:
'Use version pinning (maintain a single version only and not SemVer ranges).',
rangeStrategy: 'pin',
},
prConcurrentLimit10: {
description: 'Limit to maximum 10 open PRs at any time.',
prConcurrentLimit: 10,
},
prConcurrentLimit20: {
description: 'Limit to maximum 20 open PRs at any time.',
prConcurrentLimit: 20,
},
prConcurrentLimitNone: {
description: 'Remove limit for open PRs at any time.',
prConcurrentLimit: 0,
},
preserveSemverRanges: {
description:
'Preserve (but continue to upgrade) any existing SemVer ranges.',
packageRules: [{ matchPackageNames: ['*'], rangeStrategy: 'replace' }],
},
prHourlyLimit1: {
description: 'Rate limit PR creation to a maximum of one per hour.',
prHourlyLimit: 1,
},
prHourlyLimit2: {
description: 'Rate limit PR creation to a maximum of two per hour.',
prHourlyLimit: 2,
},
prHourlyLimit4: {
description: 'Rate limit PR creation to a maximum of four per hour.',
prHourlyLimit: 4,
},
prHourlyLimitNone: {
description: 'Removes rate limit for PR creation per hour.',
prHourlyLimit: 0,
},
prImmediately: {
description: 'Raise PRs immediately (after branch is created).',
prCreation: 'immediate',
},
prNotPending: {
description:
'Wait for branch tests to pass or fail before creating the PR.',
prCreation: 'not-pending',
},
rebaseStalePrs: {
description:
'Rebase existing PRs any time the base branch has been updated.',
rebaseWhen: 'behind-base-branch',
},
renovatePrefix: {
branchPrefix: 'renovate/',
description: 'Add the `renovate/` prefix to all branch names.',
},
respectLatest: {
description: 'Upgrade versions up to the "latest" tag in the npm registry.',
respectLatest: true,
},
reviewer: {
description: 'Add `{{arg0}}` as reviewer for PRs.',
reviewers: ['{{arg0}}'],
},
semanticCommits: {
description: 'Use semantic prefixes for commit messages and PR titles.',
semanticCommits: 'enabled',
},
semanticCommitScope: {
description:
'Use semantic commit scope `{{arg0}}` for all commits and PR titles.',
semanticCommitScope: '{{arg0}}',
},
semanticCommitScopeDisabled: {
description: 'Disable semantic commit scope for all commits and PR titles.',
semanticCommitScope: null,
},
semanticCommitsDisabled: {
description: 'Disable semantic prefixes for commit messages and PR titles.',
semanticCommits: 'disabled',
},
semanticCommitType: {
description:
'Use `{{arg0}}` as semantic commit type for commit messages and PR titles.',
semanticCommitType: '{{arg0}}',
},
semanticCommitTypeAll: {
description:
'If Renovate detects semantic commits, it will use semantic commit type `{{arg0}}` for all commits.',
packageRules: [
{
matchFileNames: ['**/*'],
semanticCommitType: '{{arg0}}',
},
],
},
semanticPrefixChore: {
description:
'Use `chore` as semantic commit type for commit messages and PR titles.',
extends: [':semanticCommitType(chore)'],
},
semanticPrefixFix: {
description:
'Use `fix` as semantic commit type for commit messages and PR titles.',
extends: [':semanticCommitType(fix)'],
},
semanticPrefixFixDepsChoreOthers: {
description:
'Use semantic commit type `fix` for dependencies and `chore` for all others if semantic commits are in use.',
packageRules: [
{
matchPackageNames: ['*'],
semanticCommitType: 'chore',
},
{
matchDepTypes: ['dependencies', 'require'],
semanticCommitType: 'fix',
},
{
matchDatasources: ['maven'],
matchDepTypes: [
'compile',
'provided',
'runtime',
'system',
'import',
'parent',
],
semanticCommitType: 'fix',
},
{
matchDepTypes: [
'project.dependencies',
'project.optional-dependencies',
],
matchManagers: ['pep621', 'poetry'],
semanticCommitType: 'fix',
},
{
matchDepTypes: ['dependencies', 'extras'],
matchManagers: ['poetry'],
semanticCommitType: 'fix',
},
{
matchJsonata: ['isLockfileUpdate = true'],
semanticCommitType: 'chore',
},
],
},
separateMajorReleases: {
description:
'Separate `major` versions of dependencies into individual branches/PRs.',
separateMajorMinor: true,
},
separateMultipleMajorReleases: {
description:
'Separate each `major` version of dependencies into individual branches/PRs.',
separateMajorMinor: true,
separateMultipleMajor: true,
},
separateMultipleMinorReleases: {
description:
'Separate each `minor` version of dependencies into individual branches/PRs.',
separateMultipleMinor: true,
},
separatePatchReleases: {
description:
'Separate `patch` and `minor` releases of dependencies into separate PRs.',
separateMinorPatch: true,
},
skipArtifactsUpdate: {
description: 'Skips artifact updates.',
skipArtifactsUpdate: true,
},
skipStatusChecks: {
description: 'Skip status checks and automerge right away.',
ignoreTests: true,
},
timezone: {
description: 'Evaluate schedules according to timezone `{{arg0}}`.',
timezone: '{{arg0}}',
},
updateNotScheduled: {
description: 'Keep existing branches updated even when not scheduled.',
updateNotScheduled: true,
},
widenPeerDependencies: {
description:
'Always widen `peerDependencies` SemVer ranges when updating, instead of replacing.',
packageRules: [
{
matchDepTypes: ['peerDependencies'],
rangeStrategy: 'widen',
},
],
},
};