@sasjs/cli 6.6.0 → 6.8.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/flow/flowCommand.js +11 -1
- package/build/commands/flow/internal/executeFlow.js +44 -19
- package/build/commands/flow/internal/saveLog.d.ts +12 -1
- package/build/commands/flow/internal/saveLog.js +2 -2
- package/build/commands/flow/internal/spec/executeFlow.spec.js +44 -1
- package/build/commands/flow/spec/flowCommand.spec.js +44 -0
- 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/job/internal/execute/sas9.js +16 -13
- package/build/commands/job/internal/execute/sasjs.js +12 -9
- package/build/commands/job/internal/execute/viya.js +41 -36
- package/build/commands/job/jobCommand.js +13 -0
- package/build/commands/job/spec/executeLogOrder.spec.d.ts +1 -0
- package/build/commands/job/spec/executeLogOrder.spec.js +119 -0
- package/build/commands/job/spec/jobCommand.spec.js +32 -0
- package/build/commands/logcheck/collectLogs.d.ts +60 -0
- package/build/commands/logcheck/collectLogs.js +386 -0
- package/build/commands/logcheck/logCheckConfig.d.ts +83 -0
- package/build/commands/logcheck/logCheckConfig.js +343 -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 +129 -0
- package/build/commands/logcheck/renderLogCheck.js +424 -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 +384 -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 +106 -0
- package/build/commands/logcheck/types.js +14 -0
- package/build/commands/request/request.js +66 -27
- package/build/commands/request/requestCommand.js +11 -1
- package/build/commands/request/spec/requestCommand.spec.js +40 -0
- package/build/commands/run/run.d.ts +1 -3
- package/build/commands/run/run.js +20 -5
- package/build/commands/run/runCommand.js +9 -0
- package/build/commands/run/spec/runCommand.spec.js +50 -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/build/utils/index.d.ts +1 -0
- package/build/utils/index.js +1 -0
- package/build/utils/logcheck.d.ts +44 -0
- package/build/utils/logcheck.js +224 -0
- package/build/utils/spec/logcheck.spec.d.ts +1 -0
- package/build/utils/spec/logcheck.spec.js +297 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[![npm package][npm-image]][npm-url]
|
|
4
4
|
[![Github Workflow][githubworkflow-image]][githubworkflow-url]
|
|
5
|
-
[]()
|
|
5
|
+
[](<>)
|
|
6
6
|

