diff --git a/.changeset/small-shirts-lose.md b/.changeset/small-shirts-lose.md new file mode 100644 index 0000000000..2fe3d6c414 --- /dev/null +++ b/.changeset/small-shirts-lose.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-gitlab': patch +--- + +Fixed GitLab search API scope parameter from `'blob'` to `'blobs'`, resolving 400 errors in discovery provider. diff --git a/plugins/catalog-backend-module-gitlab/src/__testUtils__/handlers.ts b/plugins/catalog-backend-module-gitlab/src/__testUtils__/handlers.ts index 16adb01c10..e5b9b39ecd 100644 --- a/plugins/catalog-backend-module-gitlab/src/__testUtils__/handlers.ts +++ b/plugins/catalog-backend-module-gitlab/src/__testUtils__/handlers.ts @@ -201,7 +201,13 @@ const httpGroupFindByEncodedPathDynamic = all_groups_response.flatMap(group => [ const httpSearchFilesInGroupDynamic = all_groups_response.map(group => { return rest.get( `${apiBaseUrl}/groups/${encodeURIComponent(group.full_path)}/search`, - (_, res, ctx) => { + (req, res, ctx) => { + const scope = req.url.searchParams.get('scope'); + + if (scope !== 'blobs') { + return res(ctx.status(400), ctx.text('400 Bad Request')); + } + const searchResults = projects_with_catalog_info_yaml .filter(project => project.path_with_namespace?.startsWith(group.full_path), diff --git a/plugins/catalog-backend-module-gitlab/src/lib/client.test.ts b/plugins/catalog-backend-module-gitlab/src/lib/client.test.ts index 60974d2d0f..5e10fbffd6 100644 --- a/plugins/catalog-backend-module-gitlab/src/lib/client.test.ts +++ b/plugins/catalog-backend-module-gitlab/src/lib/client.test.ts @@ -280,6 +280,67 @@ describe('GitLabClient', () => { }); }); + describe('listFiles', () => { + it('should call group search API with correct scope parameter', async () => { + const client = new GitLabClient({ + config: readGitLabIntegrationConfig( + new ConfigReader(mock.config_self_managed), + ), + logger: mockServices.logger.mock(), + }); + + const pagedRequestSpy = jest.spyOn(client as any, 'pagedRequest'); + + await client.listFiles({ + group: 'group1', + search: 'filename:catalog-info.yaml', + page: 1, + per_page: 50, + }); + + expect(pagedRequestSpy).toHaveBeenCalledWith( + '/groups/group1/search', + expect.objectContaining({ + group: 'group1', + search: 'filename:catalog-info.yaml', + scope: 'blobs', + page: 1, + per_page: 50, + }), + ); + }); + + it('should return empty items when group is missing', async () => { + const client = new GitLabClient({ + config: readGitLabIntegrationConfig( + new ConfigReader(mock.config_self_managed), + ), + logger: mockServices.logger.mock(), + }); + + const result = await client.listFiles({ + search: 'filename:catalog-info.yaml', + }); + + expect(result.items).toEqual([]); + }); + + it('should return empty items when search is missing', async () => { + const client = new GitLabClient({ + config: readGitLabIntegrationConfig( + new ConfigReader(mock.config_self_managed), + ), + logger: mockServices.logger.mock(), + }); + + const result = await client.listFiles({ + group: 'my-group', + }); + + expect(result.items).toEqual([]); + }); + }); + describe('get gitlab.com users', () => { it('gets all users under group', async () => { const client = new GitLabClient({ diff --git a/plugins/catalog-backend-module-gitlab/src/lib/client.ts b/plugins/catalog-backend-module-gitlab/src/lib/client.ts index 4f220deb68..c04585142d 100644 --- a/plugins/catalog-backend-module-gitlab/src/lib/client.ts +++ b/plugins/catalog-backend-module-gitlab/src/lib/client.ts @@ -185,7 +185,7 @@ export class GitLabClient { `/groups/${encodeURIComponent(options?.group)}/search`, { ...options, - scope: 'blob', + scope: 'blobs', }, ); }