diff --git a/plugins/catalog-backend-module-bitbucket-cloud/src/providers/BitbucketCloudEntityProvider.test.ts b/plugins/catalog-backend-module-bitbucket-cloud/src/providers/BitbucketCloudEntityProvider.test.ts index 262582b99a..f95cb34025 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/src/providers/BitbucketCloudEntityProvider.test.ts +++ b/plugins/catalog-backend-module-bitbucket-cloud/src/providers/BitbucketCloudEntityProvider.test.ts @@ -87,6 +87,23 @@ describe('BitbucketCloudEntityProvider', () => { }, }, }); + const projectLevelConfig = new ConfigReader({ + catalog: { + providers: { + bitbucketCloud: { + myProvider: { + workspace: 'test-ws', + catalogPath: 'catalog-custom.yaml', + filters: { + projectKey: 'test-.*', + repoSlug: 'test-.*', + }, + level: 'project', + }, + }, + }, + }, + }); const schedule = new PersistingTaskRunner(); const entityProviderConnection: EntityProviderConnection = { applyMutation: jest.fn(), @@ -419,6 +436,181 @@ describe('BitbucketCloudEntityProvider', () => { }); }); + it('apply full update on scheduled execution on project-level', async () => { + const provider = BitbucketCloudEntityProvider.fromConfig( + projectLevelConfig, + { + logger, + schedule, + }, + )[0]; + expect(provider.getProviderName()).toEqual( + 'bitbucketCloud-provider:myProvider', + ); + + server.use( + rest.get( + `https://api.bitbucket.org/2.0/workspaces/test-ws/projects`, + (_req, res, ctx) => { + const response = { + values: [ + { + key: 'TEST', + }, + ], + }; + return res(ctx.json(response)); + }, + ), + rest.get( + `https://api.bitbucket.org/2.0/workspaces/test-ws/search/code`, + (req, res, ctx) => { + const query = req.url.searchParams.get('search_query'); + if (!query || !query.includes('project:TEST')) { + return res(ctx.json({ values: [] })); + } + + const response = { + values: [ + { + // skipped as empty + path_matches: [], + file: { + type: 'commit_file', + path: 'path/to/ignored/file', + }, + }, + { + path_matches: [ + { + match: true, + text: 'catalog-custom.yaml', + }, + ], + file: { + type: 'commit_file', + path: 'custom/path/catalog-custom.yaml', + commit: { + repository: { + // skipped as no match with filter + slug: 'repo', + project: { + key: 'test-project', + }, + mainbranch: { + name: 'main', + }, + links: { + html: { + href: 'https://bitbucket.org/test-ws/repo', + }, + }, + }, + }, + }, + }, + { + path_matches: [ + { + match: true, + text: 'catalog-custom.yaml', + }, + ], + file: { + type: 'commit_file', + path: 'custom/path/catalog-custom.yaml', + commit: { + repository: { + slug: 'test-repo1', + project: { + // skipped as no match with filter + key: 'project', + }, + mainbranch: { + name: 'main', + }, + links: { + html: { + href: 'https://bitbucket.org/test-ws/test-repo1', + }, + }, + }, + }, + }, + }, + { + path_matches: [ + { + match: true, + text: 'catalog-custom.yaml', + }, + ], + file: { + type: 'commit_file', + path: 'custom/path/catalog-custom.yaml', + commit: { + repository: { + slug: 'test-repo2', + project: { + key: 'test-project', + }, + mainbranch: { + name: 'main', + }, + links: { + html: { + href: 'https://bitbucket.org/test-ws/test-repo2', + }, + }, + }, + }, + }, + }, + ], + }; + return res(ctx.json(response)); + }, + ), + ); + + await provider.connect(entityProviderConnection); + + const taskDef = schedule.getTasks()[0]; + expect(taskDef.id).toEqual('bitbucketCloud-provider:myProvider:refresh'); + await (taskDef.fn as () => Promise)(); + + const url = `https://bitbucket.org/test-ws/test-repo2/src/main/custom/path/catalog-custom.yaml`; + const expectedEntities = [ + { + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Location', + metadata: { + annotations: { + 'backstage.io/managed-by-location': `url:${url}`, + 'backstage.io/managed-by-origin-location': `url:${url}`, + 'bitbucket.org/repo-url': + 'https://bitbucket.org/test-ws/test-repo2', + }, + name: 'generated-7c2e6263b6cc2d14e69fd4d029afba601ad6dc3b', + }, + spec: { + presence: 'required', + target: `${url}`, + type: 'url', + }, + }, + locationKey: 'bitbucketCloud-provider:myProvider', + }, + ]; + + expect(entityProviderConnection.applyMutation).toHaveBeenCalledTimes(1); + expect(entityProviderConnection.applyMutation).toHaveBeenCalledWith({ + type: 'full', + entities: expectedEntities, + }); + }); + it('update onRepoPush', async () => { const keptModule = createLocationEntity( 'https://bitbucket.org/test-ws/test-repo', diff --git a/plugins/catalog-backend-module-bitbucket-cloud/src/providers/BitbucketCloudEntityProvider.ts b/plugins/catalog-backend-module-bitbucket-cloud/src/providers/BitbucketCloudEntityProvider.ts index 6826804053..aac5056687 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/src/providers/BitbucketCloudEntityProvider.ts +++ b/plugins/catalog-backend-module-bitbucket-cloud/src/providers/BitbucketCloudEntityProvider.ts @@ -334,7 +334,7 @@ export class BitbucketCloudEntityProvider implements EntityProvider { } private async findCatalogFiles( - level: 'workspace' | 'project' = 'workspace', + level: 'workspace' | 'project', repoSlug?: string, ): Promise { const workspace = this.config.workspace; diff --git a/plugins/catalog-backend-module-bitbucket-cloud/src/providers/BitbucketCloudEntityProviderConfig.ts b/plugins/catalog-backend-module-bitbucket-cloud/src/providers/BitbucketCloudEntityProviderConfig.ts index 1326c53e29..12f8db1c9c 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/src/providers/BitbucketCloudEntityProviderConfig.ts +++ b/plugins/catalog-backend-module-bitbucket-cloud/src/providers/BitbucketCloudEntityProviderConfig.ts @@ -32,7 +32,7 @@ export type BitbucketCloudEntityProviderConfig = { repoSlug?: RegExp; }; schedule?: SchedulerServiceTaskScheduleDefinition; - level?: 'workspace' | 'project'; + level: 'workspace' | 'project'; }; export function readProviderConfigs( @@ -73,6 +73,12 @@ function readProviderConfig( ) : undefined; + const level = + (config.getOptionalString('level') as + | 'workspace' + | 'project' + | undefined) ?? 'workspace'; + return { id, catalogPath, @@ -84,6 +90,7 @@ function readProviderConfig( repoSlug: repoSlugPattern ? compileRegExp(repoSlugPattern) : undefined, }, schedule, + level, }; }