/
extract.ts
92 lines (85 loc) · 2.71 KB
/
extract.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
import is from '@sindresorhus/is';
import { load } from 'js-yaml';
import { GlobalConfig } from '../../../config/global';
import { logger } from '../../../logger';
import { regEx } from '../../../util/regex';
import { GitlabTagsDatasource } from '../../datasource/gitlab-tags';
import type {
GitlabInclude,
GitlabIncludeProject,
GitlabPipeline,
} from '../gitlabci/types';
import { replaceReferenceTags } from '../gitlabci/utils';
import type { PackageDependency, PackageFileContent } from '../types';
import {
filterIncludeFromGitlabPipeline,
isGitlabIncludeProject,
isNonEmptyObject,
} from './common';
function extractDepFromIncludeFile(
includeObj: GitlabIncludeProject
): PackageDependency {
const dep: PackageDependency = {
datasource: GitlabTagsDatasource.id,
depName: includeObj.project,
depType: 'repository',
};
if (!includeObj.ref) {
dep.skipReason = 'unspecified-version';
return dep;
}
dep.currentValue = includeObj.ref;
return dep;
}
function getIncludeProjectsFromInclude(
includeValue: GitlabInclude[] | GitlabInclude
): GitlabIncludeProject[] {
const includes = is.array(includeValue) ? includeValue : [includeValue];
// Filter out includes that dont have a file & project.
return includes.filter(isGitlabIncludeProject);
}
function getAllIncludeProjects(data: GitlabPipeline): GitlabIncludeProject[] {
// If Array, search each element.
if (is.array(data)) {
return (data as GitlabPipeline[])
.filter(isNonEmptyObject)
.map(getAllIncludeProjects)
.flat();
}
const childrenData = Object.values(filterIncludeFromGitlabPipeline(data))
.filter(isNonEmptyObject)
.map(getAllIncludeProjects)
.flat();
// Process include key.
if (data.include) {
childrenData.push(...getIncludeProjectsFromInclude(data.include));
}
return childrenData;
}
export function extractPackageFile(content: string): PackageFileContent | null {
const deps: PackageDependency[] = [];
const { platform, endpoint } = GlobalConfig.get();
try {
const doc = load(replaceReferenceTags(content), {
json: true,
}) as GitlabPipeline;
const includes = getAllIncludeProjects(doc);
for (const includeObj of includes) {
const dep = extractDepFromIncludeFile(includeObj);
if (platform === 'gitlab' && endpoint) {
dep.registryUrls = [endpoint.replace(regEx(/\/api\/v4\/?/), '')];
}
deps.push(dep);
}
} catch (err) /* istanbul ignore next */ {
if (err.stack?.startsWith('YAMLException:')) {
logger.debug({ err }, 'YAML exception extracting GitLab CI includes');
} else {
logger.warn({ err }, 'Error extracting GitLab CI includes');
}
}
if (!deps.length) {
return null;
}
return { deps };
}