renovate/lib/config/migrations/custom/host-rules-migration.ts

106 lines
2.9 KiB
TypeScript

import is from '@sindresorhus/is';
import { CONFIG_VALIDATION } from '../../../constants/error-messages';
import { logger } from '../../../logger';
import type { HostRule } from '../../../types';
import type { LegacyHostRule } from '../../../util/host-rules';
import { massageHostUrl } from '../../../util/url';
import { AbstractMigration } from '../base/abstract-migration';
import { migrateDatasource } from './datasource-migration';
export class HostRulesMigration extends AbstractMigration {
override readonly propertyName = 'hostRules';
override run(value: (LegacyHostRule & HostRule)[]): void {
const newHostRules: HostRule[] = [];
for (const hostRule of value) {
validateHostRule(hostRule);
const newRule: any = {};
for (const [key, value] of Object.entries(hostRule)) {
if (key === 'platform') {
if (is.string(value)) {
newRule.hostType ??= value;
}
continue;
}
if (key === 'matchHost') {
if (is.string(value)) {
newRule.matchHost ??= massageHostUrl(value);
}
continue;
}
if (key === 'hostType') {
if (is.string(value)) {
newRule.hostType ??= migrateDatasource(value);
}
continue;
}
if (
key === 'endpoint' ||
key === 'host' ||
key === 'baseUrl' ||
key === 'hostName' ||
key === 'domainName'
) {
if (is.string(value)) {
newRule.matchHost ??= massageHostUrl(value);
}
continue;
}
newRule[key] = value;
}
newHostRules.push(newRule);
}
this.rewrite(newHostRules);
}
}
function validateHostRule(rule: LegacyHostRule & HostRule): void {
const { matchHost, hostName, domainName, baseUrl, endpoint, host } = rule;
const hosts: Record<string, string> = removeUndefinedFields({
matchHost,
hostName,
domainName,
baseUrl,
endpoint,
host,
});
if (Object.keys(hosts).length > 1) {
const distinctHostValues = new Set(Object.values(hosts));
// check if the host values are duplicated
if (distinctHostValues.size > 1) {
const error = new Error(CONFIG_VALIDATION);
error.validationSource = 'config';
error.validationMessage =
'`hostRules` cannot contain more than one host-matching field - use `matchHost` only.';
error.validationError =
'The renovate configuration file contains some invalid settings';
throw error;
} else {
logger.warn(
{ hosts },
'Duplicate host values found, please only use `matchHost` to specify the host',
);
}
}
}
function removeUndefinedFields(
obj: Record<string, any>,
): Record<string, string> {
const result: Record<string, string> = {};
for (const key of Object.keys(obj)) {
if (is.string(obj[key])) {
result[key] = obj[key];
}
}
return result;
}