pr-checkmate 4.0.1 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Document, LineCounter } from 'yaml';
|
|
1
2
|
import { Check } from '../../types.js';
|
|
2
3
|
/**
|
|
3
4
|
* True when a parser problem describes something actually wrong with the file —
|
|
@@ -6,6 +7,20 @@ import { Check } from '../../types.js';
|
|
|
6
7
|
export declare function isFileDefect(problem: {
|
|
7
8
|
code?: string;
|
|
8
9
|
}): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Aliases (`*name`) that point at an anchor which does not exist before them.
|
|
12
|
+
*
|
|
13
|
+
* The parser does not treat this as a parse error: it builds the alias node and only
|
|
14
|
+
* throws when the document is converted to a JS value, which is exactly what a CI
|
|
15
|
+
* runner does next. So `doc.errors` stays empty for a pipeline that reuses a step via
|
|
16
|
+
* `*update-knowledge` after its `&update-knowledge` anchor was deleted, and the check
|
|
17
|
+
* used to pass a file Bitbucket rejects. Found by walking the alias nodes.
|
|
18
|
+
*/
|
|
19
|
+
export declare function unresolvedAliases(doc: Document.Parsed, lineCounter: LineCounter): {
|
|
20
|
+
name: string;
|
|
21
|
+
line: number;
|
|
22
|
+
col: number;
|
|
23
|
+
}[];
|
|
9
24
|
/**
|
|
10
25
|
* Bundled YAML linter (the `yaml` package — no runner dependency, always
|
|
11
26
|
* available like Markdown/Spellcheck). Parses every changed `.yml`/`.yaml` file
|
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.yamlLintCheck = void 0;
|
|
7
7
|
exports.isFileDefect = isFileDefect;
|
|
8
|
+
exports.unresolvedAliases = unresolvedAliases;
|
|
8
9
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
10
|
const node_path_1 = __importDefault(require("node:path"));
|
|
10
11
|
const yaml_1 = require("yaml");
|
|
@@ -38,6 +39,27 @@ const NON_DEFECT_CODES = new Set(['TAG_RESOLVE_FAILED']);
|
|
|
38
39
|
function isFileDefect(problem) {
|
|
39
40
|
return problem.code === undefined || !NON_DEFECT_CODES.has(problem.code);
|
|
40
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Aliases (`*name`) that point at an anchor which does not exist before them.
|
|
44
|
+
*
|
|
45
|
+
* The parser does not treat this as a parse error: it builds the alias node and only
|
|
46
|
+
* throws when the document is converted to a JS value, which is exactly what a CI
|
|
47
|
+
* runner does next. So `doc.errors` stays empty for a pipeline that reuses a step via
|
|
48
|
+
* `*update-knowledge` after its `&update-knowledge` anchor was deleted, and the check
|
|
49
|
+
* used to pass a file Bitbucket rejects. Found by walking the alias nodes.
|
|
50
|
+
*/
|
|
51
|
+
function unresolvedAliases(doc, lineCounter) {
|
|
52
|
+
const found = [];
|
|
53
|
+
(0, yaml_1.visit)(doc, {
|
|
54
|
+
Alias(_key, node) {
|
|
55
|
+
if (node.resolve(doc) !== undefined)
|
|
56
|
+
return;
|
|
57
|
+
const { line, col } = lineCounter.linePos(node.range?.[0] ?? 0);
|
|
58
|
+
found.push({ name: node.source, line, col });
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
return found;
|
|
62
|
+
}
|
|
41
63
|
/**
|
|
42
64
|
* Bundled YAML linter (the `yaml` package — no runner dependency, always
|
|
43
65
|
* available like Markdown/Spellcheck). Parses every changed `.yml`/`.yaml` file
|
|
@@ -81,8 +103,18 @@ exports.yamlLintCheck = {
|
|
|
81
103
|
}
|
|
82
104
|
// parseAllDocuments never throws — it collects problems on each document,
|
|
83
105
|
// so a single malformed file cannot abort the whole check.
|
|
84
|
-
const
|
|
106
|
+
const lineCounter = new yaml_1.LineCounter();
|
|
107
|
+
const docs = (0, yaml_1.parseAllDocuments)(source, { prettyErrors: true, lineCounter });
|
|
85
108
|
for (const doc of docs) {
|
|
109
|
+
for (const alias of unresolvedAliases(doc, lineCounter)) {
|
|
110
|
+
issues.push({
|
|
111
|
+
file,
|
|
112
|
+
blocking: true,
|
|
113
|
+
line: alias.line,
|
|
114
|
+
col: alias.col,
|
|
115
|
+
message: `Unresolved alias "*${alias.name}" (the anchor must be declared before the alias)`,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
86
118
|
const problems = [
|
|
87
119
|
...doc.errors.map(p => ({ problem: p, blocking: true })),
|
|
88
120
|
...doc.warnings.map(p => ({ problem: p, blocking: false })),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Document, LineCounter } from 'yaml';
|
|
1
2
|
import { Check } from '../../types.js';
|
|
2
3
|
/**
|
|
3
4
|
* True when a parser problem describes something actually wrong with the file —
|
|
@@ -6,6 +7,20 @@ import { Check } from '../../types.js';
|
|
|
6
7
|
export declare function isFileDefect(problem: {
|
|
7
8
|
code?: string;
|
|
8
9
|
}): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Aliases (`*name`) that point at an anchor which does not exist before them.
|
|
12
|
+
*
|
|
13
|
+
* The parser does not treat this as a parse error: it builds the alias node and only
|
|
14
|
+
* throws when the document is converted to a JS value, which is exactly what a CI
|
|
15
|
+
* runner does next. So `doc.errors` stays empty for a pipeline that reuses a step via
|
|
16
|
+
* `*update-knowledge` after its `&update-knowledge` anchor was deleted, and the check
|
|
17
|
+
* used to pass a file Bitbucket rejects. Found by walking the alias nodes.
|
|
18
|
+
*/
|
|
19
|
+
export declare function unresolvedAliases(doc: Document.Parsed, lineCounter: LineCounter): {
|
|
20
|
+
name: string;
|
|
21
|
+
line: number;
|
|
22
|
+
col: number;
|
|
23
|
+
}[];
|
|
9
24
|
/**
|
|
10
25
|
* Bundled YAML linter (the `yaml` package — no runner dependency, always
|
|
11
26
|
* available like Markdown/Spellcheck). Parses every changed `.yml`/`.yaml` file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { parseAllDocuments } from 'yaml';
|
|
3
|
+
import { LineCounter, parseAllDocuments, visit } from 'yaml';
|
|
4
4
|
import { logger, matchesAnyGlob } from '../../../utils/index.js';
|
|
5
5
|
import { resolveTargetFiles } from '../../targets.js';
|
|
6
6
|
import { pass, skip } from '../../types.js';
|
|
@@ -31,6 +31,27 @@ const NON_DEFECT_CODES = new Set(['TAG_RESOLVE_FAILED']);
|
|
|
31
31
|
export function isFileDefect(problem) {
|
|
32
32
|
return problem.code === undefined || !NON_DEFECT_CODES.has(problem.code);
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Aliases (`*name`) that point at an anchor which does not exist before them.
|
|
36
|
+
*
|
|
37
|
+
* The parser does not treat this as a parse error: it builds the alias node and only
|
|
38
|
+
* throws when the document is converted to a JS value, which is exactly what a CI
|
|
39
|
+
* runner does next. So `doc.errors` stays empty for a pipeline that reuses a step via
|
|
40
|
+
* `*update-knowledge` after its `&update-knowledge` anchor was deleted, and the check
|
|
41
|
+
* used to pass a file Bitbucket rejects. Found by walking the alias nodes.
|
|
42
|
+
*/
|
|
43
|
+
export function unresolvedAliases(doc, lineCounter) {
|
|
44
|
+
const found = [];
|
|
45
|
+
visit(doc, {
|
|
46
|
+
Alias(_key, node) {
|
|
47
|
+
if (node.resolve(doc) !== undefined)
|
|
48
|
+
return;
|
|
49
|
+
const { line, col } = lineCounter.linePos(node.range?.[0] ?? 0);
|
|
50
|
+
found.push({ name: node.source, line, col });
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
return found;
|
|
54
|
+
}
|
|
34
55
|
/**
|
|
35
56
|
* Bundled YAML linter (the `yaml` package — no runner dependency, always
|
|
36
57
|
* available like Markdown/Spellcheck). Parses every changed `.yml`/`.yaml` file
|
|
@@ -74,8 +95,18 @@ export const yamlLintCheck = {
|
|
|
74
95
|
}
|
|
75
96
|
// parseAllDocuments never throws — it collects problems on each document,
|
|
76
97
|
// so a single malformed file cannot abort the whole check.
|
|
77
|
-
const
|
|
98
|
+
const lineCounter = new LineCounter();
|
|
99
|
+
const docs = parseAllDocuments(source, { prettyErrors: true, lineCounter });
|
|
78
100
|
for (const doc of docs) {
|
|
101
|
+
for (const alias of unresolvedAliases(doc, lineCounter)) {
|
|
102
|
+
issues.push({
|
|
103
|
+
file,
|
|
104
|
+
blocking: true,
|
|
105
|
+
line: alias.line,
|
|
106
|
+
col: alias.col,
|
|
107
|
+
message: `Unresolved alias "*${alias.name}" (the anchor must be declared before the alias)`,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
79
110
|
const problems = [
|
|
80
111
|
...doc.errors.map(p => ({ problem: p, blocking: true })),
|
|
81
112
|
...doc.warnings.map(p => ({ problem: p, blocking: false })),
|
package/package.json
CHANGED