-
Notifications
You must be signed in to change notification settings - Fork 5.6k
/
CodeOwnersProcessor.ts
104 lines (92 loc) · 2.65 KB
/
CodeOwnersProcessor.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { UrlReader } from '@backstage/backend-common';
import { Entity, LocationSpec } from '@backstage/catalog-model';
import { Config } from '@backstage/config';
import {
ScmIntegrationRegistry,
ScmIntegrations,
} from '@backstage/integration';
import { Logger } from 'winston';
import { findCodeOwnerByTarget } from './codeowners';
import { CatalogProcessor } from './types';
const ALLOWED_KINDS = ['API', 'Component', 'Domain', 'Resource', 'System'];
const ALLOWED_LOCATION_TYPES = [
'url',
'azure/api',
'bitbucket/api',
'github',
'github/api',
'gitlab',
'gitlab/api',
];
export class CodeOwnersProcessor implements CatalogProcessor {
private readonly integrations: ScmIntegrationRegistry;
private readonly logger: Logger;
private readonly reader: UrlReader;
static fromConfig(
config: Config,
options: { logger: Logger; reader: UrlReader },
) {
const integrations = ScmIntegrations.fromConfig(config);
return new CodeOwnersProcessor({
...options,
integrations,
});
}
constructor(options: {
integrations: ScmIntegrationRegistry;
logger: Logger;
reader: UrlReader;
}) {
this.integrations = options.integrations;
this.logger = options.logger;
this.reader = options.reader;
}
async preProcessEntity(
entity: Entity,
location: LocationSpec,
): Promise<Entity> {
// Only continue if the owner is not set
if (
!entity ||
!ALLOWED_KINDS.includes(entity.kind) ||
!ALLOWED_LOCATION_TYPES.includes(location.type) ||
(entity.spec && entity.spec.owner)
) {
return entity;
}
const scmIntegration = this.integrations.byUrl(location.target);
if (!scmIntegration) {
return entity;
}
const owner = await findCodeOwnerByTarget(
this.reader,
location.target,
scmIntegration,
);
if (!owner) {
this.logger.debug(
`CodeOwnerProcessor could not resolve owner for ${location.target}`,
);
return entity;
}
return {
...entity,
spec: { ...entity.spec, owner },
};
}
}