diff --git a/.changeset/eighty-taxis-wash.md b/.changeset/eighty-taxis-wash.md new file mode 100644 index 0000000000..c89e7c7dea --- /dev/null +++ b/.changeset/eighty-taxis-wash.md @@ -0,0 +1,8 @@ +--- +'@backstage/plugin-catalog-backend-module-github': patch +'@backstage/plugin-catalog-backend-module-ldap': patch +'@backstage/plugin-catalog-backend-module-msgraph': patch +'@backstage/plugin-org': patch +--- + +Updated the code to handle User kind `spec.memberOf` now being optional. diff --git a/.changeset/strong-dolphins-turn.md b/.changeset/strong-dolphins-turn.md new file mode 100644 index 0000000000..4c59accba6 --- /dev/null +++ b/.changeset/strong-dolphins-turn.md @@ -0,0 +1,14 @@ +--- +'@backstage/catalog-model': minor +--- + +**BREAKING**: The User kind has an updated TypeScript type where `spec.memberOf` +is optional. + +**NOTE HOWEVER**, that this only applies to the TypeScript types `UserEntity` +and `UserEntityV1alpha1`. The catalog validation still requires the field to be +set, even if it's in the form of an empty array. If you try to ingest data that +stops producing this field, those entities _will be rejected_ by the catalog. +The reason for these choices is that consumers will get a long grace period +where old code still can rely on the underlying data being present, giving users +ample time to update before actual breakages could happen. diff --git a/packages/catalog-model/api-report.md b/packages/catalog-model/api-report.md index 618c1f7b69..fca23d6ab9 100644 --- a/packages/catalog-model/api-report.md +++ b/packages/catalog-model/api-report.md @@ -447,7 +447,7 @@ interface UserEntityV1alpha1 extends Entity { email?: string; picture?: string; }; - memberOf: string[]; + memberOf?: string[]; }; } export { UserEntityV1alpha1 as UserEntity }; diff --git a/packages/catalog-model/src/kinds/UserEntityV1alpha1.ts b/packages/catalog-model/src/kinds/UserEntityV1alpha1.ts index 82aaebd9d6..55c9b176ea 100644 --- a/packages/catalog-model/src/kinds/UserEntityV1alpha1.ts +++ b/packages/catalog-model/src/kinds/UserEntityV1alpha1.ts @@ -32,7 +32,7 @@ export interface UserEntityV1alpha1 extends Entity { email?: string; picture?: string; }; - memberOf: string[]; + memberOf?: string[]; }; } diff --git a/plugins/catalog-backend-module-github/src/lib/org.ts b/plugins/catalog-backend-module-github/src/lib/org.ts index 3c71f350e6..79a96b5e71 100644 --- a/plugins/catalog-backend-module-github/src/lib/org.ts +++ b/plugins/catalog-backend-module-github/src/lib/org.ts @@ -58,7 +58,10 @@ export function assignGroupsToUsers( for (const [groupName, userNames] of groupMemberUsers.entries()) { for (const userName of userNames) { const user = usersByName.get(userName); - if (user && !user.spec.memberOf.includes(groupName)) { + if (user && !user.spec.memberOf?.includes(groupName)) { + if (!user.spec.memberOf) { + user.spec.memberOf = []; + } user.spec.memberOf.push(groupName); } } @@ -74,7 +77,7 @@ export function buildMemberOf(groups: GroupEntity[], users: UserEntity[]) { const transitiveMemberOf = new Set(); const todo = [ - ...user.spec.memberOf, + ...(user.spec.memberOf ?? []), ...groups .filter(g => g.spec.members?.includes(user.metadata.name)) .map(g => g.metadata.name), diff --git a/plugins/catalog-backend-module-ldap/src/ldap/org.ts b/plugins/catalog-backend-module-ldap/src/ldap/org.ts index fe59451a9d..28ccbd1d3b 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/org.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/org.ts @@ -61,7 +61,7 @@ export function buildMemberOf(groups: GroupEntity[], users: UserEntity[]) { const transitiveMemberOf = new Set(); const todo = [ - ...user.spec.memberOf, + ...(user.spec.memberOf ?? []), ...groups .filter(g => g.spec.members?.includes(user.metadata.name)) .map(g => g.metadata.name), diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/org.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/org.ts index fe59451a9d..28ccbd1d3b 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/org.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/org.ts @@ -61,7 +61,7 @@ export function buildMemberOf(groups: GroupEntity[], users: UserEntity[]) { const transitiveMemberOf = new Set(); const todo = [ - ...user.spec.memberOf, + ...(user.spec.memberOf ?? []), ...groups .filter(g => g.spec.members?.includes(user.metadata.name)) .map(g => g.metadata.name), diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts index 7174a6012c..e9760f7698 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts @@ -507,6 +507,9 @@ export function resolveRelations( retrieveItems(groupMemberOf, id).forEach(p => { const parentGroup = groupMap.get(p); if (parentGroup) { + if (!user.spec.memberOf) { + user.spec.memberOf = []; + } user.spec.memberOf.push(stringifyEntityRef(parentGroup)); } }); diff --git a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.tsx b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.tsx index 8635d0d7d4..fb49843e92 100644 --- a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.tsx +++ b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.tsx @@ -118,7 +118,7 @@ const getQueryParams = ( }; if (owner.kind === 'User') { const user = owner as UserEntity; - filters.owners = [...filters.owners, ...user.spec.memberOf]; + filters.owners = [...filters.owners, ...(user.spec.memberOf ?? [])]; } const queryParams = qs.stringify( {