@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user