Skip to content

Commit

Permalink
fix(azure): getRawFile not handling 404 for Azure DevOps (#30066)
Browse files Browse the repository at this point in the history
  • Loading branch information
sindrekroknes authored Jul 9, 2024
1 parent d65effa commit f444036
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ exports[`modules/platform/azure/index getJsonFile() supports fetch from another
undefined,
undefined,
undefined,
true,
],
]
`;
Expand Down
93 changes: 48 additions & 45 deletions lib/modules/platform/azure/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = `
{
Expand All @@ -1905,71 +1914,65 @@ 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' });
});

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 () => {
Expand Down
25 changes: 12 additions & 13 deletions lib/modules/platform/azure/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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>')
Expand Down

0 comments on commit f444036

Please sign in to comment.