Files
renovate/lib/config/global.ts
Jamie Tanna 238e15a498 feat(config): add inheritConfigTrusted to trust inherited-config hostRules
Renovate deployments that are deployed across multiple organisations may
take advantage of Inherited Config as a means to decentralise some
decisions and/or preferences that their organisations would like to use
for some self-hosted configuration.

Similarly, the decision of which hosts to allowlist may be something
that a self-hosted administrator /may/ want to allow their organisation
admins to decide.

We can make this an opt-in capability to indicate that the self-hosted
administrator trusts the Inherited Config moreso, and allows someone who
can write to it the ability to allowlist access to internal hosts that
may not be intended.

If a self-hosted administrator sets `allowInternal: false`, this takes
precedence, allowing a "veto", and a self-hosted admin's `headers` are
still preferred, too.

It's not possible for Inherited Config to set grants for `extends`, as
config resolution has already occurred, so this still needs to be
performed at the self-hosted config level.

This trust is transitive: `hostRules` defined in presets the
inherited config `extends` are registered at the same inherited
tier once resolved, so this option must only be enabled when those
preset sources are trusted too.

Co-authored-by: Claude Fable 5 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
2026-09-10 14:52:01 +01:00

118 lines
3.2 KiB
TypeScript

import { globalConfigOptionDefaults } from '../global-config-option-defaults.generated.ts';
import type {
InternalGlobalConfigOptions,
RenovateConfig,
RepoGlobalConfig,
} from './types.ts';
export class GlobalConfig {
// TODO: once global config work is complete, add a test to make sure this list includes all options with globalOnly=true (#9603)
static OPTIONS = [
'allowCustomCrateRegistries',
'allowPlugins',
'allowScripts',
'allowShellExecutorForPostUpgradeCommands',
'allowedCommands',
'allowedEnv',
'allowedHeaders',
'allowedUnsafeExecutions',
'autodiscoverRepoOrder',
'autodiscoverRepoSort',
'bbUseDevelopmentBranch',
'binarySource',
'cacheDir',
'cacheHardTtlMinutes',
'cachePrivatePackages',
'cacheTtlOverride',
'checkedBranches',
'configFileNames',
'containerbaseDir',
'customEnvVariables',
'dockerChildPrefix',
'dockerCliOptions',
'dockerMaxPages',
'dockerSidecarImage',
'dockerUser',
'dryRun',
'encryptedWarning',
'endpoint',
'executionTimeout',
'exposeAllEnv',
'gitTimeout',
'githubTokenWarn',
'httpCacheTtlDays',
'ignorePrAuthor',
'includeMirrors',
'inheritConfigTrusted',
'internalHostAccess',
/** NOTE that this is not a config option, but an internal variable **/
'localDir',
'migratePresets',
'onboarding',
'onboardingAutoCloseAge',
'onboardingBranch',
'onboardingCommitMessage',
'onboardingConfig',
'onboardingConfigFileName',
'onboardingNoDeps',
'onboardingPrTitle',
'platform',
'prCacheSyncMaxPages',
'presetCachePersistence',
'productLinks',
'rebaseAllOpenBranches',
'repositoryCacheForceLocal',
'requireConfig',
's3Endpoint',
's3PathStyle',
'toolSettings',
'userAgent',
] as const satisfies readonly (
keyof RepoGlobalConfig | keyof InternalGlobalConfigOptions
)[];
private static config: RepoGlobalConfig & InternalGlobalConfigOptions = {};
static get(): RepoGlobalConfig & InternalGlobalConfigOptions;
static get<
Key extends keyof RepoGlobalConfig | keyof InternalGlobalConfigOptions,
>(key: Key): Required<RepoGlobalConfig & InternalGlobalConfigOptions>[Key];
static get<
Key extends keyof RepoGlobalConfig | keyof InternalGlobalConfigOptions,
>(
key?: Key,
):
| (RepoGlobalConfig & InternalGlobalConfigOptions)
| Required<RepoGlobalConfig & InternalGlobalConfigOptions>[Key] {
const defaultValue = key
? (globalConfigOptionDefaults[key] as Required<
RepoGlobalConfig & InternalGlobalConfigOptions
>[Key])
: undefined;
return key
? ((GlobalConfig.config[key] ?? defaultValue) as Required<
RepoGlobalConfig & InternalGlobalConfigOptions
>[Key])
: GlobalConfig.config;
}
static set(
config: RenovateConfig & RepoGlobalConfig & InternalGlobalConfigOptions,
): RenovateConfig {
GlobalConfig.reset();
const result = { ...config };
for (const option of GlobalConfig.OPTIONS) {
GlobalConfig.config[option] = config[option] as never;
delete result[option];
}
return result;
}
static reset(): void {
GlobalConfig.config = {};
}
}