diff --git a/.changeset/fresh-schools-fly.md b/.changeset/fresh-schools-fly.md new file mode 100644 index 0000000000..52502a4ad8 --- /dev/null +++ b/.changeset/fresh-schools-fly.md @@ -0,0 +1,11 @@ +--- +'@backstage/plugin-catalog-backend-module-gitlab': major +--- + +The configuration of the `GitlabDiscoveryEntityProvider` has changed as follows: + +- The configuration key `branch` is now used to define the branch from which the catalog-info should be discovered. +- The old configuration key `branch` is now called `fallbackBranch`. This value specifies which branch should be used + if no default branch is defined on the project itself. + +To migrate to the new configuration value, rename `branch` to `fallbackBranch` diff --git a/docs/integrations/gitlab/discovery.md b/docs/integrations/gitlab/discovery.md index 6d0bb7e2e2..48383c4275 100644 --- a/docs/integrations/gitlab/discovery.md +++ b/docs/integrations/gitlab/discovery.md @@ -21,6 +21,7 @@ catalog: gitlab: yourProviderId: host: gitlab-host # Identifies one of the hosts set up in the integrations + branch: main # Optional. Used to discover on a concrete branch fallbackBranch: main # Optional. Fallback to be used if there is no default branch configured at the Gitlab repository. It is only used, if `branch` is undefined. Uses `master` as default group: example-group # Optional. Group and subgroup (if needed) to look for repositories. If not present the whole instance will be scanned entityFilename: catalog-info.yaml # Optional. Defaults to `catalog-info.yaml` diff --git a/plugins/catalog-backend-module-gitlab/src/lib/types.ts b/plugins/catalog-backend-module-gitlab/src/lib/types.ts index b4480efdc2..c27007861b 100644 --- a/plugins/catalog-backend-module-gitlab/src/lib/types.ts +++ b/plugins/catalog-backend-module-gitlab/src/lib/types.ts @@ -70,11 +70,12 @@ export type GitlabProviderConfig = { group: string; id: string; /** - * @deprecated use `fallbackBranch` instead + * The name of the branch to be used, to discover catalog files. */ branch?: string; /** - * If there is no default branch defined at the project, this fallback is used to discover catalog files. + * If no `branch` is configured and there is no default branch defined at the project as well, this fallback is used + * to discover catalog files. * Defaults to: `master` */ fallbackBranch: string; diff --git a/plugins/catalog-backend-module-gitlab/src/providers/GitlabDiscoveryEntityProvider.test.ts b/plugins/catalog-backend-module-gitlab/src/providers/GitlabDiscoveryEntityProvider.test.ts index 42fa1b471c..75a4c6414c 100644 --- a/plugins/catalog-backend-module-gitlab/src/providers/GitlabDiscoveryEntityProvider.test.ts +++ b/plugins/catalog-backend-module-gitlab/src/providers/GitlabDiscoveryEntityProvider.test.ts @@ -449,4 +449,111 @@ describe('GitlabDiscoveryEntityProvider', () => { 'GitlabDiscoveryEntityProvider:test-id', ); }); + + it('should filter found projects based on the branch', async () => { + const config = new ConfigReader({ + integrations: { + gitlab: [ + { + host: 'test-gitlab', + apiBaseUrl: 'https://api.gitlab.example/api/v4', + token: '1234', + }, + ], + }, + catalog: { + providers: { + gitlab: { + 'test-id': { + host: 'test-gitlab', + branch: 'test', + }, + }, + }, + }, + }); + const schedule = new PersistingTaskRunner(); + const entityProviderConnection: EntityProviderConnection = { + applyMutation: jest.fn(), + refresh: jest.fn(), + }; + const provider = GitlabDiscoveryEntityProvider.fromConfig(config, { + logger, + schedule, + })[0]; + + server.use( + rest.get( + `https://api.gitlab.example/api/v4/projects`, + (_req, res, ctx) => { + const response = [ + { + id: 123, + default_branch: 'master', + archived: false, + last_activity_at: new Date().toString(), + web_url: 'https://api.gitlab.example/test-group/test-repo', + path_with_namespace: 'test-group/test-repo', + }, + { + id: 124, + default_branch: 'master', + archived: false, + last_activity_at: new Date().toString(), + web_url: 'https://api.gitlab.example/john/example', + path_with_namespace: 'john/example', + }, + ]; + return res(ctx.json(response)); + }, + ), + rest.head( + 'https://api.gitlab.example/api/v4/projects/test-group%2Ftest-repo/repository/files/catalog-info.yaml', + (_, res, ctx) => { + return res(ctx.status(404, 'Not Found')); + }, + ), + rest.head( + 'https://api.gitlab.example/api/v4/projects/john%2Fexample/repository/files/catalog-info.yaml', + (req, res, ctx) => { + if (req.url.searchParams.get('ref') === 'test') { + return res(ctx.status(200)); + } + return res(ctx.status(404, 'Not Found')); + }, + ), + ); + + await provider.connect(entityProviderConnection); + + await provider.refresh(logger); + + expect(entityProviderConnection.applyMutation).toHaveBeenCalledWith({ + type: 'full', + entities: [ + { + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Location', + metadata: { + annotations: { + 'backstage.io/managed-by-location': + 'url:https://api.gitlab.example/john/example/-/blob/test/catalog-info.yaml', + 'backstage.io/managed-by-origin-location': + 'url:https://api.gitlab.example/john/example/-/blob/test/catalog-info.yaml', + }, + name: 'generated-232185d858fee049986d202c10316d634e76a3d1', + }, + spec: { + presence: 'optional', + target: + 'https://api.gitlab.example/john/example/-/blob/test/catalog-info.yaml', + type: 'url', + }, + }, + locationKey: 'GitlabDiscoveryEntityProvider:test-id', + }, + ], + }); + }); }); diff --git a/plugins/catalog-backend-module-gitlab/src/providers/GitlabDiscoveryEntityProvider.ts b/plugins/catalog-backend-module-gitlab/src/providers/GitlabDiscoveryEntityProvider.ts index ece10ee8c6..2f5baa68f6 100644 --- a/plugins/catalog-backend-module-gitlab/src/providers/GitlabDiscoveryEntityProvider.ts +++ b/plugins/catalog-backend-module-gitlab/src/providers/GitlabDiscoveryEntityProvider.ts @@ -181,6 +181,7 @@ export class GitlabDiscoveryEntityProvider implements EntityProvider { } if ( + !this.config.branch && this.config.fallbackBranch === '*' && project.default_branch === undefined ) { @@ -188,7 +189,9 @@ export class GitlabDiscoveryEntityProvider implements EntityProvider { } const project_branch = - project.default_branch ?? this.config.fallbackBranch; + this.config.branch ?? + project.default_branch ?? + this.config.fallbackBranch; const projectHasFile: boolean = await client.hasFile( project.path_with_namespace ?? '', @@ -211,7 +214,10 @@ export class GitlabDiscoveryEntityProvider implements EntityProvider { } private createLocationSpec(project: GitLabProject): LocationSpec { - const project_branch = project.default_branch ?? this.config.fallbackBranch; + const project_branch = + this.config.branch ?? + project.default_branch ?? + this.config.fallbackBranch; return { type: 'url', target: `${project.web_url}/-/blob/${project_branch}/${this.config.catalogFile}`, diff --git a/plugins/catalog-backend-module-gitlab/src/providers/config.test.ts b/plugins/catalog-backend-module-gitlab/src/providers/config.test.ts index c9b35e78c2..87d9e5deb0 100644 --- a/plugins/catalog-backend-module-gitlab/src/providers/config.test.ts +++ b/plugins/catalog-backend-module-gitlab/src/providers/config.test.ts @@ -53,6 +53,7 @@ describe('config', () => { expect(r).toStrictEqual({ id: 'test', group: 'group', + fallbackBranch: undefined, fallbackBranch: 'master', host: 'host', catalogFile: 'catalog-info.yaml', @@ -74,6 +75,7 @@ describe('config', () => { group: 'group', host: 'host', branch: 'not-master', + fallbackBranch: 'main', entityFilename: 'custom-file.yaml', }, }, @@ -88,6 +90,7 @@ describe('config', () => { id: 'test', group: 'group', fallbackBranch: 'not-master', + fallbackBranch: 'main', host: 'host', catalogFile: 'custom-file.yaml', projectPattern: /[\s\S]*/, @@ -125,6 +128,7 @@ describe('config', () => { expect(r).toStrictEqual({ id: 'test', group: 'group', + fallbackBranch: undefined, fallbackBranch: 'master', host: 'host', catalogFile: 'catalog-info.yaml', diff --git a/plugins/catalog-backend-module-gitlab/src/providers/config.ts b/plugins/catalog-backend-module-gitlab/src/providers/config.ts index e5cf5a6298..c9b44f601f 100644 --- a/plugins/catalog-backend-module-gitlab/src/providers/config.ts +++ b/plugins/catalog-backend-module-gitlab/src/providers/config.ts @@ -36,15 +36,7 @@ function readGitlabConfig( const group = config.getOptionalString('group') ?? ''; const host = config.getString('host'); const branch = config.getOptionalString('branch'); - - if (branch) { - logger.warn( - 'The configuration key `branch` has been deprecated in favor of the configuration key `fallbackBranch`.', - ); - } - - const fallbackBranch = - config.getOptionalString('fallbackBranch') ?? branch ?? 'master'; + const fallbackBranch = config.getOptionalString('fallbackBranch') ?? 'master'; const catalogFile = config.getOptionalString('entityFilename') ?? 'catalog-info.yaml'; const projectPattern = new RegExp( @@ -65,6 +57,7 @@ function readGitlabConfig( return { id, group, + branch, fallbackBranch, host, catalogFile,