mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-11 06:26:26 +00:00
refactor: encapsulate hostRulesFromEnv (#12277)
This commit is contained in:
parent
a0b8b52a75
commit
42fd18d101
4 changed files with 184 additions and 54 deletions
|
@ -0,0 +1,55 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`workers/global/config/parse/host-rules-from-env regression test for #10937 1`] = `
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"hostType": "git-tags",
|
||||||
|
"matchHost": "gitlab.example-domain.net",
|
||||||
|
"password": "some-password",
|
||||||
|
"username": "some-user",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`workers/global/config/parse/host-rules-from-env supports datasource env token 1`] = `
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"hostType": "pypi",
|
||||||
|
"token": "some-token",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`workers/global/config/parse/host-rules-from-env supports docker username/password 1`] = `
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"hostType": "docker",
|
||||||
|
"password": "some-password",
|
||||||
|
"username": "some-username",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`workers/global/config/parse/host-rules-from-env supports domain and host names with case insensitivity 1`] = `
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"hostType": "github-tags",
|
||||||
|
"matchHost": "github.com",
|
||||||
|
"token": "some-token",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"hostType": "pypi",
|
||||||
|
"matchHost": "my.custom.host",
|
||||||
|
"password": "some-password",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`workers/global/config/parse/host-rules-from-env supports password-only 1`] = `
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"hostType": "npm",
|
||||||
|
"password": "some-password",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`;
|
|
@ -3,9 +3,8 @@ import is from '@sindresorhus/is';
|
||||||
import { getOptions } from '../../../../config/options';
|
import { getOptions } from '../../../../config/options';
|
||||||
import type { AllConfig, RenovateOptions } from '../../../../config/types';
|
import type { AllConfig, RenovateOptions } from '../../../../config/types';
|
||||||
import { PlatformId } from '../../../../constants';
|
import { PlatformId } from '../../../../constants';
|
||||||
import { getDatasourceList } from '../../../../datasource';
|
|
||||||
import { logger } from '../../../../logger';
|
import { logger } from '../../../../logger';
|
||||||
import type { HostRule } from '../../../../types';
|
import { hostRulesFromEnv } from './host-rules-from-env';
|
||||||
|
|
||||||
function normalizePrefixes(
|
function normalizePrefixes(
|
||||||
env: NodeJS.ProcessEnv,
|
env: NodeJS.ProcessEnv,
|
||||||
|
@ -120,58 +119,7 @@ export function getConfig(inputEnv: NodeJS.ProcessEnv): AllConfig {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const datasources = new Set(getDatasourceList());
|
config.hostRules = [...config.hostRules, ...hostRulesFromEnv(env)];
|
||||||
const fields = ['token', 'username', 'password'];
|
|
||||||
|
|
||||||
const hostRules: HostRule[] = [];
|
|
||||||
|
|
||||||
const npmEnvPrefixes = ['npm_config_', 'npm_lifecycle_', 'npm_package_'];
|
|
||||||
|
|
||||||
for (const envName of Object.keys(env).sort()) {
|
|
||||||
if (npmEnvPrefixes.some((prefix) => envName.startsWith(prefix))) {
|
|
||||||
logger.trace('Ignoring npm env: ' + envName);
|
|
||||||
continue; // eslint-disable-line no-continue
|
|
||||||
}
|
|
||||||
// Double underscore __ is used in place of hyphen -
|
|
||||||
const splitEnv = envName.toLowerCase().replace(/__/g, '-').split('_');
|
|
||||||
const hostType = splitEnv.shift();
|
|
||||||
if (datasources.has(hostType)) {
|
|
||||||
const suffix = splitEnv.pop();
|
|
||||||
if (fields.includes(suffix)) {
|
|
||||||
let matchHost: string;
|
|
||||||
const rule: HostRule = {};
|
|
||||||
rule[suffix] = env[envName];
|
|
||||||
if (splitEnv.length === 0) {
|
|
||||||
// host-less rule
|
|
||||||
} else if (splitEnv.length === 1) {
|
|
||||||
logger.warn(`Cannot parse ${envName} env`);
|
|
||||||
continue; // eslint-disable-line no-continue
|
|
||||||
} else {
|
|
||||||
matchHost = splitEnv.join('.');
|
|
||||||
}
|
|
||||||
const existingRule = hostRules.find(
|
|
||||||
(hr) => hr.hostType === hostType && hr.matchHost === matchHost
|
|
||||||
);
|
|
||||||
logger.debug(`Converting ${envName} into a global host rule`);
|
|
||||||
if (existingRule) {
|
|
||||||
// Add current field to existing rule
|
|
||||||
existingRule[suffix] = env[envName];
|
|
||||||
} else {
|
|
||||||
// Create a new rule
|
|
||||||
const newRule: HostRule = {
|
|
||||||
hostType,
|
|
||||||
};
|
|
||||||
if (matchHost) {
|
|
||||||
newRule.matchHost = matchHost;
|
|
||||||
}
|
|
||||||
newRule[suffix] = env[envName];
|
|
||||||
hostRules.push(newRule);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
config.hostRules = [...config.hostRules, ...hostRules];
|
|
||||||
|
|
||||||
// These env vars are deprecated and deleted to make sure they're not used
|
// These env vars are deprecated and deleted to make sure they're not used
|
||||||
const unsupportedEnv = [
|
const unsupportedEnv = [
|
||||||
|
|
70
lib/workers/global/config/parse/host-rules-from-env.spec.ts
Normal file
70
lib/workers/global/config/parse/host-rules-from-env.spec.ts
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
import { hostRulesFromEnv } from './host-rules-from-env';
|
||||||
|
|
||||||
|
describe('workers/global/config/parse/host-rules-from-env', () => {
|
||||||
|
it('supports docker username/password', () => {
|
||||||
|
const envParam: NodeJS.ProcessEnv = {
|
||||||
|
DOCKER_USERNAME: 'some-username',
|
||||||
|
DOCKER_PASSWORD: 'some-password',
|
||||||
|
};
|
||||||
|
expect(hostRulesFromEnv(envParam)).toMatchSnapshot([
|
||||||
|
{
|
||||||
|
hostType: 'docker',
|
||||||
|
password: 'some-password',
|
||||||
|
username: 'some-username',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
it('supports password-only', () => {
|
||||||
|
const envParam: NodeJS.ProcessEnv = {
|
||||||
|
NPM_PASSWORD: 'some-password',
|
||||||
|
};
|
||||||
|
expect(hostRulesFromEnv(envParam)).toMatchSnapshot([
|
||||||
|
{ hostType: 'npm', password: 'some-password' },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
it('supports domain and host names with case insensitivity', () => {
|
||||||
|
const envParam: NodeJS.ProcessEnv = {
|
||||||
|
GITHUB__TAGS_GITHUB_COM_TOKEN: 'some-token',
|
||||||
|
pypi_my_CUSTOM_HOST_passWORD: 'some-password',
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(hostRulesFromEnv(envParam)).toMatchSnapshot([
|
||||||
|
{ matchHost: 'github.com', token: 'some-token' },
|
||||||
|
{ matchHost: 'my.custom.host', password: 'some-password' },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
it('regression test for #10937', () => {
|
||||||
|
const envParam: NodeJS.ProcessEnv = {
|
||||||
|
GIT__TAGS_GITLAB_EXAMPLE__DOMAIN_NET_USERNAME: 'some-user',
|
||||||
|
GIT__TAGS_GITLAB_EXAMPLE__DOMAIN_NET_PASSWORD: 'some-password',
|
||||||
|
};
|
||||||
|
expect(hostRulesFromEnv(envParam)).toMatchSnapshot([
|
||||||
|
{
|
||||||
|
hostType: 'git-tags',
|
||||||
|
matchHost: 'gitlab.example-domain.net',
|
||||||
|
password: 'some-password',
|
||||||
|
username: 'some-user',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
it('supports datasource env token', () => {
|
||||||
|
const envParam: NodeJS.ProcessEnv = {
|
||||||
|
PYPI_TOKEN: 'some-token',
|
||||||
|
};
|
||||||
|
expect(hostRulesFromEnv(envParam)).toMatchSnapshot([
|
||||||
|
{ hostType: 'pypi', token: 'some-token' },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
it('rejects incomplete datasource env token', () => {
|
||||||
|
const envParam: NodeJS.ProcessEnv = {
|
||||||
|
PYPI_FOO_TOKEN: 'some-token',
|
||||||
|
};
|
||||||
|
expect(hostRulesFromEnv(envParam)).toHaveLength(0);
|
||||||
|
});
|
||||||
|
it('rejects npm env', () => {
|
||||||
|
const envParam: NodeJS.ProcessEnv = {
|
||||||
|
npm_package_devDependencies__types_registry_auth_token: '4.2.0',
|
||||||
|
};
|
||||||
|
expect(hostRulesFromEnv(envParam)).toHaveLength(0);
|
||||||
|
});
|
||||||
|
});
|
57
lib/workers/global/config/parse/host-rules-from-env.ts
Normal file
57
lib/workers/global/config/parse/host-rules-from-env.ts
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import { getDatasourceList } from '../../../../datasource';
|
||||||
|
import { logger } from '../../../../logger';
|
||||||
|
import type { HostRule } from '../../../../types';
|
||||||
|
|
||||||
|
export function hostRulesFromEnv(env: NodeJS.ProcessEnv): HostRule[] {
|
||||||
|
const datasources = new Set(getDatasourceList());
|
||||||
|
const fields = ['token', 'username', 'password'];
|
||||||
|
|
||||||
|
const hostRules: HostRule[] = [];
|
||||||
|
|
||||||
|
const npmEnvPrefixes = ['npm_config_', 'npm_lifecycle_', 'npm_package_'];
|
||||||
|
|
||||||
|
for (const envName of Object.keys(env).sort()) {
|
||||||
|
if (npmEnvPrefixes.some((prefix) => envName.startsWith(prefix))) {
|
||||||
|
logger.trace('Ignoring npm env: ' + envName);
|
||||||
|
continue; // eslint-disable-line no-continue
|
||||||
|
}
|
||||||
|
// Double underscore __ is used in place of hyphen -
|
||||||
|
const splitEnv = envName.toLowerCase().replace(/__/g, '-').split('_');
|
||||||
|
const hostType = splitEnv.shift();
|
||||||
|
if (datasources.has(hostType)) {
|
||||||
|
const suffix = splitEnv.pop();
|
||||||
|
if (fields.includes(suffix)) {
|
||||||
|
let matchHost: string;
|
||||||
|
const rule: HostRule = {};
|
||||||
|
rule[suffix] = env[envName];
|
||||||
|
if (splitEnv.length === 0) {
|
||||||
|
// host-less rule
|
||||||
|
} else if (splitEnv.length === 1) {
|
||||||
|
logger.warn(`Cannot parse ${envName} env`);
|
||||||
|
continue; // eslint-disable-line no-continue
|
||||||
|
} else {
|
||||||
|
matchHost = splitEnv.join('.');
|
||||||
|
}
|
||||||
|
const existingRule = hostRules.find(
|
||||||
|
(hr) => hr.hostType === hostType && hr.matchHost === matchHost
|
||||||
|
);
|
||||||
|
logger.debug(`Converting ${envName} into a global host rule`);
|
||||||
|
if (existingRule) {
|
||||||
|
// Add current field to existing rule
|
||||||
|
existingRule[suffix] = env[envName];
|
||||||
|
} else {
|
||||||
|
// Create a new rule
|
||||||
|
const newRule: HostRule = {
|
||||||
|
hostType,
|
||||||
|
};
|
||||||
|
if (matchHost) {
|
||||||
|
newRule.matchHost = matchHost;
|
||||||
|
}
|
||||||
|
newRule[suffix] = env[envName];
|
||||||
|
hostRules.push(newRule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hostRules;
|
||||||
|
}
|
Loading…
Reference in a new issue