From 51b2d09e0f8e2528fd135123dada02523c99a37d Mon Sep 17 00:00:00 2001 From: Oleg Krivtsov <olegkrivtsov@gmail.com> Date: Wed, 24 Nov 2021 12:40:03 +0700 Subject: [PATCH] feat(platform): get file branchOrTag (#12710) --- lib/platform/azure/index.spec.ts | 16 ++ lib/platform/azure/index.ts | 8 +- .../__snapshots__/index.spec.ts.snap | 164 ++++++++++++++++++ lib/platform/bitbucket-server/index.spec.ts | 41 +++++ lib/platform/bitbucket-server/index.ts | 11 +- .../__snapshots__/index.spec.ts.snap | 52 ++++++ lib/platform/bitbucket/index.spec.ts | 24 +++ lib/platform/bitbucket/index.ts | 11 +- lib/platform/gitea/index.spec.ts | 21 +++ lib/platform/gitea/index.ts | 11 +- .../github/__snapshots__/index.spec.ts.snap | 122 +++++++++++++ lib/platform/github/index.spec.ts | 31 ++++ lib/platform/github/index.ts | 11 +- .../gitlab/__snapshots__/index.spec.ts.snap | 54 ++++++ lib/platform/gitlab/index.spec.ts | 36 ++++ lib/platform/gitlab/index.ts | 11 +- lib/platform/types.ts | 12 +- 17 files changed, 611 insertions(+), 25 deletions(-) diff --git a/lib/platform/azure/index.spec.ts b/lib/platform/azure/index.spec.ts index 4a4d8bcc55..f9946440b6 100644 --- a/lib/platform/azure/index.spec.ts +++ b/lib/platform/azure/index.spec.ts @@ -1245,6 +1245,7 @@ describe('platform/azure/index', () => { const res = await azure.getJsonFile('file.json'); expect(res).toEqual(data); }); + it('returns file content in json5 format', async () => { const json5Data = ` { @@ -1263,6 +1264,21 @@ describe('platform/azure/index', () => { const res = await azure.getJsonFile('file.json5'); expect(res).toEqual({ foo: 'bar' }); }); + + it('ignores branchOrTag', async () => { + const data = { foo: 'bar' }; + azureApi.gitApi.mockImplementationOnce( + () => + ({ + getItemContent: jest.fn(() => + Promise.resolve(Readable.from(JSON.stringify(data))) + ), + } as any) + ); + const res = await azure.getJsonFile('file.json', undefined, 'dev'); + expect(res).toEqual(data); + }); + it('throws on malformed JSON', async () => { azureApi.gitApi.mockImplementationOnce( () => diff --git a/lib/platform/azure/index.ts b/lib/platform/azure/index.ts index adacb465fe..cccec641fd 100644 --- a/lib/platform/azure/index.ts +++ b/lib/platform/azure/index.ts @@ -113,7 +113,8 @@ export async function getRepos(): Promise<string[]> { export async function getRawFile( fileName: string, - repoName?: string + repoName?: string, + branchOrTag?: string ): Promise<string | null> { const azureApiGit = await azureApi.gitApi(); @@ -133,9 +134,10 @@ export async function getRawFile( export async function getJsonFile( fileName: string, - repoName?: string + repoName?: string, + branchOrTag?: string ): Promise<any | null> { - const raw = await getRawFile(fileName, repoName); + const raw = await getRawFile(fileName, repoName, branchOrTag); if (fileName.endsWith('.json5')) { return JSON5.parse(raw); } diff --git a/lib/platform/bitbucket-server/__snapshots__/index.spec.ts.snap b/lib/platform/bitbucket-server/__snapshots__/index.spec.ts.snap index ac53786634..e1dba3d9a6 100644 --- a/lib/platform/bitbucket-server/__snapshots__/index.spec.ts.snap +++ b/lib/platform/bitbucket-server/__snapshots__/index.spec.ts.snap @@ -2027,6 +2027,47 @@ Array [ ] `; +exports[`platform/bitbucket-server/index endpoint with no path getJsonFile() ignores branchOrTag argument 1`] = ` +Array [ + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Basic YWJjOjEyMw==", + "host": "stash.renovatebot.com", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + "x-atlassian-token": "no-check", + }, + "method": "GET", + "url": "https://stash.renovatebot.com/rest/api/1.0/projects/SOME/repos/repo", + }, + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Basic YWJjOjEyMw==", + "host": "stash.renovatebot.com", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + "x-atlassian-token": "no-check", + }, + "method": "GET", + "url": "https://stash.renovatebot.com/rest/api/1.0/projects/SOME/repos/repo/branches/default", + }, + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Basic YWJjOjEyMw==", + "host": "stash.renovatebot.com", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + "x-atlassian-token": "no-check", + }, + "method": "GET", + "url": "https://stash.renovatebot.com/rest/api/1.0/projects/SOME/repos/repo/browse/file.json?limit=20000", + }, +] +`; + exports[`platform/bitbucket-server/index endpoint with no path getJsonFile() returns file content 1`] = ` Array [ Object { @@ -2068,6 +2109,47 @@ Array [ ] `; +exports[`platform/bitbucket-server/index endpoint with no path getJsonFile() returns file content from given repo 1`] = ` +Array [ + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Basic YWJjOjEyMw==", + "host": "stash.renovatebot.com", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + "x-atlassian-token": "no-check", + }, + "method": "GET", + "url": "https://stash.renovatebot.com/rest/api/1.0/projects/SOME/repos/repo", + }, + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Basic YWJjOjEyMw==", + "host": "stash.renovatebot.com", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + "x-atlassian-token": "no-check", + }, + "method": "GET", + "url": "https://stash.renovatebot.com/rest/api/1.0/projects/SOME/repos/repo/branches/default", + }, + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Basic YWJjOjEyMw==", + "host": "stash.renovatebot.com", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + "x-atlassian-token": "no-check", + }, + "method": "GET", + "url": "https://stash.renovatebot.com/rest/api/1.0/projects/DIFFERENT/repos/repo/browse/file.json?limit=20000", + }, +] +`; + exports[`platform/bitbucket-server/index endpoint with no path getJsonFile() returns file content in json5 format 1`] = ` Array [ Object { @@ -6443,6 +6525,47 @@ Array [ ] `; +exports[`platform/bitbucket-server/index endpoint with path getJsonFile() ignores branchOrTag argument 1`] = ` +Array [ + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Basic YWJjOjEyMw==", + "host": "stash.renovatebot.com", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + "x-atlassian-token": "no-check", + }, + "method": "GET", + "url": "https://stash.renovatebot.com/vcs/rest/api/1.0/projects/SOME/repos/repo", + }, + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Basic YWJjOjEyMw==", + "host": "stash.renovatebot.com", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + "x-atlassian-token": "no-check", + }, + "method": "GET", + "url": "https://stash.renovatebot.com/vcs/rest/api/1.0/projects/SOME/repos/repo/branches/default", + }, + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Basic YWJjOjEyMw==", + "host": "stash.renovatebot.com", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + "x-atlassian-token": "no-check", + }, + "method": "GET", + "url": "https://stash.renovatebot.com/vcs/rest/api/1.0/projects/SOME/repos/repo/browse/file.json?limit=20000", + }, +] +`; + exports[`platform/bitbucket-server/index endpoint with path getJsonFile() returns file content 1`] = ` Array [ Object { @@ -6484,6 +6607,47 @@ Array [ ] `; +exports[`platform/bitbucket-server/index endpoint with path getJsonFile() returns file content from given repo 1`] = ` +Array [ + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Basic YWJjOjEyMw==", + "host": "stash.renovatebot.com", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + "x-atlassian-token": "no-check", + }, + "method": "GET", + "url": "https://stash.renovatebot.com/vcs/rest/api/1.0/projects/SOME/repos/repo", + }, + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Basic YWJjOjEyMw==", + "host": "stash.renovatebot.com", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + "x-atlassian-token": "no-check", + }, + "method": "GET", + "url": "https://stash.renovatebot.com/vcs/rest/api/1.0/projects/SOME/repos/repo/branches/default", + }, + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Basic YWJjOjEyMw==", + "host": "stash.renovatebot.com", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + "x-atlassian-token": "no-check", + }, + "method": "GET", + "url": "https://stash.renovatebot.com/vcs/rest/api/1.0/projects/DIFFERENT/repos/repo/browse/file.json?limit=20000", + }, +] +`; + exports[`platform/bitbucket-server/index endpoint with path getJsonFile() returns file content in json5 format 1`] = ` Array [ Object { diff --git a/lib/platform/bitbucket-server/index.spec.ts b/lib/platform/bitbucket-server/index.spec.ts index 2f77e0e4d0..cdd64adf09 100644 --- a/lib/platform/bitbucket-server/index.spec.ts +++ b/lib/platform/bitbucket-server/index.spec.ts @@ -2109,6 +2109,7 @@ Followed by some information. expect(res).toEqual(data); expect(httpMock.getTrace()).toMatchSnapshot(); }); + it('returns file content in json5 format', async () => { const json5Data = ` { @@ -2129,6 +2130,46 @@ Followed by some information. expect(res).toEqual({ foo: 'bar' }); expect(httpMock.getTrace()).toMatchSnapshot(); }); + + it('returns file content from given repo', async () => { + const data = { foo: 'bar' }; + const scope = await initRepo(); + scope + .get( + `${urlPath}/rest/api/1.0/projects/DIFFERENT/repos/repo/browse/file.json?limit=20000` + ) + .reply(200, { + isLastPage: true, + lines: [{ text: JSON.stringify(data) }], + }); + const res = await bitbucket.getJsonFile( + 'file.json', + 'DIFFERENT/repo' + ); + expect(res).toEqual(data); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + + it('ignores branchOrTag argument', async () => { + const data = { foo: 'bar' }; + const scope = await initRepo(); + scope + .get( + `${urlPath}/rest/api/1.0/projects/SOME/repos/repo/browse/file.json?limit=20000` + ) + .reply(200, { + isLastPage: true, + lines: [{ text: JSON.stringify(data) }], + }); + const res = await bitbucket.getJsonFile( + 'file.json', + 'SOME/repo', + 'dev' + ); + expect(res).toEqual(data); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + it('throws on malformed JSON', async () => { const scope = await initRepo(); scope diff --git a/lib/platform/bitbucket-server/index.ts b/lib/platform/bitbucket-server/index.ts index 5b06c01dbc..f7d2a194da 100644 --- a/lib/platform/bitbucket-server/index.ts +++ b/lib/platform/bitbucket-server/index.ts @@ -123,9 +123,11 @@ export async function getRepos(): Promise<string[]> { export async function getRawFile( fileName: string, - repoName: string = config.repository + repoName?: string, + branchOrTag?: string ): Promise<string | null> { - const [project, slug] = repoName.split('/'); + const repo = repoName ?? config.repository; + const [project, slug] = repo.split('/'); const fileUrl = `./rest/api/1.0/projects/${project}/repos/${slug}/browse/${fileName}?limit=20000`; const res = await bitbucketServerHttp.getJson<FileData>(fileUrl); const { isLastPage, lines, size } = res.body; @@ -139,9 +141,10 @@ export async function getRawFile( export async function getJsonFile( fileName: string, - repoName: string = config.repository + repoName?: string, + branchOrTag?: string ): Promise<any | null> { - const raw = await getRawFile(fileName, repoName); + const raw = await getRawFile(fileName, repoName, branchOrTag); if (fileName.endsWith('.json5')) { return JSON5.parse(raw); } diff --git a/lib/platform/bitbucket/__snapshots__/index.spec.ts.snap b/lib/platform/bitbucket/__snapshots__/index.spec.ts.snap index 44df44b929..5a3567ff52 100644 --- a/lib/platform/bitbucket/__snapshots__/index.spec.ts.snap +++ b/lib/platform/bitbucket/__snapshots__/index.spec.ts.snap @@ -912,6 +912,32 @@ Array [ ] `; +exports[`platform/bitbucket/index getJsonFile() ignores branchOrTag 1`] = ` +Array [ + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Basic YWJjOjEyMw==", + "host": "api.bitbucket.org", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + }, + "method": "GET", + "url": "https://api.bitbucket.org/2.0/repositories/some/repo", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "authorization": "Basic YWJjOjEyMw==", + "host": "api.bitbucket.org", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + }, + "method": "GET", + "url": "https://api.bitbucket.org/2.0/repositories/some/repo/src/HEAD/file.json", + }, +] +`; + exports[`platform/bitbucket/index getJsonFile() returns file content 1`] = ` Array [ Object { @@ -938,6 +964,32 @@ Array [ ] `; +exports[`platform/bitbucket/index getJsonFile() returns file content from given repo 1`] = ` +Array [ + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Basic YWJjOjEyMw==", + "host": "api.bitbucket.org", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + }, + "method": "GET", + "url": "https://api.bitbucket.org/2.0/repositories/some/repo", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "authorization": "Basic YWJjOjEyMw==", + "host": "api.bitbucket.org", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + }, + "method": "GET", + "url": "https://api.bitbucket.org/2.0/repositories/different/repo/src/HEAD/file.json", + }, +] +`; + exports[`platform/bitbucket/index getJsonFile() returns file content in json5 format 1`] = ` Array [ Object { diff --git a/lib/platform/bitbucket/index.spec.ts b/lib/platform/bitbucket/index.spec.ts index 2f8bda30a3..05cc557e71 100644 --- a/lib/platform/bitbucket/index.spec.ts +++ b/lib/platform/bitbucket/index.spec.ts @@ -938,6 +938,7 @@ describe('platform/bitbucket/index', () => { expect(res).toEqual(data); expect(httpMock.getTrace()).toMatchSnapshot(); }); + it('returns file content in json5 format', async () => { const json5Data = ` { @@ -953,6 +954,29 @@ describe('platform/bitbucket/index', () => { expect(res).toEqual({ foo: 'bar' }); expect(httpMock.getTrace()).toMatchSnapshot(); }); + + it('returns file content from given repo', async () => { + const data = { foo: 'bar' }; + const scope = await initRepoMock(); + scope + .get('/2.0/repositories/different/repo/src/HEAD/file.json') + .reply(200, JSON.stringify(data)); + const res = await bitbucket.getJsonFile('file.json', 'different/repo'); + expect(res).toEqual(data); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + + it('ignores branchOrTag', async () => { + const data = { foo: 'bar' }; + const scope = await initRepoMock(); + scope + .get('/2.0/repositories/some/repo/src/HEAD/file.json') + .reply(200, JSON.stringify(data)); + const res = await bitbucket.getJsonFile('file.json', 'some/repo', 'dev'); + expect(res).toEqual(data); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + it('throws on malformed JSON', async () => { const scope = await initRepoMock(); scope diff --git a/lib/platform/bitbucket/index.ts b/lib/platform/bitbucket/index.ts index 4ec06444c1..31b36a17ff 100644 --- a/lib/platform/bitbucket/index.ts +++ b/lib/platform/bitbucket/index.ts @@ -110,20 +110,23 @@ export async function getRepos(): Promise<string[]> { export async function getRawFile( fileName: string, - repoName: string = config.repository + repoName?: string, + branchOrTag?: string ): Promise<string | null> { // See: https://developer.atlassian.com/bitbucket/api/2/reference/resource/repositories/%7Bworkspace%7D/%7Brepo_slug%7D/src/%7Bcommit%7D/%7Bpath%7D + const repo = repoName ?? config.repository; const path = fileName; - const url = `/2.0/repositories/${repoName}/src/HEAD/${path}`; + const url = `/2.0/repositories/${repo}/src/HEAD/${path}`; const res = await bitbucketHttp.get(url); return res.body; } export async function getJsonFile( fileName: string, - repoName: string = config.repository + repoName?: string, + branchOrTag?: string ): Promise<any | null> { - const raw = await getRawFile(fileName, repoName); + const raw = await getRawFile(fileName, repoName, branchOrTag); if (fileName.endsWith('.json5')) { return JSON5.parse(raw); } diff --git a/lib/platform/gitea/index.spec.ts b/lib/platform/gitea/index.spec.ts index 01af9de574..871c400d02 100644 --- a/lib/platform/gitea/index.spec.ts +++ b/lib/platform/gitea/index.spec.ts @@ -1527,6 +1527,27 @@ describe('platform/gitea/index', () => { const res = await gitea.getJsonFile('file.json'); expect(res).toEqual(data); }); + + it('returns file content from given repo', async () => { + const data = { foo: 'bar' }; + helper.getRepoContents.mockResolvedValueOnce({ + contentString: JSON.stringify(data), + } as never); + await initFakeRepo({ full_name: 'different/repo' }); + const res = await gitea.getJsonFile('file.json', 'different/repo'); + expect(res).toEqual(data); + }); + + it('ignores branchOrTag', async () => { + const data = { foo: 'bar' }; + helper.getRepoContents.mockResolvedValueOnce({ + contentString: JSON.stringify(data), + } as never); + await initFakeRepo({ full_name: 'some/repo' }); + const res = await gitea.getJsonFile('file.json', 'some/repo', 'dev'); + expect(res).toEqual(data); + }); + it('returns file content in json5 format', async () => { const json5Data = ` { diff --git a/lib/platform/gitea/index.ts b/lib/platform/gitea/index.ts index e006e8883d..9ed3cd688c 100644 --- a/lib/platform/gitea/index.ts +++ b/lib/platform/gitea/index.ts @@ -211,17 +211,20 @@ const platform: Platform = { async getRawFile( fileName: string, - repoName: string = config.repository + repoName?: string, + branchOrTag?: string ): Promise<string | null> { - const contents = await helper.getRepoContents(repoName, fileName); + const repo = repoName ?? config.repository; + const contents = await helper.getRepoContents(repo, fileName); return contents.contentString; }, async getJsonFile( fileName: string, - repoName: string = config.repository + repoName?: string, + branchOrTag?: string ): Promise<any | null> { - const raw = await platform.getRawFile(fileName, repoName); + const raw = await platform.getRawFile(fileName, repoName, branchOrTag); if (fileName.endsWith('.json5')) { return JSON5.parse(raw); } diff --git a/lib/platform/github/__snapshots__/index.spec.ts.snap b/lib/platform/github/__snapshots__/index.spec.ts.snap index 57fcf445b0..e95821a17a 100644 --- a/lib/platform/github/__snapshots__/index.spec.ts.snap +++ b/lib/platform/github/__snapshots__/index.spec.ts.snap @@ -4945,6 +4945,67 @@ Array [ ] `; +exports[`platform/github/index getJsonFile() ignores branchOrTag 1`] = ` +Array [ + Object { + "graphql": Object { + "query": Object { + "__vars": Object { + "$name": "String!", + "$owner": "String!", + }, + "repository": Object { + "__args": Object { + "name": "$name", + "owner": "$owner", + }, + "autoMergeAllowed": null, + "defaultBranchRef": Object { + "name": null, + "target": Object { + "oid": null, + }, + }, + "hasIssuesEnabled": null, + "isArchived": null, + "isFork": null, + "mergeCommitAllowed": null, + "nameWithOwner": null, + "rebaseMergeAllowed": null, + "squashMergeAllowed": null, + }, + }, + "variables": Object { + "name": "repo", + "owner": "some", + }, + }, + "headers": Object { + "accept": "application/vnd.github.v3+json", + "accept-encoding": "gzip, deflate, br", + "authorization": "token 123test", + "content-length": "395", + "content-type": "application/json", + "host": "api.github.com", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + }, + "method": "POST", + "url": "https://api.github.com/graphql", + }, + Object { + "headers": Object { + "accept": "application/vnd.github.v3+json", + "accept-encoding": "gzip, deflate, br", + "authorization": "token 123test", + "host": "api.github.com", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + }, + "method": "GET", + "url": "https://api.github.com/repos/some/repo/contents/file.json", + }, +] +`; + exports[`platform/github/index getJsonFile() returns file content 1`] = ` Array [ Object { @@ -5006,6 +5067,67 @@ Array [ ] `; +exports[`platform/github/index getJsonFile() returns file content from given repo 1`] = ` +Array [ + Object { + "graphql": Object { + "query": Object { + "__vars": Object { + "$name": "String!", + "$owner": "String!", + }, + "repository": Object { + "__args": Object { + "name": "$name", + "owner": "$owner", + }, + "autoMergeAllowed": null, + "defaultBranchRef": Object { + "name": null, + "target": Object { + "oid": null, + }, + }, + "hasIssuesEnabled": null, + "isArchived": null, + "isFork": null, + "mergeCommitAllowed": null, + "nameWithOwner": null, + "rebaseMergeAllowed": null, + "squashMergeAllowed": null, + }, + }, + "variables": Object { + "name": "repo", + "owner": "different", + }, + }, + "headers": Object { + "accept": "application/vnd.github.v3+json", + "accept-encoding": "gzip, deflate, br", + "authorization": "token 123test", + "content-length": "400", + "content-type": "application/json", + "host": "api.github.com", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + }, + "method": "POST", + "url": "https://api.github.com/graphql", + }, + Object { + "headers": Object { + "accept": "application/vnd.github.v3+json", + "accept-encoding": "gzip, deflate, br", + "authorization": "token 123test", + "host": "api.github.com", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + }, + "method": "GET", + "url": "https://api.github.com/repos/different/repo/contents/file.json", + }, +] +`; + exports[`platform/github/index getJsonFile() returns file content in json5 format 1`] = ` Array [ Object { diff --git a/lib/platform/github/index.spec.ts b/lib/platform/github/index.spec.ts index 1f4cb3419d..a16ab9c08e 100644 --- a/lib/platform/github/index.spec.ts +++ b/lib/platform/github/index.spec.ts @@ -2410,6 +2410,7 @@ describe('platform/github/index', () => { expect(res).toEqual(data); expect(httpMock.getTrace()).toMatchSnapshot(); }); + it('returns file content in json5 format', async () => { const json5Data = ` { @@ -2427,6 +2428,36 @@ describe('platform/github/index', () => { expect(res).toEqual({ foo: 'bar' }); expect(httpMock.getTrace()).toMatchSnapshot(); }); + + it('returns file content from given repo', async () => { + const data = { foo: 'bar' }; + const scope = httpMock.scope(githubApiHost); + initRepoMock(scope, 'different/repo'); + await github.initRepo({ + repository: 'different/repo', + token: 'token', + } as any); + scope.get('/repos/different/repo/contents/file.json').reply(200, { + content: Buffer.from(JSON.stringify(data)).toString('base64'), + }); + const res = await github.getJsonFile('file.json', 'different/repo'); + expect(res).toEqual(data); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + + it('ignores branchOrTag', async () => { + const data = { foo: 'bar' }; + const scope = httpMock.scope(githubApiHost); + initRepoMock(scope, 'some/repo'); + await github.initRepo({ repository: 'some/repo', token: 'token' } as any); + scope.get('/repos/some/repo/contents/file.json').reply(200, { + content: Buffer.from(JSON.stringify(data)).toString('base64'), + }); + const res = await github.getJsonFile('file.json', 'some/repo', 'dev'); + expect(res).toEqual(data); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + it('throws on malformed JSON', async () => { const scope = httpMock.scope(githubApiHost); initRepoMock(scope, 'some/repo'); diff --git a/lib/platform/github/index.ts b/lib/platform/github/index.ts index e6b50f7f87..4ead5ef8fa 100644 --- a/lib/platform/github/index.ts +++ b/lib/platform/github/index.ts @@ -173,9 +173,11 @@ async function getBranchProtection( export async function getRawFile( fileName: string, - repoName: string = config.repository + repoName?: string, + branchOrTag?: string ): Promise<string | null> { - const url = `repos/${repoName}/contents/${fileName}`; + const repo = repoName ?? config.repository; + const url = `repos/${repo}/contents/${fileName}`; const res = await githubApi.getJson<{ content: string }>(url); const buf = res.body.content; const str = Buffer.from(buf, 'base64').toString(); @@ -184,9 +186,10 @@ export async function getRawFile( export async function getJsonFile( fileName: string, - repoName: string = config.repository + repoName?: string, + branchOrTag?: string ): Promise<any | null> { - const raw = await getRawFile(fileName, repoName); + const raw = await getRawFile(fileName, repoName, branchOrTag); if (fileName.endsWith('.json5')) { return JSON5.parse(raw); } diff --git a/lib/platform/gitlab/__snapshots__/index.spec.ts.snap b/lib/platform/gitlab/__snapshots__/index.spec.ts.snap index 35afb53a28..9a4910787a 100644 --- a/lib/platform/gitlab/__snapshots__/index.spec.ts.snap +++ b/lib/platform/gitlab/__snapshots__/index.spec.ts.snap @@ -2272,6 +2272,33 @@ Array [ ] `; +exports[`platform/gitlab/index getJsonFile() ingores branchOrTag 1`] = ` +Array [ + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Bearer 123test", + "host": "gitlab.com", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + }, + "method": "GET", + "url": "https://gitlab.com/api/v4/projects/some%2Frepo", + }, + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Bearer 123test", + "host": "gitlab.com", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + }, + "method": "GET", + "url": "https://gitlab.com/api/v4/projects/some%2Frepo/repository/files/dir%2Ffile.json?ref=HEAD", + }, +] +`; + exports[`platform/gitlab/index getJsonFile() returns file content 1`] = ` Array [ Object { @@ -2299,6 +2326,33 @@ Array [ ] `; +exports[`platform/gitlab/index getJsonFile() returns file content from given repo 1`] = ` +Array [ + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Bearer 123test", + "host": "gitlab.com", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + }, + "method": "GET", + "url": "https://gitlab.com/api/v4/projects/some%2Frepo", + }, + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Bearer 123test", + "host": "gitlab.com", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + }, + "method": "GET", + "url": "https://gitlab.com/api/v4/projects/different%2Frepo/repository/files/dir%2Ffile.json?ref=HEAD", + }, +] +`; + exports[`platform/gitlab/index getJsonFile() returns file content in json5 format 1`] = ` Array [ Object { diff --git a/lib/platform/gitlab/index.spec.ts b/lib/platform/gitlab/index.spec.ts index f269426ed3..e4f42a6791 100644 --- a/lib/platform/gitlab/index.spec.ts +++ b/lib/platform/gitlab/index.spec.ts @@ -1984,6 +1984,7 @@ These updates have all been created already. Click a checkbox below to force a r expect(res).toEqual(data); expect(httpMock.getTrace()).toMatchSnapshot(); }); + it('returns file content in json5 format', async () => { const json5Data = ` { @@ -2003,6 +2004,41 @@ These updates have all been created already. Click a checkbox below to force a r expect(res).toEqual({ foo: 'bar' }); expect(httpMock.getTrace()).toMatchSnapshot(); }); + + it('returns file content from given repo', async () => { + const data = { foo: 'bar' }; + const scope = await initRepo(); + scope + .get( + '/api/v4/projects/different%2Frepo/repository/files/dir%2Ffile.json?ref=HEAD' + ) + .reply(200, { + content: Buffer.from(JSON.stringify(data)).toString('base64'), + }); + const res = await gitlab.getJsonFile('dir/file.json', 'different%2Frepo'); + expect(res).toEqual(data); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + + it('ingores branchOrTag', async () => { + const data = { foo: 'bar' }; + const scope = await initRepo(); + scope + .get( + '/api/v4/projects/some%2Frepo/repository/files/dir%2Ffile.json?ref=HEAD' + ) + .reply(200, { + content: Buffer.from(JSON.stringify(data)).toString('base64'), + }); + const res = await gitlab.getJsonFile( + 'dir/file.json', + 'some%2Frepo', + 'dev' + ); + expect(res).toEqual(data); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + it('throws on malformed JSON', async () => { const scope = await initRepo(); scope diff --git a/lib/platform/gitlab/index.ts b/lib/platform/gitlab/index.ts index 447e59dd4b..059c3b54de 100644 --- a/lib/platform/gitlab/index.ts +++ b/lib/platform/gitlab/index.ts @@ -157,10 +157,12 @@ function urlEscape(str: string): string { export async function getRawFile( fileName: string, - repoName: string = config.repository + repoName?: string, + branchOrTag?: string ): Promise<string | null> { const escapedFileName = urlEscape(fileName); - const url = `projects/${repoName}/repository/files/${escapedFileName}?ref=HEAD`; + const repo = repoName ?? config.repository; + const url = `projects/${repo}/repository/files/${escapedFileName}?ref=HEAD`; const res = await gitlabApi.getJson<{ content: string }>(url); const buf = res.body.content; const str = Buffer.from(buf, 'base64').toString(); @@ -169,9 +171,10 @@ export async function getRawFile( export async function getJsonFile( fileName: string, - repoName: string = config.repository + repoName?: string, + branchOrTag?: string ): Promise<any | null> { - const raw = await getRawFile(fileName, repoName); + const raw = await getRawFile(fileName, repoName, branchOrTag); if (fileName.endsWith('.json5')) { return JSON5.parse(raw); } diff --git a/lib/platform/types.ts b/lib/platform/types.ts index 86768972bc..0c0936e446 100644 --- a/lib/platform/types.ts +++ b/lib/platform/types.ts @@ -153,8 +153,16 @@ export interface Platform { getIssueList(): Promise<Issue[]>; getIssue?(number: number, useCache?: boolean): Promise<Issue>; getVulnerabilityAlerts(): Promise<VulnerabilityAlert[]>; - getRawFile(fileName: string, repoName?: string): Promise<string | null>; - getJsonFile(fileName: string, repoName?: string): Promise<any | null>; + getRawFile( + fileName: string, + repoName?: string, + branchOrTag?: string + ): Promise<string | null>; + getJsonFile( + fileName: string, + repoName?: string, + branchOrTag?: string + ): Promise<any | null>; initRepo(config: RepoParams): Promise<RepoResult>; getPrList(): Promise<Pr[]>; ensureIssueClosing(title: string): Promise<void>; -- GitLab