diff --git a/docs/usage/config-presets.md b/docs/usage/config-presets.md index 2cf5f060ca231d..7fb80d9316816c 100644 --- a/docs/usage/config-presets.md +++ b/docs/usage/config-presets.md @@ -180,6 +180,18 @@ The answer is to host your preset using GitHub or GitLab - not npmjs - and make Have you configured a rule that you think others might benefit from? Please consider contributing it to the [Renovate](https://github.com/renovatebot/renovate) repository so that it gains higher visibility and saves others from reinventing the same thing. -## Organisation level presets +## Organization level presets -When repository onboarding happens, if a repository called `renovate-config` exists under the same organization and contains a default Renovate preset, that repository will be suggested as the the sole extended preset, and any existing `onboardingConfig` config will be ignored/overriden. This allows for a seamless onboarding workflow with your own organization settings. +Whenever repository onboarding happens, Renovate checks if the current user/group/org contains a default config to extend. It looks for: + +- A repository called `renovate-config` under the same user/group/org with either `default.json` or `renovate.json`, or +- A repository named like `.{{platform}}` (e.g. `.github`) under the same user/group/org with `renovate-config.json` + +If found, that repository's preset will be suggested as the the sole extended preset, and any existing `onboardingConfig` config will be ignored/overriden. For example the result may be: + +```json +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": ["local>myorgname/.github:renovate-config"] +} +``` diff --git a/lib/workers/repository/onboarding/branch/config.spec.ts b/lib/workers/repository/onboarding/branch/config.spec.ts index 8c3c7c3d060f20..7a7726b7bea145 100644 --- a/lib/workers/repository/onboarding/branch/config.spec.ts +++ b/lib/workers/repository/onboarding/branch/config.spec.ts @@ -13,22 +13,35 @@ describe('workers/repository/onboarding/branch', () => { beforeEach(() => { jest.clearAllMocks(); config = getConfig(); + config.platform = 'github'; config.repository = 'some/repo'; }); describe('getOnboardingConfig', () => { it('handles finding an organization preset', async () => { + mockedPresets.getPreset.mockResolvedValueOnce({ enabled: true }); onboardingConfig = await getOnboardingConfig(config); expect(mockedPresets.getPreset).toHaveBeenCalledTimes(1); expect(JSON.parse(onboardingConfig).extends[0]).toEqual( 'local>some/renovate-config' ); }); + it('handles finding an organization dot platform preset', async () => { + mockedPresets.getPreset.mockRejectedValueOnce( + new Error(PRESET_DEP_NOT_FOUND) + ); + mockedPresets.getPreset.mockResolvedValueOnce({ enabled: true }); + onboardingConfig = await getOnboardingConfig(config); + expect(mockedPresets.getPreset).toHaveBeenCalledTimes(2); + expect(JSON.parse(onboardingConfig).extends[0]).toEqual( + 'local>some/.github:renovate-config' + ); + }); it('handles not finding an organization preset', async () => { mockedPresets.getPreset.mockRejectedValue( new Error(PRESET_DEP_NOT_FOUND) ); onboardingConfig = await getOnboardingConfig(config); - expect(mockedPresets.getPreset).toHaveBeenCalledTimes(1); + expect(mockedPresets.getPreset).toHaveBeenCalledTimes(2); expect(JSON.parse(onboardingConfig)).toEqual(config.onboardingConfig); }); it('ignores an unknown error', async () => { @@ -36,7 +49,7 @@ describe('workers/repository/onboarding/branch', () => { new Error('unknown error for test') ); onboardingConfig = await getOnboardingConfig(config); - expect(mockedPresets.getPreset).toHaveBeenCalledTimes(1); + expect(mockedPresets.getPreset).toHaveBeenCalledTimes(2); expect(JSON.parse(onboardingConfig)).toEqual(config.onboardingConfig); }); }); diff --git a/lib/workers/repository/onboarding/branch/config.ts b/lib/workers/repository/onboarding/branch/config.ts index 8718cd03a1df27..aab3ba974366e6 100644 --- a/lib/workers/repository/onboarding/branch/config.ts +++ b/lib/workers/repository/onboarding/branch/config.ts @@ -28,6 +28,19 @@ export async function getOnboardingConfig( } } + if (!orgPreset) { + // Check for org/.{{platform}} + try { + const orgDotPlatformConfig = `local>${orgName}/.${config.platform}:renovate-config`; + await getPreset(orgDotPlatformConfig, config); + orgPreset = orgDotPlatformConfig; + } catch (err) { + if (err.message !== PRESET_DEP_NOT_FOUND) { + logger.warn({ err }, 'Unknown error fetching default owner preset'); + } + } + } + if (orgPreset) { onboardingConfig = { $schema: 'https://docs.renovatebot.com/renovate-schema.json',