@sasjs/cli 6.6.0 → 6.7.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.
- package/README.md +2 -1
- package/build/commands/help/help.js +10 -0
- package/build/commands/index.d.ts +1 -0
- package/build/commands/index.js +3 -1
- package/build/commands/logcheck/collectLogs.d.ts +60 -0
- package/build/commands/logcheck/collectLogs.js +386 -0
- package/build/commands/logcheck/logCheckConfig.d.ts +72 -0
- package/build/commands/logcheck/logCheckConfig.js +283 -0
- package/build/commands/logcheck/logcheckCommand.d.ts +6 -0
- package/build/commands/logcheck/logcheckCommand.js +200 -0
- package/build/commands/logcheck/processLogCheck.d.ts +44 -0
- package/build/commands/logcheck/processLogCheck.js +242 -0
- package/build/commands/logcheck/renderLogCheck.d.ts +128 -0
- package/build/commands/logcheck/renderLogCheck.js +423 -0
- package/build/commands/logcheck/spec/collectLogs.spec.d.ts +1 -0
- package/build/commands/logcheck/spec/collectLogs.spec.js +477 -0
- package/build/commands/logcheck/spec/logCheckConfig.spec.d.ts +1 -0
- package/build/commands/logcheck/spec/logCheckConfig.spec.js +323 -0
- package/build/commands/logcheck/spec/logcheckCommand.spec.d.ts +1 -0
- package/build/commands/logcheck/spec/logcheckCommand.spec.js +360 -0
- package/build/commands/logcheck/spec/processLogCheck.spec.d.ts +1 -0
- package/build/commands/logcheck/spec/processLogCheck.spec.js +354 -0
- package/build/commands/logcheck/spec/renderLogCheck.spec.d.ts +1 -0
- package/build/commands/logcheck/spec/renderLogCheck.spec.js +426 -0
- package/build/commands/logcheck/types.d.ts +98 -0
- package/build/commands/logcheck/types.js +14 -0
- package/build/types/command/commandAliases.js +1 -0
- package/build/types/command/commandFactory.js +2 -0
- package/build/types/command/returnCode.d.ts +2 -1
- package/build/types/command/returnCode.js +4 -0
- package/package.json +3 -3
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
var __values = (this && this.__values) || function(o) {
|
|
14
|
+
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
15
|
+
if (m) return m.call(o);
|
|
16
|
+
if (o && typeof o.length === "number") return {
|
|
17
|
+
next: function () {
|
|
18
|
+
if (o && i >= o.length) o = void 0;
|
|
19
|
+
return { value: o && o[i++], done: !o };
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
23
|
+
};
|
|
24
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
25
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
26
|
+
if (!m) return o;
|
|
27
|
+
var i = m.call(o), r, ar = [], e;
|
|
28
|
+
try {
|
|
29
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
30
|
+
}
|
|
31
|
+
catch (error) { e = { error: error }; }
|
|
32
|
+
finally {
|
|
33
|
+
try {
|
|
34
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
35
|
+
}
|
|
36
|
+
finally { if (e) throw e.error; }
|
|
37
|
+
}
|
|
38
|
+
return ar;
|
|
39
|
+
};
|
|
40
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
41
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
42
|
+
if (ar || !(i in from)) {
|
|
43
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
44
|
+
ar[i] = from[i];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
48
|
+
};
|
|
49
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
50
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
51
|
+
};
|
|
52
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
53
|
+
exports.toAnnotations = exports.toReportIssue = exports.toJson = exports.summarise = exports.truncate = exports.severityLabel = exports.lineLabel = exports.columns = exports.issueDetails = exports.fileFails = exports.fileSummary = exports.renderHuman = exports.renderLogCheck = exports.MAX_MESSAGE_WIDTH = void 0;
|
|
54
|
+
var chalk_1 = __importDefault(require("chalk"));
|
|
55
|
+
var types_1 = require("./types");
|
|
56
|
+
/** Longest message shown in the human report before it is cut short. */
|
|
57
|
+
exports.MAX_MESSAGE_WIDTH = 110;
|
|
58
|
+
/** Blank line between two blocks of the human report. */
|
|
59
|
+
var GAP = '';
|
|
60
|
+
/**
|
|
61
|
+
* Prints the result in the requested format.
|
|
62
|
+
*
|
|
63
|
+
* The three formats are three views of one summary, never three scans: the
|
|
64
|
+
* terminal report, the JSON document and the CI annotations must all be
|
|
65
|
+
* describing the same parse, or they will disagree about the same log.
|
|
66
|
+
*/
|
|
67
|
+
var renderLogCheck = function (summary, config, options) {
|
|
68
|
+
if (options === void 0) { options = {}; }
|
|
69
|
+
var format = options.format || 'human';
|
|
70
|
+
if (format === 'json') {
|
|
71
|
+
process.stdout.write("".concat(JSON.stringify((0, exports.toJson)(summary, config), null, 2), "\n"));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (format === 'annotations') {
|
|
75
|
+
var lines = (0, exports.toAnnotations)(summary);
|
|
76
|
+
if (lines.length)
|
|
77
|
+
process.stdout.write("".concat(lines.join('\n'), "\n"));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
(0, exports.renderHuman)(summary, config, options.verbose || false);
|
|
81
|
+
};
|
|
82
|
+
exports.renderLogCheck = renderLogCheck;
|
|
83
|
+
/**
|
|
84
|
+
* The human report: what was checked, what was found, and the verdict.
|
|
85
|
+
*
|
|
86
|
+
* Colour carries severity and nothing else, so a reader scanning for trouble
|
|
87
|
+
* has one thing to look at, and the same report pasted into a ticket or
|
|
88
|
+
* piped into a log file without a terminal is still readable.
|
|
89
|
+
*/
|
|
90
|
+
var renderHuman = function (summary, config, verbose) {
|
|
91
|
+
var e_1, _a, e_2, _b;
|
|
92
|
+
var _c;
|
|
93
|
+
if (verbose === void 0) { verbose = false; }
|
|
94
|
+
var lines = [];
|
|
95
|
+
lines.push("".concat(chalk_1.default.bold('SASjs logcheck')).concat(chalk_1.default.dim(summary.searched.length ? " ".concat(summary.searched.join(', ')) : '')));
|
|
96
|
+
lines.push(GAP);
|
|
97
|
+
try {
|
|
98
|
+
for (var _d = __values(summary.missing), _e = _d.next(); !_e.done; _e = _d.next()) {
|
|
99
|
+
var missing = _e.value;
|
|
100
|
+
lines.push(chalk_1.default.red(" Path not found: ".concat(missing)) +
|
|
101
|
+
(summary.usedDefaultInput
|
|
102
|
+
? chalk_1.default.dim(' - nothing has run yet, or pass a path')
|
|
103
|
+
: ''));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
107
|
+
finally {
|
|
108
|
+
try {
|
|
109
|
+
if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
|
|
110
|
+
}
|
|
111
|
+
finally { if (e_1) throw e_1.error; }
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
for (var _f = __values(summary.unreadable), _g = _f.next(); !_g.done; _g = _f.next()) {
|
|
115
|
+
var folder = _g.value;
|
|
116
|
+
lines.push(chalk_1.default.red(" Could not read: ".concat(folder.displayPath)) +
|
|
117
|
+
chalk_1.default.dim(" (".concat(folder.reason, ") - its logs were not checked")));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
121
|
+
finally {
|
|
122
|
+
try {
|
|
123
|
+
if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
|
|
124
|
+
}
|
|
125
|
+
finally { if (e_2) throw e_2.error; }
|
|
126
|
+
}
|
|
127
|
+
var scanned = summary.logs.filter(function (entry) { return !entry.skippedReason; });
|
|
128
|
+
if (!scanned.length) {
|
|
129
|
+
if (!summary.missing.length) {
|
|
130
|
+
lines.push(summary.skipped.length
|
|
131
|
+
? chalk_1.default.yellow(' No SAS logs found - every file was skipped.')
|
|
132
|
+
: chalk_1.default.yellow(' No logs found at the path searched.'));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
lines.push.apply(lines, __spreadArray([], __read((0, exports.fileSummary)(scanned, config)), false));
|
|
137
|
+
lines.push.apply(lines, __spreadArray([], __read(skippedLines(summary, verbose)), false));
|
|
138
|
+
var details = (0, exports.issueDetails)(scanned);
|
|
139
|
+
if (details.length)
|
|
140
|
+
lines.push.apply(lines, __spreadArray([GAP], __read(details), false));
|
|
141
|
+
lines.push(GAP);
|
|
142
|
+
lines.push(" ".concat((0, exports.summarise)(summary, scanned.length)));
|
|
143
|
+
if (summary.totals.suppressed) {
|
|
144
|
+
lines.push(chalk_1.default.dim(" ".concat(plural(summary.totals.suppressed, 'issue'), " suppressed by message code").concat(config.ignoreCodes.length
|
|
145
|
+
? " (".concat(config.ignoreCodes.join(', '), ")")
|
|
146
|
+
: '')));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (summary.failure) {
|
|
150
|
+
lines.push("".concat(chalk_1.default.red.bold(' Logcheck failed: ')).concat(chalk_1.default.red(summary.failure)) +
|
|
151
|
+
chalk_1.default.dim(" (fail-on: ".concat(config.failOn, ")")));
|
|
152
|
+
}
|
|
153
|
+
else if (scanned.length) {
|
|
154
|
+
lines.push(chalk_1.default.green(" Logcheck passed (fail-on: ".concat(config.failOn, ")")));
|
|
155
|
+
}
|
|
156
|
+
lines.push('');
|
|
157
|
+
(_c = process.logger) === null || _c === void 0 ? void 0 : _c.log(lines.join('\n'));
|
|
158
|
+
};
|
|
159
|
+
exports.renderHuman = renderHuman;
|
|
160
|
+
/** The one-line-per-file table: what each log carried, and whether it failed. */
|
|
161
|
+
var fileSummary = function (scanned, config) {
|
|
162
|
+
if (config === void 0) { config = types_1.defaultLogCheckConfig; }
|
|
163
|
+
var rows = scanned.map(function (entry) { return [
|
|
164
|
+
entry.displayPath,
|
|
165
|
+
countCell(entry.counts.errors, chalk_1.default.red),
|
|
166
|
+
countCell(entry.counts.warnings, chalk_1.default.yellow),
|
|
167
|
+
countCell(entry.counts.notes, chalk_1.default.cyan),
|
|
168
|
+
(0, exports.fileFails)(entry.counts, config)
|
|
169
|
+
? chalk_1.default.red.bold('FAIL')
|
|
170
|
+
: chalk_1.default.green('pass')
|
|
171
|
+
]; });
|
|
172
|
+
return (0, exports.columns)(rows, ['FILE', 'ERRORS', 'WARNINGS', 'NOTES', 'STATUS'], ' ');
|
|
173
|
+
};
|
|
174
|
+
exports.fileSummary = fileSummary;
|
|
175
|
+
/**
|
|
176
|
+
* Whether a single log breaks the policy.
|
|
177
|
+
*
|
|
178
|
+
* The warnings budget is deliberately not applied here: it is a budget for the
|
|
179
|
+
* whole run, so a log carrying three warnings is not the one that broke it.
|
|
180
|
+
*/
|
|
181
|
+
var fileFails = function (counts, config) {
|
|
182
|
+
if (config.failOn === 'never')
|
|
183
|
+
return false;
|
|
184
|
+
if (counts.errors)
|
|
185
|
+
return true;
|
|
186
|
+
if (config.failOn === 'warning' || config.failOn === 'note') {
|
|
187
|
+
if (counts.warnings)
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
return config.failOn === 'note' && counts.notes > 0;
|
|
191
|
+
};
|
|
192
|
+
exports.fileFails = fileFails;
|
|
193
|
+
/**
|
|
194
|
+
* The issues themselves, grouped under the log they came from.
|
|
195
|
+
*
|
|
196
|
+
* This is the shape a compiler prints and a reader already knows how to scan:
|
|
197
|
+
* the file once, then `line:column`, the severity, the SAS code where there is
|
|
198
|
+
* one, and the message.
|
|
199
|
+
*/
|
|
200
|
+
var issueDetails = function (scanned) {
|
|
201
|
+
var e_3, _a;
|
|
202
|
+
var blocks = [];
|
|
203
|
+
try {
|
|
204
|
+
for (var scanned_1 = __values(scanned), scanned_1_1 = scanned_1.next(); !scanned_1_1.done; scanned_1_1 = scanned_1.next()) {
|
|
205
|
+
var entry = scanned_1_1.value;
|
|
206
|
+
if (!entry.issues.length)
|
|
207
|
+
continue;
|
|
208
|
+
blocks.push(__spreadArray([
|
|
209
|
+
chalk_1.default.bold(" ".concat(entry.displayPath))
|
|
210
|
+
], __read((0, exports.columns)(entry.issues.map(function (issue) { return [
|
|
211
|
+
(0, exports.lineLabel)(issue),
|
|
212
|
+
(0, exports.severityLabel)(issue.severity),
|
|
213
|
+
issue.code || chalk_1.default.dim('-'),
|
|
214
|
+
(0, exports.truncate)(issue.message)
|
|
215
|
+
]; }), ['LINE:COL', 'SEVERITY', 'CODE', 'MESSAGE'], ' ', ' ')), false));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
219
|
+
finally {
|
|
220
|
+
try {
|
|
221
|
+
if (scanned_1_1 && !scanned_1_1.done && (_a = scanned_1.return)) _a.call(scanned_1);
|
|
222
|
+
}
|
|
223
|
+
finally { if (e_3) throw e_3.error; }
|
|
224
|
+
}
|
|
225
|
+
// One blank between two logs' issues, none after the last: the caller adds
|
|
226
|
+
// the gap before the summary line, and two would leave a hole in the report.
|
|
227
|
+
return blocks.reduce(function (lines, block, index) {
|
|
228
|
+
return index === blocks.length - 1
|
|
229
|
+
? __spreadArray(__spreadArray([], __read(lines), false), __read(block), false) : __spreadArray(__spreadArray(__spreadArray([], __read(lines), false), __read(block), false), [GAP], false);
|
|
230
|
+
}, []);
|
|
231
|
+
};
|
|
232
|
+
exports.issueDetails = issueDetails;
|
|
233
|
+
var skippedLines = function (summary, verbose) {
|
|
234
|
+
if (!summary.skipped.length)
|
|
235
|
+
return [];
|
|
236
|
+
if (!verbose) {
|
|
237
|
+
return [
|
|
238
|
+
GAP,
|
|
239
|
+
chalk_1.default.dim(" ".concat(plural(summary.skipped.length, 'file'), " skipped (not a SAS log, or excluded) - rerun with --verbose to list them."))
|
|
240
|
+
];
|
|
241
|
+
}
|
|
242
|
+
return __spreadArray([
|
|
243
|
+
GAP
|
|
244
|
+
], __read((0, exports.columns)(summary.skipped.map(function (entry) { return [
|
|
245
|
+
chalk_1.default.dim(entry.displayPath),
|
|
246
|
+
chalk_1.default.dim(entry.reason)
|
|
247
|
+
]; }), ['SKIPPED FILE', 'REASON'], ' ', ' ')), false);
|
|
248
|
+
};
|
|
249
|
+
/**
|
|
250
|
+
* Lays rows out in aligned columns, with the header underlined by dashes.
|
|
251
|
+
*
|
|
252
|
+
* Colour codes take no space on screen, so widths are measured on the text
|
|
253
|
+
* with the codes removed - otherwise every coloured cell is padded by the
|
|
254
|
+
* length of its own escape sequences and the table drifts.
|
|
255
|
+
*/
|
|
256
|
+
var columns = function (rows, head, gap, indent) {
|
|
257
|
+
if (gap === void 0) { gap = ' '; }
|
|
258
|
+
if (indent === void 0) { indent = ''; }
|
|
259
|
+
var widths = [];
|
|
260
|
+
var measure = function (row) {
|
|
261
|
+
return row.forEach(function (cell, index) {
|
|
262
|
+
widths[index] = Math.max(widths[index] || 0, visibleLength(cell));
|
|
263
|
+
});
|
|
264
|
+
};
|
|
265
|
+
measure(head.map(function (header) { return chalk_1.default.white.bold(header); }));
|
|
266
|
+
rows.forEach(measure);
|
|
267
|
+
var render = function (row) {
|
|
268
|
+
return "".concat(indent).concat(row
|
|
269
|
+
.map(function (cell, index) {
|
|
270
|
+
return cell + ' '.repeat(Math.max(0, widths[index] - visibleLength(cell)));
|
|
271
|
+
})
|
|
272
|
+
.join(gap)
|
|
273
|
+
.trimEnd());
|
|
274
|
+
};
|
|
275
|
+
return __spreadArray([
|
|
276
|
+
render(head.map(function (header) { return chalk_1.default.white.bold(header); })),
|
|
277
|
+
"".concat(indent).concat(widths.map(function (width) { return '-'.repeat(width); }).join(gap))
|
|
278
|
+
], __read(rows.map(render)), false);
|
|
279
|
+
};
|
|
280
|
+
exports.columns = columns;
|
|
281
|
+
var visibleLength = function (value) {
|
|
282
|
+
return value.replace(/\u001b\[[0-9;]*m/g, '').length;
|
|
283
|
+
};
|
|
284
|
+
/** `13:5` for a one-line message, `13-15:5` for one SAS wrapped. */
|
|
285
|
+
var lineLabel = function (issue) {
|
|
286
|
+
return issue.endLine > issue.line
|
|
287
|
+
? "".concat(issue.line + 1, "-").concat(issue.endLine + 1, ":").concat(issue.column + 1)
|
|
288
|
+
: "".concat(issue.line + 1, ":").concat(issue.column + 1);
|
|
289
|
+
};
|
|
290
|
+
exports.lineLabel = lineLabel;
|
|
291
|
+
var severityLabel = function (severity) {
|
|
292
|
+
if (severity === 'error')
|
|
293
|
+
return chalk_1.default.red.bold('error');
|
|
294
|
+
if (severity === 'warning')
|
|
295
|
+
return chalk_1.default.yellow.bold('warning');
|
|
296
|
+
return chalk_1.default.cyan.bold('note');
|
|
297
|
+
};
|
|
298
|
+
exports.severityLabel = severityLabel;
|
|
299
|
+
/** Trims a message to the report width, on a word boundary where there is one. */
|
|
300
|
+
var truncate = function (message) {
|
|
301
|
+
var flat = message.replace(/\s+/g, ' ').trim();
|
|
302
|
+
if (flat.length <= exports.MAX_MESSAGE_WIDTH)
|
|
303
|
+
return flat;
|
|
304
|
+
var cut = flat.slice(0, exports.MAX_MESSAGE_WIDTH - 3);
|
|
305
|
+
var boundary = cut.lastIndexOf(' ');
|
|
306
|
+
return "".concat(boundary > 0 ? cut.slice(0, boundary) : cut, "...");
|
|
307
|
+
};
|
|
308
|
+
exports.truncate = truncate;
|
|
309
|
+
var countCell = function (count, colour) {
|
|
310
|
+
return count ? colour(String(count)) : chalk_1.default.dim('0');
|
|
311
|
+
};
|
|
312
|
+
/**
|
|
313
|
+
* The one-line answer: what was found, and over how many logs.
|
|
314
|
+
*
|
|
315
|
+
* It names the logs that were checked rather than the files that were not,
|
|
316
|
+
* because the number a reader compares against is the size of the result they
|
|
317
|
+
* have just looked at.
|
|
318
|
+
*/
|
|
319
|
+
var summarise = function (summary, scannedCount) {
|
|
320
|
+
var _a = summary.totals, errors = _a.errors, warnings = _a.warnings, notes = _a.notes, logs = _a.logs, skipped = _a.skipped;
|
|
321
|
+
var parts = [];
|
|
322
|
+
if (errors)
|
|
323
|
+
parts.push(plural(errors, 'error'));
|
|
324
|
+
if (warnings)
|
|
325
|
+
parts.push(plural(warnings, 'warning'));
|
|
326
|
+
if (notes)
|
|
327
|
+
parts.push(plural(notes, 'note'));
|
|
328
|
+
var scope = skipped > 0 ? "".concat(logs, " of ").concat(logs + skipped, " files") : plural(logs, 'log');
|
|
329
|
+
return parts.length
|
|
330
|
+
? "".concat(parts.join(', '), " in ").concat(scope)
|
|
331
|
+
: "No issues in ".concat(scope);
|
|
332
|
+
};
|
|
333
|
+
exports.summarise = summarise;
|
|
334
|
+
/**
|
|
335
|
+
* The machine report.
|
|
336
|
+
*
|
|
337
|
+
* Line and column are one-based here, as an editor and a CI annotation count
|
|
338
|
+
* them, while the parser works in indexes - the conversion happens once, at
|
|
339
|
+
* this boundary, so no consumer has to remember which convention it holds.
|
|
340
|
+
*/
|
|
341
|
+
var toJson = function (summary, config) {
|
|
342
|
+
var _a, _b;
|
|
343
|
+
return ({
|
|
344
|
+
tool: 'sasjs logcheck',
|
|
345
|
+
version: 1,
|
|
346
|
+
config: {
|
|
347
|
+
failOn: config.failOn,
|
|
348
|
+
maxWarnings: (_a = config.maxWarnings) !== null && _a !== void 0 ? _a : null,
|
|
349
|
+
ignoreCodes: config.ignoreCodes,
|
|
350
|
+
ignorePaths: config.ignorePaths
|
|
351
|
+
},
|
|
352
|
+
summary: {
|
|
353
|
+
logs: summary.totals.logs,
|
|
354
|
+
skipped: summary.totals.skipped,
|
|
355
|
+
errors: summary.totals.errors,
|
|
356
|
+
warnings: summary.totals.warnings,
|
|
357
|
+
notes: summary.totals.notes,
|
|
358
|
+
suppressed: summary.totals.suppressed,
|
|
359
|
+
failed: !!summary.failure,
|
|
360
|
+
failure: (_b = summary.failure) !== null && _b !== void 0 ? _b : null
|
|
361
|
+
},
|
|
362
|
+
searched: summary.searched,
|
|
363
|
+
missing: summary.missing,
|
|
364
|
+
unreadable: summary.unreadable.map(function (folder) { return ({
|
|
365
|
+
folder: folder.displayPath,
|
|
366
|
+
reason: folder.reason
|
|
367
|
+
}); }),
|
|
368
|
+
logs: summary.logs.map(function (entry) {
|
|
369
|
+
var _a;
|
|
370
|
+
return ({
|
|
371
|
+
file: entry.displayPath,
|
|
372
|
+
errors: entry.counts.errors,
|
|
373
|
+
warnings: entry.counts.warnings,
|
|
374
|
+
notes: entry.counts.notes,
|
|
375
|
+
suppressed: entry.suppressed.length,
|
|
376
|
+
skipped: (_a = entry.skippedReason) !== null && _a !== void 0 ? _a : null,
|
|
377
|
+
issues: entry.issues.map(exports.toReportIssue)
|
|
378
|
+
});
|
|
379
|
+
}),
|
|
380
|
+
skipped: summary.skipped.map(function (entry) { return ({
|
|
381
|
+
file: entry.displayPath,
|
|
382
|
+
reason: entry.reason
|
|
383
|
+
}); })
|
|
384
|
+
});
|
|
385
|
+
};
|
|
386
|
+
exports.toJson = toJson;
|
|
387
|
+
var toReportIssue = function (issue) { return (__assign(__assign({ line: issue.line + 1, endLine: issue.endLine + 1, column: issue.column + 1, endColumn: issue.endColumn + 1, severity: issue.severity }, (issue.code ? { code: issue.code } : {})), { message: issue.message })); };
|
|
388
|
+
exports.toReportIssue = toReportIssue;
|
|
389
|
+
/**
|
|
390
|
+
* GitHub Actions annotations, one line per issue.
|
|
391
|
+
*
|
|
392
|
+
* The workflow commands escape three characters in the message and five in the
|
|
393
|
+
* properties; doing it here means SAS's own text arrives intact, commas and
|
|
394
|
+
* colons included.
|
|
395
|
+
*/
|
|
396
|
+
var toAnnotations = function (summary) {
|
|
397
|
+
return summary.logs.flatMap(function (entry) {
|
|
398
|
+
return entry.issues.map(function (issue) {
|
|
399
|
+
var properties = [
|
|
400
|
+
"file=".concat(escapeProperty(entry.displayPath)),
|
|
401
|
+
"line=".concat(issue.line + 1),
|
|
402
|
+
"col=".concat(issue.column + 1),
|
|
403
|
+
"endLine=".concat(issue.endLine + 1),
|
|
404
|
+
"endColumn=".concat(issue.endColumn + 1),
|
|
405
|
+
"title=".concat(escapeProperty("SAS ".concat(issue.severity.toUpperCase()).concat(issue.code ? " ".concat(issue.code) : '')))
|
|
406
|
+
].join(',');
|
|
407
|
+
return "::".concat(annotationLevel(issue.severity), " ").concat(properties, "::").concat(escapeData(issue.message));
|
|
408
|
+
});
|
|
409
|
+
});
|
|
410
|
+
};
|
|
411
|
+
exports.toAnnotations = toAnnotations;
|
|
412
|
+
var annotationLevel = function (severity) {
|
|
413
|
+
return severity === 'error' ? 'error' : severity === 'warning' ? 'warning' : 'notice';
|
|
414
|
+
};
|
|
415
|
+
var escapeData = function (value) {
|
|
416
|
+
return value.replace(/%/g, '%25').replace(/\r/g, '%0D').replace(/\n/g, '%0A');
|
|
417
|
+
};
|
|
418
|
+
var escapeProperty = function (value) {
|
|
419
|
+
return escapeData(value).replace(/:/g, '%3A').replace(/,/g, '%2C');
|
|
420
|
+
};
|
|
421
|
+
var plural = function (count, noun) {
|
|
422
|
+
return "".concat(count, " ").concat(noun).concat(count === 1 ? '' : 's');
|
|
423
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|