diff --git a/.changeset/good-papayas-fetch.md b/.changeset/good-papayas-fetch.md new file mode 100644 index 0000000000..4261d4e24b --- /dev/null +++ b/.changeset/good-papayas-fetch.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': minor +--- + +Adds optional namespacing for users in the GitHub Multi Org Plugin diff --git a/plugins/catalog-backend/config.d.ts b/plugins/catalog-backend/config.d.ts index 7da9cad139..5701c9df48 100644 --- a/plugins/catalog-backend/config.d.ts +++ b/plugins/catalog-backend/config.d.ts @@ -163,6 +163,13 @@ export interface Config { * Defaults to org name if omitted. */ groupNamespace?: string; + + /** + * The namespace of the users created from this org. + * + * Defaults to empty string if omitted. + */ + userNamespace?: string; }>; }; diff --git a/plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts index ebfcaf5b5d..dfe48939bc 100644 --- a/plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts @@ -111,6 +111,7 @@ export class GithubMultiOrgReaderProcessor implements CatalogProcessor { client, orgConfig.name, tokenType, + orgConfig.userNamespace, ); const { groups, groupMemberUsers } = await getOrganizationTeams( client, diff --git a/plugins/catalog-backend/src/ingestion/processors/github/config.test.ts b/plugins/catalog-backend/src/ingestion/processors/github/config.test.ts index 7bdc28e6dd..9aa6ee41d7 100644 --- a/plugins/catalog-backend/src/ingestion/processors/github/config.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/github/config.test.ts @@ -78,32 +78,48 @@ describe('config', () => { }); describe('readGithubMultiOrgConfig', () => { - function config(orgs: { name: string; groupNamespace?: string }[]) { + function config( + orgs: { name: string; groupNamespace?: string; userNamespace?: string }[], + ) { return new ConfigReader({ orgs }); } it('reads org configs', () => { const output = readGithubMultiOrgConfig( config([ - { name: 'foo', groupNamespace: 'apple' }, - { name: 'bar', groupNamespace: 'Orange' }, + { name: 'foo', groupNamespace: 'apple', userNamespace: 'red' }, + { name: 'bar', groupNamespace: 'Orange', userNamespace: 'blue' }, ]), ); expect(output).toEqual([ - { name: 'foo', groupNamespace: 'apple' }, - { name: 'bar', groupNamespace: 'orange' }, + { name: 'foo', groupNamespace: 'apple', userNamespace: 'red' }, + { name: 'bar', groupNamespace: 'orange', userNamespace: 'blue' }, ]); }); it('defaults groupNamespace to org name if undefined', () => { + const output = readGithubMultiOrgConfig( + config([ + { name: 'foo', userNamespace: 'red' }, + { name: 'bar', userNamespace: 'blue' }, + ]), + ); + + expect(output).toEqual([ + { name: 'foo', groupNamespace: 'foo', userNamespace: 'red' }, + { name: 'bar', groupNamespace: 'bar', userNamespace: 'blue' }, + ]); + }); + + it('defaults userNamespace to empty string if undefined', () => { const output = readGithubMultiOrgConfig( config([{ name: 'foo' }, { name: 'bar' }]), ); expect(output).toEqual([ - { name: 'foo', groupNamespace: 'foo' }, - { name: 'bar', groupNamespace: 'bar' }, + { name: 'foo', groupNamespace: 'foo', userNamespace: '' }, + { name: 'bar', groupNamespace: 'bar', userNamespace: '' }, ]); }); }); diff --git a/plugins/catalog-backend/src/ingestion/processors/github/config.ts b/plugins/catalog-backend/src/ingestion/processors/github/config.ts index 40305ff1f2..440b0d7801 100644 --- a/plugins/catalog-backend/src/ingestion/processors/github/config.ts +++ b/plugins/catalog-backend/src/ingestion/processors/github/config.ts @@ -95,6 +95,10 @@ export type GithubMultiOrgConfig = Array<{ * The namespace of the group created for this org. */ groupNamespace: string; + /** + * The namespace of the users created for this org. + */ + userNamespace: string; }>; export function readGithubMultiOrgConfig(config: Config): GithubMultiOrgConfig { @@ -104,5 +108,6 @@ export function readGithubMultiOrgConfig(config: Config): GithubMultiOrgConfig { groupNamespace: ( c.getOptionalString('groupNamespace') ?? c.getString('name') ).toLowerCase(), + userNamespace: c.getOptionalString('userNamespace') ?? '', })); } diff --git a/plugins/catalog-backend/src/ingestion/processors/github/github.ts b/plugins/catalog-backend/src/ingestion/processors/github/github.ts index 9eb5073710..91a0abc992 100644 --- a/plugins/catalog-backend/src/ingestion/processors/github/github.ts +++ b/plugins/catalog-backend/src/ingestion/processors/github/github.ts @@ -82,6 +82,7 @@ export async function getOrganizationUsers( client: typeof graphql, org: string, tokenType: GithubCredentialType, + userNamespace?: string, ): Promise<{ users: UserEntity[] }> { const query = ` query users($org: String!, $email: Boolean!, $cursor: String) { @@ -117,6 +118,7 @@ export async function getOrganizationUsers( }, }; + if (userNamespace) entity.metadata.namespace = userNamespace; if (user.bio) entity.metadata.description = user.bio; if (user.name) entity.spec.profile!.displayName = user.name; if (user.email) entity.spec.profile!.email = user.email;