hammerkit 1.4.0 → 1.5.0-alpha.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/.devcontainer/Dockerfile +5 -0
- package/.devcontainer/devcontainer.json +40 -0
- package/README.md +13 -86
- package/SUMMARY.md +43 -0
- package/build.schema.json +56 -2
- package/dist/cli.js +97 -0
- package/dist/cli.spec.js +5 -0
- package/dist/console/console-context-mock.js +11 -0
- package/dist/console/get-logger.js +23 -0
- package/dist/docker/pull.js +5 -5
- package/dist/docker/remove-container.js +21 -0
- package/dist/docker/stream.js +14 -10
- package/dist/docker/using-container.js +28 -0
- package/dist/environment/get-process-env.js +4 -4
- package/dist/environment/replace-env-variables.js +2 -3
- package/dist/executer/abort.js +13 -0
- package/dist/executer/check-readiness.js +25 -0
- package/dist/executer/create-scheduler-state.js +32 -0
- package/dist/executer/docker-node.js +123 -0
- package/dist/executer/docker-service.js +113 -0
- package/dist/executer/environment-mock.js +17 -0
- package/dist/executer/event-cache.js +165 -0
- package/dist/executer/execute-command.js +42 -0
- package/dist/executer/execute-docker.js +58 -194
- package/dist/executer/execute.spec.js +37 -37
- package/dist/executer/execution-steps.js +57 -0
- package/dist/executer/get-docker-executor.js +6 -100
- package/dist/executer/hierarchy-scheduler.js +94 -0
- package/dist/executer/kubernetes-service.js +64 -0
- package/dist/executer/label-values.js +65 -0
- package/dist/executer/local-node.js +57 -0
- package/dist/executer/print-container-options.js +17 -0
- package/dist/{logging/log-strategy.js → executer/process-item.js} +1 -1
- package/dist/executer/process-listener.js +3 -0
- package/dist/executer/process-manager.js +111 -0
- package/dist/executer/process-manager.spec.js +91 -0
- package/dist/executer/{executor.js → process.js} +1 -1
- package/dist/executer/{execute-result.js → readonly-state.js} +1 -1
- package/dist/executer/schedule.js +139 -0
- package/dist/executer/scheduler/check-for-loop.js +21 -0
- package/dist/executer/scheduler/enqueue-next.js +27 -0
- package/dist/{testing/test-context.js → executer/scheduler/node-state.js} +1 -1
- package/dist/executer/scheduler/scheduler-result.js +3 -0
- package/dist/executer/scheduler/scheduler-state.js +3 -0
- package/dist/executer/scheduler/service-state.js +3 -0
- package/dist/executer/service-dns.js +6 -0
- package/dist/executer/set-user-permission.js +16 -0
- package/dist/executer/start-node.js +59 -0
- package/dist/executer/state-listener.js +3 -0
- package/dist/executer/state.js +49 -0
- package/dist/executer/states.js +4 -159
- package/dist/executer/watch-node.js +57 -0
- package/dist/executer/watch-service.js +54 -0
- package/dist/executer/work-scope.js +10 -0
- package/dist/file/get-file-context-mock.spec.js +5 -5
- package/dist/file/get-file-context.js +41 -18
- package/dist/file/move-files.js +1 -1
- package/dist/get-work-context.js +29 -0
- package/dist/index.js +8 -4
- package/dist/log.js +192 -50
- package/dist/logging/grouped-logger.js +31 -19
- package/dist/logging/interactive-logger.js +20 -23
- package/dist/logging/live-logger.js +7 -17
- package/dist/optimizer/calculate-checksum.js +1 -1
- package/dist/optimizer/get-cache-directory.js +8 -13
- package/dist/optimizer/get-work-node-cache-stats.js +68 -21
- package/dist/optimizer/read-work-node-cache.js +2 -2
- package/dist/optimizer/work-node-cache-description.js +12 -11
- package/dist/optimizer/write-work-node-cache.js +9 -8
- package/dist/{executer/execution-context.js → parser/build-file-service.js} +1 -1
- package/dist/{optimizer → parser}/cache-method.js +0 -0
- package/dist/parser/get-build-file.js +1 -1
- package/dist/parser/parse-boolean.js +29 -0
- package/dist/parser/parse-boolean.spec.js +48 -0
- package/dist/parser/parse-build-file-references.js +2 -2
- package/dist/parser/parse-build-file-services.js +58 -0
- package/dist/parser/parse-build-file-task-command.js +6 -5
- package/dist/parser/parse-build-file-task-source.js +5 -5
- package/dist/parser/parse-build-file.js +27 -15
- package/dist/parser/parse-context.js +13 -0
- package/dist/parser/parse-envs.js +4 -3
- package/dist/parser/parse-healthcheck.js +28 -0
- package/dist/parser/parse-label-arguments.js +23 -0
- package/dist/parser/parse-service-selector.js +39 -0
- package/dist/parser/parse-string-array.js +6 -5
- package/dist/parser/parse-string-map.js +30 -0
- package/dist/parser/parse-string.js +20 -0
- package/dist/parser/read-build-file.js +16 -5
- package/dist/parser/read-env-file.js +3 -3
- package/dist/planner/utils/get-container-mounts.js +24 -0
- package/dist/planner/utils/normalize-path.js +17 -0
- package/dist/planner/utils/parse-work-node-mount.js +3 -14
- package/dist/planner/utils/parse-work-node-mount.spec.js +10 -10
- package/dist/planner/utils/parse-work-service-volume.js +21 -0
- package/dist/planner/utils/plan-work-command.js +1 -1
- package/dist/planner/utils/plan-work-dependency.js +17 -5
- package/dist/planner/utils/plan-work-node.js +203 -128
- package/dist/planner/utils/plan-work-nodes.js +59 -14
- package/dist/planner/utils/plan-work-tree.js +8 -4
- package/dist/planner/utils/plan-work-volume.js +25 -0
- package/dist/planner/validate.js +56 -8
- package/dist/planner/work-context.js +20 -0
- package/dist/planner/work-mount.js +3 -0
- package/dist/planner/work-node-id.js +4 -4
- package/dist/planner/work-node-id.spec.js +11 -8
- package/dist/planner/work-node-path.js +0 -1
- package/dist/planner/work-node-status.js +121 -18
- package/dist/planner/work-node.js +3 -3
- package/dist/planner/work-service-id.js +13 -0
- package/dist/planner/work-service-volume.js +3 -0
- package/dist/planner/work-service.js +6 -0
- package/dist/planner/work-services.js +3 -0
- package/dist/planner/work-volume.js +3 -0
- package/dist/program.js +155 -90
- package/dist/program.spec.js +20 -0
- package/dist/start-watch-processes.js +28 -0
- package/dist/testing/cli.js +73 -0
- package/dist/testing/create-build-file.js +1 -1
- package/dist/testing/example-test-suite.js +54 -0
- package/dist/testing/expect.js +30 -18
- package/dist/testing/get-logger.js +23 -0
- package/dist/testing/get-node.js +2 -2
- package/dist/testing/get-test-context.js +5 -3
- package/dist/testing/get-test-suite.js +2 -50
- package/dist/testing/integration/cache.spec.js +25 -28
- package/dist/testing/integration/cancellation.spec.js +19 -21
- package/dist/testing/integration/clean.spec.js +25 -28
- package/dist/testing/integration/cmd.spec.js +5 -8
- package/dist/testing/integration/concurrency.spec.js +8 -17
- package/dist/testing/integration/docker.spec.js +6 -9
- package/dist/testing/integration/env.spec.js +27 -34
- package/dist/testing/integration/error.spec.js +5 -9
- package/dist/testing/integration/extend.spec.js +32 -0
- package/dist/testing/integration/glob.spec.js +35 -28
- package/dist/testing/integration/include.spec.js +17 -16
- package/dist/testing/integration/invalid.spec.js +3 -2
- package/dist/testing/integration/invalid_loop.spec.js +13 -0
- package/dist/testing/integration/kubernetes.spec.js +15 -0
- package/dist/testing/integration/labels.spec.js +47 -0
- package/dist/testing/integration/local.spec.js +4 -7
- package/dist/testing/integration/monorepo.spec.js +5 -9
- package/dist/testing/integration/multi-line.spec.js +4 -4
- package/dist/testing/integration/program.spec.js +3 -10
- package/dist/testing/integration/reference.spec.js +10 -13
- package/dist/testing/integration/services.spec.js +14 -0
- package/dist/testing/integration/store.spec.js +42 -38
- package/dist/testing/integration/unknown.spec.js +4 -4
- package/dist/testing/integration/validate.spec.js +4 -4
- package/dist/testing/integration/watch.spec.js +34 -33
- package/dist/testing/lazy.js +17 -0
- package/dist/testing/start-watch-processes.js +29 -0
- package/dist/testing/test-suite-setup.js +3 -0
- package/dist/utils/abort-event.js +14 -1
- package/dist/utils/abortable-function.js +71 -0
- package/dist/utils/debouncer.spec.js +8 -8
- package/dist/utils/environment-config.js +13 -0
- package/dist/utils/fail-never.js +1 -1
- package/dist/utils/sleep.spec.js +3 -3
- package/package.json +24 -21
- package/dist/console/get-console-context-mock.js +0 -33
- package/dist/executer/clean.js +0 -17
- package/dist/executer/execute-local.js +0 -59
- package/dist/executer/execute.js +0 -139
- package/dist/executer/execution-context-event.js +0 -3
- package/dist/executer/execution-context-mock.js +0 -3
- package/dist/executer/executor-mock.js +0 -61
- package/dist/executer/get-environment-mock.js +0 -16
- package/dist/executer/get-execution-context-mock.js +0 -18
- package/dist/executer/get-local-executor.js +0 -56
- package/dist/executer/restore.js +0 -19
- package/dist/executer/store.js +0 -19
- package/dist/logging/get-logger.js +0 -23
- package/dist/logging/message-to-console.js +0 -16
- package/dist/optimizer/optimize.js +0 -32
- package/dist/optimizer/work-node-description.js +0 -12
- package/dist/planner/utils/find-build-task.js +0 -18
- package/dist/testing/create-work-tree.js +0 -11
package/dist/log.js
CHANGED
|
@@ -3,10 +3,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.showCursor = exports.hideCursor = exports.writeWorkTreeStatus = exports.formatDate = exports.getNodeName = exports.getNodeNameLength = exports.printWorkTreeResult = exports.isVerbose = exports.consoleContext = exports.getLogLevel = exports.getLogs = void 0;
|
|
6
|
+
exports.showCursor = exports.hideCursor = exports.writeWorkTreeStatus = exports.formatDate = exports.writeNodeLogToConsole = exports.getNodeName = exports.getNodeNameLengthForWorkTree = exports.getNodeNameLength = exports.printTitle = exports.printItem = exports.printProperty = exports.getNodeNameLengthForSchedulerState = exports.printWorkTreeResult = exports.getType = exports.isVerbose = exports.consoleContext = exports.getErrorMessage = exports.getLogLevel = exports.getLogs = void 0;
|
|
7
7
|
const readline_1 = require("readline");
|
|
8
8
|
const plan_work_nodes_1 = require("./planner/utils/plan-work-nodes");
|
|
9
9
|
const colors_1 = __importDefault(require("colors"));
|
|
10
|
+
const fail_never_1 = require("./utils/fail-never");
|
|
10
11
|
function getLogs(chunk) {
|
|
11
12
|
return chunk
|
|
12
13
|
.toString()
|
|
@@ -27,44 +28,88 @@ function getLogLevel(level) {
|
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
exports.getLogLevel = getLogLevel;
|
|
31
|
+
function getErrorMessage(e) {
|
|
32
|
+
if (e instanceof Error) {
|
|
33
|
+
return e.message;
|
|
34
|
+
}
|
|
35
|
+
else if (typeof e === 'string') {
|
|
36
|
+
return e;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
return `unknown error ${e}`;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.getErrorMessage = getErrorMessage;
|
|
30
43
|
function consoleContext() {
|
|
31
44
|
return {
|
|
32
45
|
debug(message) {
|
|
33
|
-
process.stdout.write(`${getLogLevel('debug')}: ${message}\n`);
|
|
46
|
+
process.stdout.write(`${formatDate(new Date())} ${getType('cli')} ${getLogLevel('debug')}: ${message}\n`);
|
|
34
47
|
},
|
|
35
48
|
error(message) {
|
|
36
|
-
process.stdout.write(`${getLogLevel('error')}: ${message}\n`);
|
|
49
|
+
process.stdout.write(`${formatDate(new Date())} ${getType('cli')} ${getLogLevel('error')}: ${message}\n`);
|
|
37
50
|
},
|
|
38
51
|
info(message) {
|
|
39
|
-
process.stdout.write(`${getLogLevel('info')}: ${message}\n`);
|
|
52
|
+
process.stdout.write(`${formatDate(new Date())} ${getType('cli')} ${getLogLevel('info')}: ${message}\n`);
|
|
40
53
|
},
|
|
41
54
|
warn(message) {
|
|
42
|
-
process.stdout.write(`${getLogLevel('warn')}: ${message}\n`);
|
|
55
|
+
process.stdout.write(`${formatDate(new Date())} ${getType('cli')} ${getLogLevel('warn')}: ${message}\n`);
|
|
43
56
|
},
|
|
44
57
|
};
|
|
45
58
|
}
|
|
46
59
|
exports.consoleContext = consoleContext;
|
|
47
60
|
exports.isVerbose = process.argv.some((a) => a === '--verbose');
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
const typeLength = ['service', 'task', 'cli']
|
|
62
|
+
.map((s) => s.length)
|
|
63
|
+
.reduce((max, current) => (max > current ? max : current), 0);
|
|
64
|
+
function getType(type) {
|
|
65
|
+
return colors_1.default.grey(getNodeName(type, typeLength) + ':');
|
|
66
|
+
}
|
|
67
|
+
exports.getType = getType;
|
|
68
|
+
async function printWorkTreeResult(schedulerState, env) {
|
|
69
|
+
const maxNodeNameLength = getNodeNameLengthForSchedulerState(schedulerState);
|
|
70
|
+
for (const log of env.status.read()) {
|
|
71
|
+
if (exports.isVerbose || (log.type === 'status' && log.level === 'error')) {
|
|
72
|
+
process.stdout.write(`${formatDate(log.date)} ${getType(log.context.type)} ${getNodeName(log.context.name, maxNodeNameLength)} - ${colors_1.default.white(log.message)}\n`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
for (const state of (0, plan_work_nodes_1.iterateWorkServices)(schedulerState.service)) {
|
|
76
|
+
if (state.type === 'end' && state.reason === 'crash') {
|
|
77
|
+
const message = `${getType('service')} ${getNodeName(state.service.name, maxNodeNameLength)}`;
|
|
78
|
+
for (const log of env.status.service(state.service).logs()) {
|
|
79
|
+
process.stdout.write(`${formatDate(log.date)} ${message} - ${log.console}: ${log.message}\n`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
for (const state of (0, plan_work_nodes_1.iterateWorkNodes)(schedulerState.node)) {
|
|
84
|
+
if (state.type === 'error' || state.type === 'crash') {
|
|
85
|
+
const message = `${getType('task')} ${getNodeName(state.node.name, maxNodeNameLength)}`;
|
|
86
|
+
for (const log of env.status.task(state.node).logs()) {
|
|
87
|
+
process.stdout.write(`${formatDate(log.date)} ${message} - ${log.console}: ${log.message}\n`);
|
|
61
88
|
}
|
|
62
89
|
}
|
|
63
90
|
}
|
|
64
|
-
for (const
|
|
65
|
-
let message = `${
|
|
66
|
-
if (
|
|
67
|
-
|
|
91
|
+
for (const state of (0, plan_work_nodes_1.iterateWorkServices)(schedulerState.service)) {
|
|
92
|
+
let message = `${formatDate(new Date())} ${getType('service')} ${getNodeName(state.service.name, maxNodeNameLength)} - ${getStateText(state)}`;
|
|
93
|
+
if (state.type === 'end') {
|
|
94
|
+
if (state.reason === 'crash') {
|
|
95
|
+
message += ` crashed`;
|
|
96
|
+
}
|
|
97
|
+
process.stdout.write(`${message}\n`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
for (const state of (0, plan_work_nodes_1.iterateWorkNodes)(schedulerState.node)) {
|
|
101
|
+
let message = `${formatDate(new Date())} ${getType('task')} ${getNodeName(state.node.name, maxNodeNameLength)} - ${getStateText(state)}`;
|
|
102
|
+
if (state.type === 'completed') {
|
|
103
|
+
message += ` in ${state.duration}ms`;
|
|
104
|
+
if (state.cached) {
|
|
105
|
+
message += ' [CACHED]';
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (state.type === 'crash') {
|
|
109
|
+
message += ` exited with ${state.exitCode}`;
|
|
110
|
+
}
|
|
111
|
+
if (state.type === 'error') {
|
|
112
|
+
message += ` with message ${state.errorMessage}`;
|
|
68
113
|
}
|
|
69
114
|
process.stdout.write(`${message}\n`);
|
|
70
115
|
}
|
|
@@ -75,40 +120,90 @@ function getStateText(state) {
|
|
|
75
120
|
if (state.type === 'running') {
|
|
76
121
|
return colors_1.default.blue(state.type);
|
|
77
122
|
}
|
|
78
|
-
else if (state.type === 'pending') {
|
|
123
|
+
else if (state.type === 'pending' || state.type === 'starting') {
|
|
79
124
|
return colors_1.default.yellow(state.type);
|
|
80
125
|
}
|
|
81
126
|
else if (state.type === 'completed') {
|
|
82
127
|
return colors_1.default.green(state.type);
|
|
83
128
|
}
|
|
84
|
-
else if (state.type === '
|
|
129
|
+
else if (state.type === 'crash') {
|
|
85
130
|
return colors_1.default.red(state.type);
|
|
86
131
|
}
|
|
87
|
-
else if (state.type === '
|
|
132
|
+
else if (state.type === 'error') {
|
|
88
133
|
return colors_1.default.red(state.type);
|
|
89
134
|
}
|
|
90
|
-
else if (state.type === '
|
|
135
|
+
else if (state.type === 'end') {
|
|
91
136
|
return colors_1.default.bgRed(state.type);
|
|
92
137
|
}
|
|
138
|
+
else if (state.type === 'canceled') {
|
|
139
|
+
return colors_1.default.bgRed(state.type);
|
|
140
|
+
}
|
|
141
|
+
else if (state.type === 'ready') {
|
|
142
|
+
return colors_1.default.blue(state.type);
|
|
143
|
+
}
|
|
93
144
|
else {
|
|
94
|
-
|
|
95
|
-
|
|
145
|
+
(0, fail_never_1.failNever)(state, 'unknown node state');
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function getNodeNameLengthForSchedulerState(schedulerState) {
|
|
149
|
+
function* Names() {
|
|
150
|
+
for (const node of (0, plan_work_nodes_1.iterateWorkNodes)(schedulerState.node)) {
|
|
151
|
+
yield node.node.name;
|
|
152
|
+
}
|
|
153
|
+
for (const service of (0, plan_work_nodes_1.iterateWorkServices)(schedulerState.service)) {
|
|
154
|
+
yield service.service.name;
|
|
155
|
+
}
|
|
96
156
|
}
|
|
157
|
+
return getNodeNameLength(Names);
|
|
158
|
+
}
|
|
159
|
+
exports.getNodeNameLengthForSchedulerState = getNodeNameLengthForSchedulerState;
|
|
160
|
+
function printProperty(name, value) {
|
|
161
|
+
process.stdout.write(` ${colors_1.default.grey(`${name}:`)} ${value}\n`);
|
|
97
162
|
}
|
|
98
|
-
|
|
163
|
+
exports.printProperty = printProperty;
|
|
164
|
+
function printItem(item) {
|
|
165
|
+
process.stdout.write(`• ${item.name}${item.description ? `: ${colors_1.default.white(item.description)}` : ''}\n`);
|
|
166
|
+
}
|
|
167
|
+
exports.printItem = printItem;
|
|
168
|
+
function printTitle(name) {
|
|
169
|
+
process.stdout.write(`${colors_1.default.bgWhite(name + ':\n')}`);
|
|
170
|
+
}
|
|
171
|
+
exports.printTitle = printTitle;
|
|
172
|
+
function getNodeNameLength(names) {
|
|
99
173
|
let maxNodeNameLength = 0;
|
|
100
|
-
for (const
|
|
101
|
-
if (
|
|
102
|
-
maxNodeNameLength =
|
|
174
|
+
for (const name of names()) {
|
|
175
|
+
if (name.length > maxNodeNameLength) {
|
|
176
|
+
maxNodeNameLength = name.length;
|
|
103
177
|
}
|
|
104
178
|
}
|
|
105
179
|
return maxNodeNameLength;
|
|
106
180
|
}
|
|
107
181
|
exports.getNodeNameLength = getNodeNameLength;
|
|
108
|
-
function
|
|
109
|
-
|
|
182
|
+
function getNodeNameLengthForWorkTree(nodes, services) {
|
|
183
|
+
function* Names() {
|
|
184
|
+
for (const node of (0, plan_work_nodes_1.iterateWorkNodes)(nodes)) {
|
|
185
|
+
yield node.node.name;
|
|
186
|
+
}
|
|
187
|
+
for (const service of (0, plan_work_nodes_1.iterateWorkServices)(services)) {
|
|
188
|
+
yield service.service.name;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return getNodeNameLength(Names);
|
|
192
|
+
}
|
|
193
|
+
exports.getNodeNameLengthForWorkTree = getNodeNameLengthForWorkTree;
|
|
194
|
+
function getNodeName(name, maxNodeNameLength) {
|
|
195
|
+
return colors_1.default.white(name) + ' '.repeat(Math.max(0, maxNodeNameLength - name.length));
|
|
110
196
|
}
|
|
111
197
|
exports.getNodeName = getNodeName;
|
|
198
|
+
function writeNodeLogToConsole(log, maxNodeNameLength) {
|
|
199
|
+
const content = log.type === 'console'
|
|
200
|
+
? log.console === 'stdout'
|
|
201
|
+
? colors_1.default.white(log.message)
|
|
202
|
+
: colors_1.default.red(log.message)
|
|
203
|
+
: `${getLogLevel(log.level)} - ${log.message}`;
|
|
204
|
+
process.stdout.write(`${formatDate(log.date)} ${colors_1.default.grey(log.context.type + ':')} ${getNodeName(log.context.name, maxNodeNameLength)} - ${log.date.toLocaleTimeString()} - ${content}\n`);
|
|
205
|
+
}
|
|
206
|
+
exports.writeNodeLogToConsole = writeNodeLogToConsole;
|
|
112
207
|
function formatDate(date) {
|
|
113
208
|
return colors_1.default.grey(`[${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date
|
|
114
209
|
.getDay()
|
|
@@ -122,34 +217,81 @@ function formatDate(date) {
|
|
|
122
217
|
.padStart(3, '0')}]`);
|
|
123
218
|
}
|
|
124
219
|
exports.formatDate = formatDate;
|
|
125
|
-
function writeWorkTreeStatus(
|
|
126
|
-
readline_1.clearScreenDown(process.stdout);
|
|
127
|
-
const maxNodeNameLength =
|
|
220
|
+
function writeWorkTreeStatus(schedulerState, env, ticker) {
|
|
221
|
+
(0, readline_1.clearScreenDown)(process.stdout);
|
|
222
|
+
const maxNodeNameLength = getNodeNameLengthForSchedulerState(schedulerState);
|
|
128
223
|
let count = 0;
|
|
129
|
-
for (const
|
|
130
|
-
let message = `${
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
224
|
+
for (const state of (0, plan_work_nodes_1.iterateWorkServices)(schedulerState.service)) {
|
|
225
|
+
let message = `${getType('service')} ${getNodeName(state.service.name, maxNodeNameLength)} - ${getStateText(state)}`;
|
|
226
|
+
const currentMessage = env.status.service(state.service).current();
|
|
227
|
+
if (currentMessage) {
|
|
228
|
+
message += ` ${currentMessage.message}`;
|
|
229
|
+
}
|
|
230
|
+
count += printWithTruncate(message);
|
|
231
|
+
}
|
|
232
|
+
for (const state of (0, plan_work_nodes_1.iterateWorkNodes)(schedulerState.node)) {
|
|
233
|
+
let message = `${getType('task')} ${getNodeName(state.node.name, maxNodeNameLength)} - ${getStateText(state)}`;
|
|
234
|
+
if (state.type === 'pending') {
|
|
235
|
+
const totalDepCount = state.node.deps.length;
|
|
236
|
+
const totalServiceCount = state.node.needs.length;
|
|
237
|
+
const completedDepCount = state.node.deps.filter((d) => schedulerState.node[d.id]?.type === 'completed').length;
|
|
238
|
+
const runningServiceCount = state.node.needs.filter((n) => schedulerState.service[n.id]?.type === 'ready').length;
|
|
134
239
|
if (totalDepCount > 0 && completedDepCount !== totalDepCount) {
|
|
135
240
|
message += ` | ${colors_1.default.grey(` awaiting dependencies (${completedDepCount}/${totalDepCount})`)}`;
|
|
136
241
|
}
|
|
242
|
+
if (totalServiceCount > 0 && runningServiceCount !== totalServiceCount) {
|
|
243
|
+
message += ` | ${colors_1.default.grey(` awaiting service (${runningServiceCount}/${totalServiceCount})`)}`;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
if (state.type === 'starting' || state.type === 'ready') {
|
|
247
|
+
message += ` | ${spinner[ticker % spinner.length]}`;
|
|
248
|
+
const currentMessage = env.status.task(state.node).current();
|
|
249
|
+
if (currentMessage) {
|
|
250
|
+
message += ` ${currentMessage.message}`;
|
|
251
|
+
}
|
|
137
252
|
}
|
|
138
|
-
if (
|
|
253
|
+
else if (state.type === 'running') {
|
|
139
254
|
message += ` | ${spinner[ticker % spinner.length]}`;
|
|
140
|
-
|
|
141
|
-
|
|
255
|
+
const currentMessage = env.status.task(state.node).currentLog();
|
|
256
|
+
if (currentMessage) {
|
|
257
|
+
message += ` ${currentMessage.message}`;
|
|
142
258
|
}
|
|
143
259
|
}
|
|
144
|
-
else if (
|
|
145
|
-
message += ` in ${
|
|
260
|
+
else if (state.type === 'completed') {
|
|
261
|
+
message += ` in ${state.duration}ms`;
|
|
262
|
+
if (state.cached) {
|
|
263
|
+
message += ' [CACHED]';
|
|
264
|
+
}
|
|
146
265
|
}
|
|
147
|
-
|
|
148
|
-
|
|
266
|
+
else if (state.type === 'error') {
|
|
267
|
+
message += ` ${state.errorMessage}`;
|
|
268
|
+
}
|
|
269
|
+
count += printWithTruncate(message);
|
|
149
270
|
}
|
|
150
|
-
readline_1.moveCursor(process.stdout, 0, -1 * count);
|
|
271
|
+
(0, readline_1.moveCursor)(process.stdout, 0, -1 * count);
|
|
151
272
|
}
|
|
152
273
|
exports.writeWorkTreeStatus = writeWorkTreeStatus;
|
|
274
|
+
function countChar(message, char) {
|
|
275
|
+
let result = 0;
|
|
276
|
+
for (let i = 0; i < message.length; i++) {
|
|
277
|
+
if (message[i] === char) {
|
|
278
|
+
result++;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return result;
|
|
282
|
+
}
|
|
283
|
+
function printWithTruncate(message) {
|
|
284
|
+
let lineCount = 0;
|
|
285
|
+
let index = 0;
|
|
286
|
+
do {
|
|
287
|
+
const newLineCount = countChar(message, '\n');
|
|
288
|
+
process.stdout.write(`${message.substr(index, process.stdout.columns)}\n`);
|
|
289
|
+
index += process.stdout.columns;
|
|
290
|
+
lineCount++;
|
|
291
|
+
lineCount += newLineCount;
|
|
292
|
+
} while (index < message.length);
|
|
293
|
+
return lineCount;
|
|
294
|
+
}
|
|
153
295
|
function hideCursor() {
|
|
154
296
|
process.stdout.write('\x1B[?25l');
|
|
155
297
|
}
|
|
@@ -2,26 +2,38 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.groupedLogger = void 0;
|
|
4
4
|
const log_1 = require("../log");
|
|
5
|
-
const
|
|
6
|
-
function groupedLogger() {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
5
|
+
const plan_work_nodes_1 = require("../planner/utils/plan-work-nodes");
|
|
6
|
+
function groupedLogger(state, env) {
|
|
7
|
+
const maxNodeNameLength = (0, log_1.getNodeNameLengthForWorkTree)(state.current.node, state.current.service);
|
|
8
|
+
const completedNodes = [];
|
|
9
|
+
const completedServices = [];
|
|
10
|
+
state.on((currentState) => {
|
|
11
|
+
for (const node of (0, plan_work_nodes_1.iterateWorkNodes)(currentState.node)) {
|
|
12
|
+
if (completedNodes.indexOf(node.node.id) >= 0) {
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
if (node.type === 'crash' || node.type === 'error' || node.type === 'completed') {
|
|
16
|
+
completedNodes.push(node.node.id);
|
|
17
|
+
for (const log of env.status.task(node.node).read()) {
|
|
18
|
+
(0, log_1.writeNodeLogToConsole)(log, maxNodeNameLength);
|
|
17
19
|
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
for (const service of (0, plan_work_nodes_1.iterateWorkServices)(currentState.service)) {
|
|
23
|
+
if (completedServices.indexOf(service.service.id) >= 0) {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (service.type === 'end') {
|
|
27
|
+
completedServices.push(service.service.id);
|
|
28
|
+
for (const log of env.status.service(service.service).read()) {
|
|
29
|
+
(0, log_1.writeNodeLogToConsole)(log, maxNodeNameLength);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
return {
|
|
35
|
+
async complete(evt, env) {
|
|
36
|
+
await (0, log_1.printWorkTreeResult)(evt.state, env);
|
|
25
37
|
},
|
|
26
38
|
};
|
|
27
39
|
}
|
|
@@ -3,33 +3,30 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.interactiveLogger = void 0;
|
|
4
4
|
const log_1 = require("../log");
|
|
5
5
|
const readline_1 = require("readline");
|
|
6
|
-
function interactiveLogger() {
|
|
6
|
+
function interactiveLogger(state, env) {
|
|
7
7
|
let running = true;
|
|
8
8
|
let count = 0;
|
|
9
|
+
const tickerFn = () => {
|
|
10
|
+
if (!running) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
count++;
|
|
14
|
+
(0, log_1.writeWorkTreeStatus)(state.current, env, count);
|
|
15
|
+
if (running) {
|
|
16
|
+
setTimeout(tickerFn, 100);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
(0, log_1.hideCursor)();
|
|
20
|
+
tickerFn();
|
|
21
|
+
state.on((currentState) => {
|
|
22
|
+
(0, log_1.writeWorkTreeStatus)(currentState, env, count);
|
|
23
|
+
});
|
|
9
24
|
return {
|
|
10
|
-
|
|
11
|
-
log_1.hideCursor();
|
|
12
|
-
log_1.writeWorkTreeStatus(workTree, count);
|
|
13
|
-
const tickerFn = () => {
|
|
14
|
-
count++;
|
|
15
|
-
log_1.writeWorkTreeStatus(workTree, count);
|
|
16
|
-
if (running) {
|
|
17
|
-
setTimeout(tickerFn, 100);
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
tickerFn();
|
|
21
|
-
executionContext.events.on(({ workTree }) => {
|
|
22
|
-
log_1.writeWorkTreeStatus(workTree, count);
|
|
23
|
-
});
|
|
24
|
-
},
|
|
25
|
-
async finish(workTree, result) {
|
|
25
|
+
async complete(evt, env) {
|
|
26
26
|
running = false;
|
|
27
|
-
readline_1.clearScreenDown(process.stdout);
|
|
28
|
-
await log_1.printWorkTreeResult(
|
|
29
|
-
log_1.showCursor();
|
|
30
|
-
},
|
|
31
|
-
abort(e) {
|
|
32
|
-
process.stderr.write(`${e.message}\n`);
|
|
27
|
+
(0, readline_1.clearScreenDown)(process.stdout);
|
|
28
|
+
await (0, log_1.printWorkTreeResult)(evt.state, env);
|
|
29
|
+
(0, log_1.showCursor)();
|
|
33
30
|
},
|
|
34
31
|
};
|
|
35
32
|
}
|
|
@@ -2,24 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.liveLogger = void 0;
|
|
4
4
|
const log_1 = require("../log");
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
function liveLogger(state, env) {
|
|
6
|
+
const maxNodeNameLength = (0, log_1.getNodeNameLengthForWorkTree)(state.current.node, state.current.service);
|
|
7
|
+
env.status.on((log) => {
|
|
8
|
+
(0, log_1.writeNodeLogToConsole)(log, maxNodeNameLength);
|
|
9
|
+
});
|
|
9
10
|
return {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
for (const node of plan_work_nodes_1.iterateWorkNodes(workTree.nodes)) {
|
|
13
|
-
node.status.console.on((log) => {
|
|
14
|
-
message_to_console_1.logMessageToConsole(node, log, maxNodeNameLength);
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
},
|
|
18
|
-
async finish(workTree, result) {
|
|
19
|
-
await log_1.printWorkTreeResult(workTree, result, false);
|
|
20
|
-
},
|
|
21
|
-
abort(e) {
|
|
22
|
-
process.stderr.write(`${e.message}\n`);
|
|
11
|
+
async complete(evt, env) {
|
|
12
|
+
await (0, log_1.printWorkTreeResult)(evt.state, env);
|
|
23
13
|
},
|
|
24
14
|
};
|
|
25
15
|
}
|
|
@@ -4,7 +4,7 @@ exports.calculateChecksum = void 0;
|
|
|
4
4
|
const crypto_1 = require("crypto");
|
|
5
5
|
async function calculateChecksum(environment, path) {
|
|
6
6
|
const input = await environment.file.read(path);
|
|
7
|
-
return crypto_1.createHash('sha1').update(input).digest('hex');
|
|
7
|
+
return (0, crypto_1.createHash)('sha1').update(input).digest('hex');
|
|
8
8
|
}
|
|
9
9
|
exports.calculateChecksum = calculateChecksum;
|
|
10
10
|
//# sourceMappingURL=calculate-checksum.js.map
|
|
@@ -1,33 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getHammerkitDirectory = exports.getCacheStatsFile = exports.
|
|
3
|
+
exports.getHammerkitDirectory = exports.getCacheStatsFile = exports.getCacheDescriptionFile = exports.getCacheDirectory = void 0;
|
|
4
4
|
const path_1 = require("path");
|
|
5
|
-
const crypto_1 = require("crypto");
|
|
6
5
|
function getCacheDirectory(nodeId) {
|
|
7
|
-
return path_1.join(getHammerkitDirectory(), 'cache', nodeId);
|
|
6
|
+
return (0, path_1.join)(getHammerkitDirectory(), 'cache', nodeId);
|
|
8
7
|
}
|
|
9
8
|
exports.getCacheDirectory = getCacheDirectory;
|
|
10
9
|
function getCacheDescriptionFile(nodeId) {
|
|
11
|
-
return path_1.join(getCacheDirectory(nodeId), 'description.json');
|
|
10
|
+
return (0, path_1.join)(getCacheDirectory(nodeId), 'description.json');
|
|
12
11
|
}
|
|
13
12
|
exports.getCacheDescriptionFile = getCacheDescriptionFile;
|
|
14
|
-
function
|
|
15
|
-
return path_1.join(getCacheDirectory(nodeId),
|
|
16
|
-
}
|
|
17
|
-
exports.getCacheStatsDirectory = getCacheStatsDirectory;
|
|
18
|
-
function getCacheStatsFile(nodeId, cwd) {
|
|
19
|
-
return path_1.join(getCacheStatsDirectory(nodeId, cwd), 'stats.json');
|
|
13
|
+
function getCacheStatsFile(nodeId) {
|
|
14
|
+
return (0, path_1.join)(getCacheDirectory(nodeId), 'stats.json');
|
|
20
15
|
}
|
|
21
16
|
exports.getCacheStatsFile = getCacheStatsFile;
|
|
22
17
|
function getHammerkitDirectory() {
|
|
23
18
|
if (process.platform === 'win32') {
|
|
24
|
-
return path_1.join(process.env.APPDATA, 'hammerkit');
|
|
19
|
+
return (0, path_1.join)(process.env.APPDATA, 'hammerkit');
|
|
25
20
|
}
|
|
26
21
|
else if (process.platform === 'darwin') {
|
|
27
|
-
return path_1.join(process.env.HOME, 'Library', 'Application Support', 'hammerkit');
|
|
22
|
+
return (0, path_1.join)(process.env.HOME, 'Library', 'Application Support', 'hammerkit');
|
|
28
23
|
}
|
|
29
24
|
else {
|
|
30
|
-
return path_1.join(process.env.HOME, '.hammerkit');
|
|
25
|
+
return (0, path_1.join)(process.env.HOME, '.hammerkit');
|
|
31
26
|
}
|
|
32
27
|
}
|
|
33
28
|
exports.getHammerkitDirectory = getHammerkitDirectory;
|
|
@@ -1,51 +1,98 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.getStateKey = exports.getCacheState = exports.getWorkNodeCacheStats = exports.getServiceNodeCacheStats = void 0;
|
|
4
4
|
const calculate_checksum_1 = require("./calculate-checksum");
|
|
5
5
|
const path_1 = require("path");
|
|
6
|
-
|
|
6
|
+
const crypto_1 = require("crypto");
|
|
7
|
+
async function addWorkNodeCacheStats(result, cwd, path, matcher, context) {
|
|
8
|
+
const exists = await context.file.exists(path);
|
|
9
|
+
if (!exists) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
7
12
|
const stats = await context.file.stats(path);
|
|
8
13
|
if (stats.type === 'file') {
|
|
9
14
|
if (matcher(path)) {
|
|
10
|
-
const checksum = await calculate_checksum_1.calculateChecksum(context, path);
|
|
11
|
-
result.files[path_1.relative(
|
|
15
|
+
const checksum = await (0, calculate_checksum_1.calculateChecksum)(context, path);
|
|
16
|
+
result.files[(0, path_1.relative)(cwd, path)] = { lastModified: stats.lastModified, checksum };
|
|
12
17
|
}
|
|
13
18
|
}
|
|
14
19
|
else if (stats.type === 'directory') {
|
|
15
20
|
const files = await context.file.listFiles(path);
|
|
16
21
|
for (const file of files) {
|
|
17
|
-
const subPath = path_1.join(path, file);
|
|
22
|
+
const subPath = (0, path_1.join)(path, file);
|
|
18
23
|
if (matcher(subPath)) {
|
|
19
|
-
await addWorkNodeCacheStats(result, path_1.join(path, file), matcher, context);
|
|
24
|
+
await addWorkNodeCacheStats(result, cwd, (0, path_1.join)(path, file), matcher, context);
|
|
20
25
|
}
|
|
21
26
|
}
|
|
22
27
|
}
|
|
23
28
|
}
|
|
29
|
+
async function addWorkServiceCacheStats(result, path, context) {
|
|
30
|
+
const exists = await context.file.exists(path);
|
|
31
|
+
if (!exists) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const stats = await context.file.stats(path);
|
|
35
|
+
if (stats.type === 'file') {
|
|
36
|
+
const checksum = await (0, calculate_checksum_1.calculateChecksum)(context, path);
|
|
37
|
+
result.files[path] = { lastModified: stats.lastModified, checksum };
|
|
38
|
+
}
|
|
39
|
+
else if (stats.type === 'directory') {
|
|
40
|
+
const files = await context.file.listFiles(path);
|
|
41
|
+
for (const file of files) {
|
|
42
|
+
await addWorkServiceCacheStats(result, (0, path_1.join)(path, file), context);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async function getServiceNodeCacheStats(cache, environment) {
|
|
47
|
+
const result = {
|
|
48
|
+
files: {},
|
|
49
|
+
};
|
|
50
|
+
for (const mount of cache.mounts) {
|
|
51
|
+
await addWorkServiceCacheStats(result, mount.localPath, environment);
|
|
52
|
+
}
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
exports.getServiceNodeCacheStats = getServiceNodeCacheStats;
|
|
24
56
|
async function getWorkNodeCacheStats(cache, environment) {
|
|
25
57
|
const result = {
|
|
26
|
-
|
|
58
|
+
created: new Date(),
|
|
27
59
|
files: {},
|
|
28
60
|
};
|
|
29
61
|
for (const src of cache.src) {
|
|
30
|
-
await addWorkNodeCacheStats(result, src.absolutePath, (file) => src.matcher(file, cache.cwd), environment);
|
|
62
|
+
await addWorkNodeCacheStats(result, cache.cwd, src.absolutePath, (file) => src.matcher(file, cache.cwd), environment);
|
|
31
63
|
}
|
|
32
64
|
return result;
|
|
33
65
|
}
|
|
34
66
|
exports.getWorkNodeCacheStats = getWorkNodeCacheStats;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
67
|
+
function getCacheState(status, node, cache, current) {
|
|
68
|
+
if (cache) {
|
|
69
|
+
for (const key of Object.keys(cache.files)) {
|
|
70
|
+
if ((node.caching === 'checksum' && current.files[key]?.checksum !== cache.files[key].checksum) ||
|
|
71
|
+
(node.caching === 'modify-date' && current.files[key]?.lastModified !== cache.files[key].lastModified)) {
|
|
72
|
+
status.write('debug', node.caching === 'checksum'
|
|
73
|
+
? `${key} changed from checksum ${cache.files[key].checksum} to ${current.files[key]?.checksum}`
|
|
74
|
+
: `${key} changed from last modified ${cache.files[key].lastModified} to ${current.files[key]?.lastModified}`);
|
|
75
|
+
status.write('debug', `${node.name} can't be skipped because ${key} has been modified`);
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
stateKey: getStateKey(current, node.caching),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
exports.getCacheState = getCacheState;
|
|
85
|
+
function getStateKey(stats, cacheMethod) {
|
|
86
|
+
const contents = [];
|
|
87
|
+
for (const key of Object.keys(stats.files)) {
|
|
88
|
+
if (cacheMethod === 'checksum') {
|
|
89
|
+
contents.push(`${key}:${stats.files[key].checksum}`);
|
|
90
|
+
}
|
|
91
|
+
else if (cacheMethod === 'modify-date') {
|
|
92
|
+
contents.push(`${key}:${stats.files[key].lastModified}`);
|
|
46
93
|
}
|
|
47
94
|
}
|
|
48
|
-
return
|
|
95
|
+
return (0, crypto_1.createHash)('md5').update(contents.join(',')).digest('hex');
|
|
49
96
|
}
|
|
50
|
-
exports.
|
|
97
|
+
exports.getStateKey = getStateKey;
|
|
51
98
|
//# sourceMappingURL=get-work-node-cache-stats.js.map
|