Skip to content

Commit 0bf42e5

Browse files
committed
feat: add yaml check support
1 parent 51adf91 commit 0bf42e5

File tree

6 files changed

+177
-1
lines changed

6 files changed

+177
-1
lines changed

lib/checks/json.check.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export function jsonCheckTaskFactory(
9090
return;
9191
}
9292

93-
if (result.length) {
93+
if (result?.length) {
9494
matches.push({
9595
file,
9696
matches: result.map((r) => ({

lib/checks/yaml.check.ts

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import YAML from 'yaml';
2+
import ObjectPath from 'object-path';
3+
import { ListrDefaultRenderer, ListrTaskWrapper } from 'listr2';
4+
5+
import {
6+
DEFAULT_CHECK_EXECUTION_TIMEOUT,
7+
DEFAULT_EXCLUDE_FILES_PATTERN_CONTENT,
8+
} from '../consts';
9+
import {
10+
Context,
11+
ParentTask,
12+
ProjectCheckMatch,
13+
YAMLCheckDefinition,
14+
} from '../interface';
15+
import * as fs from '../services/fs.service';
16+
17+
import {
18+
CheckResultSymbol,
19+
getCheckFiles,
20+
resolveCheckParentTaskProgress,
21+
resolveCheckTaskFulfilledTitle,
22+
} from './check.service';
23+
24+
export function yamlCheckTaskFactory(
25+
definition: YAMLCheckDefinition,
26+
parentTask: ParentTask
27+
) {
28+
async function yamlCheckTask(
29+
ctx: Context,
30+
task: ListrTaskWrapper<Context, ListrDefaultRenderer>
31+
) {
32+
const { name, type, yamlPropertyPath } = definition;
33+
34+
const files = getCheckFiles(
35+
definition,
36+
DEFAULT_EXCLUDE_FILES_PATTERN_CONTENT
37+
);
38+
39+
task.title = `${task.title}, found ${files.length} files`;
40+
41+
if (!files.length) {
42+
ctx.results.checks![name] = {
43+
name,
44+
type,
45+
value: false,
46+
};
47+
task.title = `${CheckResultSymbol.UNFULFILLED} ${task.title}`;
48+
resolveCheckParentTaskProgress(parentTask);
49+
return;
50+
}
51+
52+
return new Promise<void>((resolve, reject) => {
53+
setTimeout(
54+
() => reject(`Check "${name}" timeout`),
55+
DEFAULT_CHECK_EXECUTION_TIMEOUT
56+
);
57+
58+
let finishedCounter = 0;
59+
60+
const errors: Error[] = [];
61+
const matches: ProjectCheckMatch[] = [];
62+
63+
for (const file of files) {
64+
setTimeout(() => {
65+
let data: any;
66+
let result: any[];
67+
try {
68+
data = YAML.parse(fs.readFile(file), { strict: false });
69+
result = ObjectPath.get(data, yamlPropertyPath);
70+
} catch (err: any) {
71+
const error = new Error(
72+
`[yaml] "${name}" - ${file} - ${err.message}`
73+
);
74+
errors.push(error);
75+
ctx.handledCheckFailures.push(error);
76+
finishedCounter++;
77+
if (finishedCounter === files.length) {
78+
resolve();
79+
}
80+
task.title = `${CheckResultSymbol.ERROR} ${task.title} - ${file} - ${err.message}`;
81+
resolveCheckParentTaskProgress(parentTask);
82+
return;
83+
}
84+
85+
if (result?.length) {
86+
matches.push({
87+
file,
88+
matches: [
89+
{
90+
match: yamlPropertyPath,
91+
groups: {
92+
[yamlPropertyPath]: result,
93+
},
94+
},
95+
],
96+
});
97+
}
98+
99+
finishedCounter++;
100+
101+
if (finishedCounter === files.length) {
102+
ctx.results.checks![name] = {
103+
name,
104+
type,
105+
value: matches.length > 0,
106+
matches,
107+
};
108+
109+
task.title = errors.length
110+
? errors.map((e) => e.message).join(',')
111+
: resolveCheckTaskFulfilledTitle(task, matches);
112+
resolveCheckParentTaskProgress(parentTask);
113+
114+
resolve();
115+
}
116+
});
117+
}
118+
});
119+
}
120+
return yamlCheckTask;
121+
}

lib/interface.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,18 @@ export interface JSONCheckDefinition extends BaseCheckDefinition {
136136
jsonPropertyPath: string;
137137
}
138138

139+
export interface YAMLCheckDefinition extends BaseCheckDefinition {
140+
yamlPropertyPath: string;
141+
}
142+
139143
export enum CheckType {
140144
CONTENT = 'content',
141145
XPATH = 'xpath',
142146
SIZE = 'size',
143147
META = 'meta',
144148
FILE = 'file',
145149
JSON = 'json',
150+
YAML = 'yaml',
146151
}
147152

148153
export enum ProjectType {

lib/tasks/run-checks.task.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
} from '../checks/check.service';
1818
import { fileCheckTaskFactory } from '../checks/file.check';
1919
import { jsonCheckTaskFactory } from '../checks/json.check';
20+
import { yamlCheckTaskFactory } from '../checks/yaml.check';
2021

2122
const DEFAULT_PROJECT_NAME_PATTERN_FLAGS = 'i';
2223

@@ -111,6 +112,8 @@ function buildTasks(ctx: Context, parentTask: ParentTask): ListrTask[] {
111112
return fileCheckTaskFactory(definition, parentTask);
112113
} else if (definition.type === CheckType.JSON) {
113114
return jsonCheckTaskFactory(definition, parentTask);
115+
} else if (definition.type === CheckType.YAML) {
116+
return yamlCheckTaskFactory(definition, parentTask);
114117
} else {
115118
return function unknownCheckTask(
116119
ctx: Context,

package-lock.json

Lines changed: 44 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,22 @@
2727
"got": "^11.8.2",
2828
"jsonpath-plus": "^6.0.1",
2929
"listr2": "^6.3.1",
30+
"object-path": "^0.11.8",
3031
"rxjs": "^7.8.0",
3132
"strip-json-comments": "^3.1.1",
3233
"strip-json-trailing-commas": "^1.1.0",
3334
"xml2js": "^0.4.23",
3435
"xmldom": "^0.6.0",
3536
"xpath": "0.0.32",
37+
"yaml": "^2.4.1",
3638
"yargs": "^17.1.1"
3739
},
3840
"devDependencies": {
3941
"@airbnb/node-memwatch": "^2.0.0",
4042
"@types/airbnb__node-memwatch": "^2.0.0",
4143
"@types/jest": "^27.0.1",
4244
"@types/node": "^16.7.2",
45+
"@types/object-path": "^0.11.4",
4346
"@types/xml2js": "^0.4.9",
4447
"@types/xmldom": "^0.1.31",
4548
"@types/yargs": "^17.0.2",

0 commit comments

Comments
 (0)