0
0
Fork 0
mirror of https://github.com/renovatebot/renovate.git synced 2025-05-12 23:51:55 +00:00
renovatebot_renovate/lib/workers/global/config/parse/file.ts
renovate[bot] 86408be681
build(deps): update dependency @sindresorhus/is to v7 (main) (#35682)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
2025-05-02 09:43:35 +00:00

136 lines
4 KiB
TypeScript

import { pathToFileURL } from 'url';
import is from '@sindresorhus/is';
import fs from 'fs-extra';
import JSON5 from 'json5';
import upath from 'upath';
import type { AllConfig, RenovateConfig } from '../../../../config/types';
import { logger } from '../../../../logger';
import { parseJson } from '../../../../util/common';
import { readSystemFile } from '../../../../util/fs';
import { parseSingleYaml } from '../../../../util/yaml';
import { migrateAndValidateConfig } from './util';
export async function getParsedContent(file: string): Promise<RenovateConfig> {
if (upath.basename(file) === '.renovaterc') {
return JSON5.parse(await readSystemFile(file, 'utf8'));
}
switch (upath.extname(file)) {
case '.yaml':
case '.yml':
return parseSingleYaml(await readSystemFile(file, 'utf8'));
case '.json5':
case '.json':
return parseJson(
await readSystemFile(file, 'utf8'),
file,
) as RenovateConfig;
case '.cjs':
case '.mjs':
case '.js': {
const absoluteFilePath = upath.isAbsolute(file)
? file
: `${process.cwd()}/${file}`;
// use file url paths to avoid issues with windows paths
// typescript does not support file URL for import
const tmpConfig = await import(pathToFileURL(absoluteFilePath).href);
/* v8 ignore next -- not testable */
let config = tmpConfig.default ?? tmpConfig;
// Allow the config to be a function
if (is.function(config)) {
config = config();
}
return config;
}
default:
throw new Error('Unsupported file type');
}
}
export async function getConfig(env: NodeJS.ProcessEnv): Promise<AllConfig> {
const configFile = env.RENOVATE_CONFIG_FILE ?? 'config.js';
const configFileExists = await fs.pathExists(configFile);
if (env.RENOVATE_CONFIG_FILE && !configFileExists) {
logger.fatal(
{ configFile },
`Custom config file specified in RENOVATE_CONFIG_FILE must exist`,
);
process.exit(1);
}
let config: AllConfig = {};
if (!configFileExists) {
logger.debug('No config file found on disk - skipping');
return config;
}
logger.debug('Checking for config file in ' + configFile);
try {
config = await getParsedContent(configFile);
} catch (err) {
if (err instanceof SyntaxError || err instanceof TypeError) {
logger.fatal({ error: err.stack }, 'Could not parse config file');
process.exit(1);
} else if (err instanceof ReferenceError) {
logger.fatal(
`Error parsing config file due to unresolved variable(s): ${err.message}`,
);
process.exit(1);
} else if (err.message === 'Unsupported file type') {
logger.fatal(err.message);
process.exit(1);
} else if (env.RENOVATE_CONFIG_FILE) {
logger.debug({ err }, 'Parse error');
logger.fatal('Error parsing config file');
process.exit(1);
}
logger.debug('Error reading or parsing file - skipping');
}
if (is.nonEmptyObject(config.processEnv)) {
const exportedKeys = [];
for (const [key, value] of Object.entries(config.processEnv)) {
if (!is.nonEmptyString(value)) {
logger.error({ key }, 'processEnv value is not a string.');
continue;
}
exportedKeys.push(key);
process.env[key] = value;
}
logger.debug(
{ keys: exportedKeys },
'processEnv keys were exported to env',
);
delete config.processEnv;
}
return migrateAndValidateConfig(config, configFile);
}
export async function deleteNonDefaultConfig(
env: NodeJS.ProcessEnv,
deleteConfigFile: boolean,
): Promise<void> {
const configFile = env.RENOVATE_CONFIG_FILE;
if (is.undefined(configFile) || is.emptyStringOrWhitespace(configFile)) {
return;
}
if (!deleteConfigFile) {
return;
}
if (!(await fs.pathExists(configFile))) {
return;
}
try {
await fs.remove(configFile);
logger.trace({ path: configFile }, 'config file successfully deleted');
} catch (err) {
logger.warn({ err }, 'error deleting config file');
}
}