diff --git a/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.test.ts index 73f4281a51..1f01b77f42 100644 --- a/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.test.ts @@ -17,21 +17,73 @@ import { getVoidLogger } from '@backstage/backend-common'; import { BitbucketDiscoveryProcessor } from './BitbucketDiscoveryProcessor'; import { ConfigReader } from '@backstage/config'; import { LocationSpec } from '@backstage/catalog-model'; -import { - BitbucketClient, - BitbucketRepositoryParser, - PagedResponse, -} from './bitbucket'; +import { BitbucketRepositoryParser, PagedResponse } from './bitbucket'; import { results } from './index'; +import { RequestHandler, rest } from 'msw'; +import { setupServer } from 'msw/node'; -function pagedResponse(values: any): PagedResponse { - return { - values: values, - isLastPage: true, - } as PagedResponse; +const server = setupServer(); + +function setupStubs(projects: any[]) { + function pagedResponse(values: any): PagedResponse { + return { + values: values, + isLastPage: true, + } as PagedResponse; + } + + function stubbedProject( + project: string, + repos: string[], + ): RequestHandler { + return rest.get( + `https://bitbucket.mycompany.com/api/rest/1.0/projects/${project}/repos`, + (_, res, ctx) => { + const response = []; + for (const repo of repos) { + response.push({ + slug: repo, + links: { + self: [ + { + href: `https://bitbucket.mycompany.com/projects/${project}/repos/${repo}/browse`, + }, + ], + }, + }); + } + return res(ctx.json(pagedResponse(response))); + }, + ); + } + + server.use( + rest.get( + `https://bitbucket.mycompany.com/api/rest/1.0/projects`, + (_, res, ctx) => { + return res( + ctx.json( + pagedResponse( + projects.map(p => { + return { key: p.key }; + }), + ), + ), + ); + }, + ), + ); + + for (const project of projects) { + server.use(stubbedProject(project.key, project.repos)); + } } describe('BitbucketDiscoveryProcessor', () => { + beforeAll(() => server.listen()); + afterEach(() => server.resetHandlers()); + afterAll(() => server.close()); + afterEach(() => jest.resetAllMocks()); describe('reject unrelated entries', () => { @@ -81,58 +133,29 @@ describe('BitbucketDiscoveryProcessor', () => { const processor = BitbucketDiscoveryProcessor.fromConfig( new ConfigReader({ integrations: { - bitbucket: [{ host: 'bitbucket.mycompany.com', token: 'blob' }], + bitbucket: [ + { + host: 'bitbucket.mycompany.com', + token: 'blob', + apiBaseUrl: 'https://bitbucket.mycompany.com/api/rest/1.0', + }, + ], }, }), { logger: getVoidLogger() }, ); it('output all repositories', async () => { + setupStubs([ + { key: 'backstage', repos: ['backstage'] }, + { key: 'demo', repos: ['demo'] }, + ]); const location: LocationSpec = { type: 'bitbucket-discovery', target: 'https://bitbucket.mycompany.com/projects/*/repos/*/catalog.yaml', }; - jest - .spyOn(BitbucketClient.prototype, 'listProjects') - .mockResolvedValue( - pagedResponse([{ key: 'backstage' }, { key: 'demo' }]), - ); - jest - .spyOn(BitbucketClient.prototype, 'listRepositories') - .mockResolvedValueOnce( - pagedResponse([ - { - slug: 'backstage', - links: { - self: [ - { - href: - 'https://bitbucket.mycompany.com/projects/backstage/repos/backstage/browse', - }, - ], - }, - }, - ]), - ); - jest - .spyOn(BitbucketClient.prototype, 'listRepositories') - .mockResolvedValueOnce( - pagedResponse([ - { - slug: 'demo', - links: { - self: [ - { - href: - 'https://bitbucket.mycompany.com/projects/demo/repos/demo/browse', - }, - ], - }, - }, - ]), - ); const emitter = jest.fn(); await processor.readLocation(location, false, emitter); @@ -158,44 +181,16 @@ describe('BitbucketDiscoveryProcessor', () => { }); it('output repositories with wildcards', async () => { + setupStubs([ + { key: 'backstage', repos: ['backstage', 'techdocs-cli'] }, + { key: 'demo', repos: ['demo'] }, + ]); const location: LocationSpec = { type: 'bitbucket-discovery', target: 'https://bitbucket.mycompany.com/projects/backstage/repos/techdocs-*/catalog.yaml', }; - jest - .spyOn(BitbucketClient.prototype, 'listProjects') - .mockResolvedValue(pagedResponse([{ key: 'backstage' }])); - jest - .spyOn(BitbucketClient.prototype, 'listRepositories') - .mockResolvedValueOnce( - pagedResponse([ - { slug: 'backstage' }, - { - slug: 'techdocs-cli', - links: { - self: [ - { - href: - 'https://bitbucket.mycompany.com/projects/backstage/repos/techdocs-cli/browse', - }, - ], - }, - }, - { - slug: 'techdocs-container', - links: { - self: [ - { - href: - 'https://bitbucket.mycompany.com/projects/backstage/repos/techdocs-container/browse', - }, - ], - }, - }, - ]), - ); const emitter = jest.fn(); await processor.readLocation(location, false, emitter); @@ -208,46 +203,15 @@ describe('BitbucketDiscoveryProcessor', () => { }, optional: true, }); - expect(emitter).toHaveBeenCalledWith({ - type: 'location', - location: { - type: 'url', - target: - 'https://bitbucket.mycompany.com/projects/backstage/repos/techdocs-container/browse/catalog.yaml', - }, - optional: true, - }); }); it('filter unrelated repositories', async () => { + setupStubs([{ key: 'backstage', repos: ['test', 'abctest', 'testxyz'] }]); const location: LocationSpec = { type: 'bitbucket-discovery', target: 'https://bitbucket.mycompany.com/projects/backstage/repos/test/catalog.yaml', }; - jest - .spyOn(BitbucketClient.prototype, 'listProjects') - .mockResolvedValue(pagedResponse([{ key: 'backstage' }])); - jest - .spyOn(BitbucketClient.prototype, 'listRepositories') - .mockResolvedValue( - pagedResponse([ - { slug: 'abstest' }, - { slug: 'testxyz' }, - { - slug: 'test', - links: { - self: [ - { - href: - 'https://bitbucket.mycompany.com/projects/backstage/repos/test', - }, - ], - }, - }, - ]), - ); - const emitter = jest.fn(); await processor.readLocation(location, false, emitter); @@ -256,7 +220,7 @@ describe('BitbucketDiscoveryProcessor', () => { location: { type: 'url', target: - 'https://bitbucket.mycompany.com/projects/backstage/repos/test/catalog.yaml', + 'https://bitbucket.mycompany.com/projects/backstage/repos/test/browse/catalog.yaml', }, optional: true, }); @@ -277,26 +241,27 @@ describe('BitbucketDiscoveryProcessor', () => { const processor = BitbucketDiscoveryProcessor.fromConfig( new ConfigReader({ integrations: { - bitbucket: [{ host: 'bitbucket.mycompany.com', token: 'blob' }], + bitbucket: [ + { + host: 'bitbucket.mycompany.com', + token: 'blob', + apiBaseUrl: 'https://bitbucket.mycompany.com/api/rest/1.0', + }, + ], }, }), { parser: customRepositoryParser, logger: getVoidLogger() }, ); it('use custom repository parser', async () => { + setupStubs([{ key: 'backstage', repos: ['test'] }]); + const location: LocationSpec = { type: 'bitbucket-discovery', target: 'https://bitbucket.mycompany.com/projects/backstage/repos/test/catalog.yaml', }; - jest - .spyOn(BitbucketClient.prototype, 'listProjects') - .mockResolvedValue(pagedResponse([{ key: 'backstage' }])); - jest - .spyOn(BitbucketClient.prototype, 'listRepositories') - .mockResolvedValue(pagedResponse([{ slug: 'test' }])); - const emitter = jest.fn(); await processor.readLocation(location, false, emitter); diff --git a/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.ts index 9c56eb14e3..399adfbc14 100644 --- a/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.ts @@ -90,7 +90,7 @@ export class BitbucketDiscoveryProcessor implements CatalogProcessor { for (const repository of result.matches) { for await (const entity of this.parser({ integration: integration, - target: `${repository.links.self[0]}${catalogPath}`, + target: `${repository.links.self[0].href}${catalogPath}`, logger: this.logger, })) { emit(entity); diff --git a/plugins/catalog-backend/src/ingestion/processors/bitbucket/index.ts b/plugins/catalog-backend/src/ingestion/processors/bitbucket/index.ts index ba2a2b3afe..06effffcd2 100644 --- a/plugins/catalog-backend/src/ingestion/processors/bitbucket/index.ts +++ b/plugins/catalog-backend/src/ingestion/processors/bitbucket/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ export { BitbucketClient, paginated } from './client'; -export type { PagedResponse } from './client'; -export * from './types'; -export type { BitbucketRepositoryParser } from './BitbucketRepositoryParser'; export { defaultRepositoryParser } from './BitbucketRepositoryParser'; +export type { PagedResponse } from './client'; +export type { BitbucketRepository } from './types'; +export type { BitbucketRepositoryParser } from './BitbucketRepositoryParser'; diff --git a/plugins/catalog-backend/src/ingestion/processors/index.ts b/plugins/catalog-backend/src/ingestion/processors/index.ts index c8f51bbccc..a92cc9ed3b 100644 --- a/plugins/catalog-backend/src/ingestion/processors/index.ts +++ b/plugins/catalog-backend/src/ingestion/processors/index.ts @@ -36,5 +36,4 @@ export { UrlReaderProcessor } from './UrlReaderProcessor'; export { parseEntityYaml } from './util/parse'; export { results }; -export { BitbucketClient } from './bitbucket'; -export type { BitbucketRepositoryParser, Bitbucket } from './bitbucket'; +export type { BitbucketRepositoryParser } from './bitbucket';