fix(config-validator): allow default null val for globalOptions (#27616)

This commit is contained in:
RahulGautamSingh 2024-02-28 21:13:20 +05:45 committed by GitHub
parent 9f2394680e
commit 1efa2f21da
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 174 additions and 119 deletions

View file

@ -1251,6 +1251,39 @@ describe('config/validation', () => {
}, },
]); ]);
}); });
it('validates options with different type but defaultValue=null', async () => {
const config = {
minimumReleaseAge: null,
groupName: null,
groupSlug: null,
dependencyDashboardLabels: null,
defaultRegistryUrls: null,
registryUrls: null,
hostRules: [
{
artifactAuth: null,
concurrentRequestLimit: null,
httpsCertificate: null,
httpsPrivateKey: null,
httpsCertificateAuthority: null,
},
],
encrypted: null,
milestone: null,
branchConcurrentLimit: null,
hashedBranchLength: null,
assigneesSampleSize: null,
reviewersSampleSize: null,
};
const { warnings, errors } = await configValidation.validateConfig(
false,
// @ts-expect-error: contains invalid values
config,
);
expect(warnings).toHaveLength(0);
expect(errors).toHaveLength(0);
});
}); });
describe('validate globalOptions()', () => { describe('validate globalOptions()', () => {
@ -1540,5 +1573,25 @@ describe('config/validation', () => {
expect(warnings).toHaveLength(0); expect(warnings).toHaveLength(0);
expect(errors).toHaveLength(0); expect(errors).toHaveLength(0);
}); });
it('validates options with different type but defaultValue=null', async () => {
const config = {
onboardingCommitMessage: null,
dryRun: null,
logContext: null,
endpoint: null,
skipInstalls: null,
autodiscoverFilter: null,
autodiscoverNamespaces: null,
autodiscoverTopics: null,
};
const { warnings, errors } = await configValidation.validateConfig(
true,
// @ts-expect-error: contains invalid values
config,
);
expect(warnings).toHaveLength(0);
expect(errors).toHaveLength(0);
});
}); });
}); });

View file

