2020-03-05 20:57:24 +00:00
|
|
|
import * as configValidation from './validation';
|
|
|
|
import { RenovateConfig } from '.';
|
2017-07-28 19:15:27 +00:00
|
|
|
|
|
|
|
describe('config/validation', () => {
|
|
|
|
describe('validateConfig(config)', () => {
|
2018-04-17 06:39:26 +00:00
|
|
|
it('returns deprecation warnings', async () => {
|
|
|
|
const config = {
|
|
|
|
prTitle: 'something',
|
|
|
|
};
|
|
|
|
const { warnings } = await configValidation.validateConfig(config);
|
|
|
|
expect(warnings).toHaveLength(1);
|
|
|
|
expect(warnings).toMatchSnapshot();
|
|
|
|
});
|
2020-04-05 08:09:55 +00:00
|
|
|
it('catches invalid templates', async () => {
|
2020-01-27 11:48:08 +00:00
|
|
|
const config = {
|
|
|
|
commitMessage: '{{{something}}',
|
|
|
|
};
|
|
|
|
const { errors } = await configValidation.validateConfig(config);
|
|
|
|
expect(errors).toHaveLength(1);
|
|
|
|
expect(errors).toMatchSnapshot();
|
|
|
|
});
|
2020-04-15 20:07:53 +00:00
|
|
|
it('catches invalid allowedVersions regex', async () => {
|
|
|
|
const config = {
|
|
|
|
packageRules: [
|
|
|
|
{
|
|
|
|
packageNames: ['foo'],
|
|
|
|
allowedVersions: '/^2/',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
packageNames: ['bar'],
|
|
|
|
allowedVersions: '/***$}{]][/',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
packageNames: ['baz'],
|
|
|
|
allowedVersions: '!/^2/',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
packageNames: ['quack'],
|
|
|
|
allowedVersions: '!/***$}{]][/',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
const { errors } = await configValidation.validateConfig(config);
|
|
|
|
expect(errors).toHaveLength(2);
|
|
|
|
expect(errors).toMatchSnapshot();
|
|
|
|
});
|
2018-03-28 08:04:07 +00:00
|
|
|
it('returns nested errors', async () => {
|
2020-03-07 10:27:10 +00:00
|
|
|
const config: RenovateConfig = {
|
2017-07-28 19:15:27 +00:00
|
|
|
foo: 1,
|
2017-08-02 14:14:09 +00:00
|
|
|
schedule: ['after 5pm'],
|
2018-03-12 03:24:45 +00:00
|
|
|
timezone: 'Asia/Singapore',
|
2018-04-11 20:08:48 +00:00
|
|
|
packageRules: [
|
|
|
|
{
|
|
|
|
packagePatterns: ['*'],
|
2019-10-22 06:48:40 +00:00
|
|
|
excludePackagePatterns: ['abc ([a-z]+) ([a-z]+))'],
|
2018-04-11 20:08:48 +00:00
|
|
|
},
|
|
|
|
],
|
2017-07-28 19:15:27 +00:00
|
|
|
lockFileMaintenance: {
|
|
|
|
bar: 2,
|
|
|
|
},
|
2020-03-07 10:27:10 +00:00
|
|
|
major: null,
|
2017-07-28 19:15:27 +00:00
|
|
|
};
|
2018-03-28 08:04:07 +00:00
|
|
|
const { warnings, errors } = await configValidation.validateConfig(
|
|
|
|
config
|
|
|
|
);
|
2017-07-31 12:50:44 +00:00
|
|
|
expect(warnings).toHaveLength(0);
|
2018-04-13 04:52:08 +00:00
|
|
|
expect(errors).toHaveLength(3);
|
2017-07-28 19:15:27 +00:00
|
|
|
expect(errors).toMatchSnapshot();
|
|
|
|
});
|
2019-02-20 21:29:38 +00:00
|
|
|
it('included unsupported manager', async () => {
|
|
|
|
const config = {
|
|
|
|
packageRules: [
|
|
|
|
{
|
|
|
|
managers: ['foo'],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
const { warnings, errors } = await configValidation.validateConfig(
|
|
|
|
config
|
|
|
|
);
|
|
|
|
expect(warnings).toHaveLength(0);
|
|
|
|
expect(errors).toHaveLength(1);
|
2020-05-18 12:33:44 +00:00
|
|
|
expect(errors[0].message).toContain('ansible');
|
2019-02-20 21:29:38 +00:00
|
|
|
});
|
|
|
|
it('included managers of the wrong type', async () => {
|
|
|
|
const config = {
|
|
|
|
packageRules: [
|
|
|
|
{
|
|
|
|
managers: 'string not an array',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
const { warnings, errors } = await configValidation.validateConfig(
|
|
|
|
config
|
|
|
|
);
|
|
|
|
expect(warnings).toHaveLength(0);
|
|
|
|
expect(errors).toHaveLength(2);
|
|
|
|
expect(errors).toMatchSnapshot();
|
|
|
|
});
|
2018-03-28 08:04:07 +00:00
|
|
|
it('errors for all types', async () => {
|
2019-08-23 13:46:31 +00:00
|
|
|
const config: RenovateConfig = {
|
2018-03-02 22:10:42 +00:00
|
|
|
allowedVersions: 'foo',
|
2019-08-23 13:46:31 +00:00
|
|
|
enabled: 1 as any,
|
2017-08-14 09:09:14 +00:00
|
|
|
schedule: ['every 15 mins every weekday'],
|
2018-03-12 03:24:45 +00:00
|
|
|
timezone: 'Asia',
|
2019-10-04 07:36:07 +00:00
|
|
|
labels: 5 as any,
|
2019-08-23 13:46:31 +00:00
|
|
|
semanticCommitType: 7 as any,
|
|
|
|
lockFileMaintenance: false as any,
|
2018-03-13 20:47:08 +00:00
|
|
|
extends: [':timezone(Europe/Brussel)'],
|
2017-08-03 05:55:59 +00:00
|
|
|
packageRules: [
|
2018-03-28 08:04:07 +00:00
|
|
|
{
|
|
|
|
excludePackageNames: ['foo'],
|
|
|
|
enabled: true,
|
|
|
|
},
|
2017-08-02 05:52:28 +00:00
|
|
|
{
|
|
|
|
foo: 1,
|
|
|
|
},
|
2019-08-23 13:46:31 +00:00
|
|
|
'what?' as any,
|
2018-04-11 19:54:16 +00:00
|
|
|
{
|
|
|
|
packagePatterns: 'abc ([a-z]+) ([a-z]+))',
|
|
|
|
excludePackagePatterns: ['abc ([a-z]+) ([a-z]+))'],
|
|
|
|
enabled: false,
|
|
|
|
},
|
2017-08-02 05:52:28 +00:00
|
|
|
],
|
2020-03-07 10:27:10 +00:00
|
|
|
major: null,
|
2017-07-28 19:15:27 +00:00
|
|
|
};
|
2018-03-28 08:04:07 +00:00
|
|
|
const { warnings, errors } = await configValidation.validateConfig(
|
|
|
|
config
|
|
|
|
);
|
2018-03-28 13:13:32 +00:00
|
|
|
expect(warnings).toHaveLength(0);
|
2017-07-28 19:15:27 +00:00
|
|
|
expect(errors).toMatchSnapshot();
|
2018-05-27 14:54:11 +00:00
|
|
|
expect(errors).toHaveLength(12);
|
2018-04-12 10:13:39 +00:00
|
|
|
});
|
|
|
|
it('selectors outside packageRules array trigger errors', async () => {
|
|
|
|
const config = {
|
|
|
|
packageNames: ['angular'],
|
|
|
|
meteor: {
|
|
|
|
packageRules: [
|
|
|
|
{
|
|
|
|
packageNames: ['meteor'],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
docker: {
|
|
|
|
minor: {
|
|
|
|
packageNames: ['testPackage'],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
const { warnings, errors } = await configValidation.validateConfig(
|
|
|
|
config
|
|
|
|
);
|
|
|
|
expect(warnings).toHaveLength(0);
|
|
|
|
expect(errors).toMatchSnapshot();
|
|
|
|
expect(errors).toHaveLength(2);
|
|
|
|
});
|
|
|
|
it('ignore packageRule nesting validation for presets', async () => {
|
|
|
|
const config = {
|
|
|
|
description: ['All angular.js packages'],
|
|
|
|
packageNames: [
|
|
|
|
'angular',
|
|
|
|
'angular-animate',
|
|
|
|
'angular-scroll',
|
|
|
|
'angular-sanitize',
|
|
|
|
],
|
|
|
|
};
|
|
|
|
const { warnings, errors } = await configValidation.validateConfig(
|
|
|
|
config,
|
|
|
|
true
|
|
|
|
);
|
|
|
|
expect(warnings).toHaveLength(0);
|
2018-04-11 20:08:48 +00:00
|
|
|
expect(errors).toMatchSnapshot();
|
2018-04-12 10:13:39 +00:00
|
|
|
expect(errors).toHaveLength(0);
|
2017-07-28 19:15:27 +00:00
|
|
|
});
|
2019-10-22 06:48:40 +00:00
|
|
|
|
2018-04-30 11:18:51 +00:00
|
|
|
it('errors for unsafe fileMatches', async () => {
|
|
|
|
const config = {
|
|
|
|
npm: {
|
|
|
|
fileMatch: ['abc ([a-z]+) ([a-z]+))'],
|
|
|
|
},
|
2020-10-18 05:56:16 +00:00
|
|
|
dockerfile: {
|
2019-10-22 06:48:40 +00:00
|
|
|
fileMatch: ['x?+'],
|
2018-04-30 11:18:51 +00:00
|
|
|
},
|
|
|
|
};
|
|
|
|
const { warnings, errors } = await configValidation.validateConfig(
|
|
|
|
config
|
|
|
|
);
|
|
|
|
expect(warnings).toHaveLength(0);
|
2019-10-15 08:14:49 +00:00
|
|
|
expect(errors).toHaveLength(2);
|
2018-04-30 11:18:51 +00:00
|
|
|
expect(errors).toMatchSnapshot();
|
|
|
|
});
|
2019-10-22 06:48:40 +00:00
|
|
|
|
|
|
|
it('validates regEx for each fileMatch', async () => {
|
|
|
|
const config = {
|
2020-10-18 05:56:16 +00:00
|
|
|
regexManagers: [
|
|
|
|
{
|
|
|
|
fileMatch: ['js', '***$}{]]['],
|
|
|
|
matchStrings: ['^(?<depName>foo)(?<currentValue>bar)$'],
|
|
|
|
datasourceTemplate: 'maven',
|
|
|
|
versioningTemplate: 'gradle',
|
|
|
|
},
|
|
|
|
],
|
2019-10-22 06:48:40 +00:00
|
|
|
};
|
|
|
|
const { warnings, errors } = await configValidation.validateConfig(
|
|
|
|
config,
|
|
|
|
true
|
|
|
|
);
|
|
|
|
expect(warnings).toHaveLength(0);
|
|
|
|
expect(errors).toHaveLength(1);
|
2020-10-18 05:56:16 +00:00
|
|
|
expect(errors).toMatchSnapshot();
|
2019-10-22 06:48:40 +00:00
|
|
|
});
|
2020-03-06 08:07:55 +00:00
|
|
|
it('errors if no regexManager matchStrings', async () => {
|
|
|
|
const config = {
|
|
|
|
regexManagers: [
|
|
|
|
{
|
2020-05-03 14:57:17 +00:00
|
|
|
fileMatch: [],
|
2020-03-06 08:07:55 +00:00
|
|
|
matchStrings: [],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
const { warnings, errors } = await configValidation.validateConfig(
|
|
|
|
config,
|
|
|
|
true
|
|
|
|
);
|
|
|
|
expect(warnings).toHaveLength(0);
|
|
|
|
expect(errors).toHaveLength(1);
|
|
|
|
});
|
2020-10-19 07:33:54 +00:00
|
|
|
it('errors if no regexManager fileMatch', async () => {
|
|
|
|
const config = {
|
|
|
|
regexManagers: [
|
|
|
|
{
|
|
|
|
matchStrings: ['^(?<depName>foo)(?<currentValue>bar)$'],
|
|
|
|
datasourceTemplate: 'maven',
|
|
|
|
versioningTemplate: 'gradle',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
const { warnings, errors } = await configValidation.validateConfig(
|
|
|
|
config as any,
|
|
|
|
true
|
|
|
|
);
|
|
|
|
expect(warnings).toHaveLength(0);
|
|
|
|
expect(errors).toHaveLength(1);
|
|
|
|
});
|
2020-03-06 08:07:55 +00:00
|
|
|
it('validates regEx for each matchStrings', async () => {
|
|
|
|
const config = {
|
|
|
|
regexManagers: [
|
|
|
|
{
|
2020-05-03 14:57:17 +00:00
|
|
|
fileMatch: ['Dockerfile'],
|
2020-03-06 08:07:55 +00:00
|
|
|
matchStrings: ['***$}{]]['],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
const { warnings, errors } = await configValidation.validateConfig(
|
|
|
|
config,
|
|
|
|
true
|
|
|
|
);
|
|
|
|
expect(warnings).toHaveLength(0);
|
|
|
|
expect(errors).toHaveLength(1);
|
|
|
|
});
|
|
|
|
it('passes if regexManager fields are present', async () => {
|
|
|
|
const config = {
|
|
|
|
regexManagers: [
|
|
|
|
{
|
2020-05-03 14:57:17 +00:00
|
|
|
fileMatch: ['Dockerfile'],
|
2020-03-06 08:07:55 +00:00
|
|
|
matchStrings: ['ENV (?<currentValue>.*?)\\s'],
|
|
|
|
depNameTemplate: 'foo',
|
|
|
|
datasourceTemplate: 'bar',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
const { warnings, errors } = await configValidation.validateConfig(
|
|
|
|
config,
|
|
|
|
true
|
|
|
|
);
|
|
|
|
expect(warnings).toHaveLength(0);
|
|
|
|
expect(errors).toHaveLength(0);
|
|
|
|
});
|
|
|
|
it('errors if extra regexManager fields are present', async () => {
|
|
|
|
const config = {
|
|
|
|
regexManagers: [
|
|
|
|
{
|
2020-05-03 14:57:17 +00:00
|
|
|
fileMatch: ['Dockerfile'],
|
2020-03-06 08:07:55 +00:00
|
|
|
matchStrings: ['ENV (?<currentValue>.*?)\\s'],
|
|
|
|
depNameTemplate: 'foo',
|
|
|
|
datasourceTemplate: 'bar',
|
|
|
|
automerge: true,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
const { warnings, errors } = await configValidation.validateConfig(
|
|
|
|
config,
|
|
|
|
true
|
|
|
|
);
|
|
|
|
expect(warnings).toHaveLength(0);
|
|
|
|
expect(errors).toHaveLength(1);
|
|
|
|
});
|
|
|
|
it('errors if regexManager fields are missing', async () => {
|
|
|
|
const config = {
|
|
|
|
regexManagers: [
|
|
|
|
{
|
2020-05-03 14:57:17 +00:00
|
|
|
fileMatch: ['Dockerfile'],
|
2020-03-06 08:07:55 +00:00
|
|
|
matchStrings: ['ENV (.*?)\\s'],
|
|
|
|
depNameTemplate: 'foo',
|
|
|
|
datasourceTemplate: 'bar',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
const { warnings, errors } = await configValidation.validateConfig(
|
|
|
|
config,
|
|
|
|
true
|
|
|
|
);
|
|
|
|
expect(warnings).toHaveLength(0);
|
|
|
|
expect(errors).toMatchSnapshot();
|
|
|
|
expect(errors).toHaveLength(1);
|
|
|
|
});
|
2020-03-07 10:27:10 +00:00
|
|
|
it('ignore keys', async () => {
|
|
|
|
const config = {
|
|
|
|
$schema: 'renovate.json',
|
|
|
|
};
|
|
|
|
const { warnings, errors } = await configValidation.validateConfig(
|
|
|
|
config,
|
|
|
|
true
|
|
|
|
);
|
|
|
|
expect(warnings).toHaveLength(0);
|
|
|
|
expect(errors).toHaveLength(0);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('validates timezone preset', async () => {
|
|
|
|
const config = {
|
|
|
|
extends: [':timezone', ':timezone(Europe/Berlin)'],
|
|
|
|
};
|
|
|
|
const { warnings, errors } = await configValidation.validateConfig(
|
|
|
|
config,
|
|
|
|
true
|
|
|
|
);
|
|
|
|
expect(warnings).toHaveLength(0);
|
|
|
|
expect(errors).toHaveLength(0);
|
|
|
|
});
|
|
|
|
|
2020-09-30 09:02:25 +00:00
|
|
|
it('does not validate constraints children', async () => {
|
2020-03-07 10:27:10 +00:00
|
|
|
const config = {
|
2020-09-30 09:02:25 +00:00
|
|
|
constraints: { packageRules: [{}] },
|
2020-03-07 10:27:10 +00:00
|
|
|
};
|
|
|
|
const { warnings, errors } = await configValidation.validateConfig(
|
|
|
|
config,
|
|
|
|
true
|
|
|
|
);
|
|
|
|
expect(warnings).toHaveLength(0);
|
|
|
|
expect(errors).toHaveLength(0);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('validates object with ignored children', async () => {
|
|
|
|
const config = {
|
|
|
|
prBodyDefinitions: {},
|
|
|
|
};
|
|
|
|
const { warnings, errors } = await configValidation.validateConfig(
|
|
|
|
config,
|
|
|
|
true
|
|
|
|
);
|
|
|
|
expect(warnings).toHaveLength(0);
|
|
|
|
expect(errors).toHaveLength(0);
|
|
|
|
});
|
2020-06-04 13:47:56 +00:00
|
|
|
|
|
|
|
it('validates valid alias objects', async () => {
|
|
|
|
const config = {
|
|
|
|
aliases: {
|
|
|
|
example1: 'http://www.example.com',
|
|
|
|
example2: 'https://www.example2.com/example',
|
|
|
|
},
|
|
|
|
};
|
|
|
|
const { warnings, errors } = await configValidation.validateConfig(
|
|
|
|
config
|
|
|
|
);
|
|
|
|
expect(warnings).toHaveLength(0);
|
|
|
|
expect(errors).toHaveLength(0);
|
|
|
|
expect(errors).toMatchSnapshot();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('errors if aliases depth is more than 1', async () => {
|
|
|
|
const config = {
|
|
|
|
aliases: {
|
|
|
|
sample: {
|
|
|
|
example1: 'http://www.example.com',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
const { warnings, errors } = await configValidation.validateConfig(
|
|
|
|
config
|
|
|
|
);
|
|
|
|
expect(warnings).toHaveLength(0);
|
|
|
|
expect(errors).toHaveLength(1);
|
|
|
|
expect(errors).toMatchSnapshot();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('errors if aliases have invalid url', async () => {
|
|
|
|
const config = {
|
|
|
|
aliases: {
|
|
|
|
example1: 'noturl',
|
|
|
|
example2: 'http://www.example.com',
|
|
|
|
},
|
|
|
|
};
|
|
|
|
const { warnings, errors } = await configValidation.validateConfig(
|
|
|
|
config
|
|
|
|
);
|
|
|
|
expect(warnings).toHaveLength(0);
|
|
|
|
expect(errors).toHaveLength(1);
|
|
|
|
expect(errors).toMatchSnapshot();
|
|
|
|
});
|
2020-10-18 05:56:16 +00:00
|
|
|
|
|
|
|
it('errors if fileMatch has wrong parent', async () => {
|
|
|
|
const config = {
|
|
|
|
fileMatch: ['foo'],
|
|
|
|
npm: {
|
|
|
|
fileMatch: ['package\\.json'],
|
|
|
|
gradle: {
|
|
|
|
fileMatch: ['bar'],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
regexManagers: [
|
|
|
|
{
|
|
|
|
fileMatch: ['build.gradle'],
|
|
|
|
matchStrings: ['^(?<depName>foo)(?<currentValue>bar)$'],
|
|
|
|
datasourceTemplate: 'maven',
|
|
|
|
versioningTemplate: 'gradle',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
const { warnings, errors } = await configValidation.validateConfig(
|
|
|
|
config
|
|
|
|
);
|
|
|
|
expect(errors).toHaveLength(1);
|
|
|
|
expect(warnings).toHaveLength(1);
|
|
|
|
expect(errors).toMatchSnapshot();
|
|
|
|
expect(warnings).toMatchSnapshot();
|
|
|
|
});
|
2020-10-27 15:39:11 +00:00
|
|
|
|
|
|
|
it('validates preset values', async () => {
|
|
|
|
const config = {
|
|
|
|
extends: ['foo', 'bar', 42] as never,
|
|
|
|
};
|
|
|
|
const { warnings, errors } = await configValidation.validateConfig(
|
|
|
|
config,
|
|
|
|
true
|
|
|
|
);
|
|
|
|
expect(warnings).toHaveLength(0);
|
|
|
|
expect(errors).toHaveLength(1);
|
|
|
|
});
|
2017-07-28 19:15:27 +00:00
|
|
|
});
|
|
|
|
});
|