From f4440364e8d51a1c0ce2ec77c9f815a9711ca359 Mon Sep 17 00:00:00 2001 From: sindrekroknes <143387557+sindrekroknes@users.noreply.github.com> Date: Tue, 9 Jul 2024 11:43:29 +0200 Subject: [PATCH] fix(azure): getRawFile not handling 404 for Azure DevOps (#30066) --- .../azure/__snapshots__/index.spec.ts.snap | 1 + lib/modules/platform/azure/index.spec.ts | 93 ++++++++++--------- lib/modules/platform/azure/index.ts | 25 +++-- 3 files changed, 61 insertions(+), 58 deletions(-) diff --git a/lib/modules/platform/azure/__snapshots__/index.spec.ts.snap b/lib/modules/platform/azure/__snapshots__/index.spec.ts.snap index 1475060660..bc735f9bbd 100644 --- a/lib/modules/platform/azure/__snapshots__/index.spec.ts.snap +++ b/lib/modules/platform/azure/__snapshots__/index.spec.ts.snap @@ -147,6 +147,7 @@ exports[`modules/platform/azure/index getJsonFile() supports fetch from another undefined, undefined, undefined, + true, ], ] `; diff --git a/lib/modules/platform/azure/index.spec.ts b/lib/modules/platform/azure/index.spec.ts index 934cb93e8c..a30bdfce5f 100644 --- a/lib/modules/platform/azure/index.spec.ts +++ b/lib/modules/platform/azure/index.spec.ts @@ -1886,17 +1886,26 @@ describe('modules/platform/azure/index', () => { it('returns file content', async () => { const data = { foo: 'bar' }; azureApi.gitApi.mockImplementationOnce( - () => - ({ - getItemContent: jest.fn(() => - Promise.resolve(Readable.from(JSON.stringify(data))), - ), - }) as any, + jest.fn().mockImplementationOnce(() => ({ + getItem: jest.fn(() => + Promise.resolve({ content: JSON.stringify(data) }), + ), + })), ); const res = await azure.getJsonFile('file.json'); expect(res).toEqual(data); }); + it('returns null when file not found', async () => { + azureApi.gitApi.mockImplementationOnce( + jest.fn().mockImplementationOnce(() => ({ + getItem: jest.fn(() => Promise.resolve(null)), + })), + ); + const res = await azure.getJsonFile('file.json'); + expect(res).toBeNull(); + }); + it('returns file content in json5 format', async () => { const json5Data = ` { @@ -1905,12 +1914,9 @@ describe('modules/platform/azure/index', () => { } `; azureApi.gitApi.mockImplementationOnce( - () => - ({ - getItemContent: jest.fn(() => - Promise.resolve(Readable.from(json5Data)), - ), - }) as any, + jest.fn().mockImplementationOnce(() => ({ + getItem: jest.fn(() => Promise.resolve({ content: json5Data })), + })), ); const res = await azure.getJsonFile('file.json5'); expect(res).toEqual({ foo: 'bar' }); @@ -1918,58 +1924,55 @@ describe('modules/platform/azure/index', () => { it('returns file content from branch or tag', async () => { const data = { foo: 'bar' }; - azureApi.gitApi.mockImplementationOnce( - () => - ({ - getItemContent: jest.fn(() => - Promise.resolve(Readable.from(JSON.stringify(data))), - ), - }) as any, + azureApi.gitApi.mockResolvedValueOnce( + partial<IGitApi>({ + getItem: jest.fn(() => + Promise.resolve({ content: JSON.stringify(data) }), + ), + }), ); const res = await azure.getJsonFile('file.json', undefined, 'dev'); expect(res).toEqual(data); }); it('throws on malformed JSON', async () => { - azureApi.gitApi.mockImplementationOnce( - () => - ({ - getItemContent: jest.fn(() => - Promise.resolve(Readable.from('!@#')), - ), - }) as any, + azureApi.gitApi.mockResolvedValueOnce( + partial<IGitApi>({ + getItemContent: jest.fn(() => Promise.resolve(Readable.from('!@#'))), + }), ); await expect(azure.getJsonFile('file.json')).rejects.toThrow(); }); it('throws on errors', async () => { - azureApi.gitApi.mockImplementationOnce( - () => - ({ - getItemContent: jest.fn(() => { - throw new Error('some error'); - }), - }) as any, + azureApi.gitApi.mockResolvedValueOnce( + partial<IGitApi>({ + getItemContent: jest.fn(() => { + throw new Error('some error'); + }), + }), ); await expect(azure.getJsonFile('file.json')).rejects.toThrow(); }); it('supports fetch from another repo', async () => { const data = { foo: 'bar' }; - const gitApiMock = { - getItemContent: jest.fn(() => - Promise.resolve(Readable.from(JSON.stringify(data))), - ), - getRepositories: jest.fn(() => - Promise.resolve([ - { id: '123456', name: 'bar', project: { name: 'foo' } }, - ]), - ), - }; - azureApi.gitApi.mockImplementationOnce(() => gitApiMock as any); + const getItemFn = jest + .fn() + .mockResolvedValueOnce({ content: JSON.stringify(data) }); + azureApi.gitApi.mockResolvedValueOnce( + partial<IGitApi>({ + getItem: getItemFn, + getRepositories: jest + .fn() + .mockResolvedValue([ + { id: '123456', name: 'bar', project: { name: 'foo' } }, + ]), + }), + ); const res = await azure.getJsonFile('file.json', 'foo/bar'); expect(res).toEqual(data); - expect(gitApiMock.getItemContent.mock.calls).toMatchSnapshot(); + expect(getItemFn.mock.calls).toMatchSnapshot(); }); it('returns null', async () => { diff --git a/lib/modules/platform/azure/index.ts b/lib/modules/platform/azure/index.ts index f866e0dcdf..36a2313632 100644 --- a/lib/modules/platform/azure/index.ts +++ b/lib/modules/platform/azure/index.ts @@ -22,7 +22,6 @@ import * as git from '../../../util/git'; import * as hostRules from '../../../util/host-rules'; import { regEx } from '../../../util/regex'; import { sanitize } from '../../../util/sanitize'; -import { streamToString } from '../../../util/streams'; import { ensureTrailingSlash } from '../../../util/url'; import type { BranchStatusConfig, @@ -146,20 +145,20 @@ export async function getRawFile( version: branchOrTag, } satisfies GitVersionDescriptor; - const buf = await azureApiGit.getItemContent( - repoId, - fileName, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - branchOrTag ? versionDescriptor : undefined, + const item = await azureApiGit.getItem( + repoId, // repositoryId + fileName, // path + undefined, // project + undefined, // scopePath + undefined, // recursionLevel + undefined, // includeContentMetadata + undefined, // latestProcessedChange + undefined, // download + branchOrTag ? versionDescriptor : undefined, // versionDescriptor + true, // includeContent ); - const str = await streamToString(buf); - return str; + return item?.content ?? null; } catch (err) /* istanbul ignore next */ { if ( err.message?.includes('<title>Azure DevOps Services Unavailable</title>') -- GitLab