Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
fix(migration): throw error for invalid hostRules (#20540)
  • Loading branch information
RahulGautamSingh committed May 22, 2023
1 parent 48d4cf3 commit 0d85cea
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 4 deletions.
1 change: 0 additions & 1 deletion lib/config/migration.spec.ts
Expand Up @@ -20,7 +20,6 @@ describe('config/migration', () => {
{
platform: 'docker',
endpoint: 'https://docker.io',
host: 'docker.io',
username: 'some-username',
password: 'some-password',
},
Expand Down
39 changes: 39 additions & 0 deletions lib/config/migrations/custom/host-rules-migration.spec.ts
@@ -1,3 +1,4 @@
import { CONFIG_VALIDATION } from '../../../constants/error-messages';
import { HostRulesMigration } from './host-rules-migration';

describe('config/migrations/custom/host-rules-migration', () => {
Expand All @@ -10,6 +11,12 @@ describe('config/migrations/custom/host-rules-migration', () => {
baseUrl: 'https://some.domain.com',
token: '123test',
},
{
hostType: 'dotnet',
baseUrl: 'https://some.domain.com',
matchHost: 'https://some.domain.com',
token: '123test',
},
{
hostType: 'adoptium-java',
domainName: 'domain.com',
Expand All @@ -18,10 +25,17 @@ describe('config/migrations/custom/host-rules-migration', () => {
{ domainName: 'domain.com/', token: '123test' },
{ hostType: 'docker', matchHost: 'domain.com/', token: '123test' },
{ hostName: 'some.domain.com', token: '123test' },
{ endpoint: 'domain.com/', token: '123test' },
{ host: 'some.domain.com', token: '123test' },
],
} as any,
{
hostRules: [
{
hostType: 'dotnet-version',
matchHost: 'https://some.domain.com',
token: '123test',
},
{
hostType: 'dotnet-version',
matchHost: 'https://some.domain.com',
Expand All @@ -42,8 +56,33 @@ describe('config/migrations/custom/host-rules-migration', () => {
token: '123test',
},
{ matchHost: 'some.domain.com', token: '123test' },
{ matchHost: 'https://domain.com/', token: '123test' },
{ matchHost: 'some.domain.com', token: '123test' },
],
}
);
});

it('throws when multiple hosts are present', () => {
expect(() =>
new HostRulesMigration(
{
hostRules: [
{
matchHost: 'https://some-diff.domain.com',
baseUrl: 'https://some.domain.com',
token: '123test',
},
],
} as any,
{}
).run([
{
matchHost: 'https://some-diff.domain.com',
baseUrl: 'https://some.domain.com',
token: '123test',
},
])
).toThrow(CONFIG_VALIDATION);
});
});
48 changes: 47 additions & 1 deletion lib/config/migrations/custom/host-rules-migration.ts
@@ -1,14 +1,18 @@
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 { AbstractMigration } from '../base/abstract-migration';
import { migrateDatasource } from './datasource-migration';

export class HostRulesMigration extends AbstractMigration {
override readonly propertyName = 'hostRules';

override run(value: Record<string, unknown>[]): void {
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)) {
Expand Down Expand Up @@ -56,10 +60,52 @@ export class HostRulesMigration extends AbstractMigration {
}
}

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 massageUrl(url: string): string {
if (!url.includes('://') && url.includes('/')) {
return 'https://' + url;
} else {
return url;
}
}

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;
}
6 changes: 4 additions & 2 deletions lib/util/host-rules.ts
Expand Up @@ -8,13 +8,15 @@ import { parseUrl, validateUrl } from './url';

let hostRules: HostRule[] = [];

interface LegacyHostRule {
export interface LegacyHostRule {
hostName?: string;
domainName?: string;
baseUrl?: string;
host?: string;
endpoint?: string;
}

function migrateRule(rule: LegacyHostRule & HostRule): HostRule {
export function migrateRule(rule: LegacyHostRule & HostRule): HostRule {
const cloned: LegacyHostRule & HostRule = structuredClone(rule);
delete cloned.hostName;
delete cloned.domainName;
Expand Down

0 comments on commit 0d85cea

Please sign in to comment.