From c531345df68d943c4652c30b898f9c6e7d40de7e Mon Sep 17 00:00:00 2001 From: Brian Fletcher Date: Mon, 23 Aug 2021 18:44:21 +0100 Subject: [PATCH] ability to discover catalog-infos from default branch Previously the github-discovery supported only repos from a specific branch. This change cause the discovery to work in two modes. It continues to work as it did with a wildcard for repositories on a specified branch. The new mode added causes the discovery processor to use the default branch and looks for a file called catalog-info.yaml. Signed-off-by: Brian Fletcher --- .../GithubDiscoveryProcessor.test.ts | 5 ++- .../processors/GithubDiscoveryProcessor.ts | 32 +++++++++++++++---- .../src/ingestion/processors/github/github.ts | 6 ++++ 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/plugins/catalog-backend/src/ingestion/processors/GithubDiscoveryProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/GithubDiscoveryProcessor.test.ts index ca8c702c8f..0717e24452 100644 --- a/plugins/catalog-backend/src/ingestion/processors/GithubDiscoveryProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/GithubDiscoveryProcessor.test.ts @@ -45,12 +45,15 @@ describe('GithubDiscoveryProcessor', () => { repoSearchPath: /^proj.*$/, catalogPath: '/blob/master/catalog.yaml', }); + expect(parseUrl('https://github.com/foo')).toEqual({ + org: 'foo', + host: 'github.com', + }); }); it('throws on incorrectly formed URLs', () => { expect(() => parseUrl('https://github.com')).toThrow(); expect(() => parseUrl('https://github.com//')).toThrow(); - expect(() => parseUrl('https://github.com/foo')).toThrow(); expect(() => parseUrl('https://github.com//foo')).toThrow(); expect(() => parseUrl('https://github.com/org/teams')).toThrow(); expect(() => parseUrl('https://github.com/org//teams')).toThrow(); diff --git a/plugins/catalog-backend/src/ingestion/processors/GithubDiscoveryProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/GithubDiscoveryProcessor.ts index f7069a9f64..8333728fb9 100644 --- a/plugins/catalog-backend/src/ingestion/processors/GithubDiscoveryProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/GithubDiscoveryProcessor.ts @@ -28,7 +28,15 @@ import { CatalogProcessor, CatalogProcessorEmit } from './types'; /** * Extracts repositories out of a GitHub org. - */ + * + * It can be configured in two modes. The first will create locations for all + * catalog-info.yaml files on the default branch. The second will create locations + * for all projects which have a catalog-info.yaml on the master branch. + * + * target: "https://github.com/backstage" + * or + * target: https://github.com/backstage/*\/blob/master/catalog-info.yaml + **/ export class GithubDiscoveryProcessor implements CatalogProcessor { private readonly integrations: ScmIntegrations; private readonly logger: Logger; @@ -87,9 +95,9 @@ export class GithubDiscoveryProcessor implements CatalogProcessor { this.logger.info(`Reading GitHub repositories from ${location.target}`); const { repositories } = await getOrganizationRepositories(client, org); - const matching = repositories.filter( - r => !r.isArchived && repoSearchPath.test(r.name), - ); + const matching = repoSearchPath + ? repositories.filter(r => !r.isArchived && repoSearchPath.test(r.name)) + : repositories; const duration = ((Date.now() - startTimestamp) / 1000).toFixed(1); this.logger.debug( @@ -97,11 +105,14 @@ export class GithubDiscoveryProcessor implements CatalogProcessor { ); for (const repository of matching) { + const path = catalogPath + ? catalogPath + : `/blob/${repository.defaultBranchRef.name}/catalog-info.yaml`; emit( results.location( { type: 'url', - target: `${repository.url}${catalogPath}`, + target: `${repository.url}${path}`, }, // Not all locations may actually exist, since the user defined them as a wildcard pattern. // Thus, we emit them as optional and let the downstream processor find them while not outputting @@ -121,14 +132,16 @@ export class GithubDiscoveryProcessor implements CatalogProcessor { export function parseUrl(urlString: string): { org: string; - repoSearchPath: RegExp; - catalogPath: string; + repoSearchPath?: RegExp; + catalogPath?: string; host: string; } { const url = new URL(urlString); const path = url.pathname.substr(1).split('/'); // /backstage/techdocs-*/blob/master/catalog-info.yaml + // can also be + // /backstage if (path.length > 2 && path[0].length && path[1].length) { return { org: decodeURIComponent(path[0]), @@ -136,6 +149,11 @@ export function parseUrl(urlString: string): { catalogPath: `/${decodeURIComponent(path.slice(2).join('/'))}`, host: url.host, }; + } else if (path.length === 1 && path[0].length) { + return { + org: decodeURIComponent(path[0]), + host: url.host, + }; } throw new Error(`Failed to parse ${urlString}`); diff --git a/plugins/catalog-backend/src/ingestion/processors/github/github.ts b/plugins/catalog-backend/src/ingestion/processors/github/github.ts index 70479110c2..9eb5073710 100644 --- a/plugins/catalog-backend/src/ingestion/processors/github/github.ts +++ b/plugins/catalog-backend/src/ingestion/processors/github/github.ts @@ -60,6 +60,9 @@ export type Repository = { name: string; url: string; isArchived: boolean; + defaultBranchRef: { + name: string; + }; }; export type Connection = { @@ -252,6 +255,9 @@ export async function getOrganizationRepositories( name url isArchived + defaultBranchRef { + name + } } pageInfo { hasNextPage