diff --git a/packages/catalog-model/src/schema/kinds/Template.v1beta2.schema.json b/packages/catalog-model/src/schema/kinds/Template.v1beta2.schema.json
index 01a012e5aa..b14cdb8ee0 100644
--- a/packages/catalog-model/src/schema/kinds/Template.v1beta2.schema.json
+++ b/packages/catalog-model/src/schema/kinds/Template.v1beta2.schema.json
@@ -146,7 +146,7 @@
"description": "A list of external hyperlinks, typically pointing to resources created or updated by the template",
"items": {
"type": "object",
- "required": ["url"],
+ "required": [],
"properties": {
"url": {
"type": "string",
@@ -154,6 +154,12 @@
"examples": ["https://github.com/my-org/my-new-repo"],
"minLength": 1
},
+ "entityRef": {
+ "type": "string",
+ "description": "An entity reference to an entity in the catalog.",
+ "examples": ["Component:default/my-app"],
+ "minLength": 1
+ },
"title": {
"type": "string",
"description": "A user friendly display name for the link.",
diff --git a/plugins/scaffolder-backend/sample-templates/v1beta2-demo/template.yaml b/plugins/scaffolder-backend/sample-templates/v1beta2-demo/template.yaml
index f15bef6f75..86f41b43d2 100644
--- a/plugins/scaffolder-backend/sample-templates/v1beta2-demo/template.yaml
+++ b/plugins/scaffolder-backend/sample-templates/v1beta2-demo/template.yaml
@@ -99,5 +99,9 @@ spec:
listWorkspace: true
output:
- remoteUrl: '{{ steps.publish.output.remoteUrl }}'
- entityRef: '{{ steps.register.output.entityRef }}'
+ links:
+ - title: Repository
+ url: '{{ steps.publish.output.remoteUrl }}'
+ - title: Open in catalog
+ icon: 'catalog'
+ entityRef: '{{ steps.register.output.entityRef }}'
diff --git a/plugins/scaffolder/src/components/TaskPage/TaskPageLinks.test.tsx b/plugins/scaffolder/src/components/TaskPage/TaskPageLinks.test.tsx
index cd51488242..230df903da 100644
--- a/plugins/scaffolder/src/components/TaskPage/TaskPageLinks.test.tsx
+++ b/plugins/scaffolder/src/components/TaskPage/TaskPageLinks.test.tsx
@@ -14,10 +14,10 @@
* limitations under the License.
*/
+import { entityRouteRef } from '@backstage/plugin-catalog-react';
+import { renderInTestApp } from '@backstage/test-utils';
import React from 'react';
import { TaskPageLinks } from './TaskPageLinks';
-import { renderInTestApp } from '@backstage/test-utils';
-import { entityRouteRef } from '@backstage/plugin-catalog-react';
describe('TaskPageLinks', () => {
beforeEach(() => {});
@@ -68,9 +68,11 @@ describe('TaskPageLinks', () => {
links: [
{ url: 'https://first.url', title: 'Cool link 1' },
{ url: 'https://second.url', title: 'Cool link 2' },
+ { entityRef: 'Component:default/my-app', title: 'Open in catalog' },
+ { title: 'Skipped' },
],
};
- const { findByText } = await renderInTestApp(
+ const { findByText, queryByText } = await renderInTestApp(
,
{
mountedRoutes: {
@@ -88,5 +90,15 @@ describe('TaskPageLinks', () => {
expect(element).toBeInTheDocument();
expect(element).toHaveAttribute('href', 'https://second.url');
+
+ element = await findByText('Open in catalog');
+
+ expect(element).toBeInTheDocument();
+ expect(element).toHaveAttribute(
+ 'href',
+ '/catalog/default/Component/my-app',
+ );
+
+ expect(queryByText('Skipped')).not.toBeInTheDocument();
});
});
diff --git a/plugins/scaffolder/src/components/TaskPage/TaskPageLinks.tsx b/plugins/scaffolder/src/components/TaskPage/TaskPageLinks.tsx
index c0b55193c2..394d755424 100644
--- a/plugins/scaffolder/src/components/TaskPage/TaskPageLinks.tsx
+++ b/plugins/scaffolder/src/components/TaskPage/TaskPageLinks.tsx
@@ -14,21 +14,21 @@
* limitations under the License.
*/
-import React from 'react';
import { parseEntityName } from '@backstage/catalog-model';
import { IconComponent, IconKey, useApp, useRouteRef } from '@backstage/core';
-import { IconLink } from './IconLink';
import { entityRouteRef } from '@backstage/plugin-catalog-react';
import { Box } from '@material-ui/core';
import LanguageIcon from '@material-ui/icons/Language';
+import React from 'react';
import { TaskOutput } from '../../types';
+import { IconLink } from './IconLink';
type TaskPageLinksProps = {
output: TaskOutput;
};
export const TaskPageLinks = ({ output }: TaskPageLinksProps) => {
- const { entityRef, remoteUrl } = output;
+ const { entityRef: entityRefOutput, remoteUrl } = output;
let { links = [] } = output;
const app = useApp();
const entityRoute = useRouteRef(entityRouteRef);
@@ -40,12 +40,10 @@ export const TaskPageLinks = ({ output }: TaskPageLinksProps) => {
links = [{ url: remoteUrl, title: 'Repo' }, ...links];
}
- if (entityRef) {
- const entityName = parseEntityName(entityRef);
- const target = entityRoute(entityName);
+ if (entityRefOutput) {
links = [
{
- url: target,
+ entityRef: entityRefOutput,
title: 'Open in catalog',
icon: 'catalog',
},
@@ -55,15 +53,25 @@ export const TaskPageLinks = ({ output }: TaskPageLinksProps) => {
return (
- {links.map(({ url, title, icon }, i) => (
-
- ))}
+ {links
+ .filter(({ url, entityRef }) => url || entityRef)
+ .map(({ url, entityRef, title, icon }) => {
+ if (entityRef) {
+ const entityName = parseEntityName(entityRef);
+ const target = entityRoute(entityName);
+ return { title, icon, url: target };
+ }
+ return { title, icon, url: url! };
+ })
+ .map(({ url, title, icon }, i) => (
+
+ ))}
);
};
diff --git a/plugins/scaffolder/src/types.ts b/plugins/scaffolder/src/types.ts
index e821d8fa9c..0a34450678 100644
--- a/plugins/scaffolder/src/types.ts
+++ b/plugins/scaffolder/src/types.ts
@@ -66,12 +66,14 @@ export type ListActionsResponse = Array<{
}>;
type OutputLink = {
- url: string;
title?: string;
icon?: string;
+ url?: string;
+ entityRef?: string;
};
export type TaskOutput = {
+ /** @deprecated use the `links` property to link out to relevant resources */
entityRef?: string;
/** @deprecated use the `links` property to link out to relevant resources */
remoteUrl?: string;