|
|
7
7
|
[](https://github.com/sasjs/cli/issues?q=is%3Aissue+is%3Aclosed)
|
|
8
8
|
[](https://github.com/sasjs/cli/issues)
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
- Optionally synchronise a local folder onto the server filesystem using `sasjs fs`
|
|
24
24
|
- Trigger Viya Jobs & Flows (`sasjs job execute` / `sasjs flow execute`)
|
|
25
25
|
- Enforce code quality rules with `sasjs lint`
|
|
26
|
+
- Check what SAS actually printed, and fail a pipeline on it, with `sasjs logcheck` - the same check reports the log of `run`, `request`, `job execute` and `flow execute`, and can fail those commands too via `logCheck.autoCheck`
|
|
26
27
|
- Generate HTML5 documentation (requires doxygen) with `sasjs doc`
|
|
27
28
|
- Create and execute SAS tests (`sasjs test`)
|
|
28
29
|
|
|
@@ -60,6 +60,7 @@ var command_1 = require("../../types/command");
|
|
|
60
60
|
var targetCommand_1 = require("../../types/command/targetCommand");
|
|
61
61
|
var utils_1 = require("../../utils");
|
|
62
62
|
var execute_1 = require("./execute");
|
|
63
|
+
var logcheck_1 = require("../../utils/logcheck");
|
|
63
64
|
var FlowSubCommand;
|
|
64
65
|
(function (FlowSubCommand) {
|
|
65
66
|
FlowSubCommand["Execute"] = "execute";
|
|
@@ -97,6 +98,11 @@ var executeParseOptions = {
|
|
|
97
98
|
streamLog: {
|
|
98
99
|
type: 'boolean',
|
|
99
100
|
description: 'Flag indicating whether the logs should be streamed to a local file as the job executes.'
|
|
101
|
+
},
|
|
102
|
+
logcheck: {
|
|
103
|
+
type: 'boolean',
|
|
104
|
+
default: undefined,
|
|
105
|
+
description: 'Check the log of every job in the flow, and fail when logCheck in sasjsconfig.json says so. --no-logcheck switches both the report and the verdict off. A log streamed with --streamLog goes straight to its file and is not checked.'
|
|
100
106
|
}
|
|
101
107
|
};
|
|
102
108
|
var FlowCommand = /** @class */ (function (_super) {
|
|
@@ -117,7 +123,9 @@ var FlowCommand = /** @class */ (function (_super) {
|
|
|
117
123
|
var target, sasjs, authConfig, _a;
|
|
118
124
|
return __generator(this, function (_b) {
|
|
119
125
|
switch (_b.label) {
|
|
120
|
-
case 0:
|
|
126
|
+
case 0:
|
|
127
|
+
(0, logcheck_1.setLogCheckMode)((0, logcheck_1.logCheckModeOf)(this.parsed.logcheck));
|
|
128
|
+
return [4 /*yield*/, this.getTargetInfo()];
|
|
121
129
|
case 1:
|
|
122
130
|
target = (_b.sent()).target;
|
|
123
131
|
sasjs = (0, utils_1.getSASjs)(target);
|
|
@@ -160,6 +168,8 @@ var FlowCommand = /** @class */ (function (_super) {
|
|
|
160
168
|
return command_1.ReturnCode.Success;
|
|
161
169
|
})
|
|
162
170
|
.catch(function (err) {
|
|
171
|
+
if ((0, logcheck_1.isLogCheckFailure)(err))
|
|
172
|
+
return command_1.ReturnCode.LogCheckError;
|
|
163
173
|
(0, utils_1.displayError)(err, 'An error has occurred when executing this flow.');
|
|
164
174
|
return command_1.ReturnCode.InternalError;
|
|
165
175
|
})];
|
|
@@ -44,6 +44,7 @@ var utils_1 = require("../../../utils");
|
|
|
44
44
|
var _1 = require(".");
|
|
45
45
|
var csvColumns_1 = __importDefault(require("./csvColumns"));
|
|
46
46
|
var flow_1 = require("../../../types/flow");
|
|
47
|
+
var logcheck_1 = require("../../../utils/logcheck");
|
|
47
48
|
var executeFlow = function (flow, sasjs, pollOptions, target, authConfig, csvFile) { return __awaiter(void 0, void 0, void 0, function () {
|
|
48
49
|
var logFolder, flowName, jobStatus, flowStatus;
|
|
49
50
|
return __generator(this, function (_a) {
|
|
@@ -55,10 +56,10 @@ var executeFlow = function (flow, sasjs, pollOptions, target, authConfig, csvFil
|
|
|
55
56
|
jobStatus = true, flowStatus = { terminate: false, message: '' };
|
|
56
57
|
flow.execution = 'started';
|
|
57
58
|
return [4 /*yield*/, Promise.all(flow.jobs.map(function (job) { return __awaiter(void 0, void 0, void 0, function () {
|
|
58
|
-
var jobLocation, logName, submittedJob, details, predecessors, data;
|
|
59
|
-
var _a, _b;
|
|
60
|
-
return __generator(this, function (
|
|
61
|
-
switch (
|
|
59
|
+
var jobLocation, logName, submittedJob, details, jobLogText, savedLog, predecessors, data;
|
|
60
|
+
var _a, _b, _c;
|
|
61
|
+
return __generator(this, function (_d) {
|
|
62
|
+
switch (_d.label) {
|
|
62
63
|
case 0:
|
|
63
64
|
jobLocation = (0, utils_1.prefixAppLoc)(target.appLoc, job.location);
|
|
64
65
|
(0, utils_1.displaySuccess)("'".concat(job.location, "' has been submitted for execution."));
|
|
@@ -71,7 +72,7 @@ var executeFlow = function (flow, sasjs, pollOptions, target, authConfig, csvFil
|
|
|
71
72
|
contextName: target.contextName
|
|
72
73
|
}, authConfig, true, pollOptions, true, job.macroVars, undefined, (0, utils_1.persistTokensRefreshedByAdapter)(target))
|
|
73
74
|
.catch(function (err) { return __awaiter(void 0, void 0, void 0, function () {
|
|
74
|
-
var
|
|
75
|
+
var savedLog, predecessors, data;
|
|
75
76
|
var _a, _b, _c, _d;
|
|
76
77
|
return __generator(this, function (_e) {
|
|
77
78
|
switch (_e.label) {
|
|
@@ -88,8 +89,10 @@ var executeFlow = function (flow, sasjs, pollOptions, target, authConfig, csvFil
|
|
|
88
89
|
(0, utils_1.displayError)(err, 'Error while saving log file.');
|
|
89
90
|
})];
|
|
90
91
|
case 1:
|
|
91
|
-
|
|
92
|
-
logName =
|
|
92
|
+
savedLog = _e.sent();
|
|
93
|
+
logName = (savedLog === null || savedLog === void 0 ? void 0 : savedLog.fileName)
|
|
94
|
+
? "".concat(logFolder, "/").concat(savedLog.fileName)
|
|
95
|
+
: '';
|
|
93
96
|
predecessors = ((_c = flow.predecessors) === null || _c === void 0 ? void 0 : _c.length)
|
|
94
97
|
? flow.predecessors
|
|
95
98
|
: ['none'];
|
|
@@ -103,9 +106,18 @@ var executeFlow = function (flow, sasjs, pollOptions, target, authConfig, csvFil
|
|
|
103
106
|
];
|
|
104
107
|
return [4 /*yield*/, (0, _1.saveToCsv)(csvFile, data, Object.values(csvColumns_1.default), 'id').catch(function (err) {
|
|
105
108
|
(0, utils_1.displayError)(err, 'Error while saving CSV file.');
|
|
106
|
-
})
|
|
109
|
+
})
|
|
110
|
+
// after the report and the log file: a check that fails is still a job
|
|
111
|
+
// someone has to find in the CSV, with its log on disk
|
|
112
|
+
];
|
|
107
113
|
case 2:
|
|
108
114
|
_e.sent();
|
|
115
|
+
if (!(savedLog === null || savedLog === void 0 ? void 0 : savedLog.logText)) return [3 /*break*/, 4];
|
|
116
|
+
return [4 /*yield*/, (0, logcheck_1.checkLog)(savedLog.logText, "".concat(flowName, "/").concat(jobLocation))];
|
|
117
|
+
case 3:
|
|
118
|
+
_e.sent();
|
|
119
|
+
_e.label = 4;
|
|
120
|
+
case 4:
|
|
109
121
|
job.status = flow_1.FlowWaveJobStatus.Failure;
|
|
110
122
|
if (logName) {
|
|
111
123
|
(_d = process.logger) === null || _d === void 0 ? void 0 : _d.info("Log file located at: ".concat((0, _1.normalizeFilePath)(logName)));
|
|
@@ -120,20 +132,24 @@ var executeFlow = function (flow, sasjs, pollOptions, target, authConfig, csvFil
|
|
|
120
132
|
});
|
|
121
133
|
}); })];
|
|
122
134
|
case 1:
|
|
123
|
-
submittedJob =
|
|
124
|
-
if (!(submittedJob === null || submittedJob === void 0 ? void 0 : submittedJob.job)) return [3 /*break*/,
|
|
135
|
+
submittedJob = _d.sent();
|
|
136
|
+
if (!(submittedJob === null || submittedJob === void 0 ? void 0 : submittedJob.job)) return [3 /*break*/, 7];
|
|
125
137
|
submittedJob = submittedJob.job;
|
|
126
138
|
details = (0, _1.parseJobDetails)(submittedJob);
|
|
139
|
+
jobLogText = '';
|
|
127
140
|
if (!!pollOptions.streamLog) return [3 /*break*/, 3];
|
|
128
141
|
return [4 /*yield*/, (0, _1.saveLog)(submittedJob.links, flowName, jobLocation, logFolder, sasjs, target.serverUrl, authConfig.access_token, details === null || details === void 0 ? void 0 : details.lineCount).catch(function (err) {
|
|
129
142
|
(0, utils_1.displayError)(err, 'Error while saving log file.');
|
|
130
143
|
})];
|
|
131
144
|
case 2:
|
|
132
|
-
|
|
133
|
-
logName =
|
|
134
|
-
|
|
145
|
+
savedLog = _d.sent();
|
|
146
|
+
logName = (savedLog === null || savedLog === void 0 ? void 0 : savedLog.fileName)
|
|
147
|
+
? "".concat(logFolder, "/").concat(savedLog.fileName)
|
|
148
|
+
: '';
|
|
149
|
+
jobLogText = (_a = savedLog === null || savedLog === void 0 ? void 0 : savedLog.logText) !== null && _a !== void 0 ? _a : '';
|
|
150
|
+
_d.label = 3;
|
|
135
151
|
case 3:
|
|
136
|
-
predecessors = ((
|
|
152
|
+
predecessors = ((_b = flow.predecessors) === null || _b === void 0 ? void 0 : _b.length)
|
|
137
153
|
? flow.predecessors
|
|
138
154
|
: ['none'];
|
|
139
155
|
data = [
|
|
@@ -144,9 +160,18 @@ var executeFlow = function (flow, sasjs, pollOptions, target, authConfig, csvFil
|
|
|
144
160
|
logName,
|
|
145
161
|
details === null || details === void 0 ? void 0 : details.details
|
|
146
162
|
];
|
|
147
|
-
return [4 /*yield*/, (0, _1.saveToCsv)(csvFile, data, Object.values(csvColumns_1.default), 'id').catch(function (err) { return (0, utils_1.displayError)(err, 'Error while saving CSV file.'); })
|
|
163
|
+
return [4 /*yield*/, (0, _1.saveToCsv)(csvFile, data, Object.values(csvColumns_1.default), 'id').catch(function (err) { return (0, utils_1.displayError)(err, 'Error while saving CSV file.'); })
|
|
164
|
+
// after the report and the log file: a check that fails is still a job
|
|
165
|
+
// someone has to find in the CSV, with its log on disk
|
|
166
|
+
];
|
|
148
167
|
case 4:
|
|
149
|
-
|
|
168
|
+
_d.sent();
|
|
169
|
+
if (!jobLogText) return [3 /*break*/, 6];
|
|
170
|
+
return [4 /*yield*/, (0, logcheck_1.checkLog)(jobLogText, "".concat(flowName, "/").concat(jobLocation))];
|
|
171
|
+
case 5:
|
|
172
|
+
_d.sent();
|
|
173
|
+
_d.label = 6;
|
|
174
|
+
case 6:
|
|
150
175
|
job.status =
|
|
151
176
|
submittedJob.state === 'completed'
|
|
152
177
|
? 'success'
|
|
@@ -160,7 +185,7 @@ var executeFlow = function (flow, sasjs, pollOptions, target, authConfig, csvFil
|
|
|
160
185
|
: ''));
|
|
161
186
|
}
|
|
162
187
|
if (logName) {
|
|
163
|
-
(
|
|
188
|
+
(_c = process.logger) === null || _c === void 0 ? void 0 : _c.info("Log file located at: ".concat((0, _1.normalizeFilePath)(logName)));
|
|
164
189
|
}
|
|
165
190
|
if (flow.jobs.filter(function (j) { return j.status === 'success'; })
|
|
166
191
|
.length === flow.jobs.length) {
|
|
@@ -171,8 +196,8 @@ var executeFlow = function (flow, sasjs, pollOptions, target, authConfig, csvFil
|
|
|
171
196
|
(0, utils_1.displayError)({}, "'".concat(flowName, "' flow failed!"));
|
|
172
197
|
jobStatus = false;
|
|
173
198
|
}
|
|
174
|
-
|
|
175
|
-
case
|
|
199
|
+
_d.label = 7;
|
|
200
|
+
case 7: return [2 /*return*/];
|
|
176
201
|
}
|
|
177
202
|
});
|
|
178
203
|
}); }))];
|
|
@@ -1,2 +1,13 @@
|
|
|
1
1
|
import SASjs from '@sasjs/adapter/node';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* A job's log, both as written and as text.
|
|
4
|
+
*
|
|
5
|
+
* The caller checks the text after the file is on disk: a job whose log fails
|
|
6
|
+
* the check is exactly the job whose log is wanted for reading, so writing it
|
|
7
|
+
* first is the difference between a diagnosable failure and an empty folder.
|
|
8
|
+
*/
|
|
9
|
+
export interface SavedFlowLog {
|
|
10
|
+
fileName: string | null;
|
|
11
|
+
logText: string;
|
|
12
|
+
}
|
|
13
|
+
export declare const saveLog: (links: any[], flowName: string, jobLocation: string, logFolder: string, sasjs: SASjs, serverUrl: string, access_token: string, lineCount?: number) => Promise<SavedFlowLog>;
|
|
@@ -108,8 +108,8 @@ var saveLog = function (links_1, flowName_1, jobLocation_1, logFolder_1, sasjs_1
|
|
|
108
108
|
})];
|
|
109
109
|
case 5:
|
|
110
110
|
_a.sent();
|
|
111
|
-
return [2 /*return*/, logName];
|
|
112
|
-
case 6: return [2 /*return*/, null];
|
|
111
|
+
return [2 /*return*/, { fileName: logName, logText: logParsed }];
|
|
112
|
+
case 6: return [2 /*return*/, { fileName: null, logText: '' }];
|
|
113
113
|
}
|
|
114
114
|
});
|
|
115
115
|
});
|
|
@@ -78,6 +78,7 @@ var executeFlow_1 = require("../executeFlow");
|
|
|
78
78
|
var saveLogModule = __importStar(require("../saveLog"));
|
|
79
79
|
var saveToCsvModule = __importStar(require("../saveToCsv"));
|
|
80
80
|
var normalizeFilePath = __importStar(require("../normalizeFilePath"));
|
|
81
|
+
var logcheckModule = __importStar(require("../../../../utils/logcheck"));
|
|
81
82
|
var csvColumns_1 = __importDefault(require("../csvColumns"));
|
|
82
83
|
var pollOptions = {
|
|
83
84
|
maxPollCount: 0,
|
|
@@ -103,7 +104,9 @@ describe('executeFlow', function () {
|
|
|
103
104
|
beforeEach(function () {
|
|
104
105
|
jest
|
|
105
106
|
.spyOn(saveLogModule, 'saveLog')
|
|
106
|
-
.mockImplementation(function () {
|
|
107
|
+
.mockImplementation(function () {
|
|
108
|
+
return Promise.resolve({ fileName: fakeLogFileName, logText: '' });
|
|
109
|
+
});
|
|
107
110
|
jest
|
|
108
111
|
.spyOn(saveToCsvModule, 'saveToCsv')
|
|
109
112
|
.mockImplementation(function () { return Promise.resolve(); });
|
|
@@ -244,6 +247,46 @@ describe('executeFlow', function () {
|
|
|
244
247
|
}
|
|
245
248
|
});
|
|
246
249
|
}); });
|
|
250
|
+
it('writes the report and the log before a failing check stops the flow', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
251
|
+
var flowName, flow, saveLogSpy, csvSpy, checkSpy;
|
|
252
|
+
return __generator(this, function (_a) {
|
|
253
|
+
switch (_a.label) {
|
|
254
|
+
case 0:
|
|
255
|
+
flowName = 'checkedFlow';
|
|
256
|
+
flow = {
|
|
257
|
+
name: flowName,
|
|
258
|
+
jobs: [{ location: 'jobs/testJob/job' }],
|
|
259
|
+
predecessors: []
|
|
260
|
+
};
|
|
261
|
+
jest
|
|
262
|
+
.spyOn(sasjs, 'startComputeJob')
|
|
263
|
+
.mockResolvedValue({ job: { state: 'success' } });
|
|
264
|
+
saveLogSpy = jest
|
|
265
|
+
.spyOn(saveLogModule, 'saveLog')
|
|
266
|
+
.mockImplementation(function () {
|
|
267
|
+
return Promise.resolve({ fileName: fakeLogFileName, logText: 'ERROR 22-322' });
|
|
268
|
+
});
|
|
269
|
+
csvSpy = jest
|
|
270
|
+
.spyOn(saveToCsvModule, 'saveToCsv')
|
|
271
|
+
.mockImplementation(function () { return Promise.resolve(); });
|
|
272
|
+
checkSpy = jest
|
|
273
|
+
.spyOn(logcheckModule, 'checkLog')
|
|
274
|
+
.mockRejectedValue(new Error('SAS log check failed'));
|
|
275
|
+
return [4 /*yield*/, expect((0, executeFlow_1.executeFlow)(flow, sasjs, pollOptions, target, {}, '')).rejects.toThrow('SAS log check failed')
|
|
276
|
+
// the job whose log fails the check is the job a reader has to find in the
|
|
277
|
+
// CSV, with its log on disk
|
|
278
|
+
];
|
|
279
|
+
case 1:
|
|
280
|
+
_a.sent();
|
|
281
|
+
// the job whose log fails the check is the job a reader has to find in the
|
|
282
|
+
// CSV, with its log on disk
|
|
283
|
+
expect(saveLogSpy.mock.invocationCallOrder[0]).toBeLessThan(checkSpy.mock.invocationCallOrder[0]);
|
|
284
|
+
expect(csvSpy.mock.invocationCallOrder[0]).toBeLessThan(checkSpy.mock.invocationCallOrder[0]);
|
|
285
|
+
checkSpy.mockRestore();
|
|
286
|
+
return [2 /*return*/];
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
}); });
|
|
247
290
|
});
|
|
248
291
|
var validateSaveToCsv = function (jobExecutionInOrder) {
|
|
249
292
|
expect(saveToCsvModule.saveToCsv).toHaveBeenCalledTimes(jobExecutionInOrder.length);
|
|
@@ -100,6 +100,7 @@ var utils_1 = require("@sasjs/utils");
|
|
|
100
100
|
var configUtils = __importStar(require("../../../utils/config"));
|
|
101
101
|
var setConstantsUtils = __importStar(require("../../../utils/setConstants"));
|
|
102
102
|
var command_1 = require("../../../types/command");
|
|
103
|
+
var logcheck_1 = require("../../../utils/logcheck");
|
|
103
104
|
var defaultArgs = ['node', 'sasjs'];
|
|
104
105
|
var target = new utils_1.Target({
|
|
105
106
|
name: 'test',
|
|
@@ -115,6 +116,49 @@ describe('FlowCommand', function () {
|
|
|
115
116
|
beforeEach(function () {
|
|
116
117
|
setupMocks();
|
|
117
118
|
});
|
|
119
|
+
afterEach(function () { return (0, logcheck_1.setLogCheckMode)('auto'); });
|
|
120
|
+
it('should return the logcheck code when the log check failed the flow', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
121
|
+
var command, _a;
|
|
122
|
+
return __generator(this, function (_b) {
|
|
123
|
+
switch (_b.label) {
|
|
124
|
+
case 0:
|
|
125
|
+
jest
|
|
126
|
+
.spyOn(executeModule, 'execute')
|
|
127
|
+
.mockImplementation(function () { return Promise.reject(new logcheck_1.LogCheckFailure('3 errors')); });
|
|
128
|
+
command = new flowCommand_1.FlowCommand(__spreadArray(__spreadArray([], __read(defaultArgs), false), [
|
|
129
|
+
'flow',
|
|
130
|
+
'execute',
|
|
131
|
+
'--source',
|
|
132
|
+
source
|
|
133
|
+
], false));
|
|
134
|
+
_a = expect;
|
|
135
|
+
return [4 /*yield*/, command.execute()];
|
|
136
|
+
case 1:
|
|
137
|
+
_a.apply(void 0, [_b.sent()]).toEqual(command_1.ReturnCode.LogCheckError);
|
|
138
|
+
return [2 /*return*/];
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}); });
|
|
142
|
+
it('should switch the log check off for --no-logcheck', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
143
|
+
var command;
|
|
144
|
+
return __generator(this, function (_a) {
|
|
145
|
+
switch (_a.label) {
|
|
146
|
+
case 0:
|
|
147
|
+
command = new flowCommand_1.FlowCommand(__spreadArray(__spreadArray([], __read(defaultArgs), false), [
|
|
148
|
+
'flow',
|
|
149
|
+
'execute',
|
|
150
|
+
'--source',
|
|
151
|
+
source,
|
|
152
|
+
'--no-logcheck'
|
|
153
|
+
], false));
|
|
154
|
+
return [4 /*yield*/, command.execute()];
|
|
155
|
+
case 1:
|
|
156
|
+
_a.sent();
|
|
157
|
+
expect((0, logcheck_1.getLogCheckMode)()).toEqual('off');
|
|
158
|
+
return [2 /*return*/];
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}); });
|
|
118
162
|
it('should parse sasjs flow execute command', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
119
163
|
var args, command, targetInfo;
|
|
120
164
|
return __generator(this, function (_a) {
|
|
@@ -326,6 +326,15 @@ function printHelpText() {
|
|
|
326
326
|
"Provides the capability to identify, for SAS file, whether there are any ERRORs or WARNINGs present and if so, which line number they are on."
|
|
327
327
|
]
|
|
328
328
|
},
|
|
329
|
+
{
|
|
330
|
+
name: 'logcheck',
|
|
331
|
+
title: 'logcheck [paths..]',
|
|
332
|
+
description: [
|
|
333
|
+
"Checks SAS logs for the messages SAS printed - ERRORs, WARNINGs and the notes that flag a problem - and fails when the failure policy is broken.",
|
|
334
|
+
"[2spaces]With no path, the project's results folder is checked. No target, no login and no project are needed, so a log produced elsewhere checks the same way.",
|
|
335
|
+
"[2spaces]command example: sasjs logcheck --fail-on warning --format json"
|
|
336
|
+
]
|
|
337
|
+
},
|
|
329
338
|
{
|
|
330
339
|
name: 'test',
|
|
331
340
|
title: 'test',
|
|
@@ -361,6 +370,7 @@ function printHelpText() {
|
|
|
361
370
|
{ name: 'deploy', aliases: ['d'] },
|
|
362
371
|
{ name: 'doc', aliases: ['docs'] },
|
|
363
372
|
{ name: 'help', aliases: ['h'] },
|
|
373
|
+
{ name: 'logcheck', aliases: ['lc'] },
|
|
364
374
|
{ name: 'request', aliases: ['rq'] },
|
|
365
375
|
{ name: 'run', aliases: ['r'] },
|
|
366
376
|
{ name: 'test', aliases: ['t'] },
|
package/build/commands/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.initLint = exports.processLint = exports.runTest = exports.createWebAppServices = exports.printVersion = exports.runSasCode = exports.runSasJob = exports.printHelpText = exports.deploy = exports.buildDB = exports.initDocs = exports.generateDot = exports.generateDocs = exports.create = exports.buildMockSite = exports.getBuildVars = exports.build = exports.compileSingleFile = exports.compile = exports.addCredential = exports.addTarget = void 0;
|
|
3
|
+
exports.processLogCheck = exports.initLint = exports.processLint = exports.runTest = exports.createWebAppServices = exports.printVersion = exports.runSasCode = exports.runSasJob = exports.printHelpText = exports.deploy = exports.buildDB = exports.initDocs = exports.generateDot = exports.generateDocs = exports.create = exports.buildMockSite = exports.getBuildVars = exports.build = exports.compileSingleFile = exports.compile = exports.addCredential = exports.addTarget = void 0;
|
|
4
4
|
var addTarget_1 = require("./add/addTarget");
|
|
5
5
|
Object.defineProperty(exports, "addTarget", { enumerable: true, get: function () { return addTarget_1.addTarget; } });
|
|
6
6
|
var addCredential_1 = require("./add/addCredential");
|
|
@@ -44,3 +44,5 @@ var processLint_1 = require("./lint/processLint");
|
|
|
44
44
|
Object.defineProperty(exports, "processLint", { enumerable: true, get: function () { return processLint_1.processLint; } });
|
|
45
45
|
var initLint_1 = require("./lint/initLint");
|
|
46
46
|
Object.defineProperty(exports, "initLint", { enumerable: true, get: function () { return initLint_1.initLint; } });
|
|
47
|
+
var processLogCheck_1 = require("./logcheck/processLogCheck");
|
|
48
|
+
Object.defineProperty(exports, "processLogCheck", { enumerable: true, get: function () { return processLogCheck_1.processLogCheck; } });
|
|
@@ -39,6 +39,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
39
39
|
exports.executeJobSas9 = executeJobSas9;
|
|
40
40
|
var utils_1 = require("../utils");
|
|
41
41
|
var parseSourceFile_1 = require("../../../../utils/parseSourceFile");
|
|
42
|
+
var logcheck_1 = require("../../../../utils/logcheck");
|
|
42
43
|
/**
|
|
43
44
|
* Triggers an existing Stored Process for execution as a "job". See online documentation here: https://cli.sasjs.io/job/
|
|
44
45
|
* @param {object} sasjs - Configuration object of the SASJS adapter.
|
|
@@ -70,30 +71,32 @@ function executeJobSas9(sasjs, config, jobPath, logFile, output, source) {
|
|
|
70
71
|
case 3:
|
|
71
72
|
result = _a.sent();
|
|
72
73
|
endTime = new Date().getTime();
|
|
73
|
-
if (!result) return [3 /*break*/,
|
|
74
|
-
if (!(result.status === 200)) return [3 /*break*/,
|
|
74
|
+
if (!result) return [3 /*break*/, 10];
|
|
75
|
+
if (!(result.status === 200)) return [3 /*break*/, 9];
|
|
75
76
|
// handle success
|
|
76
77
|
process.logger.success("Job executed successfully! in ".concat((endTime - startTime) / 1000, " seconds"));
|
|
77
78
|
if (!(!!logFile && result.log)) return [3 /*break*/, 5];
|
|
78
|
-
return [4 /*yield*/, (0, utils_1.saveLog)(result.log, logFile, jobPath)
|
|
79
|
-
// save output if it is present
|
|
80
|
-
];
|
|
79
|
+
return [4 /*yield*/, (0, utils_1.saveLog)(result.log, logFile, jobPath)];
|
|
81
80
|
case 4:
|
|
82
81
|
_a.sent();
|
|
83
82
|
_a.label = 5;
|
|
84
|
-
case 5:
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
case 5: return [4 /*yield*/, (0, logcheck_1.checkLog)(result.log, jobPath)
|
|
84
|
+
// save output if it is present
|
|
85
|
+
];
|
|
87
86
|
case 6:
|
|
88
87
|
_a.sent();
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
case
|
|
88
|
+
if (!(!!output && result.result)) return [3 /*break*/, 8];
|
|
89
|
+
return [4 /*yield*/, (0, utils_1.saveOutput)(result.result, output)];
|
|
90
|
+
case 7:
|
|
91
|
+
_a.sent();
|
|
92
|
+
_a.label = 8;
|
|
93
|
+
case 8: return [3 /*break*/, 10];
|
|
94
|
+
case 9:
|
|
92
95
|
// handle failure
|
|
93
96
|
process.logger.error(result.message);
|
|
94
97
|
process.logger.error(JSON.stringify(result.error, null, 2));
|
|
95
|
-
_a.label =
|
|
96
|
-
case
|
|
98
|
+
_a.label = 10;
|
|
99
|
+
case 10: return [2 /*return*/, result];
|
|
97
100
|
}
|
|
98
101
|
});
|
|
99
102
|
});
|
|
@@ -38,6 +38,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.executeJobSasjs = executeJobSasjs;
|
|
40
40
|
var utils_1 = require("../utils");
|
|
41
|
+
var logcheck_1 = require("../../../../utils/logcheck");
|
|
41
42
|
/**
|
|
42
43
|
* Triggers existing job for execution on SASJS server.
|
|
43
44
|
* @param {object} sasjs - configuration object of SAS adapter.
|
|
@@ -58,23 +59,25 @@ function executeJobSasjs(sasjs, target, jobPath, logFile, output, authConfig) {
|
|
|
58
59
|
}, target.appLoc, authConfig)];
|
|
59
60
|
case 1:
|
|
60
61
|
response = _b.sent();
|
|
61
|
-
if (!response) return [3 /*break*/,
|
|
62
|
+
if (!response) return [3 /*break*/, 6];
|
|
62
63
|
// handle success
|
|
63
64
|
(_a = process.logger) === null || _a === void 0 ? void 0 : _a.success('Job executed successfully!');
|
|
64
65
|
if (!(!!logFile && response.log)) return [3 /*break*/, 3];
|
|
65
|
-
return [4 /*yield*/, (0, utils_1.saveLog)(response.log, logFile, jobPath)
|
|
66
|
-
// save output if it is present
|
|
67
|
-
];
|
|
66
|
+
return [4 /*yield*/, (0, utils_1.saveLog)(response.log, logFile, jobPath)];
|
|
68
67
|
case 2:
|
|
69
68
|
_b.sent();
|
|
70
69
|
_b.label = 3;
|
|
71
|
-
case 3:
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
case 3: return [4 /*yield*/, (0, logcheck_1.checkLog)(response.log, jobPath)
|
|
71
|
+
// save output if it is present
|
|
72
|
+
];
|
|
74
73
|
case 4:
|
|
75
74
|
_b.sent();
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
if (!(!!output && response.result)) return [3 /*break*/, 6];
|
|
76
|
+
return [4 /*yield*/, (0, utils_1.saveOutput)(response.result, output)];
|
|
77
|
+
case 5:
|
|
78
|
+
_b.sent();
|
|
79
|
+
_b.label = 6;
|
|
80
|
+
case 6: return [2 /*return*/, response];
|
|
78
81
|
}
|
|
79
82
|
});
|
|
80
83
|
});
|