import { logger } from '../logger/index.ts'; import { clone } from '../util/clone.ts'; import { getHighestVulnerabilitySeverity } from '../util/vulnerability/utils.ts'; import * as options from './options/index.ts'; import type { RenovateConfig } from './types.ts'; export function mergeChildConfig< T extends Record, TChild extends Record | undefined, >(parent: T, child: TChild): T & TChild { logger.trace({ parent, child }, `mergeChildConfig`); if (!child) { return parent as never; } const parentConfig = clone(parent); const childConfig = clone(child); const config: Record = { ...parentConfig, ...childConfig }; // Ensure highest severity survives parent / child merge if (config?.isVulnerabilityAlert) { config.vulnerabilitySeverity = getHighestVulnerabilitySeverity( parent, child, ); } for (const option of options.getOptions()) { if ( option.mergeable && childConfig[option.name] && parentConfig[option.name] ) { logger.trace(`mergeable option: ${option.name}`); if (option.name === 'constraints') { config[option.name] = { ...parentConfig[option.name], ...childConfig[option.name], }; } else if (option.type === 'array') { config[option.name] = (parentConfig[option.name] as unknown[]).concat( config[option.name], ); } else { config[option.name] = mergeChildConfig( parentConfig[option.name] as RenovateConfig, childConfig[option.name] as RenovateConfig, ); } logger.trace( { result: config[option.name] }, `Merged config.${option.name}`, ); } } return { ...config, ...config.force }; }