diff --git a/lib/config/__snapshots__/validation.spec.ts.snap b/lib/config/__snapshots__/validation.spec.ts.snap index 14aef329c70218..c2c5c75f5c3859 100644 --- a/lib/config/__snapshots__/validation.spec.ts.snap +++ b/lib/config/__snapshots__/validation.spec.ts.snap @@ -259,7 +259,7 @@ exports[`config/validation validateConfig(config) validates regEx for each fileM exports[`config/validation validateConfig(config) warns if hostType has the wrong parent 1`] = ` [ { - "message": "hostType should only be configured within a "hostRules" object. Was found in .", + "message": "hostType should only be configured within one of "hostRules" objects. Was found in .", "topic": "hostType", }, ] diff --git a/lib/config/defaults.ts b/lib/config/defaults.ts index 43c18286bffb46..1fd65e07b619c3 100644 --- a/lib/config/defaults.ts +++ b/lib/config/defaults.ts @@ -23,7 +23,7 @@ export function getConfig(): AllConfig { const options = getOptions(); const config: AllConfig = {}; options.forEach((option) => { - if (!option.parent) { + if (!option.parents) { config[option.name] = getDefault(option); } }); diff --git a/lib/config/options/index.ts b/lib/config/options/index.ts index e5896456e70d88..17a556a8c69597 100644 --- a/lib/config/options/index.ts +++ b/lib/config/options/index.ts @@ -72,7 +72,7 @@ const options: RenovateOptions[] = [ 'A list of post-upgrade commands that are executed before a commit is made by Renovate.', type: 'array', subType: 'string', - parent: 'postUpgradeTasks', + parents: ['postUpgradeTasks'], default: [], cli: false, }, @@ -82,7 +82,7 @@ const options: RenovateOptions[] = [ 'Files that match the glob pattern will be committed after running a post-upgrade task.', type: 'array', subType: 'string', - parent: 'postUpgradeTasks', + parents: ['postUpgradeTasks'], default: ['**/*'], cli: false, }, @@ -90,7 +90,7 @@ const options: RenovateOptions[] = [ name: 'format', description: 'Format of the custom datasource.', type: 'string', - parent: 'customDatasources', + parents: ['customDatasources'], default: 'json', allowedValues: ['json', 'plain'], cli: false, @@ -101,7 +101,7 @@ const options: RenovateOptions[] = [ description: 'Controls when the post upgrade tasks run: on every update, or once per upgrade branch.', type: 'string', - parent: 'postUpgradeTasks', + parents: ['postUpgradeTasks'], allowedValues: ['update', 'branch'], default: 'update', cli: false, @@ -1012,7 +1012,7 @@ const options: RenovateOptions[] = [ 'Template for generating a `defaultRegistryUrl` for custom datasource.', type: 'string', default: '', - parent: 'customDatasources', + parents: ['customDatasources'], cli: false, env: false, }, @@ -1099,7 +1099,7 @@ const options: RenovateOptions[] = [ type: 'array', subType: 'string', allowString: true, - parent: 'packageRules', + parents: ['packageRules'], stage: 'package', mergeable: true, cli: false, @@ -1113,7 +1113,7 @@ const options: RenovateOptions[] = [ subType: 'string', allowString: true, stage: 'package', - parent: 'packageRules', + parents: ['packageRules'], mergeable: true, cli: false, env: false, @@ -1126,7 +1126,7 @@ const options: RenovateOptions[] = [ subType: 'string', allowString: true, stage: 'package', - parent: 'packageRules', + parents: ['packageRules'], mergeable: true, cli: false, env: false, @@ -1138,7 +1138,7 @@ const options: RenovateOptions[] = [ type: 'array', subType: 'string', allowString: true, - parent: 'packageRules', + parents: ['packageRules'], stage: 'package', mergeable: true, cli: false, @@ -1151,7 +1151,7 @@ const options: RenovateOptions[] = [ type: 'array', subType: 'string', allowString: true, - parent: 'packageRules', + parents: ['packageRules'], stage: 'package', mergeable: true, cli: false, @@ -1164,7 +1164,7 @@ const options: RenovateOptions[] = [ type: 'array', subType: 'string', allowString: true, - parent: 'packageRules', + parents: ['packageRules'], stage: 'package', mergeable: true, cli: false, @@ -1177,7 +1177,7 @@ const options: RenovateOptions[] = [ type: 'array', subType: 'string', allowString: true, - parent: 'packageRules', + parents: ['packageRules'], stage: 'package', mergeable: true, cli: false, @@ -1191,7 +1191,7 @@ const options: RenovateOptions[] = [ subType: 'string', allowString: true, stage: 'package', - parent: 'packageRules', + parents: ['packageRules'], mergeable: true, cli: false, env: false, @@ -1204,7 +1204,7 @@ const options: RenovateOptions[] = [ subType: 'string', allowString: true, stage: 'package', - parent: 'packageRules', + parents: ['packageRules'], mergeable: true, cli: false, env: false, @@ -1217,7 +1217,7 @@ const options: RenovateOptions[] = [ subType: 'string', allowString: true, stage: 'package', - parent: 'packageRules', + parents: ['packageRules'], mergeable: true, cli: false, env: false, @@ -1231,7 +1231,7 @@ const options: RenovateOptions[] = [ subType: 'string', allowString: true, stage: 'package', - parent: 'packageRules', + parents: ['packageRules'], mergeable: true, cli: false, env: false, @@ -1245,7 +1245,7 @@ const options: RenovateOptions[] = [ subType: 'string', allowString: true, stage: 'package', - parent: 'packageRules', + parents: ['packageRules'], mergeable: true, cli: false, env: false, @@ -1258,7 +1258,7 @@ const options: RenovateOptions[] = [ subType: 'string', allowString: true, stage: 'package', - parent: 'packageRules', + parents: ['packageRules'], mergeable: true, cli: false, env: false, @@ -1272,7 +1272,7 @@ const options: RenovateOptions[] = [ format: 'regex', allowString: true, stage: 'package', - parent: 'packageRules', + parents: ['packageRules'], mergeable: true, cli: false, env: false, @@ -1286,7 +1286,7 @@ const options: RenovateOptions[] = [ format: 'regex', allowString: true, stage: 'package', - parent: 'packageRules', + parents: ['packageRules'], mergeable: true, cli: false, env: false, @@ -1300,7 +1300,7 @@ const options: RenovateOptions[] = [ format: 'regex', allowString: true, stage: 'package', - parent: 'packageRules', + parents: ['packageRules'], mergeable: true, cli: false, env: false, @@ -1315,7 +1315,7 @@ const options: RenovateOptions[] = [ format: 'regex', allowString: true, stage: 'package', - parent: 'packageRules', + parents: ['packageRules'], mergeable: true, cli: false, env: false, @@ -1327,7 +1327,7 @@ const options: RenovateOptions[] = [ 'A regex to match against the raw `currentValue` string of a dependency. Valid only within a `packageRules` object.', type: 'string', stage: 'package', - parent: 'packageRules', + parents: ['packageRules'], mergeable: true, cli: false, env: false, @@ -1338,7 +1338,7 @@ const options: RenovateOptions[] = [ 'A version, or range of versions, to match against the current version of a package. Valid only within a `packageRules` object.', type: 'string', stage: 'package', - parent: 'packageRules', + parents: ['packageRules'], mergeable: true, cli: false, env: false, @@ -1351,7 +1351,7 @@ const options: RenovateOptions[] = [ subType: 'string', allowString: true, stage: 'package', - parent: 'packageRules', + parents: ['packageRules'], mergeable: true, cli: false, env: false, @@ -1363,7 +1363,7 @@ const options: RenovateOptions[] = [ subType: 'string', allowString: true, stage: 'package', - parent: 'packageRules', + parents: ['packageRules'], mergeable: true, cli: false, env: false, @@ -1381,7 +1381,7 @@ const options: RenovateOptions[] = [ 'The name of the new dependency that replaces the old deprecated dependency.', type: 'string', stage: 'package', - parent: 'packageRules', + parents: ['packageRules'], cli: false, env: false, }, @@ -1391,7 +1391,7 @@ const options: RenovateOptions[] = [ type: 'string', default: '{{{packageName}}}', stage: 'package', - parent: 'packageRules', + parents: ['packageRules'], cli: false, env: false, }, @@ -1401,7 +1401,7 @@ const options: RenovateOptions[] = [ 'The version of the new dependency that replaces the old deprecated dependency.', type: 'string', stage: 'package', - parent: 'packageRules', + parents: ['packageRules'], cli: false, env: false, }, @@ -1414,7 +1414,7 @@ const options: RenovateOptions[] = [ allowedValues: ['low', 'neutral', 'high', 'very high'], allowString: true, stage: 'package', - parent: 'packageRules', + parents: ['packageRules'], mergeable: true, cli: false, env: false, @@ -1440,7 +1440,7 @@ const options: RenovateOptions[] = [ ], allowString: true, stage: 'package', - parent: 'packageRules', + parents: ['packageRules'], mergeable: true, cli: false, env: false, @@ -1452,7 +1452,7 @@ const options: RenovateOptions[] = [ type: 'array', subType: 'string', stage: 'repository', - parent: 'packageRules', + parents: ['packageRules'], cli: false, env: false, }, @@ -1462,7 +1462,7 @@ const options: RenovateOptions[] = [ description: 'A version range or regex pattern capturing allowed versions for dependencies.', type: 'string', - parent: 'packageRules', + parents: ['packageRules'], stage: 'package', cli: false, env: false, @@ -1473,7 +1473,7 @@ const options: RenovateOptions[] = [ 'If set, Renovate will use this URL to fetch changelogs for a matched dependency. Valid only within a `packageRules` object.', type: 'string', stage: 'pr', - parent: 'packageRules', + parents: ['packageRules'], cli: false, env: false, }, @@ -1872,7 +1872,7 @@ const options: RenovateOptions[] = [ description: 'List of jsonata transformation rules.', type: 'array', subType: 'string', - parent: 'customDatasources', + parents: ['customDatasources'], default: [], }, { @@ -2286,7 +2286,7 @@ const options: RenovateOptions[] = [ 'hostType for a package rule. Can be a platform name or a datasource name.', type: 'string', stage: 'repository', - parent: 'hostRules', + parents: ['hostRules'], cli: false, env: false, }, @@ -2295,7 +2295,7 @@ const options: RenovateOptions[] = [ description: 'A domain name, host name or base URL to match against.', type: 'string', stage: 'repository', - parent: 'hostRules', + parents: ['hostRules'], cli: false, env: false, }, @@ -2304,7 +2304,7 @@ const options: RenovateOptions[] = [ description: 'Timeout (in milliseconds) for queries to external endpoints.', type: 'integer', stage: 'repository', - parent: 'hostRules', + parents: ['hostRules'], cli: false, env: false, }, @@ -2313,7 +2313,7 @@ const options: RenovateOptions[] = [ description: 'Explicitly turn on insecure Docker registry access (HTTP).', type: 'boolean', stage: 'repository', - parent: 'hostRules', + parents: ['hostRules'], cli: false, env: false, advancedUse: true, @@ -2324,7 +2324,7 @@ const options: RenovateOptions[] = [ 'If enabled, Renovate aborts its run when HTTP request errors occur.', type: 'boolean', stage: 'repository', - parent: 'hostRules', + parents: ['hostRules'], default: false, cli: false, env: false, @@ -2336,7 +2336,7 @@ const options: RenovateOptions[] = [ type: 'array', subType: 'number', stage: 'repository', - parent: 'hostRules', + parents: ['hostRules'], cli: false, env: false, }, @@ -2345,7 +2345,7 @@ const options: RenovateOptions[] = [ description: 'Enable got HTTP/2 support.', type: 'boolean', stage: 'repository', - parent: 'hostRules', + parents: ['hostRules'], default: false, cli: false, env: false, @@ -2355,7 +2355,7 @@ const options: RenovateOptions[] = [ description: 'Limit concurrent requests per host.', type: 'integer', stage: 'repository', - parent: 'hostRules', + parents: ['hostRules'], default: null, cli: false, env: false, @@ -2365,7 +2365,7 @@ const options: RenovateOptions[] = [ description: 'Limit requests rate per host.', type: 'integer', stage: 'repository', - parent: 'hostRules', + parents: ['hostRules'], default: 0, cli: false, env: false, @@ -2376,7 +2376,7 @@ const options: RenovateOptions[] = [ 'Authentication type for HTTP header. e.g. `"Bearer"` or `"Basic"`. Use `"Token-Only"` to use only the token without an authorization type.', type: 'string', stage: 'repository', - parent: 'hostRules', + parents: ['hostRules'], default: 'Bearer', cli: false, env: false, @@ -2386,7 +2386,7 @@ const options: RenovateOptions[] = [ description: 'Enable got DNS cache.', type: 'boolean', stage: 'repository', - parent: 'hostRules', + parents: ['hostRules'], default: false, cli: false, env: false, @@ -2397,7 +2397,7 @@ const options: RenovateOptions[] = [ description: 'Enable HTTP keep-alive for hosts.', type: 'boolean', stage: 'repository', - parent: 'hostRules', + parents: ['hostRules'], default: false, cli: false, env: false, @@ -2408,7 +2408,7 @@ const options: RenovateOptions[] = [ description: 'Put fields to be forwarded to the HTTP request headers in the headers config option.', type: 'object', - parent: 'hostRules', + parents: ['hostRules'], cli: false, env: false, advancedUse: true, @@ -2421,7 +2421,7 @@ const options: RenovateOptions[] = [ type: 'array', subType: 'string', stage: 'repository', - parent: 'hostRules', + parents: ['hostRules'], allowedValues: ['composer'], default: null, cli: false, @@ -2432,7 +2432,7 @@ const options: RenovateOptions[] = [ description: 'The overriding trusted CA certificate.', type: 'string', stage: 'repository', - parent: 'hostRules', + parents: ['hostRules'], default: null, cli: false, env: false, @@ -2442,7 +2442,7 @@ const options: RenovateOptions[] = [ description: 'The private key in PEM format.', type: 'string', stage: 'repository', - parent: 'hostRules', + parents: ['hostRules'], default: null, cli: false, env: false, @@ -2452,7 +2452,7 @@ const options: RenovateOptions[] = [ description: 'The certificate chains in PEM format.', type: 'string', stage: 'repository', - parent: 'hostRules', + parents: ['hostRules'], default: null, cli: false, env: false, @@ -2576,7 +2576,7 @@ const options: RenovateOptions[] = [ 'Custom manager to use. Valid only within a `customManagers` object.', type: 'string', allowedValues: ['regex'], - parent: 'customManagers', + parents: ['customManagers'], cli: false, env: false, }, @@ -2587,7 +2587,7 @@ const options: RenovateOptions[] = [ type: 'array', subType: 'string', format: 'regex', - parent: 'customManagers', + parents: ['customManagers'], cli: false, env: false, }, @@ -2597,7 +2597,7 @@ const options: RenovateOptions[] = [ type: 'string', default: 'any', allowedValues: ['any', 'recursive', 'combination'], - parent: 'customManagers', + parents: ['customManagers'], cli: false, env: false, }, @@ -2606,7 +2606,7 @@ const options: RenovateOptions[] = [ description: 'Optional depName for extracted dependencies. Valid only within a `customManagers` object.', type: 'string', - parent: 'customManagers', + parents: ['customManagers'], cli: false, env: false, }, @@ -2615,7 +2615,7 @@ const options: RenovateOptions[] = [ description: 'Optional packageName for extracted dependencies, else defaults to `depName` value. Valid only within a `customManagers` object.', type: 'string', - parent: 'customManagers', + parents: ['customManagers'], cli: false, env: false, }, @@ -2624,7 +2624,7 @@ const options: RenovateOptions[] = [ description: 'Optional datasource for extracted dependencies. Valid only within a `customManagers` object.', type: 'string', - parent: 'customManagers', + parents: ['customManagers'], cli: false, env: false, }, @@ -2633,7 +2633,7 @@ const options: RenovateOptions[] = [ description: 'Optional `depType` for extracted dependencies. Valid only within a `customManagers` object.', type: 'string', - parent: 'customManagers', + parents: ['customManagers'], cli: false, env: false, }, @@ -2642,7 +2642,7 @@ const options: RenovateOptions[] = [ description: 'Optional `currentValue` for extracted dependencies. Valid only within a `customManagers` object.', type: 'string', - parent: 'customManagers', + parents: ['customManagers'], cli: false, env: false, }, @@ -2651,7 +2651,7 @@ const options: RenovateOptions[] = [ description: 'Optional versioning for extracted dependencies. Valid only within a `customManagers` object.', type: 'string', - parent: 'customManagers', + parents: ['customManagers'], cli: false, env: false, }, @@ -2660,7 +2660,7 @@ const options: RenovateOptions[] = [ description: 'Optional registry URL for extracted dependencies. Valid only within a `customManagers` object.', type: 'string', - parent: 'customManagers', + parents: ['customManagers'], cli: false, env: false, }, @@ -2669,7 +2669,7 @@ const options: RenovateOptions[] = [ description: 'Optional `extractVersion` for extracted dependencies. Valid only within a `customManagers` object.', type: 'string', - parent: 'customManagers', + parents: ['customManagers'], cli: false, env: false, }, @@ -2678,7 +2678,7 @@ const options: RenovateOptions[] = [ description: 'Optional `extractVersion` for extracted dependencies. Valid only within a `customManagers` object.', type: 'string', - parent: 'customManagers', + parents: ['customManagers'], cli: false, env: false, }, @@ -2795,7 +2795,7 @@ const options: RenovateOptions[] = [ type: 'integer', default: 60, stage: 'package', - parent: 'hostRules', + parents: ['hostRules'], cli: false, env: false, }, diff --git a/lib/config/types.ts b/lib/config/types.ts index dddb598cc421da..6036837478c0c8 100644 --- a/lib/config/types.ts +++ b/lib/config/types.ts @@ -368,6 +368,12 @@ export interface ValidationMessage { message: string; } +export type AllowedParents = + | 'customManagers' + | 'customDatasources' + | 'hostRules' + | 'postUpgradeTasks' + | 'packageRules'; export interface RenovateOptionBase { /** * If true, the option can only be configured by people with access to the Renovate instance. @@ -396,12 +402,7 @@ export interface RenovateOptionBase { name: string; - parent?: - | 'customDatasources' - | 'hostRules' - | 'packageRules' - | 'postUpgradeTasks' - | 'customManagers'; + parents?: AllowedParents[]; stage?: RenovateConfigStage; diff --git a/lib/config/validation.ts b/lib/config/validation.ts index b22bddaebc23c8..0a459f8c378bed 100644 --- a/lib/config/validation.ts +++ b/lib/config/validation.ts @@ -20,6 +20,7 @@ import { migrateConfig } from './migration'; import { getOptions } from './options'; import { resolveConfigPresets } from './presets'; import { + AllowedParents, type RenovateConfig, type RenovateOptions, type StatusCheckKey, @@ -32,7 +33,7 @@ import * as managerValidator from './validation-helpers/managers'; const options = getOptions(); let optionTypes: Record; -let optionParents: Record; +let optionParents: Record; let optionGlobals: Set; const managerList = getManagerList(); @@ -117,8 +118,8 @@ export async function validateConfig( if (!optionParents) { optionParents = {}; options.forEach((option) => { - if (option.parent) { - optionParents[option.name] = option.parent; + if (option.parents) { + optionParents[option.name] = option.parents; } }); } @@ -224,10 +225,12 @@ export async function validateConfig( if ( !isPreset && optionParents[key] && - optionParents[key] !== parentName + !optionParents[key].includes(parentName as AllowedParents) ) { // TODO: types (#22198) - const message = `${key} should only be configured within a "${optionParents[key]}" object. Was found in ${parentName}`; + const message = `${key} should only be configured within one of "${optionParents[ + key + ]?.join(' or ')}" objects. Was found in ${parentName}`; warnings.push({ topic: `${parentPath ? `${parentPath}.` : ''}${key}`, message, diff --git a/test/documentation.spec.ts b/test/documentation.spec.ts index d40319fbf01f5b..f0f66b1e94f86a 100644 --- a/test/documentation.spec.ts +++ b/test/documentation.spec.ts @@ -31,7 +31,7 @@ describe('documentation', () => { const expectedOptions = options .filter((option) => !option.globalOnly) - .filter((option) => !option.parent) + .filter((option) => !option.parents) .filter((option) => !option.autogenerated) .map((option) => option.name) .sort(); @@ -51,7 +51,7 @@ describe('documentation', () => { const expectedSubOptions = options .filter((option) => option.stage !== 'global') .filter((option) => !option.globalOnly) - .filter((option) => option.parent) + .filter((option) => option.parents) .map((option) => option.name) .sort(); expectedSubOptions.sort(); diff --git a/tools/docs/schema.ts b/tools/docs/schema.ts index 456b3b00aa3df7..f02b13632e2c89 100644 --- a/tools/docs/schema.ts +++ b/tools/docs/schema.ts @@ -75,7 +75,7 @@ function createSingleConfig(option: RenovateOptions): Record { function createSchemaForParentConfigs(): void { for (const option of options) { - if (!option.parent) { + if (!option.parents) { properties[option.name] = createSingleConfig(option); } } @@ -83,30 +83,34 @@ function createSchemaForParentConfigs(): void { function addChildrenArrayInParents(): void { for (const option of options) { - if (option.parent) { - properties[option.parent].items = { - allOf: [ - { - type: 'object', - properties: { - description: { - type: 'string', - description: - 'A custom description for this configuration object', + if (option.parents) { + for (const parent of option.parents) { + properties[parent].items = { + allOf: [ + { + type: 'object', + properties: { + description: { + type: 'string', + description: + 'A custom description for this configuration object', + }, }, }, - }, - ], - }; + ], + }; + } } } } function createSchemaForChildConfigs(): void { for (const option of options) { - if (option.parent) { - properties[option.parent].items.allOf[0].properties[option.name] = - createSingleConfig(option); + if (option.parents) { + for (const parent of option.parents) { + properties[parent].items.allOf[0].properties[option.name] = + createSingleConfig(option); + } } } }