From b29eaea11913645d3397416a40fa0f7a9ca42902 Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Fri, 29 Nov 2024 16:14:16 +0000 Subject: [PATCH] release-manifests: allow overriding fetch implementation This allows us to use yarn's built in HTTP request utilities in the Backstage yarn plugin, thereby benefiting from the built-in caching and proxy configuration utilities. Signed-off-by: MT Lewis --- .changeset/violet-snakes-laugh.md | 5 +++ packages/release-manifests/report.api.md | 6 ++++ .../release-manifests/src/manifest.test.ts | 31 +++++++++++++++++++ packages/release-manifests/src/manifest.ts | 18 ++++++++--- 4 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 .changeset/violet-snakes-laugh.md diff --git a/.changeset/violet-snakes-laugh.md b/.changeset/violet-snakes-laugh.md new file mode 100644 index 0000000000..7002cfeaf0 --- /dev/null +++ b/.changeset/violet-snakes-laugh.md @@ -0,0 +1,5 @@ +--- +'@backstage/release-manifests': patch +--- + +Allow overriding the fetch function used inside getManifestByVersion diff --git a/packages/release-manifests/report.api.md b/packages/release-manifests/report.api.md index 1ffa35838b..2d2cc00767 100644 --- a/packages/release-manifests/report.api.md +++ b/packages/release-manifests/report.api.md @@ -21,6 +21,12 @@ export function getManifestByVersion( // @public export type GetManifestByVersionOptions = { version: string; + fetch?: ( + url: string, + options?: { + signal?: AbortSignal; + }, + ) => Promise>; }; // @public diff --git a/packages/release-manifests/src/manifest.test.ts b/packages/release-manifests/src/manifest.test.ts index 3c7657a83f..ad5bf13496 100644 --- a/packages/release-manifests/src/manifest.test.ts +++ b/packages/release-manifests/src/manifest.test.ts @@ -55,6 +55,37 @@ describe('Release Manifests', () => { getManifestByVersion({ version: '999.0.1' }), ).rejects.toThrow('No release found for 999.0.1 version'); }); + + it('should allow overriding the fetch implementation', async () => { + const mockFetch = jest.fn().mockImplementation(async url => ({ + status: 200, + url, + json: () => ({ + packages: [{ name: '@backstage/core', version: '2.3.4' }], + }), + })); + + const pkgs = await getManifestByVersion({ + version: '0.0.0', + fetch: mockFetch, + }); + + expect(pkgs.packages).toEqual([ + { + name: '@backstage/core', + version: '2.3.4', + }, + ]); + + mockFetch.mockImplementation(async url => ({ + status: 404, + url, + })); + + await expect( + getManifestByVersion({ version: '0.0.0', fetch: mockFetch }), + ).rejects.toThrow('No release found for 0.0.0 version'); + }); }); describe('getManifestByReleaseLine', () => { diff --git a/packages/release-manifests/src/manifest.ts b/packages/release-manifests/src/manifest.ts index d3edc1051a..66a5f62151 100644 --- a/packages/release-manifests/src/manifest.ts +++ b/packages/release-manifests/src/manifest.ts @@ -33,6 +33,10 @@ export type ReleaseManifest = { */ export type GetManifestByVersionOptions = { version: string; + fetch?: ( + url: string, + options?: { signal?: AbortSignal }, + ) => Promise>; }; // Wait for waitMs, or until signal is aborted. @@ -82,15 +86,21 @@ export async function getManifestByVersion( options: GetManifestByVersionOptions, ): Promise { const versionEnc = encodeURIComponent(options.version); + + const fetchFn = options.fetch ?? fetch; + const res = await withFallback( signal => - fetch(`${VERSIONS_BASE_URL}/v1/releases/${versionEnc}/manifest.json`, { + fetchFn(`${VERSIONS_BASE_URL}/v1/releases/${versionEnc}/manifest.json`, { signal, }), signal => - fetch(`${GITHUB_RAW_BASE_URL}/v1/releases/${versionEnc}/manifest.json`, { - signal, - }), + fetchFn( + `${GITHUB_RAW_BASE_URL}/v1/releases/${versionEnc}/manifest.json`, + { + signal, + }, + ), 500, ); if (res.status === 404) {