renovate
Version:
Automated dependency updates. Flexible so you don't need to be.
232 lines • 9.88 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.replaceArgs = replaceArgs;
exports.getPreset = getPreset;
exports.resolveConfigPresets = resolveConfigPresets;
const tslib_1 = require("tslib");
const is_1 = tslib_1.__importDefault(require("@sindresorhus/is"));
const error_messages_1 = require("../../constants/error-messages");
const logger_1 = require("../../logger");
const external_host_error_1 = require("../../types/errors/external-host-error");
const memCache = tslib_1.__importStar(require("../../util/cache/memory"));
const packageCache = tslib_1.__importStar(require("../../util/cache/package"));
const ttl_1 = require("../../util/cache/package/ttl");
const clone_1 = require("../../util/clone");
const regex_1 = require("../../util/regex");
const template = tslib_1.__importStar(require("../../util/template"));
const global_1 = require("../global");
const massage = tslib_1.__importStar(require("../massage"));
const migration = tslib_1.__importStar(require("../migration"));
const utils_1 = require("../utils");
const common_1 = require("./common");
const gitea = tslib_1.__importStar(require("./gitea"));
const github = tslib_1.__importStar(require("./github"));
const gitlab = tslib_1.__importStar(require("./gitlab"));
const http = tslib_1.__importStar(require("./http"));
const internal = tslib_1.__importStar(require("./internal"));
const local = tslib_1.__importStar(require("./local"));
const npm = tslib_1.__importStar(require("./npm"));
const parse_1 = require("./parse");
const util_1 = require("./util");
const presetSources = {
github,
npm,
gitlab,
gitea,
local,
internal,
http,
};
const presetCacheNamespace = 'preset';
function replaceArgs(obj, argMapping) {
if (is_1.default.string(obj)) {
let returnStr = obj;
for (const [arg, argVal] of Object.entries(argMapping)) {
const re = (0, regex_1.regEx)(`{{${arg}}}`, 'g', false);
returnStr = returnStr.replace(re, argVal);
}
return returnStr;
}
if (is_1.default.array(obj)) {
const returnArray = [];
for (const item of obj) {
returnArray.push(replaceArgs(item, argMapping));
}
return returnArray;
}
if (is_1.default.object(obj)) {
const returnObj = {};
for (const [key, val] of Object.entries(obj)) {
returnObj[key] = replaceArgs(val, argMapping);
}
return returnObj;
}
return obj;
}
async function getPreset(preset, baseConfig) {
logger_1.logger.trace(`getPreset(${preset})`);
// Check if the preset has been removed or replaced
const newPreset = common_1.removedPresets[preset];
if (newPreset) {
return getPreset(newPreset, baseConfig);
}
if (newPreset === null) {
return {};
}
const { presetSource, repo, presetPath, presetName, tag, params } = (0, parse_1.parsePreset)(preset);
const cacheKey = `preset:${preset}`;
const presetCachePersistence = global_1.GlobalConfig.get('presetCachePersistence', false);
let presetConfig;
if (presetCachePersistence) {
presetConfig = await packageCache.get(presetCacheNamespace, cacheKey);
}
else {
presetConfig = memCache.get(cacheKey);
}
if (is_1.default.nullOrUndefined(presetConfig)) {
presetConfig = await presetSources[presetSource].getPreset({
repo,
presetPath,
presetName,
tag,
});
if (presetCachePersistence) {
await packageCache.set(presetCacheNamespace, cacheKey, presetConfig, (0, ttl_1.getTtlOverride)(presetCacheNamespace) ?? 15);
}
else {
memCache.set(cacheKey, presetConfig);
}
}
if (!presetConfig) {
throw new Error(util_1.PRESET_DEP_NOT_FOUND);
}
logger_1.logger.trace({ presetConfig }, `Found preset ${preset}`);
if (params) {
const argMapping = {};
for (const [index, value] of params.entries()) {
argMapping[`arg${index}`] = value;
}
presetConfig = replaceArgs(presetConfig, argMapping);
}
logger_1.logger.trace({ presetConfig }, `Applied params to preset ${preset}`);
const presetKeys = Object.keys(presetConfig);
if (presetKeys.length === 2 &&
presetKeys.includes('description') &&
presetKeys.includes('extends')) {
// preset is just a collection of other presets
delete presetConfig.description;
}
const packageListKeys = ['description', 'matchPackageNames'];
if (presetKeys.every((key) => packageListKeys.includes(key))) {
delete presetConfig.description;
}
const { migratedConfig } = migration.migrateConfig(presetConfig);
return massage.massageConfig(migratedConfig);
}
async function resolveConfigPresets(inputConfig, baseConfig, _ignorePresets, existingPresets = []) {
let ignorePresets = (0, clone_1.clone)(_ignorePresets);
if (!ignorePresets || ignorePresets.length === 0) {
ignorePresets = inputConfig.ignorePresets ?? [];
}
logger_1.logger.trace({ config: inputConfig, existingPresets }, 'resolveConfigPresets');
let config = {};
// First, merge all the preset configs from left to right
if (inputConfig.extends?.length) {
// Compile templates
inputConfig.extends = inputConfig.extends.map((tmpl) => template.compile(tmpl, {}));
for (const preset of inputConfig.extends) {
if (shouldResolvePreset(preset, existingPresets, ignorePresets)) {
logger_1.logger.trace(`Resolving preset "${preset}"`);
const fetchedPreset = await fetchPreset(preset, baseConfig, inputConfig, existingPresets);
const presetConfig = await resolveConfigPresets(fetchedPreset, baseConfig ?? inputConfig, ignorePresets, existingPresets.concat([preset]));
if (inputConfig?.ignoreDeps?.length === 0) {
delete presetConfig.description;
}
config = (0, utils_1.mergeChildConfig)(config, presetConfig);
}
}
}
logger_1.logger.trace({ config }, `Post-preset resolve config`);
// Now assign "regular" config on top
config = (0, utils_1.mergeChildConfig)(config, inputConfig);
delete config.extends;
delete config.ignorePresets;
logger_1.logger.trace({ config }, `Post-merge resolve config`);
for (const [key, val] of Object.entries(config)) {
const ignoredKeys = ['content', 'onboardingConfig'];
if (is_1.default.array(val)) {
// Resolve nested objects inside arrays
config[key] = [];
for (const element of val) {
if (is_1.default.object(element)) {
config[key].push(await resolveConfigPresets(element, baseConfig, ignorePresets, existingPresets));
}
else {
config[key].push(element);
}
}
}
else if (is_1.default.object(val) && !ignoredKeys.includes(key)) {
// Resolve nested objects
logger_1.logger.trace(`Resolving object "${key}"`);
config[key] = await resolveConfigPresets(val, baseConfig, ignorePresets, existingPresets);
}
}
logger_1.logger.trace({ config: inputConfig }, 'Input config');
logger_1.logger.trace({ config }, 'Resolved config');
return config;
}
async function fetchPreset(preset, baseConfig, inputConfig, existingPresets) {
try {
return await getPreset(preset, baseConfig ?? inputConfig);
}
catch (err) {
logger_1.logger.debug({ preset, err }, 'Preset fetch error');
if (err instanceof external_host_error_1.ExternalHostError) {
throw err;
}
if (err.message === error_messages_1.PLATFORM_RATE_LIMIT_EXCEEDED) {
throw err;
}
const error = new Error(error_messages_1.CONFIG_VALIDATION);
if (err.message === util_1.PRESET_DEP_NOT_FOUND) {
error.validationError = `Cannot find preset's package (${preset})`;
}
else if (err.message === util_1.PRESET_RENOVATE_CONFIG_NOT_FOUND) {
error.validationError = `Preset package is missing a renovate-config entry (${preset})`;
}
else if (err.message === util_1.PRESET_NOT_FOUND) {
error.validationError = `Preset name not found within published preset config (${preset})`;
}
else if (err.message === util_1.PRESET_INVALID) {
error.validationError = `Preset is invalid (${preset})`;
}
else if (err.message === util_1.PRESET_PROHIBITED_SUBPRESET) {
error.validationError = `Sub-presets cannot be combined with a custom path (${preset})`;
}
else if (err.message === util_1.PRESET_INVALID_JSON) {
error.validationError = `Preset is invalid JSON (${preset})`;
}
else {
error.validationError = `Preset caused unexpected error (${preset})`;
}
if (existingPresets.length) {
error.validationError +=
'. Note: this is a *nested* preset so please contact the preset author if you are unable to fix it yourself.';
}
logger_1.logger.info({ validationError: error.validationError }, 'Throwing preset error');
throw error;
}
}
function shouldResolvePreset(preset, existingPresets, ignorePresets) {
if (existingPresets.includes(preset)) {
logger_1.logger.debug(`Already seen preset ${preset} in [${existingPresets.join(', ')}]`);
return false;
}
if (ignorePresets.includes(preset)) {
logger_1.logger.debug(`Ignoring preset ${preset} in [${existingPresets.join(', ')}]`);
return false;
}
return true;
}
//# sourceMappingURL=index.js.map