@ -828,139 +828,141 @@ async function validateGlobalConfig(
warnings: ValidationMessage[], warnings: ValidationMessage[],
currentPath: string | undefined, currentPath: string | undefined,
): Promise<void> { ): Promise<void> {
if (type === 'string') { if (val !== null) {
if (is.string(val)) { if (type === 'string') {
if ( if (is.string(val)) {
key === 'onboardingConfigFileName' && if (
!configFileNames.includes(val) key === 'onboardingConfigFileName' &&
) { !configFileNames.includes(val)
) {
warnings.push({
topic: 'Configuration Error',
message: `Invalid value \`${val}\` for \`${currentPath}\`. The allowed values are ${configFileNames.join(', ')}.`,
});
} else if (
key === 'repositoryCache' &&
!['enabled', 'disabled', 'reset'].includes(val)
) {
warnings.push({
topic: 'Configuration Error',
message: `Invalid value \`${val}\` for \`${currentPath}\`. The allowed values are ${['enabled', 'disabled', 'reset'].join(', ')}.`,
});
} else if (
key === 'dryRun' &&
!['extract', 'lookup', 'full'].includes(val)
) {
warnings.push({
topic: 'Configuration Error',
message: `Invalid value \`${val}\` for \`${currentPath}\`. The allowed values are ${['extract', 'lookup', 'full'].join(', ')}.`,
});
} else if (
key === 'binarySource' &&
!['docker', 'global', 'install', 'hermit'].includes(val)
) {
warnings.push({
topic: 'Configuration Error',
message: `Invalid value \`${val}\` for \`${currentPath}\`. The allowed values are ${['docker', 'global', 'install', 'hermit'].join(', ')}.`,
});
} else if (
key === 'requireConfig' &&
!['required', 'optional', 'ignored'].includes(val)
) {
warnings.push({
topic: 'Configuration Error',
message: `Invalid value \`${val}\` for \`${currentPath}\`. The allowed values are ${['required', 'optional', 'ignored'].join(', ')}.`,
});
} else if (
key === 'gitUrl' &&
!['default', 'ssh', 'endpoint'].includes(val)
) {
warnings.push({
topic: 'Configuration Error',
message: `Invalid value \`${val}\` for \`${currentPath}\`. The allowed values are ${['default', 'ssh', 'endpoint'].join(', ')}.`,
});
}
} else {
warnings.push({ warnings.push({
topic: 'Configuration Error', topic: 'Configuration Error',
message: `Invalid value \`${val}\` for \`${currentPath}\`. The allowed values are ${configFileNames.join(', ')}.`, message: `Configuration option \`${currentPath}\` should be a string.`,
});
} else if (
key === 'repositoryCache' &&
!['enabled', 'disabled', 'reset'].includes(val)
) {
warnings.push({
topic: 'Configuration Error',
message: `Invalid value \`${val}\` for \`${currentPath}\`. The allowed values are ${['enabled', 'disabled', 'reset'].join(', ')}.`,
});
} else if (
key === 'dryRun' &&
!['extract', 'lookup', 'full'].includes(val)
) {
warnings.push({
topic: 'Configuration Error',
message: `Invalid value \`${val}\` for \`${currentPath}\`. The allowed values are ${['extract', 'lookup', 'full'].join(', ')}.`,
});
} else if (
key === 'binarySource' &&
!['docker', 'global', 'install', 'hermit'].includes(val)
) {
warnings.push({
topic: 'Configuration Error',
message: `Invalid value \`${val}\` for \`${currentPath}\`. The allowed values are ${['docker', 'global', 'install', 'hermit'].join(', ')}.`,
});
} else if (
key === 'requireConfig' &&
!['required', 'optional', 'ignored'].includes(val)
) {
warnings.push({
topic: 'Configuration Error',
message: `Invalid value \`${val}\` for \`${currentPath}\`. The allowed values are ${['required', 'optional', 'ignored'].join(', ')}.`,
});
} else if (
key === 'gitUrl' &&
!['default', 'ssh', 'endpoint'].includes(val)
) {
warnings.push({
topic: 'Configuration Error',
message: `Invalid value \`${val}\` for \`${currentPath}\`. The allowed values are ${['default', 'ssh', 'endpoint'].join(', ')}.`,
}); });
} }
} else { } else if (type === 'integer') {
warnings.push({ if (!is.number(val)) {
topic: 'Configuration Error', warnings.push({
message: `Configuration option \`${currentPath}\` should be a string.`, topic: 'Configuration Error',
}); message: `Configuration option \`${currentPath}\` should be an integer. Found: ${JSON.stringify(
} val,
} else if (type === 'integer') { )} (${typeof val}).`,
if (!is.number(val)) { });
warnings.push({ }
topic: 'Configuration Error', } else if (type === 'boolean') {
message: `Configuration option \`${currentPath}\` should be an integer. Found: ${JSON.stringify( if (val !== true && val !== false) {
val, warnings.push({
)} (${typeof val}).`, topic: 'Configuration Error',
}); message: `Configuration option \`${currentPath}\` should be a boolean. Found: ${JSON.stringify(
} val,
} else if (type === 'boolean') { )} (${typeof val}).`,
if (val !== true && val !== false) { });
warnings.push({ }
topic: 'Configuration Error', } else if (type === 'array') {
message: `Configuration option \`${currentPath}\` should be a boolean. Found: ${JSON.stringify( if (is.array(val)) {
val, if (key === 'gitNoVerify') {
)} (${typeof val}).`, const allowedValues = ['commit', 'push'];
}); for (const value of val as string[]) {
} if (!allowedValues.includes(value)) {
} else if (type === 'array') { warnings.push({
if (is.array(val)) { topic: 'Configuration Error',
if (key === 'gitNoVerify') { message: `Invalid value for \`${currentPath}\`. The allowed values are ${allowedValues.join(', ')}.`,
const allowedValues = ['commit', 'push']; });
for (const value of val as string[]) { }
if (!allowedValues.includes(value)) {
warnings.push({
topic: 'Configuration Error',
message: `Invalid value for \`${currentPath}\`. The allowed values are ${allowedValues.join(', ')}.`,
});
} }
} }
} else {
warnings.push({
topic: 'Configuration Error',
message: `Configuration option \`${currentPath}\` should be a list (Array).`,
});
} }
} else { } else if (type === 'object') {
warnings.push({ if (is.plainObject(val)) {
topic: 'Configuration Error', if (key === 'onboardingConfig') {
message: `Configuration option \`${currentPath}\` should be a list (Array).`, const subValidation = await validateConfig(false, val);
}); for (const warning of subValidation.warnings.concat(
} subValidation.errors,
} else if (type === 'object') { )) {
if (is.plainObject(val)) { warnings.push(warning);
if (key === 'onboardingConfig') { }
const subValidation = await validateConfig(false, val); } else if (key === 'force') {
for (const warning of subValidation.warnings.concat( const subValidation = await validateConfig(true, val);
subValidation.errors, for (const warning of subValidation.warnings.concat(
)) { subValidation.errors,
warnings.push(warning); )) {
} warnings.push(warning);
} else if (key === 'force') { }
const subValidation = await validateConfig(true, val); } else if (key === 'cacheTtlOverride') {
for (const warning of subValidation.warnings.concat( for (const [subKey, subValue] of Object.entries(val)) {
subValidation.errors, if (!is.number(subValue)) {
)) { warnings.push({
warnings.push(warning); topic: 'Configuration Error',
} message: `Invalid \`${currentPath}.${subKey}\` configuration: value must be an integer.`,
} else if (key === 'cacheTtlOverride') { });
for (const [subKey, subValue] of Object.entries(val)) { }
if (!is.number(subValue)) { }
} else {
const res = validatePlainObject(val);
if (res !== true) {
warnings.push({ warnings.push({
topic: 'Configuration Error', topic: 'Configuration Error',
message: `Invalid \`${currentPath}.${subKey}\` configuration: value must be an integer.`, message: `Invalid \`${currentPath}.${res}\` configuration: value must be a string.`,
}); });
} }
} }
} else { } else {
const res = validatePlainObject(val); warnings.push({
if (res !== true) { topic: 'Configuration Error',
warnings.push({ message: `Configuration option \`${currentPath}\` should be a JSON object.`,
topic: 'Configuration Error', });
message: `Invalid \`${currentPath}.${res}\` configuration: value must be a string.`,
});
}
} }
} else {
warnings.push({
topic: 'Configuration Error',
message: `Configuration option \`${currentPath}\` should be a JSON object.`,
});
} }
} }
} }