diff --git a/lib/config-validator.ts b/lib/config-validator.ts index 2a8aff79a338da04fb155269bca8546e3c1f3673..3c809bc2ea2e297e159ed6d4bba9cac744af628a 100644 --- a/lib/config-validator.ts +++ b/lib/config-validator.ts @@ -17,7 +17,7 @@ import { let returnVal = 0; async function validate( - isGlobalConfig: boolean, + configType: 'global' | 'repo', desc: string, config: RenovateConfig, strict: boolean, @@ -37,7 +37,7 @@ async function validate( } } const massagedConfig = massageConfig(migratedConfig); - const res = await validateConfig(isGlobalConfig, massagedConfig, isPreset); + const res = await validateConfig(configType, massagedConfig, isPreset); if (res.errors.length) { logger.error( { file: desc, errors: res.errors }, @@ -76,7 +76,7 @@ type PackageJson = { const parsedContent = await getParsedContent(file); try { logger.info(`Validating ${file}`); - await validate(true, file, parsedContent, strict); + await validate('global', file, parsedContent, strict); } catch (err) { logger.warn({ file, err }, 'File is not valid Renovate config'); returnVal = 1; @@ -97,7 +97,7 @@ type PackageJson = { const parsedContent = await getParsedContent(file); try { logger.info(`Validating ${file}`); - await validate(false, file, parsedContent, strict); + await validate('repo', file, parsedContent, strict); } catch (err) { logger.warn({ file, err }, 'File is not valid Renovate config'); returnVal = 1; @@ -114,7 +114,7 @@ type PackageJson = { if (pkgJson.renovate) { logger.info(`Validating package.json > renovate`); await validate( - false, + 'repo', 'package.json > renovate', pkgJson.renovate, strict, @@ -124,7 +124,7 @@ type PackageJson = { logger.info(`Validating package.json > renovate-config`); for (const presetConfig of Object.values(pkgJson['renovate-config'])) { await validate( - false, + 'repo', 'package.json > renovate-config', presetConfig, strict, @@ -141,7 +141,7 @@ type PackageJson = { const file = process.env.RENOVATE_CONFIG_FILE ?? 'config.js'; logger.info(`Validating ${file}`); try { - await validate(true, file, fileConfig, strict); + await validate('global', file, fileConfig, strict); } catch (err) { logger.error({ file, err }, 'File is not valid Renovate config'); returnVal = 1; diff --git a/lib/config/migrate-validate.ts b/lib/config/migrate-validate.ts index a3d8f8b42c62a8fa9d10203d65bcd6cc1a3dd7ad..2ba19032334fe4a4d5cd0e5923cebc8912d0e1e7 100644 --- a/lib/config/migrate-validate.ts +++ b/lib/config/migrate-validate.ts @@ -32,7 +32,7 @@ export async function migrateAndValidate( }: { warnings: ValidationMessage[]; errors: ValidationMessage[]; - } = await configValidation.validateConfig(false, massagedConfig); + } = await configValidation.validateConfig('repo', massagedConfig); // istanbul ignore if if (is.nonEmptyArray(warnings)) { logger.warn({ warnings }, 'Found renovate config warnings'); diff --git a/lib/config/presets/internal/index.spec.ts b/lib/config/presets/internal/index.spec.ts index fd439b817579e88109102b6e4349620858829b84..17bc263677c9f028d630db6ff49173ada8fe1b54 100644 --- a/lib/config/presets/internal/index.spec.ts +++ b/lib/config/presets/internal/index.spec.ts @@ -30,7 +30,7 @@ describe('config/presets/internal/index', () => { const config = await resolveConfigPresets( massageConfig(presetConfig), ); - const res = await validateConfig(false, config, true); + const res = await validateConfig('repo', config, true); expect(res.errors).toHaveLength(0); expect(res.warnings).toHaveLength(0); } catch (err) { diff --git a/lib/config/validation.spec.ts b/lib/config/validation.spec.ts index 67943b9aa6b52a44c860764ec8b7d1722c2ff620..b92743957a670f32001ba04d902f850384a450c6 100644 --- a/lib/config/validation.spec.ts +++ b/lib/config/validation.spec.ts @@ -25,7 +25,10 @@ describe('config/validation', () => { const config = { prTitle: 'something', }; - const { warnings } = await configValidation.validateConfig(false, config); + const { warnings } = await configValidation.validateConfig( + 'repo', + config, + ); expect(warnings).toHaveLength(1); expect(warnings).toMatchSnapshot(); }); @@ -35,7 +38,10 @@ describe('config/validation', () => { binarySource: 'something', username: 'user', }; - const { warnings } = await configValidation.validateConfig(false, config); + const { warnings } = await configValidation.validateConfig( + 'repo', + config, + ); expect(warnings).toHaveLength(2); expect(warnings).toMatchObject([ { @@ -57,7 +63,10 @@ describe('config/validation', () => { }, ], }; - const { warnings } = await configValidation.validateConfig(false, config); + const { warnings } = await configValidation.validateConfig( + 'repo', + config, + ); expect(warnings).toHaveLength(0); }); @@ -65,7 +74,7 @@ describe('config/validation', () => { const config = { commitMessage: '{{{something}}', }; - const { errors } = await configValidation.validateConfig(false, config); + const { errors } = await configValidation.validateConfig('repo', config); expect(errors).toHaveLength(1); expect(errors).toMatchSnapshot(); }); @@ -95,7 +104,7 @@ describe('config/validation', () => { }, ], }; - const { errors } = await configValidation.validateConfig(false, config); + const { errors } = await configValidation.validateConfig('repo', config); expect(errors).toHaveLength(2); expect(errors).toMatchSnapshot(); }); @@ -125,7 +134,7 @@ describe('config/validation', () => { }, ], }; - const { errors } = await configValidation.validateConfig(false, config); + const { errors } = await configValidation.validateConfig('repo', config); expect(errors).toHaveLength(2); }); @@ -154,7 +163,7 @@ describe('config/validation', () => { }, ], }; - const { errors } = await configValidation.validateConfig(false, config); + const { errors } = await configValidation.validateConfig('repo', config); expect(errors).toHaveLength(2); }); @@ -188,7 +197,7 @@ describe('config/validation', () => { }, ], }; - const { errors } = await configValidation.validateConfig(false, config); + const { errors } = await configValidation.validateConfig('repo', config); expect(errors).toHaveLength(2); expect(errors).toMatchSnapshot(); }); @@ -203,7 +212,7 @@ describe('config/validation', () => { }, }, } as any; - const { errors } = await configValidation.validateConfig(false, config); + const { errors } = await configValidation.validateConfig('repo', config); expect(errors).toMatchObject([ { message: @@ -230,7 +239,7 @@ describe('config/validation', () => { }, }; // @ts-expect-error invalid options - const { errors } = await configValidation.validateConfig(false, config); + const { errors } = await configValidation.validateConfig('repo', config); expect(errors).toMatchObject([ { message: @@ -250,7 +259,7 @@ describe('config/validation', () => { randomKey: '', }, } as any; - const { errors } = await configValidation.validateConfig(false, config); + const { errors } = await configValidation.validateConfig('repo', config); expect(errors).toMatchObject([ { message: @@ -263,7 +272,7 @@ describe('config/validation', () => { const config = { baseBranches: ['/***$}{]][/', '/branch/i'], }; - const { errors } = await configValidation.validateConfig(false, config); + const { errors } = await configValidation.validateConfig('repo', config); expect(errors).toEqual([ { topic: 'Configuration Error', @@ -290,7 +299,7 @@ describe('config/validation', () => { major: null, }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, ); expect(warnings).toHaveLength(0); @@ -308,7 +317,7 @@ describe('config/validation', () => { ], }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, ); expect(warnings).toHaveLength(0); @@ -326,7 +335,7 @@ describe('config/validation', () => { ], }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config as any, ); expect(warnings).toHaveLength(0); @@ -346,7 +355,7 @@ describe('config/validation', () => { ], ])('validates enabled managers for %s', async (_case, config) => { const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, ); expect(warnings).toHaveLength(0); @@ -364,7 +373,7 @@ describe('config/validation', () => { 'errors if included not supported enabled managers for %s', async (_case, config) => { const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, ); expect(warnings).toHaveLength(0); @@ -405,7 +414,7 @@ describe('config/validation', () => { major: null, }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, ); expect(warnings).toHaveLength(1); @@ -434,7 +443,7 @@ describe('config/validation', () => { }, }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, ); expect(warnings).toHaveLength(4); @@ -453,7 +462,7 @@ describe('config/validation', () => { ], }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, true, ); @@ -472,7 +481,7 @@ describe('config/validation', () => { }, }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, ); expect(warnings).toHaveLength(0); @@ -493,7 +502,7 @@ describe('config/validation', () => { ], }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, true, ); @@ -512,7 +521,7 @@ describe('config/validation', () => { ], }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config as any, true, ); @@ -540,7 +549,7 @@ describe('config/validation', () => { ], }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config as any, true, ); @@ -569,7 +578,7 @@ describe('config/validation', () => { ], }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config as any, true, ); @@ -606,7 +615,7 @@ describe('config/validation', () => { ], }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config as RenovateConfig, true, ); @@ -637,7 +646,7 @@ describe('config/validation', () => { ], }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config as any, true, ); @@ -659,7 +668,7 @@ describe('config/validation', () => { ], }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, true, ); @@ -680,7 +689,7 @@ describe('config/validation', () => { ], }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, true, ); @@ -704,7 +713,7 @@ describe('config/validation', () => { ], }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, true, ); @@ -727,7 +736,7 @@ describe('config/validation', () => { ], }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config as any, true, ); @@ -748,7 +757,7 @@ describe('config/validation', () => { ], }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, true, ); @@ -762,7 +771,7 @@ describe('config/validation', () => { $schema: 'renovate.json', }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, true, ); @@ -775,7 +784,7 @@ describe('config/validation', () => { extends: [':timezone', ':timezone(Europe/Berlin)'], }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, true, ); @@ -788,7 +797,7 @@ describe('config/validation', () => { constraints: { packageRules: [{}] }, }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config as never, // TODO: #15963 true, ); @@ -801,7 +810,7 @@ describe('config/validation', () => { prBodyDefinitions: {}, }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, true, ); @@ -817,7 +826,7 @@ describe('config/validation', () => { }, }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, ); expect(warnings).toHaveLength(0); @@ -833,7 +842,7 @@ describe('config/validation', () => { }, }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, ); expect(warnings).toHaveLength(0); @@ -854,7 +863,7 @@ describe('config/validation', () => { }, }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, ); expect(warnings).toHaveLength(0); @@ -887,7 +896,7 @@ describe('config/validation', () => { ], }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, ); expect(errors).toHaveLength(1); @@ -908,7 +917,7 @@ describe('config/validation', () => { }, } as never; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, ); expect(errors).toHaveLength(1); @@ -921,7 +930,7 @@ describe('config/validation', () => { hostType: 'npm', }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, ); expect(errors).toHaveLength(0); @@ -934,7 +943,7 @@ describe('config/validation', () => { extends: ['foo', 'bar', 42] as never, }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, true, ); @@ -949,7 +958,7 @@ describe('config/validation', () => { ], }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, true, ); @@ -968,7 +977,7 @@ describe('config/validation', () => { ], } as any; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, true, ); @@ -988,7 +997,7 @@ describe('config/validation', () => { ], }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, true, ); @@ -1004,7 +1013,10 @@ describe('config/validation', () => { example2: 123, }, }; - const { warnings } = await configValidation.validateConfig(false, config); + const { warnings } = await configValidation.validateConfig( + 'repo', + config, + ); expect(warnings).toMatchObject([ { topic: 'Configuration Error', @@ -1018,7 +1030,7 @@ describe('config/validation', () => { schedule: ['30 5 * * *'], }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, ); expect(warnings).toHaveLength(0); @@ -1046,7 +1058,7 @@ describe('config/validation', () => { ], }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, ); expect(warnings).toHaveLength(0); @@ -1073,7 +1085,7 @@ describe('config/validation', () => { ], }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, ); expect(warnings).toHaveLength(0); @@ -1100,7 +1112,7 @@ describe('config/validation', () => { ], }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', config, ); expect(warnings).toHaveLength(0); @@ -1123,7 +1135,7 @@ describe('config/validation', () => { }, }; const { errors, warnings } = await configValidation.validateConfig( - false, + 'repo', // @ts-expect-error: testing invalid values in env object config, ); @@ -1159,7 +1171,7 @@ describe('config/validation', () => { ], }; const { errors, warnings } = await configValidation.validateConfig( - false, + 'repo', config, ); expect(errors).toMatchObject([ @@ -1193,7 +1205,7 @@ describe('config/validation', () => { allowedHeaders: ['X-Auth-Token'], }; const { warnings, errors } = await configValidation.validateConfig( - true, + 'global', config, ); expect(warnings).toHaveLength(0); @@ -1211,7 +1223,10 @@ describe('config/validation', () => { }, ], }; - const { errors } = await configValidation.validateConfig(true, config); + const { errors } = await configValidation.validateConfig( + 'global', + config, + ); expect(errors).toMatchObject([ { message: @@ -1229,7 +1244,7 @@ describe('config/validation', () => { allowedEnv: ['SOME*'], }; const { warnings, errors } = await configValidation.validateConfig( - true, + 'global', config, ); expect(warnings).toHaveLength(0); @@ -1242,7 +1257,10 @@ describe('config/validation', () => { SOME_VAR: 'SOME_VALUE', }, }; - const { errors } = await configValidation.validateConfig(true, config); + const { errors } = await configValidation.validateConfig( + 'global', + config, + ); expect(errors).toMatchObject([ { message: @@ -1277,7 +1295,7 @@ describe('config/validation', () => { reviewersSampleSize: null, }; const { warnings, errors } = await configValidation.validateConfig( - false, + 'repo', // @ts-expect-error: contains invalid values config, ); @@ -1293,7 +1311,7 @@ describe('config/validation', () => { binarySource: 'invalid' as never, }; const { warnings } = await configValidation.validateConfig( - true, + 'global', config, ); expect(warnings).toEqual([ @@ -1310,7 +1328,7 @@ describe('config/validation', () => { baseDir: false as never, }; const { warnings } = await configValidation.validateConfig( - true, + 'global', config, ); expect(warnings).toEqual([ @@ -1326,7 +1344,7 @@ describe('config/validation', () => { requireConfig: 'invalid' as never, }; const { warnings } = await configValidation.validateConfig( - true, + 'global', config, ); expect(warnings).toEqual([ @@ -1343,7 +1361,7 @@ describe('config/validation', () => { dryRun: 'invalid' as never, }; const { warnings } = await configValidation.validateConfig( - true, + 'global', config, ); expect(warnings).toEqual([ @@ -1360,7 +1378,7 @@ describe('config/validation', () => { repositoryCache: 'invalid' as never, }; const { warnings } = await configValidation.validateConfig( - true, + 'global', config, ); expect(warnings).toEqual([ @@ -1377,7 +1395,7 @@ describe('config/validation', () => { onboardingConfigFileName: 'invalid' as never, }; const { warnings } = await configValidation.validateConfig( - true, + 'global', config, ); expect(warnings).toEqual([ @@ -1397,7 +1415,7 @@ describe('config/validation', () => { }, }; const { warnings } = await configValidation.validateConfig( - true, + 'global', config, ); expect(warnings).toEqual([ @@ -1425,7 +1443,7 @@ describe('config/validation', () => { }, }; const { warnings } = await configValidation.validateConfig( - true, + 'global', config, ); expect(warnings).toEqual([ @@ -1442,7 +1460,7 @@ describe('config/validation', () => { gitUrl: 'invalid' as never, }; const { warnings } = await configValidation.validateConfig( - true, + 'global', config, ); expect(warnings).toEqual([ @@ -1460,7 +1478,10 @@ describe('config/validation', () => { unicodeEmoji: false, detectGlobalManagerConfig: 'invalid-type', }; - const { warnings } = await configValidation.validateConfig(true, config); + const { warnings } = await configValidation.validateConfig( + 'global', + config, + ); expect(warnings).toMatchObject([ { message: `Configuration option \`detectGlobalManagerConfig\` should be a boolean. Found: ${JSON.stringify( @@ -1476,7 +1497,10 @@ describe('config/validation', () => { prCommitsPerRunLimit: 2, gitTimeout: 'invalid-type', }; - const { warnings } = await configValidation.validateConfig(true, config); + const { warnings } = await configValidation.validateConfig( + 'global', + config, + ); expect(warnings).toMatchObject([ { message: `Configuration option \`gitTimeout\` should be an integer. Found: ${JSON.stringify( @@ -1494,7 +1518,7 @@ describe('config/validation', () => { gitNoVerify: ['invalid'], }; const { warnings } = await configValidation.validateConfig( - true, + 'global', // @ts-expect-error: contains invalid values config, ); @@ -1525,7 +1549,7 @@ describe('config/validation', () => { }, }; const { warnings } = await configValidation.validateConfig( - true, + 'global', // @ts-expect-error: contains invalid values config, ); @@ -1549,7 +1573,10 @@ describe('config/validation', () => { example2: 123, }, }; - const { warnings } = await configValidation.validateConfig(true, config); + const { warnings } = await configValidation.validateConfig( + 'global', + config, + ); expect(warnings).toMatchObject([ { message: @@ -1567,7 +1594,7 @@ describe('config/validation', () => { }, }; const { warnings, errors } = await configValidation.validateConfig( - true, + 'global', config, ); expect(warnings).toHaveLength(0); @@ -1586,7 +1613,7 @@ describe('config/validation', () => { autodiscoverTopics: null, }; const { warnings, errors } = await configValidation.validateConfig( - true, + 'global', // @ts-expect-error: contains invalid values config, ); diff --git a/lib/config/validation.ts b/lib/config/validation.ts index 1a5b269cda667181edde0674e200b6f66c56194d..f555df8fd688de438ee555a5eb6b882376c7eac9 100644 --- a/lib/config/validation.ts +++ b/lib/config/validation.ts @@ -121,7 +121,7 @@ export function getParentName(parentPath: string | undefined): string { } export async function validateConfig( - isGlobalConfig: boolean, + configType: 'global' | 'repo', config: RenovateConfig, isPreset?: boolean, parentPath?: string, @@ -164,7 +164,7 @@ export async function validateConfig( }); } - if (isGlobalConfig && isGlobalOption(key)) { + if (configType === 'global' && isGlobalOption(key)) { await validateGlobalConfig( key, val, @@ -327,7 +327,7 @@ export async function validateConfig( for (const [subIndex, subval] of val.entries()) { if (is.object(subval)) { const subValidation = await validateConfig( - isGlobalConfig, + configType, subval as RenovateConfig, isPreset, `${currentPath}[${subIndex}]`, @@ -627,9 +627,10 @@ export async function validateConfig( }); } } else if (key === 'env') { - const allowedEnvVars = isGlobalConfig - ? (config.allowedEnv as string[]) ?? [] - : GlobalConfig.get('allowedEnv', []); + const allowedEnvVars = + configType === 'global' + ? (config.allowedEnv as string[]) ?? [] + : GlobalConfig.get('allowedEnv', []); for (const [envVarName, envVarValue] of Object.entries(val)) { if (!is.string(envVarValue)) { errors.push({ @@ -715,7 +716,7 @@ export async function validateConfig( .map((option) => option.name); if (!ignoredObjects.includes(key)) { const subValidation = await validateConfig( - isGlobalConfig, + configType, val, isPreset, currentPath, @@ -735,9 +736,10 @@ export async function validateConfig( } if (key === 'hostRules' && is.array(val)) { - const allowedHeaders = isGlobalConfig - ? (config.allowedHeaders as string[]) ?? [] - : GlobalConfig.get('allowedHeaders', []); + const allowedHeaders = + configType === 'global' + ? (config.allowedHeaders as string[]) ?? [] + : GlobalConfig.get('allowedHeaders', []); for (const rule of val as HostRule[]) { if (!rule.headers) { continue; @@ -926,14 +928,14 @@ async function validateGlobalConfig( } else if (type === 'object') { if (is.plainObject(val)) { if (key === 'onboardingConfig') { - const subValidation = await validateConfig(false, val); + const subValidation = await validateConfig('repo', val); for (const warning of subValidation.warnings.concat( subValidation.errors, )) { warnings.push(warning); } } else if (key === 'force') { - const subValidation = await validateConfig(true, val); + const subValidation = await validateConfig('global', val); for (const warning of subValidation.warnings.concat( subValidation.errors, )) { diff --git a/lib/workers/repository/reconfigure/index.ts b/lib/workers/repository/reconfigure/index.ts index 22ee0135f9356ff9edb2366472ab2e9682eb9b32..b27e7b5e50613afb50f38d4e1454e57b486712bf 100644 --- a/lib/workers/repository/reconfigure/index.ts +++ b/lib/workers/repository/reconfigure/index.ts @@ -151,7 +151,7 @@ export async function validateReconfigureBranch( } // perform validation and provide a passing or failing check run based on result - const validationResult = await validateConfig(false, configFileParsed); + const validationResult = await validateConfig('repo', configFileParsed); // failing check if (validationResult.errors.length > 0) {