Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(config): reusable env getConfig function #33350

Merged
merged 4 commits into from
Dec 31, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion lib/workers/global/config/parse/env.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,11 @@ describe('workers/global/config/parse/env', () => {

it('crashes', async () => {
const envParam: NodeJS.ProcessEnv = { RENOVATE_CONFIG: '!@#' };
await env.getConfig(envParam);
processExit.mockImplementationOnce(() => {
throw new Error('terminate function to simulate process.exit call');
});

await expect(env.getConfig(envParam)).toReject();
expect(processExit).toHaveBeenCalledWith(1);
});

Expand Down
171 changes: 91 additions & 80 deletions lib/workers/global/config/parse/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,102 +118,92 @@ function massageConvertedExperimentalVars(

export async function getConfig(
inputEnv: NodeJS.ProcessEnv,
configEnvKey = 'RENOVATE_CONFIG',
): Promise<AllConfig> {
let env = inputEnv;
env = normalizePrefixes(inputEnv, inputEnv.ENV_PREFIX);
let env = normalizePrefixes(inputEnv, inputEnv.ENV_PREFIX);
env = massageConvertedExperimentalVars(env);
env = renameEnvKeys(env);
// massage the values of migrated configuration keys
env = massageEnvKeyValues(env);

const options = getOptions();

let config: AllConfig = {};
const config = await parseAndValidateOrExit(env, configEnvKey);

if (env.RENOVATE_CONFIG) {
try {
config = JSON5.parse(env.RENOVATE_CONFIG);
logger.debug({ config }, 'Detected config in env RENOVATE_CONFIG');
config.hostRules ??= [];

config = await migrateAndValidateConfig(config, 'RENOVATE_CONFIG');
} catch (err) {
logger.fatal({ err }, 'Could not parse RENOVATE_CONFIG');
process.exit(1);
for (const option of options) {
if (option.env === false) {
continue;
}
}

config.hostRules ??= [];
const envName = getEnvName(option);
const envVal = env[envName];
if (!envVal) {
continue;
viceice marked this conversation as resolved.
Show resolved Hide resolved
}

options.forEach((option) => {
if (option.env !== false) {
const envName = getEnvName(option);
const envVal = env[envName];
if (envVal) {
if (option.type === 'array' && option.subType === 'object') {
try {
const parsed = JSON5.parse(envVal);
if (is.array(parsed)) {
config[option.name] = parsed;
} else {
logger.debug(
{ val: envVal, envName },
'Could not parse object array',
);
}
} catch {
logger.debug(
{ val: envVal, envName },
'Could not parse environment variable',
);
}
if (option.type === 'array' && option.subType === 'object') {
try {
const parsed = JSON5.parse(envVal);
if (is.array(parsed)) {
config[option.name] = parsed;
} else {
const coerce = coersions[option.type];
config[option.name] = coerce(envVal);
if (option.name === 'dryRun') {
if ((config[option.name] as string) === 'true') {
logger.warn(
'env config dryRun property has been changed to full',
);
config[option.name] = 'full';
} else if ((config[option.name] as string) === 'false') {
logger.warn(
'env config dryRun property has been changed to null',
);
delete config[option.name];
} else if ((config[option.name] as string) === 'null') {
delete config[option.name];
}
}
if (option.name === 'requireConfig') {
if ((config[option.name] as string) === 'true') {
logger.warn(
'env config requireConfig property has been changed to required',
);
config[option.name] = 'required';
} else if ((config[option.name] as string) === 'false') {
logger.warn(
'env config requireConfig property has been changed to optional',
);
config[option.name] = 'optional';
}
}
if (option.name === 'platformCommit') {
if ((config[option.name] as string) === 'true') {
logger.warn(
'env config platformCommit property has been changed to enabled',
);
config[option.name] = 'enabled';
} else if ((config[option.name] as string) === 'false') {
logger.warn(
'env config platformCommit property has been changed to disabled',
);
config[option.name] = 'disabled';
}
}
logger.debug(
{ val: envVal, envName },
'Could not parse object array',
);
}
} catch {
logger.debug(
{ val: envVal, envName },
'Could not parse environment variable',
);
}
} else {
const coerce = coersions[option.type];
config[option.name] = coerce(envVal);
if (option.name === 'dryRun') {
if ((config[option.name] as string) === 'true') {
logger.warn('env config dryRun property has been changed to full');
config[option.name] = 'full';
} else if ((config[option.name] as string) === 'false') {
logger.warn('env config dryRun property has been changed to null');
delete config[option.name];
} else if ((config[option.name] as string) === 'null') {
delete config[option.name];
}
}

if (option.name === 'requireConfig') {
if ((config[option.name] as string) === 'true') {
logger.warn(
'env config requireConfig property has been changed to required',
);
config[option.name] = 'required';
} else if ((config[option.name] as string) === 'false') {
logger.warn(
'env config requireConfig property has been changed to optional',
);
config[option.name] = 'optional';
}
}

if (option.name === 'platformCommit') {
if ((config[option.name] as string) === 'true') {
logger.warn(
'env config platformCommit property has been changed to enabled',
);
config[option.name] = 'enabled';
} else if ((config[option.name] as string) === 'false') {
logger.warn(
'env config platformCommit property has been changed to disabled',
);
config[option.name] = 'disabled';
}
}
}
});
}

if (env.GITHUB_COM_TOKEN) {
logger.debug(`Converting GITHUB_COM_TOKEN into a global host rule`);
Expand All @@ -237,7 +227,28 @@ export async function getConfig(
'VSTS_TOKEN',
];

unsupportedEnv.forEach((val) => delete env[val]);
for (const val of unsupportedEnv) {
delete env[val];
}

return config;
}

async function parseAndValidateOrExit(
env: NodeJS.ProcessEnv,
configEnvKey: string,
): Promise<AllConfig> {
if (!env[configEnvKey]) {
return {};
}

try {
const config = JSON5.parse(env[configEnvKey]);
Gabriel-Ladzaretti marked this conversation as resolved.
Show resolved Hide resolved
logger.debug({ config }, `Detected config in env ${configEnvKey}`);

return await migrateAndValidateConfig(config, `${configEnvKey}`);
} catch (err) {
logger.fatal({ err }, `Could not parse ${configEnvKey}`);
process.exit(1);
}
}
Loading