renovate 44.33.2 → 44.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/types.d.ts +2 -1
- package/dist/config/types.js.map +1 -1
- package/dist/config/validation-helpers/match-base-branches.js +2 -1
- package/dist/config/validation-helpers/match-base-branches.js.map +1 -1
- package/dist/config/validation-helpers/regex-glob-matchers.js +4 -3
- package/dist/config/validation-helpers/regex-glob-matchers.js.map +1 -1
- package/dist/config/validation-helpers/types.d.ts +17 -0
- package/dist/config/validation-helpers/types.js +16 -0
- package/dist/config/validation-helpers/types.js.map +1 -0
- package/dist/config/validation-helpers/utils.js +12 -11
- package/dist/config/validation-helpers/utils.js.map +1 -1
- package/dist/config/validation.js +80 -79
- package/dist/config/validation.js.map +1 -1
- package/dist/modules/manager/fingerprint.generated.js +1 -1
- package/dist/modules/manager/fingerprint.generated.js.map +1 -1
- package/dist/modules/manager/poetry/artifacts.js +15 -8
- package/dist/modules/manager/poetry/artifacts.js.map +1 -1
- package/dist/modules/manager/types.d.ts +1 -0
- package/dist/workers/repository/update/pr/changelog/bitbucket/source.js +4 -0
- package/dist/workers/repository/update/pr/changelog/bitbucket/source.js.map +1 -1
- package/dist/workers/repository/update/pr/changelog/bitbucket-server/source.js +5 -1
- package/dist/workers/repository/update/pr/changelog/bitbucket-server/source.js.map +1 -1
- package/dist/workers/repository/update/pr/changelog/release-notes.js +7 -13
- package/dist/workers/repository/update/pr/changelog/release-notes.js.map +1 -1
- package/dist/workers/repository/update/pr/changelog/source.js +17 -3
- package/dist/workers/repository/update/pr/changelog/source.js.map +1 -1
- package/package.json +3 -3
- package/renovate-schema.json +2 -2
|
@@ -22,6 +22,7 @@ import { getExpression } from "../util/jsonata.js";
|
|
|
22
22
|
import { hasValidSchedule, hasValidTimezone } from "../workers/repository/update/branch/schedule.js";
|
|
23
23
|
import { isRelativePresetReference, parsePreset } from "./presets/parse.js";
|
|
24
24
|
import { resolveConfigPresets } from "./presets/index.js";
|
|
25
|
+
import { ConfigValidationTopic } from "./validation-helpers/types.js";
|
|
25
26
|
import { check } from "./validation-helpers/match-base-branches.js";
|
|
26
27
|
import { check as check$1 } from "./validation-helpers/regex-glob-matchers.js";
|
|
27
28
|
import { getParentName, isFalseGlobal, validateJSONataManagerFields, validateNumber, validatePlainObject, validateRegexManagerFields } from "./validation-helpers/utils.js";
|
|
@@ -151,13 +152,13 @@ async function validateConfig(configType, config, isPreset, parentPath) {
|
|
|
151
152
|
/* v8 ignore next 7 -- TODO: add test */
|
|
152
153
|
if (key === "__proto__") {
|
|
153
154
|
errors.push({
|
|
154
|
-
topic:
|
|
155
|
+
topic: ConfigValidationTopic.Security,
|
|
155
156
|
message: "__proto__"
|
|
156
157
|
});
|
|
157
158
|
continue;
|
|
158
159
|
}
|
|
159
160
|
if (parentPath && parentPath !== "onboardingConfig" && !repoEntryRe.test(parentPath) && topLevelObjects.includes(key)) errors.push({
|
|
160
|
-
topic:
|
|
161
|
+
topic: ConfigValidationTopic.Error,
|
|
161
162
|
message: `The "${key}" object can only be configured at the top level of a config but was found inside "${parentPath}"`
|
|
162
163
|
});
|
|
163
164
|
if (isGlobalOption(key)) {
|
|
@@ -166,7 +167,7 @@ async function validateConfig(configType, config, isPreset, parentPath) {
|
|
|
166
167
|
continue;
|
|
167
168
|
} else if (!isFalseGlobal(key, parentPath) && !(configType === "inherit" && isInhertConfigOption(key))) {
|
|
168
169
|
warnings.push({
|
|
169
|
-
topic:
|
|
170
|
+
topic: ConfigValidationTopic.Error,
|
|
170
171
|
message: `The "${key}" option is a global option reserved only for Renovate's global configuration and cannot be configured within a repository's config file.`
|
|
171
172
|
});
|
|
172
173
|
continue;
|
|
@@ -175,28 +176,28 @@ async function validateConfig(configType, config, isPreset, parentPath) {
|
|
|
175
176
|
if (key === "enabledManagers" && val) {
|
|
176
177
|
const unsupportedManagers = getUnsupportedEnabledManagers(val);
|
|
177
178
|
if (isNonEmptyArray(unsupportedManagers)) errors.push({
|
|
178
|
-
topic:
|
|
179
|
+
topic: ConfigValidationTopic.Error,
|
|
179
180
|
message: `The following managers configured in enabledManagers are not supported: "${unsupportedManagers.join(", ")}"`
|
|
180
181
|
});
|
|
181
182
|
}
|
|
182
183
|
if (key === "registryUrls" && !parentPath && isNonEmptyArray(val)) warnings.push({
|
|
183
|
-
topic:
|
|
184
|
+
topic: ConfigValidationTopic.Warning,
|
|
184
185
|
message: "Setting `registryUrls` at the top level of your config will apply it to all managers and datasources, which can cause the wrong registry URL to be used for some packages. Use `registryUrls` inside `packageRules` to target specific managers or packages."
|
|
185
186
|
});
|
|
186
187
|
if (key === "defaultRegistryUrls" && !parentPath && isNonEmptyArray(val)) warnings.push({
|
|
187
|
-
topic:
|
|
188
|
+
topic: ConfigValidationTopic.Warning,
|
|
188
189
|
message: "Setting `defaultRegistryUrls` at the top level of your config will apply it to all managers and datasources, which can cause the wrong registry URL to be used for some packages. Use `defaultRegistryUrls` inside `packageRules` to target specific managers or packages."
|
|
189
190
|
});
|
|
190
191
|
if (!isIgnored(key) && !is.function(val)) {
|
|
191
192
|
if (getDeprecationMessage(key)) warnings.push({
|
|
192
|
-
topic:
|
|
193
|
+
topic: ConfigValidationTopic.Deprecation,
|
|
193
194
|
message: getDeprecationMessage(key)
|
|
194
195
|
});
|
|
195
196
|
if (optionSupportsTemplating.has(key) && val) try {
|
|
196
197
|
validate(val.toString());
|
|
197
198
|
} catch {
|
|
198
199
|
errors.push({
|
|
199
|
-
topic:
|
|
200
|
+
topic: ConfigValidationTopic.Error,
|
|
200
201
|
message: `Invalid template in config path: ${currentPath}`
|
|
201
202
|
});
|
|
202
203
|
}
|
|
@@ -210,13 +211,13 @@ async function validateConfig(configType, config, isPreset, parentPath) {
|
|
|
210
211
|
}
|
|
211
212
|
// v8 ignore else -- intentionally unhandled - if we knew what was to be covered here, we'd add validation
|
|
212
213
|
if (!optionTypes[key]) errors.push({
|
|
213
|
-
topic:
|
|
214
|
+
topic: ConfigValidationTopic.Error,
|
|
214
215
|
message: `Invalid configuration option: ${currentPath}`
|
|
215
216
|
});
|
|
216
217
|
else if (key === "schedule") {
|
|
217
218
|
const [validSchedule, errorMessage] = hasValidSchedule(val);
|
|
218
219
|
if (!validSchedule) errors.push({
|
|
219
|
-
topic:
|
|
220
|
+
topic: ConfigValidationTopic.Error,
|
|
220
221
|
message: `Invalid ${currentPath}: \`${errorMessage}\``
|
|
221
222
|
});
|
|
222
223
|
} else if ([
|
|
@@ -226,20 +227,20 @@ async function validateConfig(configType, config, isPreset, parentPath) {
|
|
|
226
227
|
"matchNewValue"
|
|
227
228
|
].includes(key) && isRegexMatch(val)) {
|
|
228
229
|
if (!getRegexPredicate(val)) errors.push({
|
|
229
|
-
topic:
|
|
230
|
+
topic: ConfigValidationTopic.Error,
|
|
230
231
|
message: `Invalid regExp for ${currentPath}: \`${val}\``
|
|
231
232
|
});
|
|
232
233
|
} else if (key === "timezone" && val !== null) {
|
|
233
234
|
const [validTimezone, errorMessage] = hasValidTimezone(val);
|
|
234
235
|
if (!validTimezone) errors.push({
|
|
235
|
-
topic:
|
|
236
|
+
topic: ConfigValidationTopic.Error,
|
|
236
237
|
message: `${currentPath}: ${errorMessage}`
|
|
237
238
|
});
|
|
238
239
|
} else if (val !== null) {
|
|
239
240
|
const type = optionTypes[key];
|
|
240
241
|
if (type === "boolean") {
|
|
241
242
|
if (val !== true && val !== false) errors.push({
|
|
242
|
-
topic:
|
|
243
|
+
topic: ConfigValidationTopic.Error,
|
|
243
244
|
message: `Configuration option \`${currentPath}\` should be boolean. Found: ${JSON.stringify(val)} (${typeof val})`
|
|
244
245
|
});
|
|
245
246
|
} else if (type === "integer") {
|
|
@@ -257,18 +258,18 @@ async function validateConfig(configType, config, isPreset, parentPath) {
|
|
|
257
258
|
}));
|
|
258
259
|
if (key === "extends") for (const subval of val) if (isString(subval)) {
|
|
259
260
|
if (configType !== "global" && subval.startsWith("global:")) errors.push({
|
|
260
|
-
topic:
|
|
261
|
+
topic: ConfigValidationTopic.Error,
|
|
261
262
|
message: `${currentPath}: you cannot extend from "global:" presets in a repository config's "extends"`
|
|
262
263
|
});
|
|
263
264
|
if (parentName === "packageRules" && subval.startsWith("group:")) warnings.push({
|
|
264
|
-
topic:
|
|
265
|
+
topic: ConfigValidationTopic.Warning,
|
|
265
266
|
message: `${currentPath}: you should not extend "group:" presets`
|
|
266
267
|
});
|
|
267
268
|
if (tzRe.test(subval)) {
|
|
268
269
|
const [, timezone] = tzRe.exec(subval);
|
|
269
270
|
const [validTimezone, errorMessage] = hasValidTimezone(timezone);
|
|
270
271
|
if (!validTimezone) errors.push({
|
|
271
|
-
topic:
|
|
272
|
+
topic: ConfigValidationTopic.Error,
|
|
272
273
|
message: `${currentPath}: ${errorMessage}`
|
|
273
274
|
});
|
|
274
275
|
}
|
|
@@ -276,17 +277,17 @@ async function validateConfig(configType, config, isPreset, parentPath) {
|
|
|
276
277
|
parsePreset(subval);
|
|
277
278
|
} catch {
|
|
278
279
|
errors.push({
|
|
279
|
-
topic:
|
|
280
|
+
topic: ConfigValidationTopic.Error,
|
|
280
281
|
message: `${currentPath}: preset "${subval}" is not valid`
|
|
281
282
|
});
|
|
282
283
|
}
|
|
283
284
|
} else errors.push({
|
|
284
|
-
topic:
|
|
285
|
+
topic: ConfigValidationTopic.Error,
|
|
285
286
|
message: `${currentPath}: preset value is not a string`
|
|
286
287
|
});
|
|
287
288
|
if (key === "commitTrailers") {
|
|
288
289
|
for (const subval of val) if (!isValidCommitTrailer(subval)) errors.push({
|
|
289
|
-
topic:
|
|
290
|
+
topic: ConfigValidationTopic.Error,
|
|
290
291
|
message: `Invalid commit trailer: \`${JSON.stringify(subval)}\`. Must be a single-line string in the form \`Key: value\`, where the key contains only letters, digits and \`-\`.`
|
|
291
292
|
});
|
|
292
293
|
}
|
|
@@ -324,20 +325,20 @@ async function validateConfig(configType, config, isPreset, parentPath) {
|
|
|
324
325
|
if (!selectorLength) if (hasRelativePresets) {
|
|
325
326
|
const message = `${currentPath}[${subIndex}]: this rule extends a relative preset that cannot be resolved during validation, so its selectors could not be checked. Rule: ${JSON.stringify(packageRule)}`;
|
|
326
327
|
warnings.push({
|
|
327
|
-
topic:
|
|
328
|
+
topic: ConfigValidationTopic.Error,
|
|
328
329
|
message
|
|
329
330
|
});
|
|
330
331
|
} else {
|
|
331
332
|
const message = `${currentPath}[${subIndex}]: Each packageRule must contain at least one match* or exclude* selector. Rule: ${JSON.stringify(packageRule)}`;
|
|
332
333
|
errors.push({
|
|
333
|
-
topic:
|
|
334
|
+
topic: ConfigValidationTopic.Error,
|
|
334
335
|
message
|
|
335
336
|
});
|
|
336
337
|
}
|
|
337
338
|
if (!hasRelativePresets && selectorLength === Object.keys(resolvedRule).length) {
|
|
338
339
|
const message = `${currentPath}[${subIndex}]: Each packageRule must contain at least one non-match* or non-exclude* field. Rule: ${JSON.stringify(packageRule)}`;
|
|
339
340
|
warnings.push({
|
|
340
|
-
topic:
|
|
341
|
+
topic: ConfigValidationTopic.Error,
|
|
341
342
|
message
|
|
342
343
|
});
|
|
343
344
|
}
|
|
@@ -361,13 +362,13 @@ async function validateConfig(configType, config, isPreset, parentPath) {
|
|
|
361
362
|
for (const option of preLookupOptions) if (resolvedRule[option] !== void 0) {
|
|
362
363
|
const message = `${currentPath}[${subIndex}]: packageRules cannot combine both matchUpdateTypes and ${option}. Rule: ${JSON.stringify(packageRule)}`;
|
|
363
364
|
errors.push({
|
|
364
|
-
topic:
|
|
365
|
+
topic: ConfigValidationTopic.Error,
|
|
365
366
|
message
|
|
366
367
|
});
|
|
367
368
|
}
|
|
368
369
|
}
|
|
369
370
|
} else errors.push({
|
|
370
|
-
topic:
|
|
371
|
+
topic: ConfigValidationTopic.Error,
|
|
371
372
|
message: `${currentPath} must contain JSON objects`
|
|
372
373
|
});
|
|
373
374
|
if (key === "customManagers") {
|
|
@@ -391,7 +392,7 @@ async function validateConfig(configType, config, isPreset, parentPath) {
|
|
|
391
392
|
for (const customManager of val) if (Object.keys(customManager).some((k) => !allowedKeys.includes(k))) {
|
|
392
393
|
const disallowedKeys = Object.keys(customManager).filter((k) => !allowedKeys.includes(k));
|
|
393
394
|
errors.push({
|
|
394
|
-
topic:
|
|
395
|
+
topic: ConfigValidationTopic.Error,
|
|
395
396
|
message: `Custom Manager contains disallowed fields: ${disallowedKeys.join(", ")}`
|
|
396
397
|
});
|
|
397
398
|
} else if (isNonEmptyString(customManager.customType) && isCustomManager(customManager.customType)) if (isNonEmptyArray(customManager.managerFilePatterns)) switch (customManager.customType) {
|
|
@@ -401,15 +402,15 @@ async function validateConfig(configType, config, isPreset, parentPath) {
|
|
|
401
402
|
case "jsonata": validateJSONataManagerFields(customManager, currentPath, errors);
|
|
402
403
|
}
|
|
403
404
|
else errors.push({
|
|
404
|
-
topic:
|
|
405
|
+
topic: ConfigValidationTopic.Error,
|
|
405
406
|
message: `Each Custom Manager must contain a non-empty managerFilePatterns array`
|
|
406
407
|
});
|
|
407
408
|
else if (isEmptyString(customManager.customType) || isUndefined(customManager.customType)) errors.push({
|
|
408
|
-
topic:
|
|
409
|
+
topic: ConfigValidationTopic.Error,
|
|
409
410
|
message: `Each Custom Manager must contain a non-empty customType string`
|
|
410
411
|
});
|
|
411
412
|
else errors.push({
|
|
412
|
-
topic:
|
|
413
|
+
topic: ConfigValidationTopic.Error,
|
|
413
414
|
message: `Invalid customType: ${customManager.customType}. Key is not a custom manager`
|
|
414
415
|
});
|
|
415
416
|
}
|
|
@@ -420,57 +421,57 @@ async function validateConfig(configType, config, isPreset, parentPath) {
|
|
|
420
421
|
regEx(pattern.replace(startPattern, "/"));
|
|
421
422
|
} catch {
|
|
422
423
|
errors.push({
|
|
423
|
-
topic:
|
|
424
|
+
topic: ConfigValidationTopic.Error,
|
|
424
425
|
message: `Invalid regExp for ${currentPath}: \`${pattern}\``
|
|
425
426
|
});
|
|
426
427
|
}
|
|
427
428
|
}
|
|
428
429
|
if (key === "baseBranchPatterns") {
|
|
429
430
|
for (const baseBranchPattern of val) if (isRegexMatch(baseBranchPattern) && !getRegexPredicate(baseBranchPattern)) errors.push({
|
|
430
|
-
topic:
|
|
431
|
+
topic: ConfigValidationTopic.Error,
|
|
431
432
|
message: `Invalid regExp for ${currentPath}: \`${baseBranchPattern}\``
|
|
432
433
|
});
|
|
433
434
|
}
|
|
434
435
|
if ((selectors.includes(key) || key === "matchCurrentVersion" || key === "matchCurrentValue") && !rulesRe.test(parentPath) && (isString(parentPath) || !isPreset)) errors.push({
|
|
435
|
-
topic:
|
|
436
|
+
topic: ConfigValidationTopic.Error,
|
|
436
437
|
message: `${currentPath}: ${key} should be inside a \`packageRule\` only`
|
|
437
438
|
});
|
|
438
439
|
} else errors.push({
|
|
439
|
-
topic:
|
|
440
|
+
topic: ConfigValidationTopic.Error,
|
|
440
441
|
message: `Configuration option \`${currentPath}\` should be a list (Array)`
|
|
441
442
|
});
|
|
442
443
|
else if (type === "string") {
|
|
443
444
|
if (!isString(val)) errors.push({
|
|
444
|
-
topic:
|
|
445
|
+
topic: ConfigValidationTopic.Error,
|
|
445
446
|
message: `Configuration option \`${currentPath}\` should be a string`
|
|
446
447
|
});
|
|
447
448
|
} else if (type === "object") if (isPlainObject(val)) {
|
|
448
449
|
if (key === "registryAliases") {
|
|
449
450
|
const res = validatePlainObject(val);
|
|
450
451
|
if (res !== true) errors.push({
|
|
451
|
-
topic:
|
|
452
|
+
topic: ConfigValidationTopic.Error,
|
|
452
453
|
message: `Invalid \`${currentPath}.${key}.${res}\` configuration: value is not a string`
|
|
453
454
|
});
|
|
454
455
|
} else if (key === "env") {
|
|
455
456
|
const allowedEnvVars = configType === "global" ? config.allowedEnv ?? [] : GlobalConfig.get("allowedEnv");
|
|
456
457
|
for (const [envVarName, envVarValue] of Object.entries(val)) {
|
|
457
458
|
if (!isString(envVarValue)) errors.push({
|
|
458
|
-
topic:
|
|
459
|
+
topic: ConfigValidationTopic.Error,
|
|
459
460
|
message: `Invalid env variable value: \`${currentPath}.${envVarName}\` must be a string.`
|
|
460
461
|
});
|
|
461
462
|
if (!matchRegexOrGlobList(envVarName, allowedEnvVars)) errors.push({
|
|
462
|
-
topic:
|
|
463
|
+
topic: ConfigValidationTopic.Error,
|
|
463
464
|
message: `Env variable name \`${envVarName}\` is not allowed by this bot's \`allowedEnv\`.`
|
|
464
465
|
});
|
|
465
466
|
}
|
|
466
467
|
} else if (key === "statusCheckNames") for (const [statusCheckKey, statusCheckValue] of Object.entries(val)) {
|
|
467
468
|
if (!allowedStatusCheckStrings.includes(statusCheckKey)) errors.push({
|
|
468
|
-
topic:
|
|
469
|
+
topic: ConfigValidationTopic.Error,
|
|
469
470
|
message: `Invalid \`${currentPath}.${key}.${statusCheckKey}\` configuration: key is not allowed.`
|
|
470
471
|
});
|
|
471
472
|
if (!(isString(statusCheckValue) || null === statusCheckValue)) {
|
|
472
473
|
errors.push({
|
|
473
|
-
topic:
|
|
474
|
+
topic: ConfigValidationTopic.Error,
|
|
474
475
|
message: `Invalid \`${currentPath}.${statusCheckKey}\` configuration: status check is not a string.`
|
|
475
476
|
});
|
|
476
477
|
continue;
|
|
@@ -484,12 +485,12 @@ async function validateConfig(configType, config, isPreset, parentPath) {
|
|
|
484
485
|
];
|
|
485
486
|
for (const [statusCheckKey, statusCheckValue] of Object.entries(val)) {
|
|
486
487
|
if (!allowedStatusCheckStrings.includes(statusCheckKey)) errors.push({
|
|
487
|
-
topic:
|
|
488
|
+
topic: ConfigValidationTopic.Error,
|
|
488
489
|
message: `Invalid \`${currentPath}.${key}.${statusCheckKey}\` configuration: key is not allowed.`
|
|
489
490
|
});
|
|
490
491
|
if (!isString(statusCheckValue) || !allowedWhenValues.includes(statusCheckValue)) {
|
|
491
492
|
errors.push({
|
|
492
|
-
topic:
|
|
493
|
+
topic: ConfigValidationTopic.Error,
|
|
493
494
|
message: `Invalid \`${currentPath}.${statusCheckKey}\` configuration: value must be one of "always", "never", or "failed".`
|
|
494
495
|
});
|
|
495
496
|
continue;
|
|
@@ -505,33 +506,33 @@ async function validateConfig(configType, config, isPreset, parentPath) {
|
|
|
505
506
|
for (const [customDatasourceName, customDatasourceValue] of Object.entries(val)) {
|
|
506
507
|
if (!isPlainObject(customDatasourceValue)) {
|
|
507
508
|
errors.push({
|
|
508
|
-
topic:
|
|
509
|
+
topic: ConfigValidationTopic.Error,
|
|
509
510
|
message: `Invalid \`${currentPath}.${customDatasourceName}\` configuration: customDatasource is not an object`
|
|
510
511
|
});
|
|
511
512
|
continue;
|
|
512
513
|
}
|
|
513
514
|
for (const [subKey, subValue] of Object.entries(customDatasourceValue)) if (!allowedKeys.includes(subKey)) errors.push({
|
|
514
|
-
topic:
|
|
515
|
+
topic: ConfigValidationTopic.Error,
|
|
515
516
|
message: `Invalid \`${currentPath}.${subKey}\` configuration: key is not allowed`
|
|
516
517
|
});
|
|
517
518
|
else if (subKey === "transformTemplates") {
|
|
518
519
|
if (!isArray(subValue, isString)) errors.push({
|
|
519
|
-
topic:
|
|
520
|
+
topic: ConfigValidationTopic.Error,
|
|
520
521
|
message: `Invalid \`${currentPath}.${subKey}\` configuration: is not an array of string`
|
|
521
522
|
});
|
|
522
523
|
} else if (subKey === "description") {
|
|
523
524
|
if (!(isString(subValue) || isArray(subValue, isString))) errors.push({
|
|
524
|
-
topic:
|
|
525
|
+
topic: ConfigValidationTopic.Error,
|
|
525
526
|
message: `Invalid \`${currentPath}.${subKey}\` configuration: is not an array of strings`
|
|
526
527
|
});
|
|
527
528
|
} else if (!isString(subValue)) errors.push({
|
|
528
|
-
topic:
|
|
529
|
+
topic: ConfigValidationTopic.Error,
|
|
529
530
|
message: `Invalid \`${currentPath}.${subKey}\` configuration: is a string`
|
|
530
531
|
});
|
|
531
532
|
}
|
|
532
533
|
} else if (key === "installTools") {
|
|
533
534
|
for (const toolName of Object.keys(val)) if (!isToolName(toolName)) warnings.push({
|
|
534
|
-
topic:
|
|
535
|
+
topic: ConfigValidationTopic.Error,
|
|
535
536
|
message: `Invalid \`${currentPath}.${toolName}\` configuration: not a valid tool name.`
|
|
536
537
|
});
|
|
537
538
|
} else if (key === "constraints") {
|
|
@@ -539,19 +540,19 @@ async function validateConfig(configType, config, isPreset, parentPath) {
|
|
|
539
540
|
for (const [k, v] of Object.entries(val)) {
|
|
540
541
|
if (!isString(v)) {
|
|
541
542
|
errors.push({
|
|
542
|
-
topic:
|
|
543
|
+
topic: ConfigValidationTopic.Error,
|
|
543
544
|
message: `Configuration option \`${currentPath}.${k}\` should be an object of key-value pairs of constraints and their value`
|
|
544
545
|
});
|
|
545
546
|
break;
|
|
546
547
|
}
|
|
547
548
|
if (!isConstraintName(k)) warnings.push({
|
|
548
|
-
topic:
|
|
549
|
+
topic: ConfigValidationTopic.Error,
|
|
549
550
|
message: `Configuration option \`${currentPath}.${k}\`: \`${k}\` is not a supported constraint name`
|
|
550
551
|
});
|
|
551
552
|
else if (isToolName(k)) {
|
|
552
553
|
const versioningId = getToolConfig(k).versioning;
|
|
553
554
|
if (!getVersioning(versioningId).isValid(v)) warnings.push({
|
|
554
|
-
topic:
|
|
555
|
+
topic: ConfigValidationTopic.Error,
|
|
555
556
|
message: `Configuration option \`${currentPath}.${k}=${v}\` is not a valid tool version constraint, according to \`${versioningId}\` versioning`
|
|
556
557
|
});
|
|
557
558
|
}
|
|
@@ -559,23 +560,23 @@ async function validateConfig(configType, config, isPreset, parentPath) {
|
|
|
559
560
|
} else if (key === "constraintsVersioning") for (const [k, v] of Object.entries(val)) {
|
|
560
561
|
if (!isString(v)) {
|
|
561
562
|
errors.push({
|
|
562
|
-
topic:
|
|
563
|
+
topic: ConfigValidationTopic.Error,
|
|
563
564
|
message: `Configuration option \`${currentPath}.${k}\` should be an object of key-value pairs of additional constraint names and their versioning`
|
|
564
565
|
});
|
|
565
566
|
break;
|
|
566
567
|
}
|
|
567
568
|
if (isToolName(k)) errors.push({
|
|
568
|
-
topic:
|
|
569
|
+
topic: ConfigValidationTopic.Error,
|
|
569
570
|
message: `Configuration option \`${currentPath}.${k}\` is not a valid additional constraint name, as \`${k}\` is a tool name, and \`constraintsVersioning\` can only override the versioning for a non-tool constraint`
|
|
570
571
|
});
|
|
571
572
|
else if (isConstraintName(k)) {
|
|
572
573
|
const versioningName = v.split(":")[0];
|
|
573
574
|
if (!AllVersioningsListLiteral.includes(versioningName)) errors.push({
|
|
574
|
-
topic:
|
|
575
|
+
topic: ConfigValidationTopic.Error,
|
|
575
576
|
message: `Configuration option \`${currentPath}.${k}=${v}\`: \`${v}\` is not a valid versioning scheme`
|
|
576
577
|
});
|
|
577
578
|
} else errors.push({
|
|
578
|
-
topic:
|
|
579
|
+
topic: ConfigValidationTopic.Error,
|
|
579
580
|
message: `Configuration option \`${currentPath}.${k}\`: \`${k}\` is not a known additional constraint name`
|
|
580
581
|
});
|
|
581
582
|
}
|
|
@@ -585,7 +586,7 @@ async function validateConfig(configType, config, isPreset, parentPath) {
|
|
|
585
586
|
errors = errors.concat(subValidation.errors);
|
|
586
587
|
}
|
|
587
588
|
} else errors.push({
|
|
588
|
-
topic:
|
|
589
|
+
topic: ConfigValidationTopic.Error,
|
|
589
590
|
message: `Configuration option \`${currentPath}\` should be a json object`
|
|
590
591
|
});
|
|
591
592
|
else
|
|
@@ -598,21 +599,21 @@ async function validateConfig(configType, config, isPreset, parentPath) {
|
|
|
598
599
|
for (const rule of val) {
|
|
599
600
|
if (isNonEmptyString(rule.matchHost)) {
|
|
600
601
|
if (rule.matchHost.includes("://") && parseUrl(rule.matchHost) === null) errors.push({
|
|
601
|
-
topic:
|
|
602
|
+
topic: ConfigValidationTopic.Error,
|
|
602
603
|
message: `hostRules matchHost \`${rule.matchHost}\` is not a valid URL.`
|
|
603
604
|
});
|
|
604
605
|
} else if (isEmptyString(rule.matchHost)) errors.push({
|
|
605
|
-
topic:
|
|
606
|
+
topic: ConfigValidationTopic.Error,
|
|
606
607
|
message: "Invalid value for hostRules matchHost. It cannot be an empty string."
|
|
607
608
|
});
|
|
608
609
|
if (!rule.headers) continue;
|
|
609
610
|
for (const [header, value] of Object.entries(rule.headers)) {
|
|
610
611
|
if (!isString(value)) errors.push({
|
|
611
|
-
topic:
|
|
612
|
+
topic: ConfigValidationTopic.Error,
|
|
612
613
|
message: `Invalid hostRules headers value configuration: header must be a string.`
|
|
613
614
|
});
|
|
614
615
|
if (!matchRegexOrGlobList(header, allowedHeaders)) errors.push({
|
|
615
|
-
topic:
|
|
616
|
+
topic: ConfigValidationTopic.Error,
|
|
616
617
|
message: `hostRules header \`${header}\` is not allowed by this bot's \`allowedHeaders\`.`
|
|
617
618
|
});
|
|
618
619
|
}
|
|
@@ -621,7 +622,7 @@ async function validateConfig(configType, config, isPreset, parentPath) {
|
|
|
621
622
|
if (key === "matchJsonata" && isArray(val, isString)) for (const expression of val) {
|
|
622
623
|
const res = getExpression(expression);
|
|
623
624
|
if (res instanceof Error) errors.push({
|
|
624
|
-
topic:
|
|
625
|
+
topic: ConfigValidationTopic.Error,
|
|
625
626
|
message: `Invalid JSONata expression for ${currentPath}: ${res.message}`
|
|
626
627
|
});
|
|
627
628
|
}
|
|
@@ -644,11 +645,11 @@ async function validateConfig(configType, config, isPreset, parentPath) {
|
|
|
644
645
|
async function validateGlobalConfig(key, val, type, warnings, errors, currentPath, config) {
|
|
645
646
|
/* v8 ignore next 5 -- not testable yet */
|
|
646
647
|
if (getDeprecationMessage(key)) warnings.push({
|
|
647
|
-
topic:
|
|
648
|
+
topic: ConfigValidationTopic.Deprecation,
|
|
648
649
|
message: getDeprecationMessage(key)
|
|
649
650
|
});
|
|
650
651
|
if (key === "binarySource" && val === "docker") warnings.push({
|
|
651
|
-
topic:
|
|
652
|
+
topic: ConfigValidationTopic.Deprecation,
|
|
652
653
|
message: "Usage of `binarySource=docker` is deprecated, and will be removed in the future. Please migrate to `binarySource=install`. Feedback on the usage of `binarySource=docker` is welcome at https://github.com/renovatebot/renovate/discussions/40742"
|
|
653
654
|
});
|
|
654
655
|
if (val !== null) {
|
|
@@ -658,7 +659,7 @@ async function validateGlobalConfig(key, val, type, warnings, errors, currentPat
|
|
|
658
659
|
configFileNames: config.configFileNames,
|
|
659
660
|
platform: config.platform
|
|
660
661
|
}).includes(val)) warnings.push({
|
|
661
|
-
topic:
|
|
662
|
+
topic: ConfigValidationTopic.Error,
|
|
662
663
|
message: `Invalid value \`${val}\` for \`${currentPath}\`. The allowed values are ${getPossibleConfigFileNames({
|
|
663
664
|
configFileNames: config.configFileNames,
|
|
664
665
|
platform: config.platform
|
|
@@ -669,7 +670,7 @@ async function validateGlobalConfig(key, val, type, warnings, errors, currentPat
|
|
|
669
670
|
"disabled",
|
|
670
671
|
"reset"
|
|
671
672
|
].includes(val)) warnings.push({
|
|
672
|
-
topic:
|
|
673
|
+
topic: ConfigValidationTopic.Error,
|
|
673
674
|
message: `Invalid value \`${val}\` for \`${currentPath}\`. The allowed values are ${[
|
|
674
675
|
"enabled",
|
|
675
676
|
"disabled",
|
|
@@ -681,7 +682,7 @@ async function validateGlobalConfig(key, val, type, warnings, errors, currentPat
|
|
|
681
682
|
"lookup",
|
|
682
683
|
"full"
|
|
683
684
|
].includes(val)) warnings.push({
|
|
684
|
-
topic:
|
|
685
|
+
topic: ConfigValidationTopic.Error,
|
|
685
686
|
message: `Invalid value \`${val}\` for \`${currentPath}\`. The allowed values are ${[
|
|
686
687
|
"extract",
|
|
687
688
|
"lookup",
|
|
@@ -694,7 +695,7 @@ async function validateGlobalConfig(key, val, type, warnings, errors, currentPat
|
|
|
694
695
|
"install",
|
|
695
696
|
"hermit"
|
|
696
697
|
].includes(val)) warnings.push({
|
|
697
|
-
topic:
|
|
698
|
+
topic: ConfigValidationTopic.Error,
|
|
698
699
|
message: `Invalid value \`${val}\` for \`${currentPath}\`. The allowed values are ${[
|
|
699
700
|
"docker",
|
|
700
701
|
"global",
|
|
@@ -707,7 +708,7 @@ async function validateGlobalConfig(key, val, type, warnings, errors, currentPat
|
|
|
707
708
|
"optional",
|
|
708
709
|
"ignored"
|
|
709
710
|
].includes(val)) warnings.push({
|
|
710
|
-
topic:
|
|
711
|
+
topic: ConfigValidationTopic.Error,
|
|
711
712
|
message: `Invalid value \`${val}\` for \`${currentPath}\`. The allowed values are ${[
|
|
712
713
|
"required",
|
|
713
714
|
"optional",
|
|
@@ -719,7 +720,7 @@ async function validateGlobalConfig(key, val, type, warnings, errors, currentPat
|
|
|
719
720
|
"ssh",
|
|
720
721
|
"endpoint"
|
|
721
722
|
].includes(val)) warnings.push({
|
|
722
|
-
topic:
|
|
723
|
+
topic: ConfigValidationTopic.Error,
|
|
723
724
|
message: `Invalid value \`${val}\` for \`${currentPath}\`. The allowed values are ${[
|
|
724
725
|
"default",
|
|
725
726
|
"ssh",
|
|
@@ -727,11 +728,11 @@ async function validateGlobalConfig(key, val, type, warnings, errors, currentPat
|
|
|
727
728
|
].join(", ")}.`
|
|
728
729
|
});
|
|
729
730
|
if (key === "reportType" && ["s3", "file"].includes(val) && !isString(config.reportPath)) errors.push({
|
|
730
|
-
topic:
|
|
731
|
+
topic: ConfigValidationTopic.Error,
|
|
731
732
|
message: `reportType '${val}' requires a configured reportPath`
|
|
732
733
|
});
|
|
733
734
|
} else warnings.push({
|
|
734
|
-
topic:
|
|
735
|
+
topic: ConfigValidationTopic.Error,
|
|
735
736
|
message: `Configuration option \`${currentPath}\` should be a string.`
|
|
736
737
|
});
|
|
737
738
|
else if (type === "integer") {
|
|
@@ -739,7 +740,7 @@ async function validateGlobalConfig(key, val, type, warnings, errors, currentPat
|
|
|
739
740
|
warnings.push(...validateNumber(key, val, allowsNegative, currentPath));
|
|
740
741
|
} else if (type === "boolean") {
|
|
741
742
|
if (val !== true && val !== false) warnings.push({
|
|
742
|
-
topic:
|
|
743
|
+
topic: ConfigValidationTopic.Error,
|
|
743
744
|
message: `Configuration option \`${currentPath}\` should be a boolean. Found: ${JSON.stringify(val)} (${typeof val}).`
|
|
744
745
|
});
|
|
745
746
|
} else if (type === "array") if (isArray(val) && key !== "repositories") {
|
|
@@ -757,7 +758,7 @@ async function validateGlobalConfig(key, val, type, warnings, errors, currentPat
|
|
|
757
758
|
for (const value of val)
|
|
758
759
|
// v8 ignore else -- TODO: add test #40625
|
|
759
760
|
if (!allowedValues.includes(value)) warnings.push({
|
|
760
|
-
topic:
|
|
761
|
+
topic: ConfigValidationTopic.Error,
|
|
761
762
|
message: `Invalid value for \`${currentPath}\`. The allowed values are ${allowedValues.join(", ")}.`
|
|
762
763
|
});
|
|
763
764
|
}
|
|
@@ -766,13 +767,13 @@ async function validateGlobalConfig(key, val, type, warnings, errors, currentPat
|
|
|
766
767
|
for (const value of val)
|
|
767
768
|
// v8 ignore else -- TODO: add test #40625
|
|
768
769
|
if (!allowedValues.includes(value)) warnings.push({
|
|
769
|
-
topic:
|
|
770
|
+
topic: ConfigValidationTopic.Error,
|
|
770
771
|
message: `Invalid value \`${value}\` for \`${currentPath}\`. The allowed values are ${allowedValues.join(", ")}.`
|
|
771
772
|
});
|
|
772
773
|
}
|
|
773
774
|
} else if (isArray(val)) for (const [subIndex, subval] of val.entries()) if (isPlainObject(subval)) {
|
|
774
775
|
if (!isNonEmptyString(subval.repository)) errors.push({
|
|
775
|
-
topic:
|
|
776
|
+
topic: ConfigValidationTopic.Error,
|
|
776
777
|
message: `${currentPath}[${subIndex}]: each repository object entry must have a \`repository\` string property`
|
|
777
778
|
});
|
|
778
779
|
const { repository: _, ...repoEntryConfig } = subval;
|
|
@@ -785,15 +786,15 @@ async function validateGlobalConfig(key, val, type, warnings, errors, currentPat
|
|
|
785
786
|
errors.push(...subValidation.errors);
|
|
786
787
|
} else if (isString(subval)) {
|
|
787
788
|
if (!isNonEmptyStringAndNotWhitespace(subval)) warnings.push({
|
|
788
|
-
topic:
|
|
789
|
+
topic: ConfigValidationTopic.Error,
|
|
789
790
|
message: `${currentPath}[${subIndex}]: each repository string entry entry must be a non-empty string`
|
|
790
791
|
});
|
|
791
792
|
} else warnings.push({
|
|
792
|
-
topic:
|
|
793
|
+
topic: ConfigValidationTopic.Error,
|
|
793
794
|
message: `${currentPath}[${subIndex}]: invalid type, should be either a string or an object`
|
|
794
795
|
});
|
|
795
796
|
else warnings.push({
|
|
796
|
-
topic:
|
|
797
|
+
topic: ConfigValidationTopic.Error,
|
|
797
798
|
message: `Configuration option \`${currentPath}\` should be a list (Array).`
|
|
798
799
|
});
|
|
799
800
|
else if (type === "object") if (isPlainObject(val)) if (key === "onboardingConfig") {
|
|
@@ -807,18 +808,18 @@ async function validateGlobalConfig(key, val, type, warnings, errors, currentPat
|
|
|
807
808
|
warnings.push(...validateNumber(key, subValue, allowsNegative, currentPath, subKey));
|
|
808
809
|
if (!packageCacheNamespaces.includes(subKey) && !anyMatchRegexOrGlobList(packageCacheNamespaces, [subKey])) errors.push({
|
|
809
810
|
message: `${currentPath}: namespace \`${subKey}\` does not exist`,
|
|
810
|
-
topic:
|
|
811
|
+
topic: ConfigValidationTopic.Error
|
|
811
812
|
});
|
|
812
813
|
}
|
|
813
814
|
else {
|
|
814
815
|
const res = validatePlainObject(val);
|
|
815
816
|
if (res !== true) warnings.push({
|
|
816
|
-
topic:
|
|
817
|
+
topic: ConfigValidationTopic.Error,
|
|
817
818
|
message: `Invalid \`${currentPath}.${res}\` configuration: value must be a string.`
|
|
818
819
|
});
|
|
819
820
|
}
|
|
820
821
|
else warnings.push({
|
|
821
|
-
topic:
|
|
822
|
+
topic: ConfigValidationTopic.Error,
|
|
822
823
|
message: `Configuration option \`${currentPath}\` should be a JSON object.`
|
|
823
824
|
});
|
|
824
825
|
}
|