diff --git a/docs/usage/config-presets.md b/docs/usage/config-presets.md index abb41cfbe19520e1e2a98318cb217b7da54996f1..aab57a90a7db38e7848fe1f471f2f1f6137bc591 100644 --- a/docs/usage/config-presets.md +++ b/docs/usage/config-presets.md @@ -202,7 +202,6 @@ To host your preset config on Gitea: Renovate also supports local presets, e.g. presets that are hosted on the same platform as the target repository. This is especially helpful in self-hosted scenarios where public presets cannot be used. -Local presets are only supported on GitHub, GitLab, Gitea, Bitbucket Cloud and Bitbucket Server. Local presets are specified either by leaving out any prefix, e.g. `owner/name`, or explicitly by adding a `local>` prefix, e.g. `local>owner/name`. Renovate will determine the current platform and look up the preset from there. diff --git a/lib/config/presets/azure/__snapshots__/index.spec.ts.snap b/lib/config/presets/azure/__snapshots__/index.spec.ts.snap new file mode 100644 index 0000000000000000000000000000000000000000..c9758c77a590f428bbe0c93f90ce73d64ac07364 --- /dev/null +++ b/lib/config/presets/azure/__snapshots__/index.spec.ts.snap @@ -0,0 +1,10 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`config/presets/azure/index fetchJSONFile() returns JSON 1`] = ` +Array [ + Array [ + "123456", + "some-filename.json", + ], +] +`; diff --git a/lib/config/presets/azure/index.spec.ts b/lib/config/presets/azure/index.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..03430d19e06f23f36cb73e0a71d7c0a92e5a9628 --- /dev/null +++ b/lib/config/presets/azure/index.spec.ts @@ -0,0 +1,103 @@ +import { Readable } from 'stream'; +import { getName, mocked } from '../../../../test/util'; +import { setPlatformApi } from '../../../platform'; +import * as _azureApi from '../../../platform/azure/azure-got-wrapper'; +import { PRESET_DEP_NOT_FOUND, PRESET_INVALID_JSON } from '../util'; +import * as azure from '.'; + +jest.unmock('../../../platform'); +jest.mock('../../../platform/azure/azure-got-wrapper'); + +const azureApi = mocked(_azureApi); + +describe(getName(__filename), () => { + beforeAll(() => { + setPlatformApi('azure'); + }); + + describe('fetchJSONFile()', () => { + it('returns JSON', async () => { + const data = { foo: 'bar' }; + const azureApiMock = { + getItemContent: jest.fn(() => + Promise.resolve(Readable.from(JSON.stringify(data))) + ), + getRepositories: jest.fn(() => + Promise.resolve([ + { id: '123456', name: 'repo', project: { name: 'some' } }, + ]) + ), + }; + azureApi.gitApi.mockImplementationOnce(() => azureApiMock as any); + + const res = await azure.fetchJSONFile('some/repo', 'some-filename.json'); + expect(res).toEqual(data); + expect(azureApiMock.getItemContent.mock.calls).toMatchSnapshot(); + }); + + it('throws on error', async () => { + azureApi.gitApi.mockImplementationOnce( + () => + ({ + getItemContent: jest.fn(() => { + throw new Error('unknown'); + }), + getRepositories: jest.fn(() => + Promise.resolve([ + { id: '123456', name: 'repo', project: { name: 'some' } }, + ]) + ), + } as any) + ); + await expect( + azure.fetchJSONFile('some/repo', 'some-filename.json') + ).rejects.toThrow(PRESET_DEP_NOT_FOUND); + }); + + it('throws on invalid json', async () => { + azureApi.gitApi.mockImplementationOnce( + () => + ({ + getItemContent: jest.fn(() => + Promise.resolve(Readable.from('!@#')) + ), + getRepositories: jest.fn(() => + Promise.resolve([ + { id: '123456', name: 'repo', project: { name: 'some' } }, + ]) + ), + } as any) + ); + + await expect( + azure.fetchJSONFile('some/repo', 'some-filename.json') + ).rejects.toThrow(PRESET_INVALID_JSON); + }); + }); + + describe('getPresetFromEndpoint()', () => { + it('uses custom path', async () => { + const data = { foo: 'bar' }; + azureApi.gitApi.mockImplementationOnce( + () => + ({ + getItemContent: jest.fn(() => + Promise.resolve(Readable.from(JSON.stringify(data))) + ), + getRepositories: jest.fn(() => + Promise.resolve([ + { id: '123456', name: 'repo', project: { name: 'some' } }, + ]) + ), + } as any) + ); + const res = await azure.getPresetFromEndpoint( + 'some/repo', + 'some-filename', + 'foo/bar', + '' + ); + expect(res).toEqual(data); + }); + }); +}); diff --git a/lib/config/presets/azure/index.ts b/lib/config/presets/azure/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..683c271510a3ad08fa6fedb453129e14d1306a22 --- /dev/null +++ b/lib/config/presets/azure/index.ts @@ -0,0 +1 @@ +export { fetchJSONFile, getPresetFromEndpoint } from '../local/common'; diff --git a/lib/config/presets/local/__snapshots__/index.spec.ts.snap b/lib/config/presets/local/__snapshots__/index.spec.ts.snap index 83a107844f3de628c6577875f71979839f3f1d62..9560d78b285c99bd28e9f37214446a213e8796c9 100644 --- a/lib/config/presets/local/__snapshots__/index.spec.ts.snap +++ b/lib/config/presets/local/__snapshots__/index.spec.ts.snap @@ -1,5 +1,22 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`config/presets/local/index getPreset() forwards to azure 1`] = ` +Array [ + Array [ + "some/repo", + "default", + undefined, + undefined, + ], +] +`; + +exports[`config/presets/local/index getPreset() forwards to azure 2`] = ` +Object { + "resolved": "preset", +} +`; + exports[`config/presets/local/index getPreset() forwards to bitbucket 1`] = ` Array [ Array [ diff --git a/lib/config/presets/local/index.spec.ts b/lib/config/presets/local/index.spec.ts index 0d72cea5e996c564079871e4fa97d4d6a2e81fd1..743c7334144d6a600c8e6f69eaa2847450a96610 100644 --- a/lib/config/presets/local/index.spec.ts +++ b/lib/config/presets/local/index.spec.ts @@ -1,4 +1,5 @@ import { getName, mocked } from '../../../../test/util'; +import * as _azure from '../azure'; import * as _bitbucket from '../bitbucket'; import * as _bitbucketServer from '../bitbucket-server'; import * as _gitea from '../gitea'; @@ -6,12 +7,14 @@ import * as _github from '../github'; import * as _gitlab from '../gitlab'; import * as local from '.'; +jest.mock('../azure'); jest.mock('../bitbucket'); jest.mock('../bitbucket-server'); jest.mock('../gitea'); jest.mock('../github'); jest.mock('../gitlab'); +const azure = mocked(_azure); const bitbucket = mocked(_bitbucket); const bitbucketServer = mocked(_bitbucketServer); const gitea = mocked(_gitea); @@ -22,6 +25,7 @@ describe(getName(__filename), () => { beforeEach(() => { jest.resetAllMocks(); const preset = { resolved: 'preset' }; + azure.getPresetFromEndpoint.mockResolvedValueOnce(preset); bitbucket.getPresetFromEndpoint.mockResolvedValueOnce(preset); bitbucketServer.getPresetFromEndpoint.mockResolvedValueOnce(preset); gitea.getPresetFromEndpoint.mockResolvedValueOnce(preset); @@ -52,6 +56,18 @@ describe(getName(__filename), () => { }).rejects.toThrow(); }); + it('forwards to azure', async () => { + const content = await local.getPreset({ + packageName: 'some/repo', + presetName: 'default', + baseConfig: { + platform: 'azure', + }, + }); + expect(azure.getPresetFromEndpoint.mock.calls).toMatchSnapshot(); + expect(content).toMatchSnapshot(); + }); + it('forwards to bitbucket', async () => { const content = await local.getPreset({ packageName: 'some/repo', diff --git a/lib/config/presets/local/index.ts b/lib/config/presets/local/index.ts index 87f5822f2bfcc9b6a624a8a945c21f377cd20b81..319d513ce58b70e5b8572eb638d43c6231e5a0aa 100644 --- a/lib/config/presets/local/index.ts +++ b/lib/config/presets/local/index.ts @@ -1,10 +1,12 @@ import { + PLATFORM_TYPE_AZURE, PLATFORM_TYPE_BITBUCKET, PLATFORM_TYPE_BITBUCKET_SERVER, PLATFORM_TYPE_GITEA, PLATFORM_TYPE_GITHUB, PLATFORM_TYPE_GITLAB, } from '../../../constants/platforms'; +import * as azure from '../azure'; import * as bitbucket from '../bitbucket'; import * as bitbucketServer from '../bitbucket-server'; import * as gitea from '../gitea'; @@ -13,6 +15,7 @@ import * as gitlab from '../gitlab'; import type { Preset, PresetConfig } from '../types'; const resolvers = { + [PLATFORM_TYPE_AZURE]: azure, [PLATFORM_TYPE_BITBUCKET]: bitbucket, [PLATFORM_TYPE_BITBUCKET_SERVER]: bitbucketServer, [PLATFORM_TYPE_GITEA]: gitea,