feat: add entity metadata links
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/catalog-model': minor
|
||||
---
|
||||
|
||||
Adds a new optional `links` metadata field to the Entity class within the `catalog-model` package (as discussed in [[RFC] Entity Links](https://github.com/backstage/backstage/issues/3787)). This PR adds support for the entity links only. Follow up PR's will introduce the UI component to display them.
|
||||
@@ -314,6 +314,34 @@ This field is optional, and currently has no special semantics.
|
||||
Each tag must be sequences of `[a-z0-9]` separated by `-`, at most 63 characters
|
||||
in total.
|
||||
|
||||
### `links` [optional]
|
||||
|
||||
A list of external hyperlinks related to the entity. Links can provide
|
||||
additional contextual information that may be located outside of backstage
|
||||
itself. For example, an admin dashboard or external CMS page.
|
||||
|
||||
Users may add links to descriptor YAML files to provide additional reference
|
||||
information to external content & resources. Links are not intended to drive any
|
||||
additional functionality within backstage, which is best left to `annotations`
|
||||
and `labels`. It is recommended to use links only when an equivalent well-known
|
||||
`annotation` does not cover a similar use case.
|
||||
|
||||
Fields of a link are:
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------- | ------ | ------------------------------------------------------------------------------------ |
|
||||
| `url` | String | [Required] A `url` in a standard `uri` format (e.g. `https://example.com/some/page`) |
|
||||
| `title` | String | [Optional] A user friendly display name for the link. |
|
||||
| `icon` | String | [Optional] A key representing a visual icon to be displayed in the UI. |
|
||||
|
||||
_NOTE_: The `icon` field value is meant to be a semantic key that will map to a
|
||||
specific icon that may be provided by an icon library (e.g. `material-ui`
|
||||
icons). These keys should a sequence of `[a-z0-9A-Z]` and possibly separated by
|
||||
one of `[-_.]`. Backstage may support some basic icons out of the box, but the
|
||||
backstage integrator will ultimately be left to provide the appropriate icon
|
||||
component mappings. A generic fallback icon would be provided if a mapping
|
||||
cannot be resolved.
|
||||
|
||||
## Common to All Kinds: Relations
|
||||
|
||||
The `relations` root field is a read-only list of relations, between the current
|
||||
|
||||
@@ -3,6 +3,9 @@ kind: Group
|
||||
metadata:
|
||||
name: acme-corp
|
||||
description: The acme-corp organization
|
||||
links:
|
||||
- url: http://www.acme.com/
|
||||
name: Website
|
||||
spec:
|
||||
type: organization
|
||||
profile:
|
||||
|
||||
@@ -5,6 +5,10 @@ metadata:
|
||||
description: The Smartylighting Streetlights API allows you to remotely manage the city lights.
|
||||
tags:
|
||||
- mqtt
|
||||
links:
|
||||
- url: https://github.com/asyncapi/asyncapi/blob/master/examples/1.2.0/streetlights.yml
|
||||
title: Source Code
|
||||
icon: code
|
||||
spec:
|
||||
type: asyncapi
|
||||
lifecycle: production
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,10 @@ kind: Component
|
||||
metadata:
|
||||
name: petstore
|
||||
description: Petstore
|
||||
links:
|
||||
- url: https://github.com/swagger-api/swagger-petstore
|
||||
title: GitHub Repo
|
||||
icon: github
|
||||
spec:
|
||||
type: service
|
||||
lifecycle: experimental
|
||||
|
||||
@@ -3,5 +3,8 @@ kind: Domain
|
||||
metadata:
|
||||
name: artists
|
||||
description: Everything related to artists
|
||||
links:
|
||||
- url: http://example.com/domain/readme
|
||||
title: Artists Domain Readme
|
||||
spec:
|
||||
owner: team-a
|
||||
|
||||
@@ -125,6 +125,11 @@ export type EntityMeta = JsonObject & {
|
||||
* various ways.
|
||||
*/
|
||||
tags?: string[];
|
||||
|
||||
/**
|
||||
* A list of external hyperlinks related to the entity.
|
||||
*/
|
||||
links?: EntityLink[];
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -161,3 +166,23 @@ export type EntityRelationSpec = {
|
||||
*/
|
||||
target: EntityName;
|
||||
};
|
||||
|
||||
/**
|
||||
* A link to external information that is related to the entity.
|
||||
*/
|
||||
export type EntityLink = {
|
||||
/**
|
||||
* The url to the external site, document, etc.
|
||||
*/
|
||||
url: string;
|
||||
|
||||
/**
|
||||
* An optional descriptive title for the link.
|
||||
*/
|
||||
title?: string;
|
||||
|
||||
/**
|
||||
* An optional semantic key that represents a visual icon.
|
||||
*/
|
||||
icon?: string;
|
||||
};
|
||||
|
||||
@@ -38,6 +38,10 @@ describe('FieldFormatEntityPolicy', () => {
|
||||
tags:
|
||||
- java
|
||||
- data-service
|
||||
links:
|
||||
- url: https://example.org
|
||||
title: Website
|
||||
icon: website
|
||||
spec:
|
||||
custom: stuff
|
||||
`);
|
||||
@@ -110,4 +114,9 @@ describe('FieldFormatEntityPolicy', () => {
|
||||
data.metadata.tags.push('Hello World');
|
||||
await expect(policy.enforce(data)).rejects.toThrow(/tags.*"Hello World"/i);
|
||||
});
|
||||
|
||||
it('rejects bad link icon value', async () => {
|
||||
data.metadata.links.push({ url: 'https://foo', icon: 'some icon' });
|
||||
await expect(policy.enforce(data)).rejects.toThrow(/links.*"some icon"/i);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -134,6 +134,12 @@ export class FieldFormatEntityPolicy implements EntityPolicy {
|
||||
require(`tags.${i}`, tags[i], this.validators.isValidTag);
|
||||
}
|
||||
|
||||
const links = entity.metadata.links ?? [];
|
||||
|
||||
for (let i = 0; i < links.length; ++i) {
|
||||
optional(`links.${i}`, links[i]?.icon, this.validators.isValidEntityName);
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user