From 8013013c593ed82c70b7403c3dd8e96d22dce2a3 Mon Sep 17 00:00:00 2001 From: Johannes Will Date: Thu, 27 Feb 2025 13:22:24 +0100 Subject: [PATCH] feat: Add support for topics and membership in catalog-backend-module-gitlab Signed-off-by: Johannes Will --- .../catalog-backend-module-gitlab/config.d.ts | 12 ++ .../report.api.md | 2 + .../src/lib/client.ts | 2 + .../src/lib/types.ts | 12 ++ .../GitlabDiscoveryEntityProvider.ts | 2 + .../src/providers/config.test.ts | 196 ++++++++++++++++++ .../src/providers/config.ts | 7 + 7 files changed, 233 insertions(+) diff --git a/plugins/catalog-backend-module-gitlab/config.d.ts b/plugins/catalog-backend-module-gitlab/config.d.ts index ce1cda50e7..e41de67208 100644 --- a/plugins/catalog-backend-module-gitlab/config.d.ts +++ b/plugins/catalog-backend-module-gitlab/config.d.ts @@ -72,6 +72,18 @@ export interface Config { * Should be in the format group/subgroup/repo, with no leading or trailing slashes. */ excludeRepos?: string[]; + + /** + * (Optional) If true, limit by repositories that the current user is a member of. + * See: https://docs.gitlab.com/api/projects/#list-projects + */ + membership?: boolean; + + /** + * (Optional) List of topic names. Limit results to repositories that match all of given topics. + * See: https://docs.gitlab.com/api/projects/#list-projects + */ + topics?: string; }; }; }; diff --git a/plugins/catalog-backend-module-gitlab/report.api.md b/plugins/catalog-backend-module-gitlab/report.api.md index e2577553d3..5b7bfadf1d 100644 --- a/plugins/catalog-backend-module-gitlab/report.api.md +++ b/plugins/catalog-backend-module-gitlab/report.api.md @@ -120,6 +120,8 @@ export type GitlabProviderConfig = { includeArchivedRepos?: boolean; excludeRepos?: string[]; includeUsersWithoutSeat?: boolean; + membership?: boolean; + topics?: string; }; // @public diff --git a/plugins/catalog-backend-module-gitlab/src/lib/client.ts b/plugins/catalog-backend-module-gitlab/src/lib/client.ts index f5ed760b21..9053d68554 100644 --- a/plugins/catalog-backend-module-gitlab/src/lib/client.ts +++ b/plugins/catalog-backend-module-gitlab/src/lib/client.ts @@ -41,6 +41,8 @@ export type CommonListOptions = { interface ListProjectOptions extends CommonListOptions { archived?: boolean; group?: string; + membership?: boolean; + topics?: string; } interface UserListOptions extends CommonListOptions { diff --git a/plugins/catalog-backend-module-gitlab/src/lib/types.ts b/plugins/catalog-backend-module-gitlab/src/lib/types.ts index e25f9bacf4..864eca7dfe 100644 --- a/plugins/catalog-backend-module-gitlab/src/lib/types.ts +++ b/plugins/catalog-backend-module-gitlab/src/lib/types.ts @@ -248,6 +248,18 @@ export type GitlabProviderConfig = { * Defaults to `false` */ includeUsersWithoutSeat?: boolean; + + /** + * If true, the membership parameter is set to true in the GitLab API request. + * See: https://docs.gitlab.com/api/projects/#list-projects + */ + membership?: boolean; + + /** + * Optional comma seperated list of topics to filter projects by, as specified in the GitLab API documentation: + * https://docs.gitlab.com/api/projects/#list-projects + */ + topics?: string; }; /** diff --git a/plugins/catalog-backend-module-gitlab/src/providers/GitlabDiscoveryEntityProvider.ts b/plugins/catalog-backend-module-gitlab/src/providers/GitlabDiscoveryEntityProvider.ts index 66a6247295..8bf749c275 100644 --- a/plugins/catalog-backend-module-gitlab/src/providers/GitlabDiscoveryEntityProvider.ts +++ b/plugins/catalog-backend-module-gitlab/src/providers/GitlabDiscoveryEntityProvider.ts @@ -214,6 +214,8 @@ export class GitlabDiscoveryEntityProvider implements EntityProvider { page: 1, per_page: 50, ...(!this.config.includeArchivedRepos && { archived: false }), + ...(this.config.membership && { membership: true }), + ...(this.config.topics && { topics: this.config.topics }), }, ); 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 e1798df184..8790a3fe53 100644 --- a/plugins/catalog-backend-module-gitlab/src/providers/config.test.ts +++ b/plugins/catalog-backend-module-gitlab/src/providers/config.test.ts @@ -65,6 +65,8 @@ describe('config', () => { excludeRepos: [], restrictUsersToGroup: false, includeUsersWithoutSeat: false, + membership: undefined, + topics: undefined, }), ); }); @@ -109,6 +111,8 @@ describe('config', () => { excludeRepos: [], restrictUsersToGroup: false, includeUsersWithoutSeat: true, + membership: undefined, + topics: undefined, }), ); }); @@ -153,6 +157,8 @@ describe('config', () => { skipForkedRepos: true, includeArchivedRepos: false, includeUsersWithoutSeat: false, + membership: undefined, + topics: undefined, }), ); }); @@ -197,6 +203,8 @@ describe('config', () => { skipForkedRepos: false, includeArchivedRepos: true, includeUsersWithoutSeat: false, + membership: undefined, + topics: undefined, }), ); }); @@ -242,6 +250,8 @@ describe('config', () => { includeArchivedRepos: false, excludeRepos: ['foo/bar', 'quz/qux'], includeUsersWithoutSeat: false, + membership: undefined, + topics: undefined, }), ); }); @@ -287,6 +297,8 @@ describe('config', () => { restrictUsersToGroup: false, excludeRepos: [], includeUsersWithoutSeat: false, + membership: undefined, + topics: undefined, schedule: { frequency: { minutes: 30 }, timeout: { @@ -336,4 +348,188 @@ describe('config', () => { expect(result).toHaveLength(1); expect(result[0].group).toEqual(''); }); + + it('valid config with membership', () => { + const config = new ConfigReader({ + catalog: { + providers: { + gitlab: { + test: { + group: 'group', + host: 'host', + branch: 'not-master', + fallbackBranch: 'main', + entityFilename: 'custom-file.yaml', + membership: true, + }, + }, + }, + }, + }); + + const result = readGitlabConfigs(config); + expect(result).toHaveLength(1); + result.forEach(r => + expect(r).toStrictEqual({ + id: 'test', + group: 'group', + branch: 'not-master', + fallbackBranch: 'main', + host: 'host', + catalogFile: 'custom-file.yaml', + projectPattern: /[\s\S]*/, + groupPattern: /[\s\S]*/, + userPattern: /[\s\S]*/, + orgEnabled: false, + allowInherited: false, + relations: [], + schedule: undefined, + restrictUsersToGroup: false, + excludeRepos: [], + skipForkedRepos: false, + includeUsersWithoutSeat: false, + includeArchivedRepos: false, + membership: true, + topics: undefined, + }), + ); + }); + + it('valid config with empyt topics', () => { + const config = new ConfigReader({ + catalog: { + providers: { + gitlab: { + test: { + group: 'group', + host: 'host', + branch: 'not-master', + fallbackBranch: 'main', + entityFilename: 'custom-file.yaml', + topics: [], + }, + }, + }, + }, + }); + + const result = readGitlabConfigs(config); + expect(result).toHaveLength(1); + result.forEach(r => + expect(r).toStrictEqual({ + id: 'test', + group: 'group', + branch: 'not-master', + fallbackBranch: 'main', + host: 'host', + catalogFile: 'custom-file.yaml', + projectPattern: /[\s\S]*/, + groupPattern: /[\s\S]*/, + userPattern: /[\s\S]*/, + orgEnabled: false, + allowInherited: false, + relations: [], + schedule: undefined, + restrictUsersToGroup: false, + excludeRepos: [], + skipForkedRepos: false, + includeUsersWithoutSeat: false, + includeArchivedRepos: false, + membership: undefined, + topics: undefined, + }), + ); + }); + + it('valid config with single topics', () => { + const config = new ConfigReader({ + catalog: { + providers: { + gitlab: { + test: { + group: 'group', + host: 'host', + branch: 'not-master', + fallbackBranch: 'main', + entityFilename: 'custom-file.yaml', + topics: ['topic1'], + }, + }, + }, + }, + }); + + const result = readGitlabConfigs(config); + expect(result).toHaveLength(1); + result.forEach(r => + expect(r).toStrictEqual({ + id: 'test', + group: 'group', + branch: 'not-master', + fallbackBranch: 'main', + host: 'host', + catalogFile: 'custom-file.yaml', + projectPattern: /[\s\S]*/, + groupPattern: /[\s\S]*/, + userPattern: /[\s\S]*/, + orgEnabled: false, + allowInherited: false, + relations: [], + schedule: undefined, + restrictUsersToGroup: false, + excludeRepos: [], + skipForkedRepos: false, + includeUsersWithoutSeat: false, + includeArchivedRepos: false, + membership: undefined, + topics: 'topic1', + }), + ); + }); + + it('valid config with multiple topics', () => { + const config = new ConfigReader({ + catalog: { + providers: { + gitlab: { + test: { + group: 'group', + host: 'host', + branch: 'not-master', + fallbackBranch: 'main', + entityFilename: 'custom-file.yaml', + topics: ['topic1', 'topic2', 'topic3'], + }, + }, + }, + }, + }); + + const result = readGitlabConfigs(config); + expect(result).toHaveLength(1); + result.forEach(r => + expect(r).toStrictEqual({ + id: 'test', + group: 'group', + branch: 'not-master', + fallbackBranch: 'main', + host: 'host', + catalogFile: 'custom-file.yaml', + projectPattern: /[\s\S]*/, + groupPattern: /[\s\S]*/, + userPattern: /[\s\S]*/, + orgEnabled: false, + allowInherited: false, + relations: [], + schedule: undefined, + restrictUsersToGroup: false, + excludeRepos: [], + skipForkedRepos: false, + includeUsersWithoutSeat: false, + includeArchivedRepos: false, + membership: undefined, + topics: 'topic1,topic2,topic3', + }), + ); + }); }); diff --git a/plugins/catalog-backend-module-gitlab/src/providers/config.ts b/plugins/catalog-backend-module-gitlab/src/providers/config.ts index bf59bb0d36..5b50fce5b1 100644 --- a/plugins/catalog-backend-module-gitlab/src/providers/config.ts +++ b/plugins/catalog-backend-module-gitlab/src/providers/config.ts @@ -66,6 +66,11 @@ function readGitlabConfig(id: string, config: Config): GitlabProviderConfig { const includeUsersWithoutSeat = config.getOptionalBoolean('includeUsersWithoutSeat') ?? false; + const membership = config.getOptionalBoolean('membership'); + + const topicsArray = config.getOptionalStringArray('topics'); + const topics = topicsArray?.length ? topicsArray.join(',') : undefined; + return { id, group, @@ -85,6 +90,8 @@ function readGitlabConfig(id: string, config: Config): GitlabProviderConfig { excludeRepos, restrictUsersToGroup, includeUsersWithoutSeat, + membership, + topics, }; }