Use proper location ref for custom source location

This commit is contained in:
James Turley
2021-02-19 12:17:35 +00:00
committed by James Turley
parent a4f863f8f8
commit e337085d38
6 changed files with 55 additions and 20 deletions
@@ -70,7 +70,7 @@ The value of this annotation is a location reference string (see above). If this
annotation is specified, it is expected to point to a repository that the
TechDocs system can read and generate docs from.
### backstage.io/browser-view-url, backstage.io/browser-edit-url, backstage.io/browser-source-url
### backstage.io/browser-view-url, backstage.io/browser-edit-url
```yaml
# Example:
@@ -78,16 +78,26 @@ metadata:
annotations:
backstage.io/browser-view-url: https://some.website/catalog-info.yaml
backstage.io/browser-edit-url: https://github.com/my-org/catalog/edit/master/my-service.jsonnet
backstage.io/browser-source-url: https://github.com/my-org/my-service
```
These annotations allow customising links from the catalog pages. The view URL
should point to the canonical metadata YAML that governs this entity. The edit
URL should point to the source file for the metadata. The source URL should
point to the source code of the entity itself (where relevant, i.e. when the
entity is a `Component`). In the example above, `my-org` generates its catalog
data from Jsonnet files in a monorepo, and so for the `my-service` component, we
need three custom links.
URL should point to the source file for the metadata. In the example above,
`my-org` generates its catalog data from Jsonnet files in a monorepo, so the
view and edit links need changing.
### backstage.io/source-location
```yaml
# Example:
metadata:
annotations:
backstage.io/source-location: github:https://github.com/my-org/my-service
```
A `Location` reference that points to the source code of the entity (typically a
`Component`). Useful when catalog files do not get ingested from the source code
repository itself.
### jenkins.io/github-folder
@@ -17,3 +17,5 @@
export const LOCATION_ANNOTATION = 'backstage.io/managed-by-location';
export const ORIGIN_LOCATION_ANNOTATION =
'backstage.io/managed-by-origin-location';
export const SOURCE_LOCATION_ANNOTATION = 'backstage.io/source-location';
+5 -1
View File
@@ -20,4 +20,8 @@ export {
locationSpecSchema,
analyzeLocationSchema,
} from './validation';
export { LOCATION_ANNOTATION, ORIGIN_LOCATION_ANNOTATION } from './annotation';
export {
LOCATION_ANNOTATION,
ORIGIN_LOCATION_ANNOTATION,
SOURCE_LOCATION_ANNOTATION,
} from './annotation';
@@ -15,6 +15,7 @@
*/
import { EntityProvider } from '@backstage/plugin-catalog-react';
import { SOURCE_LOCATION_ANNOTATION } from '@backstage/catalog-model';
import { render } from '@testing-library/react';
import React from 'react';
import { AboutCard } from './AboutCard';
@@ -135,8 +136,8 @@ describe('<AboutCard /> custom links', () => {
'backstage.io/managed-by-location':
'bitbucket:https://bitbucket.org/backstage/backstage/src/master/software.yaml',
'backstage.io/browser-edit-url': 'https://another.place',
'backstage.io/browser-source-url':
'https://another.place/backstage.git',
[SOURCE_LOCATION_ANNOTATION]:
'url:https://another.place/backstage.git',
},
},
spec: {
@@ -16,7 +16,9 @@
import {
Entity,
LocationSpec,
ENTITY_DEFAULT_NAMESPACE,
SOURCE_LOCATION_ANNOTATION,
RELATION_PROVIDES_API,
} from '@backstage/catalog-model';
import { HeaderIconLinkRow } from '@backstage/core';
@@ -34,7 +36,7 @@ import EditIcon from '@material-ui/icons/Edit';
import ExtensionIcon from '@material-ui/icons/Extension';
import GitHubIcon from '@material-ui/icons/GitHub';
import React from 'react';
import { findLocationForEntityMeta } from '../../data/utils';
import { findLocationForEntityMeta, parseLocation } from '../../data/utils';
import { findEditUrl, determineUrlType } from '../actions';
import { AboutContent } from './AboutContent';
@@ -60,23 +62,35 @@ type CodeLinkInfo = {
href?: string;
};
function getSourceLocationForEntity(
entity: Entity,
location?: LocationSpec,
): LocationSpec | undefined {
const annotation = entity.metadata?.annotations?.[SOURCE_LOCATION_ANNOTATION];
const parsed = annotation && parseLocation(annotation);
return parsed || location;
}
function getCodeLinkInfo(entity: Entity): CodeLinkInfo {
let sourceUrl =
entity.metadata?.annotations?.['backstage.io/browser-source-url'];
const location = findLocationForEntityMeta(entity?.metadata);
const editUrl = findEditUrl(entity, location);
let sourceLocation = getSourceLocationForEntity(entity, location);
if (location) {
sourceUrl = sourceUrl || location.target;
sourceLocation = sourceLocation || location;
const type =
location.type === 'url' ? determineUrlType(sourceUrl) : location.type;
sourceLocation.type === 'url'
? determineUrlType(sourceLocation.target)
: sourceLocation.type;
return {
edithref: editUrl,
icon: iconMap[type],
href: sourceUrl,
href: sourceLocation.target,
};
}
return { edithref: editUrl, href: sourceUrl };
return { edithref: editUrl, href: sourceLocation?.target };
}
type AboutCardProps = {
+7 -3
View File
@@ -32,13 +32,17 @@ export function findLocationForEntityMeta(
return undefined;
}
const separatorIndex = annotation.indexOf(':');
return parseLocation(annotation);
}
export function parseLocation(reference: string): LocationSpec | undefined {
const separatorIndex = reference.indexOf(':');
if (separatorIndex === -1) {
return undefined;
}
return {
type: annotation.substring(0, separatorIndex),
target: annotation.substring(separatorIndex + 1),
type: reference.substring(0, separatorIndex),
target: reference.substring(separatorIndex + 1),
};
}