add pattern match

Signed-off-by: Kiss Miklos <miklos@roadie.io>
This commit is contained in:
Kiss Miklos
2023-02-06 17:53:57 +01:00
parent 26ad3398a8
commit 54cffaf07c
5 changed files with 50 additions and 11 deletions
@@ -21,7 +21,7 @@ import { LocationSpec } from '@backstage/plugin-catalog-node';
const mockCodeOwnersText = () => `
* @acme/team-foo @acme/team-bar
/docs @acme/team-bar
/docs @acme/team-docs
`;
describe('CodeOwnersProcessor', () => {
@@ -34,8 +34,12 @@ describe('CodeOwnersProcessor', () => {
});
describe('preProcessEntity', () => {
const setupTest = ({ kind = 'Component', spec = {} } = {}) => {
const entity = { kind, spec };
const setupTest = ({
kind = 'Component',
spec = {},
metadata = {},
} = {}) => {
const entity = { kind, spec, metadata };
const config = new ConfigReader({});
const reader = {
read: jest.fn(),
@@ -101,5 +105,22 @@ describe('CodeOwnersProcessor', () => {
spec: { owner: 'team-foo' },
});
});
it('should use the "backstage.io/managed-by-location" annotation as pattern', async () => {
const { entity, processor } = setupTest({
metadata: {
annotations: { 'backstage.io/managed-by-location': '/docs' },
},
});
const result = await processor.preProcessEntity(
entity as any,
mockLocation(),
);
expect(result).toEqual({
...entity,
spec: { owner: 'team-docs' },
});
});
});
});
@@ -79,8 +79,10 @@ export class CodeOwnersProcessor implements CatalogProcessor {
if (!scmIntegration) {
return entity;
}
const pattern =
entity.metadata?.annotations['backstage.io/managed-by-location'];
entity.metadata?.annotations?.['backstage.io/managed-by-location'];
const owner = await findCodeOwnerByTarget(
this.reader,
location.target,
@@ -52,7 +52,7 @@ export async function findCodeOwnerByTarget(
reader: UrlReader,
targetUrl: string,
scmIntegration: ScmIntegration,
pattern: string,
pattern?: string,
): Promise<string | undefined> {
const codeownersPaths = scmCodeOwnersPaths[scmIntegration?.type ?? ''];
@@ -18,13 +18,21 @@ import { normalizeCodeOwner, resolveCodeOwner } from './resolve';
const mockCodeOwnersText = () => `
* @acme/team-foo @acme/team-bar
/docs @acme/team-bar
/docs @acme/team-docs
`;
describe('resolveCodeOwner', () => {
it('should parse the codeowners file', () => {
expect(resolveCodeOwner(mockCodeOwnersText())).toBe('team-foo');
});
it('should include the codeowners path into the provided pattern', () => {
expect(
resolveCodeOwner(
mockCodeOwnersText(),
'url:https://github.com/acem/repo/main/docs/catalog-info.yaml',
),
).toBe('team-docs');
});
});
describe('normalizeCodeOwner', () => {
@@ -16,7 +16,7 @@
import * as codeowners from 'codeowners-utils';
import { CodeOwnersEntry } from 'codeowners-utils';
import { filter, get, head, pipe, reverse } from 'lodash/fp';
import { get, head, pipe, reverse } from 'lodash/fp';
const USER_PATTERN = /^@.*/;
const GROUP_PATTERN = /^@.*\/.*/;
@@ -24,18 +24,26 @@ const EMAIL_PATTERN = /^.*@.*\..*$/;
export function resolveCodeOwner(
contents: string,
pattern = '*',
pattern?: string,
): string | undefined {
const owners = codeowners.parse(contents);
return pipe(
filter((e: CodeOwnersEntry) => pattern.includes(e.pattern)),
let relevantOwners = owners.filter((e: CodeOwnersEntry) =>
pattern?.includes(e.pattern),
);
if (relevantOwners.length === 0) {
relevantOwners = owners.filter((e: CodeOwnersEntry) => e.pattern === '*');
}
const result = pipe(
reverse,
head,
get('owners'),
head,
normalizeCodeOwner,
)(owners);
)(relevantOwners);
return result;
}
export function normalizeCodeOwner(owner: string) {