mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-12 06:56:24 +00:00
feat(config): detectGlobalManagerConfig (#11951)
This commit is contained in:
parent
79e65bd0c7
commit
cd72cdf2ac
10 changed files with 113 additions and 0 deletions
|
@ -130,6 +130,15 @@ e.g.
|
|||
|
||||
This configuration will be applied after all other environment variables so that it can be used to override defaults.
|
||||
|
||||
## detectGlobalManagerConfig
|
||||
|
||||
The purpose of this capability is to allow a bot admin to configure manager-specific files such as a global `.npmrc` file, instead of configuring it in Renovate config.
|
||||
|
||||
This feature is disabled by default because it may prove surprising or undesirable for some users who don't expect Renovate to go into their home directory and import registry or credential information.
|
||||
|
||||
Currently this capability is supported for the `npm` manager only - specifically the `~/.npmrc` file.
|
||||
If found, it will be imported into `config.npmrc` with `config.npmrcMerge` will be set to `true`.
|
||||
|
||||
## dockerChildPrefix
|
||||
|
||||
Adds a custom prefix to the default Renovate sidecar Docker containers name and label.
|
||||
|
|
|
@ -7,6 +7,14 @@ import * as pep440Versioning from '../../versioning/pep440';
|
|||
import type { RenovateOptions } from '../types';
|
||||
|
||||
const options: RenovateOptions[] = [
|
||||
{
|
||||
name: 'detectGlobalManagerConfig',
|
||||
description:
|
||||
'If true, Renovate will attempt to read global manager config from the file system.',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
globalOnly: true,
|
||||
},
|
||||
{
|
||||
name: 'allowPostUpgradeCommandTemplating',
|
||||
description: 'If true allow templating for post-upgrade commands.',
|
||||
|
|
|
@ -2,6 +2,8 @@ import { loadModules } from '../util/modules';
|
|||
import type { ManagerApi } from './types';
|
||||
import * as manager from '.';
|
||||
|
||||
jest.mock('../util/fs');
|
||||
|
||||
describe('manager/index', () => {
|
||||
describe('get()', () => {
|
||||
it('gets something', () => {
|
||||
|
@ -43,6 +45,12 @@ describe('manager/index', () => {
|
|||
}
|
||||
});
|
||||
|
||||
describe('detectGlobalConfig()', () => {
|
||||
it('iterates through managers', async () => {
|
||||
expect(await manager.detectAllGlobalConfig()).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('extractAllPackageFiles()', () => {
|
||||
it('returns null', async () => {
|
||||
manager.getManagers().set('dummy', {
|
||||
|
|
|
@ -15,6 +15,7 @@ import type { RangeStrategy } from '../types';
|
|||
import managers from './api';
|
||||
import type {
|
||||
ExtractConfig,
|
||||
GlobalManagerConfig,
|
||||
ManagerApi,
|
||||
PackageFile,
|
||||
RangeConfig,
|
||||
|
@ -47,6 +48,18 @@ export const getLanguageList = (): string[] => languageList;
|
|||
export const getManagerList = (): string[] => managerList;
|
||||
export const getManagers = (): Map<string, ManagerApi> => managers;
|
||||
|
||||
export async function detectAllGlobalConfig(): Promise<GlobalManagerConfig> {
|
||||
let config: GlobalManagerConfig = {};
|
||||
for (const managerName of managerList) {
|
||||
const manager = managers.get(managerName);
|
||||
if (manager.detectGlobalConfig) {
|
||||
// This should use mergeChildConfig once more than one manager is supported, but introduces a cyclic dependency
|
||||
config = { ...config, ...(await manager.detectGlobalConfig()) };
|
||||
}
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
export async function extractAllPackageFiles(
|
||||
manager: string,
|
||||
config: ExtractConfig,
|
||||
|
|
29
lib/manager/npm/detect.spec.ts
Normal file
29
lib/manager/npm/detect.spec.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
import { fs } from '../../../test/util';
|
||||
import { detectGlobalConfig } from './detect';
|
||||
|
||||
jest.mock('../../util/fs');
|
||||
|
||||
describe('manager/npm/detect', () => {
|
||||
describe('.detectGlobalConfig()', () => {
|
||||
it('detects .npmrc in home directory', async () => {
|
||||
fs.readFile.mockResolvedValueOnce(
|
||||
'registry=https://registry.npmjs.org\n'
|
||||
);
|
||||
const res = await detectGlobalConfig();
|
||||
expect(res).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"npmrc": "registry=https://registry.npmjs.org
|
||||
",
|
||||
"npmrcMerge": true,
|
||||
}
|
||||
`);
|
||||
expect(res.npmrc).toBeDefined();
|
||||
expect(res.npmrcMerge).toBe(true);
|
||||
});
|
||||
it('handles no .npmrc', async () => {
|
||||
fs.readFile.mockImplementationOnce(() => Promise.reject());
|
||||
const res = await detectGlobalConfig();
|
||||
expect(res).toEqual({});
|
||||
});
|
||||
});
|
||||
});
|
23
lib/manager/npm/detect.ts
Normal file
23
lib/manager/npm/detect.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
import os from 'os';
|
||||
import is from '@sindresorhus/is';
|
||||
import { join } from 'upath';
|
||||
import { logger } from '../../logger';
|
||||
import { readFile } from '../../util/fs';
|
||||
import { GlobalManagerConfig } from '../types';
|
||||
|
||||
export async function detectGlobalConfig(): Promise<GlobalManagerConfig> {
|
||||
const res: GlobalManagerConfig = {};
|
||||
const homedir = os.homedir();
|
||||
const npmrcFileName = join(homedir, '.npmrc');
|
||||
try {
|
||||
const npmrc = await readFile(npmrcFileName, 'utf8');
|
||||
if (is.nonEmptyString(npmrc)) {
|
||||
res.npmrc = npmrc;
|
||||
res.npmrcMerge = true;
|
||||
logger.debug(`Detected ${npmrcFileName} and adding it to global config`);
|
||||
}
|
||||
} catch (err) {
|
||||
logger.warn({ npmrcFileName }, 'Error reading .npmrc file');
|
||||
}
|
||||
return res;
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
import { LANGUAGE_JAVASCRIPT } from '../../constants/languages';
|
||||
import * as npmVersioning from '../../versioning/npm';
|
||||
|
||||
export { detectGlobalConfig } from './detect';
|
||||
export { extractAllPackageFiles } from './extract';
|
||||
export {
|
||||
bumpPackageVersion,
|
||||
|
|
|
@ -220,6 +220,11 @@ export interface UpdateLockedConfig {
|
|||
newVersion?: string;
|
||||
}
|
||||
|
||||
export interface GlobalManagerConfig {
|
||||
npmrc?: string;
|
||||
npmrcMerge?: boolean;
|
||||
}
|
||||
|
||||
export interface ManagerApi {
|
||||
defaultConfig: Record<string, unknown>;
|
||||
language?: string;
|
||||
|
@ -231,6 +236,8 @@ export interface ManagerApi {
|
|||
bumpVersion: ReleaseType | string
|
||||
): Result<BumpPackageVersionResult>;
|
||||
|
||||
detectGlobalConfig?(): Result<GlobalManagerConfig>;
|
||||
|
||||
extractAllPackageFiles?(
|
||||
config: ExtractConfig,
|
||||
files: string[]
|
||||
|
|
|
@ -3,6 +3,8 @@ import { readFile } from '../../../../util/fs';
|
|||
import getArgv from './__fixtures__/argv';
|
||||
|
||||
jest.mock('../../../../datasource/npm');
|
||||
jest.mock('../../../../util/fs');
|
||||
|
||||
try {
|
||||
jest.mock('../../config.js');
|
||||
} catch (err) {
|
||||
|
@ -118,5 +120,10 @@ describe('workers/global/config/parse/index', () => {
|
|||
const parsed = await configParser.parseConfigs(defaultEnv, defaultArgv);
|
||||
expect(parsed.endpoint).toEqual('https://github.renovatebot.com/api/v3/');
|
||||
});
|
||||
it('parses global manager config', async () => {
|
||||
defaultArgv = defaultArgv.concat(['--detect-global-manager-config=true']);
|
||||
const parsed = await configParser.parseConfigs(defaultEnv, defaultArgv);
|
||||
expect(parsed.npmrc).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,6 +2,7 @@ import * as defaultsParser from '../../../../config/defaults';
|
|||
import { AllConfig } from '../../../../config/types';
|
||||
import { mergeChildConfig } from '../../../../config/utils';
|
||||
import { addStream, logger, setContext } from '../../../../logger';
|
||||
import { detectAllGlobalConfig } from '../../../../manager';
|
||||
import { ensureDir, getSubDirectory, readFile } from '../../../../util/fs';
|
||||
import { ensureTrailingSlash } from '../../../../util/url';
|
||||
import * as cliParser from './cli';
|
||||
|
@ -73,6 +74,13 @@ export async function parseConfigs(
|
|||
logger.debug({ config: envConfig }, 'Env config');
|
||||
logger.debug({ config: combinedConfig }, 'Combined config');
|
||||
|
||||
if (config.detectGlobalManagerConfig) {
|
||||
logger.debug('Detecting global manager config');
|
||||
const globalManagerConfig = await detectAllGlobalConfig();
|
||||
logger.debug({ config: globalManagerConfig }, 'Global manager config');
|
||||
config = mergeChildConfig(config, globalManagerConfig);
|
||||
}
|
||||
|
||||
// Get global config
|
||||
logger.trace({ config }, 'Full config');
|
||||
|
||||
|
|
Loading…
Reference in a new issue