fix(locationAnalyzer): don't add github slug annotation when SCM system cannot be determined
Signed-off-by: Phil Kuang <pkuang@factset.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
---
|
||||
|
||||
Correctly add `<source>/project-slug` annotation for new catalog-info.yaml PRs based on SCM integration.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/integration': patch
|
||||
---
|
||||
|
||||
Expose an `annotationPrefix` property for SCM integrations
|
||||
@@ -9,6 +9,7 @@ import { Config } from '@backstage/config';
|
||||
// @public (undocumented)
|
||||
export class AzureIntegration implements ScmIntegration {
|
||||
constructor(integrationConfig: AzureIntegrationConfig);
|
||||
get annotationPrefix(): string;
|
||||
// (undocumented)
|
||||
get config(): AzureIntegrationConfig;
|
||||
// (undocumented)
|
||||
@@ -36,6 +37,7 @@ export type AzureIntegrationConfig = {
|
||||
// @public (undocumented)
|
||||
export class BitbucketIntegration implements ScmIntegration {
|
||||
constructor(integrationConfig: BitbucketIntegrationConfig);
|
||||
get annotationPrefix(): string;
|
||||
// (undocumented)
|
||||
get config(): BitbucketIntegrationConfig;
|
||||
// (undocumented)
|
||||
@@ -118,6 +120,7 @@ export class GithubCredentialsProvider {
|
||||
// @public (undocumented)
|
||||
export class GitHubIntegration implements ScmIntegration {
|
||||
constructor(integrationConfig: GitHubIntegrationConfig);
|
||||
get annotationPrefix(): string;
|
||||
// (undocumented)
|
||||
get config(): GitHubIntegrationConfig;
|
||||
// (undocumented)
|
||||
@@ -148,6 +151,7 @@ export type GitHubIntegrationConfig = {
|
||||
// @public (undocumented)
|
||||
export class GitLabIntegration implements ScmIntegration {
|
||||
constructor(integrationConfig: GitLabIntegrationConfig);
|
||||
get annotationPrefix(): string;
|
||||
// (undocumented)
|
||||
get config(): GitLabIntegrationConfig;
|
||||
// (undocumented)
|
||||
@@ -209,6 +213,7 @@ export function readGoogleGcsIntegrationConfig(config: Config): GoogleGcsIntegra
|
||||
|
||||
// @public
|
||||
export interface ScmIntegration {
|
||||
annotationPrefix: string;
|
||||
resolveEditUrl(url: string): string;
|
||||
resolveUrl(options: {
|
||||
url: string;
|
||||
|
||||
@@ -39,6 +39,7 @@ describe('AzureIntegration', () => {
|
||||
it('returns the basics', () => {
|
||||
const integration = new AzureIntegration({ host: 'h.com' } as any);
|
||||
expect(integration.type).toBe('azure');
|
||||
expect(integration.annotationPrefix).toBe('dev.azure.com');
|
||||
expect(integration.title).toBe('h.com');
|
||||
});
|
||||
|
||||
|
||||
@@ -36,6 +36,13 @@ export class AzureIntegration implements ScmIntegration {
|
||||
return 'azure';
|
||||
}
|
||||
|
||||
/**
|
||||
* The prefix used for entity metadata.annotations for the integration.
|
||||
*/
|
||||
get annotationPrefix(): string {
|
||||
return 'dev.azure.com';
|
||||
}
|
||||
|
||||
get title(): string {
|
||||
return this.integrationConfig.host;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ describe('BitbucketIntegration', () => {
|
||||
it('returns the basics', () => {
|
||||
const integration = new BitbucketIntegration({ host: 'h.com' } as any);
|
||||
expect(integration.type).toBe('bitbucket');
|
||||
expect(integration.annotationPrefix).toBe('bitbucket.org');
|
||||
expect(integration.title).toBe('h.com');
|
||||
});
|
||||
|
||||
|
||||
@@ -41,6 +41,13 @@ export class BitbucketIntegration implements ScmIntegration {
|
||||
return 'bitbucket';
|
||||
}
|
||||
|
||||
/**
|
||||
* The prefix used for entity metadata.annotations for the integration.
|
||||
*/
|
||||
get annotationPrefix(): string {
|
||||
return 'bitbucket.org';
|
||||
}
|
||||
|
||||
get title(): string {
|
||||
return this.integrationConfig.host;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ describe('GitHubIntegration', () => {
|
||||
token: 't',
|
||||
});
|
||||
expect(integration.type).toBe('github');
|
||||
expect(integration.annotationPrefix).toBe('github.com');
|
||||
expect(integration.title).toBe('h.com');
|
||||
expect(integration.config.host).toBe('h.com');
|
||||
});
|
||||
|
||||
@@ -38,6 +38,13 @@ export class GitHubIntegration implements ScmIntegration {
|
||||
return 'github';
|
||||
}
|
||||
|
||||
/**
|
||||
* The prefix used for entity metadata.annotations for the integration.
|
||||
*/
|
||||
get annotationPrefix(): string {
|
||||
return 'github.com';
|
||||
}
|
||||
|
||||
get title(): string {
|
||||
return this.integrationConfig.host;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ describe('GitLabIntegration', () => {
|
||||
it('returns the basics', () => {
|
||||
const integration = new GitLabIntegration({ host: 'h.com' } as any);
|
||||
expect(integration.type).toBe('gitlab');
|
||||
expect(integration.annotationPrefix).toBe('gitlab.com');
|
||||
expect(integration.title).toBe('h.com');
|
||||
});
|
||||
|
||||
|
||||
@@ -38,6 +38,13 @@ export class GitLabIntegration implements ScmIntegration {
|
||||
return 'gitlab';
|
||||
}
|
||||
|
||||
/**
|
||||
* The prefix used for entity metadata.annotations for the integration.
|
||||
*/
|
||||
get annotationPrefix(): string {
|
||||
return 'gitlab.com';
|
||||
}
|
||||
|
||||
get title(): string {
|
||||
return this.integrationConfig.host;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,11 @@ export interface ScmIntegration {
|
||||
*/
|
||||
type: string;
|
||||
|
||||
/**
|
||||
* The prefix used for entity metadata.annotations for the integration , e.g. "github.com".
|
||||
*/
|
||||
annotationPrefix: string;
|
||||
|
||||
/**
|
||||
* A human readable title for the integration, that can be shown to users to
|
||||
* differentiate between different integrations.
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
import { Logger } from 'winston';
|
||||
import parseGitUrl from 'git-url-parse';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { ScmIntegrationRegistry } from '@backstage/integration';
|
||||
import {
|
||||
AnalyzeLocationRequest,
|
||||
AnalyzeLocationResponse,
|
||||
@@ -24,25 +26,32 @@ import {
|
||||
|
||||
export class RepoLocationAnalyzer implements LocationAnalyzer {
|
||||
private readonly logger: Logger;
|
||||
private readonly scmIntegrations: ScmIntegrationRegistry;
|
||||
|
||||
constructor(logger: Logger) {
|
||||
constructor(logger: Logger, scmIntegrations: ScmIntegrationRegistry) {
|
||||
this.logger = logger;
|
||||
this.scmIntegrations = scmIntegrations;
|
||||
}
|
||||
async analyzeLocation(
|
||||
request: AnalyzeLocationRequest,
|
||||
): Promise<AnalyzeLocationResponse> {
|
||||
const { owner, name, source } = parseGitUrl(request.location.target);
|
||||
const entity = {
|
||||
const { owner, name } = parseGitUrl(request.location.target);
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: name,
|
||||
// Probably won't handle properly self-hosted git providers with custom url
|
||||
annotations: { [`${source}/project-slug`]: `${owner}/${name}` },
|
||||
},
|
||||
spec: { type: 'other', lifecycle: 'unknown' },
|
||||
};
|
||||
|
||||
const integration = this.scmIntegrations.byUrl(request.location.target);
|
||||
if (integration) {
|
||||
entity.metadata.annotations = {
|
||||
[`${integration.annotationPrefix}/project-slug`]: `${owner}/${name}`,
|
||||
};
|
||||
}
|
||||
|
||||
this.logger.debug(`entity created for ${request.location.target}`);
|
||||
return {
|
||||
existingEntityFiles: [],
|
||||
|
||||
@@ -275,7 +275,7 @@ export class NextCatalogBuilder {
|
||||
);
|
||||
|
||||
const locationsCatalog = new DatabaseLocationsCatalog(db);
|
||||
const locationAnalyzer = new RepoLocationAnalyzer(logger);
|
||||
const locationAnalyzer = new RepoLocationAnalyzer(logger, integrations);
|
||||
const locationService = new DefaultLocationService(
|
||||
locationStore,
|
||||
orchestrator,
|
||||
|
||||
@@ -228,6 +228,7 @@ export class CatalogBuilder {
|
||||
locationAnalyzer: LocationAnalyzer;
|
||||
}> {
|
||||
const { config, database, logger } = this.env;
|
||||
const integrations = ScmIntegrations.fromConfig(config);
|
||||
|
||||
const policy = this.buildEntityPolicy();
|
||||
const processors = this.buildProcessors();
|
||||
@@ -255,7 +256,7 @@ export class CatalogBuilder {
|
||||
locationReader,
|
||||
logger,
|
||||
);
|
||||
const locationAnalyzer = new RepoLocationAnalyzer(logger);
|
||||
const locationAnalyzer = new RepoLocationAnalyzer(logger, integrations);
|
||||
|
||||
return {
|
||||
entitiesCatalog,
|
||||
|
||||
Reference in New Issue
Block a user