2018-03-07 05:28:09 +00:00
|
|
|
#!/usr/bin/env node
|
2020-05-16 10:11:56 +00:00
|
|
|
// istanbul ignore file
|
2022-12-23 12:12:32 +00:00
|
|
|
import 'source-map-support/register';
|
2021-03-10 22:04:12 +00:00
|
|
|
import { dequal } from 'dequal';
|
2022-04-29 08:34:55 +00:00
|
|
|
import { pathExists, readFile } from 'fs-extra';
|
2020-05-16 10:11:56 +00:00
|
|
|
import { configFileNames } from './config/app-strings';
|
|
|
|
import { massageConfig } from './config/massage';
|
2021-02-03 09:35:30 +00:00
|
|
|
import { migrateConfig } from './config/migration';
|
2021-03-02 20:44:55 +00:00
|
|
|
import type { RenovateConfig } from './config/types';
|
2020-05-16 10:11:56 +00:00
|
|
|
import { validateConfig } from './config/validation';
|
2021-02-03 09:35:30 +00:00
|
|
|
import { logger } from './logger';
|
2021-12-09 12:45:48 +00:00
|
|
|
import {
|
|
|
|
getConfig as getFileConfig,
|
|
|
|
getParsedContent,
|
|
|
|
} from './workers/global/config/parse/file';
|
2018-04-12 09:52:52 +00:00
|
|
|
|
2018-03-07 05:10:17 +00:00
|
|
|
let returnVal = 0;
|
|
|
|
|
2020-05-16 10:11:56 +00:00
|
|
|
async function validate(
|
2024-03-13 05:11:40 +00:00
|
|
|
configType: 'global' | 'repo',
|
2020-05-16 10:11:56 +00:00
|
|
|
desc: string,
|
|
|
|
config: RenovateConfig,
|
2023-08-03 12:26:43 +00:00
|
|
|
strict: boolean,
|
2023-11-07 15:50:29 +00:00
|
|
|
isPreset = false,
|
2020-05-16 10:11:56 +00:00
|
|
|
): Promise<void> {
|
2021-02-03 09:35:30 +00:00
|
|
|
const { isMigrated, migratedConfig } = migrateConfig(config);
|
|
|
|
if (isMigrated) {
|
|
|
|
logger.warn(
|
|
|
|
{
|
|
|
|
oldConfig: config,
|
|
|
|
newConfig: migratedConfig,
|
|
|
|
},
|
2023-11-07 15:50:29 +00:00
|
|
|
'Config migration necessary',
|
2018-03-07 05:10:17 +00:00
|
|
|
);
|
2023-08-03 12:26:43 +00:00
|
|
|
if (strict) {
|
|
|
|
returnVal = 1;
|
|
|
|
}
|
2021-02-03 09:35:30 +00:00
|
|
|
}
|
|
|
|
const massagedConfig = massageConfig(migratedConfig);
|
2024-03-13 05:11:40 +00:00
|
|
|
const res = await validateConfig(configType, massagedConfig, isPreset);
|
2021-02-03 09:35:30 +00:00
|
|
|
if (res.errors.length) {
|
2023-06-24 09:32:50 +00:00
|
|
|
logger.error(
|
|
|
|
{ file: desc, errors: res.errors },
|
2023-11-07 15:50:29 +00:00
|
|
|
'Found errors in configuration',
|
2023-06-24 09:32:50 +00:00
|
|
|
);
|
2018-03-07 05:10:17 +00:00
|
|
|
returnVal = 1;
|
|
|
|
}
|
|
|
|
if (res.warnings.length) {
|
2023-06-24 09:32:50 +00:00
|
|
|
logger.warn(
|
|
|
|
{ file: desc, warnings: res.warnings },
|
2023-11-07 15:50:29 +00:00
|
|
|
'Found errors in configuration',
|
2023-06-24 09:32:50 +00:00
|
|
|
);
|
2018-03-07 05:10:17 +00:00
|
|
|
returnVal = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-16 10:11:56 +00:00
|
|
|
type PackageJson = {
|
|
|
|
renovate?: RenovateConfig;
|
|
|
|
'renovate-config'?: Record<string, RenovateConfig>;
|
|
|
|
};
|
|
|
|
|
2018-03-29 03:47:49 +00:00
|
|
|
(async () => {
|
2023-08-03 12:26:43 +00:00
|
|
|
const strictArgIndex = process.argv.indexOf('--strict');
|
|
|
|
const strict = strictArgIndex >= 0;
|
|
|
|
if (strict) {
|
2023-08-11 05:26:00 +00:00
|
|
|
process.argv.splice(strictArgIndex, 1);
|
2023-08-03 12:26:43 +00:00
|
|
|
}
|
2022-08-04 06:25:18 +00:00
|
|
|
if (process.argv.length > 2) {
|
|
|
|
for (const file of process.argv.slice(2)) {
|
2018-03-29 03:47:49 +00:00
|
|
|
try {
|
2022-08-04 06:25:18 +00:00
|
|
|
if (!(await pathExists(file))) {
|
|
|
|
returnVal = 1;
|
2023-06-24 09:32:50 +00:00
|
|
|
logger.error({ file }, 'File does not exist');
|
2022-08-04 06:25:18 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
const parsedContent = await getParsedContent(file);
|
|
|
|
try {
|
|
|
|
logger.info(`Validating ${file}`);
|
2024-03-13 05:11:40 +00:00
|
|
|
await validate('global', file, parsedContent, strict);
|
2022-08-04 06:25:18 +00:00
|
|
|
} catch (err) {
|
2023-06-24 09:32:50 +00:00
|
|
|
logger.warn({ file, err }, 'File is not valid Renovate config');
|
2022-08-04 06:25:18 +00:00
|
|
|
returnVal = 1;
|
|
|
|
}
|
2018-03-29 03:47:49 +00:00
|
|
|
} catch (err) {
|
2023-06-24 09:32:50 +00:00
|
|
|
logger.warn({ file, err }, 'File could not be parsed');
|
2018-03-29 03:47:49 +00:00
|
|
|
returnVal = 1;
|
|
|
|
}
|
|
|
|
}
|
2022-08-04 06:25:18 +00:00
|
|
|
} else {
|
|
|
|
for (const file of configFileNames.filter(
|
2023-11-07 15:50:29 +00:00
|
|
|
(name) => name !== 'package.json',
|
2022-08-04 06:25:18 +00:00
|
|
|
)) {
|
2021-02-03 09:35:30 +00:00
|
|
|
try {
|
2022-08-04 06:25:18 +00:00
|
|
|
if (!(await pathExists(file))) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const parsedContent = await getParsedContent(file);
|
|
|
|
try {
|
|
|
|
logger.info(`Validating ${file}`);
|
2024-03-13 05:11:40 +00:00
|
|
|
await validate('repo', file, parsedContent, strict);
|
2022-08-04 06:25:18 +00:00
|
|
|
} catch (err) {
|
2023-06-24 09:32:50 +00:00
|
|
|
logger.warn({ file, err }, 'File is not valid Renovate config');
|
2022-08-04 06:25:18 +00:00
|
|
|
returnVal = 1;
|
|
|
|
}
|
2021-02-03 09:35:30 +00:00
|
|
|
} catch (err) {
|
2023-06-24 09:32:50 +00:00
|
|
|
logger.warn({ file, err }, 'File could not be parsed');
|
2021-02-03 09:35:30 +00:00
|
|
|
returnVal = 1;
|
|
|
|
}
|
2019-03-16 06:03:32 +00:00
|
|
|
}
|
2022-08-04 06:25:18 +00:00
|
|
|
try {
|
|
|
|
const pkgJson = JSON.parse(
|
2023-11-07 15:50:29 +00:00
|
|
|
await readFile('package.json', 'utf8'),
|
2022-08-04 06:25:18 +00:00
|
|
|
) as PackageJson;
|
|
|
|
if (pkgJson.renovate) {
|
|
|
|
logger.info(`Validating package.json > renovate`);
|
2024-01-16 10:42:26 +00:00
|
|
|
await validate(
|
2024-03-13 05:11:40 +00:00
|
|
|
'repo',
|
2024-01-16 10:42:26 +00:00
|
|
|
'package.json > renovate',
|
|
|
|
pkgJson.renovate,
|
|
|
|
strict,
|
|
|
|
);
|
2022-08-04 06:25:18 +00:00
|
|
|
}
|
|
|
|
if (pkgJson['renovate-config']) {
|
|
|
|
logger.info(`Validating package.json > renovate-config`);
|
|
|
|
for (const presetConfig of Object.values(pkgJson['renovate-config'])) {
|
2023-08-03 12:26:43 +00:00
|
|
|
await validate(
|
2024-03-13 05:11:40 +00:00
|
|
|
'repo',
|
2023-08-03 12:26:43 +00:00
|
|
|
'package.json > renovate-config',
|
|
|
|
presetConfig,
|
|
|
|
strict,
|
2023-11-07 15:50:29 +00:00
|
|
|
true,
|
2023-08-03 12:26:43 +00:00
|
|
|
);
|
2022-08-04 06:25:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
// ignore
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
const fileConfig = await getFileConfig(process.env);
|
|
|
|
if (!dequal(fileConfig, {})) {
|
|
|
|
const file = process.env.RENOVATE_CONFIG_FILE ?? 'config.js';
|
|
|
|
logger.info(`Validating ${file}`);
|
|
|
|
try {
|
2024-03-13 05:11:40 +00:00
|
|
|
await validate('global', file, fileConfig, strict);
|
2022-08-04 06:25:18 +00:00
|
|
|
} catch (err) {
|
2023-06-24 09:32:50 +00:00
|
|
|
logger.error({ file, err }, 'File is not valid Renovate config');
|
2022-08-04 06:25:18 +00:00
|
|
|
returnVal = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
// ignore
|
|
|
|
}
|
2019-03-16 06:03:32 +00:00
|
|
|
}
|
2018-03-29 03:47:49 +00:00
|
|
|
if (returnVal !== 0) {
|
|
|
|
process.exit(returnVal);
|
2018-03-07 05:10:17 +00:00
|
|
|
}
|
2021-02-03 09:35:30 +00:00
|
|
|
logger.info('Config validated successfully');
|
2020-05-16 10:11:56 +00:00
|
|
|
})().catch((e) => {
|
2023-04-28 12:17:48 +00:00
|
|
|
// eslint-disable-next-line no-console
|
2020-05-16 10:11:56 +00:00
|
|
|
console.error(e);
|
|
|
|
process.exit(99);
|
|
|
|
});
|