From c911061b753648ece3af7f4ea91d83f968c613de Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Tue, 8 Dec 2020 14:09:01 +0100 Subject: [PATCH] Add profile section to group entity --- .changeset/dirty-melons-retire.md | 6 ++ .../software-catalog/descriptor-format.md | 12 ++++ .../src/kinds/GroupEntityV1alpha1.test.ts | 72 ++++++++++++++++++- .../src/kinds/GroupEntityV1alpha1.ts | 12 ++++ 4 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 .changeset/dirty-melons-retire.md diff --git a/.changeset/dirty-melons-retire.md b/.changeset/dirty-melons-retire.md new file mode 100644 index 0000000000..2b92b44678 --- /dev/null +++ b/.changeset/dirty-melons-retire.md @@ -0,0 +1,6 @@ +--- +'@backstage/catalog-model': patch +--- + +Introduce a `profile` section for group entities that can optional include a +`displayName`, `email` and `picture`. diff --git a/docs/features/software-catalog/descriptor-format.md b/docs/features/software-catalog/descriptor-format.md index 72e6388273..e17c5ca36e 100644 --- a/docs/features/software-catalog/descriptor-format.md +++ b/docs/features/software-catalog/descriptor-format.md @@ -723,6 +723,10 @@ metadata: description: The infra business unit spec: type: business-unit + profile: + displayName: Infrastructure + email: infrastructure@example.com + picture: https://example.com/groups/bu-infrastructure.jpeg parent: ops children: [backstage, other] ``` @@ -747,6 +751,14 @@ Some common values for this field could be: - `product-area` - `root` - as a common virtual root of the hierarchy, if desired +### `spec.profile` [optional] + +Optional profile information about the group, mainly for display purposes. All +fields of this structure are also optional. The email would be a group email of +some form, that the group may wish to be used for contacting them. The picture +is expected to be a URL pointing to an image that's representative of the group, +and that a browser could fetch and render on a group page or similar. + ### `spec.parent` [optional] The immediate parent group in the hierarchy, if any. Not all groups must have a diff --git a/packages/catalog-model/src/kinds/GroupEntityV1alpha1.test.ts b/packages/catalog-model/src/kinds/GroupEntityV1alpha1.test.ts index 755a68cede..b25795cd31 100644 --- a/packages/catalog-model/src/kinds/GroupEntityV1alpha1.test.ts +++ b/packages/catalog-model/src/kinds/GroupEntityV1alpha1.test.ts @@ -28,11 +28,15 @@ describe('GroupV1alpha1Validator', () => { kind: 'Group', metadata: { name: 'doe-squad', - title: 'Doe Squad', description: 'A squad for John and Jane', }, spec: { type: 'squad', + profile: { + displayName: 'Doe Squad', + email: 'doe@doe.org', + picture: 'https://doe.org/doe', + }, parent: 'group-a', children: ['child-a', 'child-b'], }, @@ -73,6 +77,70 @@ describe('GroupV1alpha1Validator', () => { await expect(validator.check(entity)).rejects.toThrow(/type/); }); + // profile + + it('accepts missing profile', async () => { + delete (entity as any).spec.profile; + await expect(validator.check(entity)).resolves.toBe(true); + }); + + it('rejects wrong profile', async () => { + (entity as any).spec.profile = 7; + await expect(validator.check(entity)).rejects.toThrow(/profile/); + }); + + it('profile accepts missing displayName', async () => { + delete (entity as any).spec.profile.displayName; + await expect(validator.check(entity)).resolves.toBe(true); + }); + + it('profile rejects wrong displayName', async () => { + (entity as any).spec.profile.displayName = 7; + await expect(validator.check(entity)).rejects.toThrow(/displayName/); + }); + + it('profile rejects empty displayName', async () => { + (entity as any).spec.profile.displayName = ''; + await expect(validator.check(entity)).rejects.toThrow(/displayName/); + }); + + it('profile accepts missing email', async () => { + delete (entity as any).spec.profile.email; + await expect(validator.check(entity)).resolves.toBe(true); + }); + + it('profile rejects wrong email', async () => { + (entity as any).spec.profile.email = 7; + await expect(validator.check(entity)).rejects.toThrow(/email/); + }); + + it('profile rejects empty email', async () => { + (entity as any).spec.profile.email = ''; + await expect(validator.check(entity)).rejects.toThrow(/email/); + }); + + it('profile accepts missing picture', async () => { + delete (entity as any).spec.profile.picture; + await expect(validator.check(entity)).resolves.toBe(true); + }); + + it('profile rejects wrong picture', async () => { + (entity as any).spec.profile.picture = 7; + await expect(validator.check(entity)).rejects.toThrow(/picture/); + }); + + it('profile rejects empty picture', async () => { + (entity as any).spec.profile.picture = ''; + await expect(validator.check(entity)).rejects.toThrow(/picture/); + }); + + it('profile accepts unknown additional fields', async () => { + (entity as any).spec.profile.foo = 'data'; + await expect(validator.check(entity)).resolves.toBe(true); + }); + + // parent + it('accepts missing parent', async () => { delete (entity as any).spec.parent; await expect(validator.check(entity)).resolves.toBe(true); @@ -83,6 +151,8 @@ describe('GroupV1alpha1Validator', () => { await expect(validator.check(entity)).rejects.toThrow(/parent/); }); + // children + it('rejects missing children', async () => { delete (entity as any).spec.children; await expect(validator.check(entity)).rejects.toThrow(/children/); diff --git a/packages/catalog-model/src/kinds/GroupEntityV1alpha1.ts b/packages/catalog-model/src/kinds/GroupEntityV1alpha1.ts index 5f73d00e66..6f2664af77 100644 --- a/packages/catalog-model/src/kinds/GroupEntityV1alpha1.ts +++ b/packages/catalog-model/src/kinds/GroupEntityV1alpha1.ts @@ -27,6 +27,13 @@ const schema = yup.object>({ spec: yup .object({ type: yup.string().required().min(1), + profile: yup + .object({ + displayName: yup.string().min(1).notRequired(), + email: yup.string().min(1).notRequired(), + picture: yup.string().min(1).notRequired(), + }) + .notRequired(), parent: yup.string().notRequired().min(1), // Use these manual tests because yup .required() requires at least // one element and there is no simple workaround -_- @@ -46,6 +53,11 @@ export interface GroupEntityV1alpha1 extends Entity { kind: typeof KIND; spec: { type: string; + profile?: { + displayName?: string; + email?: string; + picture?: string; + }; parent?: string; children: string[]; };