hammerkit 1.4.0 → 1.5.0-alpha.1
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 +59 -195
- 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 +197 -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 +39 -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 +14 -8
- 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 +29 -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 +35 -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
|
@@ -1,145 +1,162 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.getAbsolutePaths = exports.mapSource = exports.parseWorkNodeNeeds = exports.parseContainerWorkNodePorts = exports.mapLabels = exports.getWorkNode = exports.findBuildTask = exports.planTask = void 0;
|
|
4
|
+
const work_context_1 = require("../work-context");
|
|
4
5
|
const template_value_1 = require("./template-value");
|
|
5
6
|
const plan_work_command_1 = require("./plan-work-command");
|
|
6
7
|
const split_name_1 = require("./split-name");
|
|
7
|
-
const find_build_task_1 = require("./find-build-task");
|
|
8
8
|
const parse_work_node_mount_1 = require("./parse-work-node-mount");
|
|
9
9
|
const plan_work_dependency_1 = require("./plan-work-dependency");
|
|
10
10
|
const path_1 = require("path");
|
|
11
|
-
const work_node_status_1 = require("../work-node-status");
|
|
12
11
|
const work_node_id_1 = require("../work-node-id");
|
|
13
12
|
const parse_work_node_port_1 = require("./parse-work-node-port");
|
|
14
|
-
|
|
13
|
+
const work_service_id_1 = require("../work-service-id");
|
|
14
|
+
const os_1 = require("os");
|
|
15
|
+
const parse_work_service_volume_1 = require("./parse-work-service-volume");
|
|
16
|
+
const plan_work_volume_1 = require("./plan-work-volume");
|
|
17
|
+
const get_container_mounts_1 = require("./get-container-mounts");
|
|
18
|
+
function planTask(workContext, buildTaskResult) {
|
|
19
|
+
let extendedTask = null;
|
|
20
|
+
if (buildTaskResult.task.extend) {
|
|
21
|
+
extendedTask = findBuildTask(workContext, { taskName: buildTaskResult.task.extend });
|
|
22
|
+
if (extendedTask.task.extend) {
|
|
23
|
+
throw new Error(`nested extend ${extendedTask.name} is not allowed for task ${buildTaskResult.name}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
15
26
|
const envs = {
|
|
16
|
-
...
|
|
17
|
-
...
|
|
27
|
+
...(extendedTask?.task?.envs || {}),
|
|
28
|
+
...buildTaskResult.context.build.envs,
|
|
29
|
+
...(buildTaskResult.task.envs || {}),
|
|
18
30
|
};
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
...extend.task.envs,
|
|
23
|
-
...envs,
|
|
24
|
-
};
|
|
25
|
-
return {
|
|
26
|
-
task: {
|
|
27
|
-
image: task.image || extend.task.image,
|
|
28
|
-
envs: extendEnvs,
|
|
29
|
-
ports: task.ports || extend.task.ports || [],
|
|
30
|
-
cmds: task.cmds || extend.task.cmds || [],
|
|
31
|
-
description: task.description || extend.task.description,
|
|
32
|
-
shell: task.shell || extend.task.shell,
|
|
33
|
-
continuous: task.continuous || extend.task.continuous || false,
|
|
34
|
-
unknownProps: task.unknownProps,
|
|
35
|
-
src: [...(extend.task.src || []), ...(task.src || [])],
|
|
36
|
-
mounts: [...(extend.task.mounts || []), ...(task.mounts || [])],
|
|
37
|
-
generates: [...(extend.task.generates || []), ...(task.generates || [])],
|
|
38
|
-
},
|
|
39
|
-
deps: [
|
|
40
|
-
...(extend.task.deps || []).map((d) => ({ name: d, build: extend.build })),
|
|
41
|
-
...(task.deps || []).map((d) => ({ name: d, build: build })),
|
|
42
|
-
],
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
46
|
-
return {
|
|
47
|
-
task: {
|
|
48
|
-
image: task.image,
|
|
49
|
-
src: task.src || [],
|
|
50
|
-
cmds: task.cmds || [],
|
|
51
|
-
continuous: task.continuous || false,
|
|
52
|
-
generates: task.generates || [],
|
|
53
|
-
description: task.description,
|
|
54
|
-
shell: task.shell,
|
|
55
|
-
ports: task.ports || [],
|
|
56
|
-
unknownProps: task.unknownProps,
|
|
57
|
-
mounts: task.mounts || [],
|
|
58
|
-
envs,
|
|
59
|
-
},
|
|
60
|
-
deps: [...(task.deps || []).map((d) => ({ name: d, build: build }))],
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
exports.getMergedBuildTask = getMergedBuildTask;
|
|
65
|
-
function planWorkNode(build, taskName, nodes, context) {
|
|
66
|
-
if (build.tasks[taskName]) {
|
|
67
|
-
const { task, deps } = getMergedBuildTask(build, build.tasks[taskName]);
|
|
68
|
-
const id = work_node_id_1.getWorkNodeId(context.currentWorkdir, task, deps);
|
|
69
|
-
if (nodes[id]) {
|
|
70
|
-
return nodes[id];
|
|
31
|
+
const getReferences = (task, prop) => {
|
|
32
|
+
if (!task) {
|
|
33
|
+
return [];
|
|
71
34
|
}
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
35
|
+
const value = task.task[prop];
|
|
36
|
+
if (!value) {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
return value.map((d) => ({
|
|
40
|
+
name: d,
|
|
41
|
+
build: buildTaskResult.context.build,
|
|
42
|
+
context: task.context,
|
|
43
|
+
}));
|
|
44
|
+
};
|
|
45
|
+
const mergeReferences = (first, second) => {
|
|
46
|
+
return [...first, ...second];
|
|
47
|
+
};
|
|
48
|
+
return {
|
|
49
|
+
buildTask: buildTaskResult.task,
|
|
50
|
+
build: buildTaskResult.context.build,
|
|
51
|
+
name: buildTaskResult.name,
|
|
52
|
+
cache: buildTaskResult.task.cache ?? extendedTask?.task?.cache ?? null,
|
|
53
|
+
description: buildTaskResult.task.description ?? extendedTask?.task?.description ?? null,
|
|
54
|
+
cwd: workContext.cwd,
|
|
55
|
+
image: buildTaskResult.task.image ?? extendedTask?.task?.image ?? null,
|
|
56
|
+
platform: buildTaskResult.task.platform ?? extendedTask?.task?.platform ?? null,
|
|
57
|
+
mounts: buildTaskResult.task.mounts || extendedTask?.task?.mounts || [],
|
|
58
|
+
generates: buildTaskResult.task.generates || extendedTask?.task?.generates || [],
|
|
59
|
+
shell: buildTaskResult.task.shell ?? extendedTask?.task?.shell ?? null,
|
|
60
|
+
ports: buildTaskResult.task.ports || extendedTask?.task?.ports || [],
|
|
61
|
+
src: buildTaskResult.task.src || extendedTask?.task?.src || [],
|
|
62
|
+
cmds: buildTaskResult.task.cmds || extendedTask?.task?.cmds || [],
|
|
63
|
+
continuous: buildTaskResult.task.continuous ?? extendedTask?.task?.continuous ?? false,
|
|
64
|
+
labels: {
|
|
65
|
+
...(extendedTask?.task?.labels || {}),
|
|
66
|
+
...(buildTaskResult.task.labels || {}),
|
|
67
|
+
},
|
|
68
|
+
envs,
|
|
69
|
+
deps: mergeReferences(getReferences(extendedTask, 'deps'), getReferences(buildTaskResult, 'deps')),
|
|
70
|
+
needs: mergeReferences(getReferences(extendedTask, 'needs'), getReferences(buildTaskResult, 'needs')),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
exports.planTask = planTask;
|
|
74
|
+
function findBuildTask(context, selector) {
|
|
75
|
+
if (context.build.tasks[selector.taskName]) {
|
|
76
|
+
return { task: context.build.tasks[selector.taskName], context, name: selector.taskName };
|
|
110
77
|
}
|
|
111
78
|
else {
|
|
112
|
-
const ref = split_name_1.splitName(taskName);
|
|
79
|
+
const ref = (0, split_name_1.splitName)(selector.taskName);
|
|
113
80
|
if (ref.prefix) {
|
|
114
|
-
if (build.references[ref.prefix]) {
|
|
115
|
-
return
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
namePrefix: [...context.namePrefix, ref.prefix],
|
|
120
|
-
});
|
|
81
|
+
if (context.build.references[ref.prefix]) {
|
|
82
|
+
return findBuildTask((0, work_context_1.createSubWorkContext)(context, {
|
|
83
|
+
name: ref.prefix,
|
|
84
|
+
type: 'references',
|
|
85
|
+
}), { taskName: ref.taskName });
|
|
121
86
|
}
|
|
122
|
-
else if (build.includes[ref.prefix]) {
|
|
123
|
-
return
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
87
|
+
else if (context.build.includes[ref.prefix]) {
|
|
88
|
+
return findBuildTask((0, work_context_1.createSubWorkContext)(context, {
|
|
89
|
+
name: ref.prefix,
|
|
90
|
+
type: 'includes',
|
|
91
|
+
}), {
|
|
92
|
+
taskName: ref.taskName,
|
|
127
93
|
});
|
|
128
94
|
}
|
|
129
95
|
}
|
|
130
|
-
throw new Error(`unable to find ${taskName} in ${build.path}`);
|
|
96
|
+
throw new Error(`unable to find ${selector.taskName} in ${context.build.path}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
exports.findBuildTask = findBuildTask;
|
|
100
|
+
function getWorkNode(context, selector) {
|
|
101
|
+
const rootNode = findBuildTask(context, selector);
|
|
102
|
+
const plannedTask = planTask(rootNode.context, rootNode);
|
|
103
|
+
const id = (0, work_node_id_1.getWorkNodeId)(plannedTask);
|
|
104
|
+
if (context.workTree.nodes[id]) {
|
|
105
|
+
return context.workTree.nodes[id];
|
|
106
|
+
}
|
|
107
|
+
const node = parseWorkNode(id, plannedTask, rootNode.context);
|
|
108
|
+
context.workTree.nodes[id] = node;
|
|
109
|
+
const depNodes = [];
|
|
110
|
+
for (const plannedDep of plannedTask.deps) {
|
|
111
|
+
const depName = (0, template_value_1.templateValue)(plannedDep.name, plannedDep.build.envs);
|
|
112
|
+
const depNode = getWorkNode(plannedDep.context, { taskName: depName });
|
|
113
|
+
if (!depNodes.some((d) => d.id === depNode.id)) {
|
|
114
|
+
depNodes.push(depNode);
|
|
115
|
+
}
|
|
131
116
|
}
|
|
117
|
+
(0, plan_work_dependency_1.planWorkDependency)(depNodes, node);
|
|
118
|
+
return node;
|
|
132
119
|
}
|
|
133
|
-
exports.
|
|
134
|
-
function
|
|
120
|
+
exports.getWorkNode = getWorkNode;
|
|
121
|
+
function mapLabels(labels) {
|
|
122
|
+
const result = {};
|
|
123
|
+
for (const [key, value] of Object.entries(labels)) {
|
|
124
|
+
result[key] = [value];
|
|
125
|
+
}
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
exports.mapLabels = mapLabels;
|
|
129
|
+
function parseWorkNode(id, task, context) {
|
|
130
|
+
const name = [...context.namePrefix, task.name].join(':');
|
|
131
|
+
const baseWorkNode = {
|
|
132
|
+
envs: task.envs,
|
|
133
|
+
id,
|
|
134
|
+
description: (0, template_value_1.templateValue)(task.description, task.envs),
|
|
135
|
+
continuous: task.continuous,
|
|
136
|
+
name,
|
|
137
|
+
cwd: task.cwd,
|
|
138
|
+
cmds: parseWorkNodeCommand(task, context, task.envs),
|
|
139
|
+
deps: [],
|
|
140
|
+
buildFile: task.build,
|
|
141
|
+
taskName: task.name,
|
|
142
|
+
src: parseLocalWorkNodeSource(task, context, task.envs),
|
|
143
|
+
generates: parseLocalWorkNodeGenerate(task, context, task.envs),
|
|
144
|
+
plannedTask: task,
|
|
145
|
+
needs: parseWorkNodeNeeds(task.needs, context),
|
|
146
|
+
labels: mapLabels(task.labels),
|
|
147
|
+
caching: task.cache ?? null,
|
|
148
|
+
};
|
|
135
149
|
if (task.image) {
|
|
150
|
+
const mounts = (0, get_container_mounts_1.getContainerMounts)(baseWorkNode, parseContainerWorkNodeMount(task, context, task.envs));
|
|
136
151
|
return {
|
|
137
152
|
...baseWorkNode,
|
|
138
153
|
type: 'container',
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
154
|
+
user: getContainerUser(),
|
|
155
|
+
image: (0, template_value_1.templateValue)(task.image, task.envs),
|
|
156
|
+
shell: (0, template_value_1.templateValue)(task.shell, task.envs) || '/bin/sh',
|
|
157
|
+
mounts,
|
|
142
158
|
ports: parseContainerWorkNodePorts(task, context, task.envs),
|
|
159
|
+
volumes: (0, plan_work_volume_1.getContainerVolumes)(baseWorkNode, mounts),
|
|
143
160
|
};
|
|
144
161
|
}
|
|
145
162
|
else {
|
|
@@ -150,48 +167,106 @@ function parseWorkNode(baseWorkNode, task, context) {
|
|
|
150
167
|
}
|
|
151
168
|
}
|
|
152
169
|
function parseContainerWorkNodePorts(task, context, envs) {
|
|
153
|
-
return task.ports.map((m) => template_value_1.templateValue(m, envs)).map((m) => parse_work_node_port_1.parseWorkNodePort(m));
|
|
170
|
+
return task.ports.map((m) => (0, template_value_1.templateValue)(m, envs)).map((m) => (0, parse_work_node_port_1.parseWorkNodePort)(m));
|
|
154
171
|
}
|
|
172
|
+
exports.parseContainerWorkNodePorts = parseContainerWorkNodePorts;
|
|
155
173
|
function parseContainerWorkNodeMount(task, context, envs) {
|
|
156
|
-
return task.mounts.map((m) => template_value_1.templateValue(m, envs)).map((m) => parse_work_node_mount_1.parseWorkNodeMount(context.
|
|
174
|
+
return task.mounts.map((m) => (0, template_value_1.templateValue)(m, envs)).map((m) => (0, parse_work_node_mount_1.parseWorkNodeMount)(context.cwd, m));
|
|
157
175
|
}
|
|
158
176
|
function parseLocalWorkNodeGenerate(task, context, envs) {
|
|
159
|
-
return getAbsolutePaths(task.generates, context.
|
|
160
|
-
.map((g) => template_value_1.templateValue(g, envs))
|
|
177
|
+
return getAbsolutePaths(task.generates, context.cwd)
|
|
178
|
+
.map((g) => (0, template_value_1.templateValue)(g, envs))
|
|
161
179
|
.map((path) => ({ path, inherited: false }));
|
|
162
180
|
}
|
|
163
181
|
function parseLocalWorkNodeSource(task, context, envs) {
|
|
164
182
|
return task.src
|
|
165
183
|
.map((src) => ({
|
|
166
|
-
relativePath: template_value_1.templateValue(src.relativePath, envs),
|
|
184
|
+
relativePath: (0, template_value_1.templateValue)(src.relativePath, envs),
|
|
167
185
|
matcher: src.matcher,
|
|
168
186
|
}))
|
|
169
|
-
.map((src) => mapSource(src, context.
|
|
187
|
+
.map((src) => mapSource(src, context.cwd));
|
|
188
|
+
}
|
|
189
|
+
function getContainerUser() {
|
|
190
|
+
return (0, os_1.platform)() === 'linux' || (0, os_1.platform)() === 'freebsd' || (0, os_1.platform)() === 'openbsd' || (0, os_1.platform)() === 'sunos'
|
|
191
|
+
? `${process.getuid()}:${process.getgid()}`
|
|
192
|
+
: `0:0`;
|
|
193
|
+
}
|
|
194
|
+
function parseWorkNodeNeeds(needs, context) {
|
|
195
|
+
const result = [];
|
|
196
|
+
for (const need of needs) {
|
|
197
|
+
const service = need.build.services[need.name];
|
|
198
|
+
const id = (0, work_service_id_1.getWorkServiceId)(need.build, service);
|
|
199
|
+
if (!context.workTree.services[id]) {
|
|
200
|
+
const workService = {
|
|
201
|
+
id,
|
|
202
|
+
buildService: service,
|
|
203
|
+
name: need.name,
|
|
204
|
+
description: service.description,
|
|
205
|
+
ports: (service.ports || []).map((m) => (0, template_value_1.templateValue)(m, service.envs)).map((m) => (0, parse_work_node_port_1.parseWorkNodePort)(m)),
|
|
206
|
+
};
|
|
207
|
+
if (service.image) {
|
|
208
|
+
context.workTree.services[id] = {
|
|
209
|
+
...workService,
|
|
210
|
+
type: 'container-service',
|
|
211
|
+
cmd: service.cmd,
|
|
212
|
+
envs: service.envs || {},
|
|
213
|
+
image: service.image,
|
|
214
|
+
// user: getContainerUser(),
|
|
215
|
+
healthcheck: service.healthcheck,
|
|
216
|
+
mounts: (service.mounts || [])
|
|
217
|
+
.map((m) => (0, template_value_1.templateValue)(m, service.envs))
|
|
218
|
+
.map((m) => (0, parse_work_node_mount_1.parseWorkNodeMount)(need.build.path, m)),
|
|
219
|
+
volumes: (service.volumes || [])
|
|
220
|
+
.map((m) => (0, template_value_1.templateValue)(m, service.envs))
|
|
221
|
+
.map((m) => (0, parse_work_service_volume_1.parseWorkServiceVolume)(need.build.path, m)),
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
else if (!!service.context && !!service.selector) {
|
|
225
|
+
context.workTree.services[id] = {
|
|
226
|
+
...workService,
|
|
227
|
+
context: service.context,
|
|
228
|
+
selector: service.selector,
|
|
229
|
+
kubeconfig: service.kubeconfig ?? getDefaultKubeConfig(),
|
|
230
|
+
type: 'kubernetes-service',
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
if (!result.some((s) => s.id === id)) {
|
|
235
|
+
result.push(context.workTree.services[id]);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return result;
|
|
239
|
+
}
|
|
240
|
+
exports.parseWorkNodeNeeds = parseWorkNodeNeeds;
|
|
241
|
+
function getDefaultKubeConfig() {
|
|
242
|
+
return (0, path_1.join)((0, os_1.homedir)(), '.kube/config');
|
|
170
243
|
}
|
|
171
244
|
function parseWorkNodeCommand(task, context, envs) {
|
|
172
|
-
return plan_work_command_1.planWorkCommand(task.cmds.map((cmd) => {
|
|
245
|
+
return (0, plan_work_command_1.planWorkCommand)(task.cmds.map((cmd) => {
|
|
173
246
|
if (typeof cmd === 'string') {
|
|
174
|
-
return template_value_1.templateValue(cmd, envs);
|
|
247
|
+
return (0, template_value_1.templateValue)(cmd, envs);
|
|
175
248
|
}
|
|
176
249
|
else {
|
|
177
250
|
return {
|
|
178
|
-
cmd: template_value_1.templateValue(cmd.cmd, envs),
|
|
179
|
-
path: template_value_1.templateValue(cmd.path, envs),
|
|
251
|
+
cmd: (0, template_value_1.templateValue)(cmd.cmd, envs),
|
|
252
|
+
path: (0, template_value_1.templateValue)(cmd.path, envs),
|
|
180
253
|
type: cmd.type,
|
|
181
254
|
};
|
|
182
255
|
}
|
|
183
|
-
}), context.
|
|
256
|
+
}), context.cwd);
|
|
184
257
|
}
|
|
185
258
|
function mapSource(src, workDir) {
|
|
186
259
|
return {
|
|
187
260
|
matcher: src.matcher,
|
|
188
|
-
absolutePath: path_1.join(workDir, src.relativePath),
|
|
261
|
+
absolutePath: (0, path_1.join)(workDir, src.relativePath),
|
|
189
262
|
};
|
|
190
263
|
}
|
|
264
|
+
exports.mapSource = mapSource;
|
|
191
265
|
function getAbsolutePaths(dirs, workingDir) {
|
|
192
266
|
if (!dirs) {
|
|
193
267
|
return [];
|
|
194
268
|
}
|
|
195
|
-
return dirs.map((dir) => path_1.join(workingDir, dir));
|
|
269
|
+
return dirs.map((dir) => (0, path_1.join)(workingDir, dir));
|
|
196
270
|
}
|
|
271
|
+
exports.getAbsolutePaths = getAbsolutePaths;
|
|
197
272
|
//# sourceMappingURL=plan-work-node.js.map
|
|
@@ -1,13 +1,58 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.iterateWorkNodes = exports.planWorkNodes = void 0;
|
|
3
|
+
exports.iterateWorkNodes = exports.iterateWorkServices = exports.planWorkNodes = void 0;
|
|
4
4
|
const plan_work_node_1 = require("./plan-work-node");
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
const work_context_1 = require("../work-context");
|
|
6
|
+
const label_values_1 = require("../../executer/label-values");
|
|
7
|
+
function planWorkNodes(build, options) {
|
|
8
|
+
const context = (0, work_context_1.createWorkContext)(build);
|
|
9
|
+
addWorkNodes(context, []);
|
|
10
|
+
const nodesIdsToRemove = [];
|
|
11
|
+
for (const [nodeId, node] of Object.entries(context.workTree.nodes)) {
|
|
12
|
+
if (!(0, label_values_1.matchesAllLabels)(options.filterLabels, node, context.workTree.nodes) ||
|
|
13
|
+
(0, label_values_1.matchesAnyLabel)(options.excludeLabels, node)) {
|
|
14
|
+
nodesIdsToRemove.push(nodeId);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
for (const nodeId of nodesIdsToRemove) {
|
|
18
|
+
removeNode(nodeId, context.workTree);
|
|
19
|
+
}
|
|
20
|
+
removeUnusedServices(context.workTree);
|
|
21
|
+
return context.workTree;
|
|
9
22
|
}
|
|
10
23
|
exports.planWorkNodes = planWorkNodes;
|
|
24
|
+
function removeUnusedServices(workTree) {
|
|
25
|
+
const needs = new Set();
|
|
26
|
+
for (const node of Object.values(workTree.nodes)) {
|
|
27
|
+
for (const need of node.needs) {
|
|
28
|
+
needs.add(need.id);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const services = Object.values(workTree.services);
|
|
32
|
+
for (const service of services) {
|
|
33
|
+
if (!needs.has(service.id)) {
|
|
34
|
+
delete workTree.services[service.id];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function removeNode(nodeId, workTree) {
|
|
39
|
+
const node = workTree.nodes[nodeId];
|
|
40
|
+
if (node) {
|
|
41
|
+
delete workTree.nodes[nodeId];
|
|
42
|
+
for (const node of Object.values(workTree.nodes)) {
|
|
43
|
+
if (node.deps.some((d) => d.id === nodeId)) {
|
|
44
|
+
removeNode(node.id, workTree);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function* iterateWorkServices(services) {
|
|
50
|
+
for (const serviceId of Object.keys(services)) {
|
|
51
|
+
const service = services[serviceId];
|
|
52
|
+
yield service;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
exports.iterateWorkServices = iterateWorkServices;
|
|
11
56
|
function* iterateWorkNodes(nodes) {
|
|
12
57
|
for (const nodeId of Object.keys(nodes)) {
|
|
13
58
|
const node = nodes[nodeId];
|
|
@@ -15,19 +60,19 @@ function* iterateWorkNodes(nodes) {
|
|
|
15
60
|
}
|
|
16
61
|
}
|
|
17
62
|
exports.iterateWorkNodes = iterateWorkNodes;
|
|
18
|
-
function addWorkNodes(
|
|
19
|
-
if (files.indexOf(build.fileName) !== -1) {
|
|
63
|
+
function addWorkNodes(context, files) {
|
|
64
|
+
if (files.indexOf(context.build.fileName) !== -1) {
|
|
20
65
|
return;
|
|
21
66
|
}
|
|
22
|
-
files.push(build.fileName);
|
|
23
|
-
for (const
|
|
24
|
-
plan_work_node_1.
|
|
67
|
+
files.push(context.build.fileName);
|
|
68
|
+
for (const taskName of Object.keys(context.build.tasks)) {
|
|
69
|
+
(0, plan_work_node_1.getWorkNode)(context, { taskName });
|
|
25
70
|
}
|
|
26
|
-
for (const
|
|
27
|
-
addWorkNodes(
|
|
71
|
+
for (const name of Object.keys(context.build.references)) {
|
|
72
|
+
addWorkNodes((0, work_context_1.createSubWorkContext)(context, { type: 'references', name }), files);
|
|
28
73
|
}
|
|
29
|
-
for (const
|
|
30
|
-
addWorkNodes(
|
|
74
|
+
for (const name of Object.keys(context.build.includes)) {
|
|
75
|
+
addWorkNodes((0, work_context_1.createSubWorkContext)(context, { type: 'includes', name }), files);
|
|
31
76
|
}
|
|
32
77
|
}
|
|
33
78
|
//# sourceMappingURL=plan-work-nodes.js.map
|
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.planWorkTree = void 0;
|
|
4
4
|
const plan_work_node_1 = require("./plan-work-node");
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
5
|
+
const work_context_1 = require("../work-context");
|
|
6
|
+
function planWorkTree(build, options) {
|
|
7
|
+
const context = (0, work_context_1.createWorkContext)(build);
|
|
8
|
+
const result = (0, plan_work_node_1.getWorkNode)(context, { taskName: options.taskName });
|
|
9
|
+
return {
|
|
10
|
+
...context.workTree,
|
|
11
|
+
rootNode: result,
|
|
12
|
+
};
|
|
9
13
|
}
|
|
10
14
|
exports.planWorkTree = planWorkTree;
|
|
11
15
|
//# sourceMappingURL=plan-work-tree.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getContainerVolumes = exports.getVolumeName = exports.generateId = void 0;
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
|
+
function generateId(generate) {
|
|
6
|
+
return (0, crypto_1.createHash)('sha1').update(generate).digest('hex');
|
|
7
|
+
}
|
|
8
|
+
exports.generateId = generateId;
|
|
9
|
+
function getVolumeName(generate) {
|
|
10
|
+
return `hammerkit-${generateId(generate)}`;
|
|
11
|
+
}
|
|
12
|
+
exports.getVolumeName = getVolumeName;
|
|
13
|
+
function getContainerVolumes(task, mounts) {
|
|
14
|
+
const volumes = [];
|
|
15
|
+
for (const generate of task.generates) {
|
|
16
|
+
const hasMount = mounts.some((m) => m.containerPath === generate.path);
|
|
17
|
+
if (hasMount) {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
const name = getVolumeName(generate.path);
|
|
21
|
+
volumes.push({
|
|
22
|
+
name,
|
|
23
|
+
containerPath: generate.path,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
return volumes;
|
|
27
|
+
}
|
|
28
|
+
exports.getContainerVolumes = getContainerVolumes;
|
|
29
|
+
//# sourceMappingURL=plan-work-volume.js.map
|
package/dist/planner/validate.js
CHANGED
|
@@ -1,13 +1,52 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.validate = void 0;
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
async function* validate(buildFile, context, name) {
|
|
7
|
-
const tree = name ? plan_work_tree_1.planWorkTree(buildFile, name).nodes : plan_work_nodes_1.planWorkNodes(buildFile);
|
|
3
|
+
exports.checkIfContextExists = exports.hasCycle = exports.validate = void 0;
|
|
4
|
+
const read_build_file_1 = require("../parser/read-build-file");
|
|
5
|
+
async function* validate(workTree, context) {
|
|
8
6
|
const cycleNodes = [];
|
|
9
|
-
for (const
|
|
10
|
-
|
|
7
|
+
for (const service of Object.values(workTree.services)) {
|
|
8
|
+
if (!service.description) {
|
|
9
|
+
yield { type: 'warn', message: `missing description`, node: service };
|
|
10
|
+
}
|
|
11
|
+
if (service.type === 'container-service') {
|
|
12
|
+
if (!service.healthcheck) {
|
|
13
|
+
yield { type: 'warn', message: 'missing healthcheck', node: service };
|
|
14
|
+
}
|
|
15
|
+
for (const mount of service.mounts) {
|
|
16
|
+
if (!(await context.file.exists(mount.localPath))) {
|
|
17
|
+
yield {
|
|
18
|
+
type: 'warn',
|
|
19
|
+
message: `mount ${mount.localPath} does not exist`,
|
|
20
|
+
node: service,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
if (!(await context.file.exists(service.kubeconfig))) {
|
|
27
|
+
yield {
|
|
28
|
+
type: 'warn',
|
|
29
|
+
message: `kubeconfig ${service.kubeconfig} does not exist`,
|
|
30
|
+
node: service,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
else if (!(await checkIfContextExists(service, context))) {
|
|
34
|
+
yield {
|
|
35
|
+
type: 'warn',
|
|
36
|
+
message: `context ${service.context} does not exist in kubeconfig ${service.kubeconfig}`,
|
|
37
|
+
node: service,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
for (const key of Object.keys(service.buildService.unknownProps)) {
|
|
42
|
+
yield {
|
|
43
|
+
type: 'warn',
|
|
44
|
+
message: `${key} is an unknown configuration`,
|
|
45
|
+
node: service,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
for (const node of Object.values(workTree.nodes)) {
|
|
11
50
|
if (!node.description) {
|
|
12
51
|
yield { type: 'warn', message: `missing description`, node: node };
|
|
13
52
|
}
|
|
@@ -23,7 +62,7 @@ async function* validate(buildFile, context, name) {
|
|
|
23
62
|
};
|
|
24
63
|
}
|
|
25
64
|
}
|
|
26
|
-
for (const key of Object.keys(node.unknownProps)) {
|
|
65
|
+
for (const key of Object.keys(node.plannedTask.buildTask.unknownProps)) {
|
|
27
66
|
yield {
|
|
28
67
|
type: 'warn',
|
|
29
68
|
message: `${key} is an unknown configuration`,
|
|
@@ -52,4 +91,13 @@ function hasCycle(node, currentPath) {
|
|
|
52
91
|
}
|
|
53
92
|
return null;
|
|
54
93
|
}
|
|
94
|
+
exports.hasCycle = hasCycle;
|
|
95
|
+
async function checkIfContextExists(service, context) {
|
|
96
|
+
const kubeconfig = await (0, read_build_file_1.read)(service.kubeconfig, context);
|
|
97
|
+
if (kubeconfig.contexts && kubeconfig.contexts instanceof Array) {
|
|
98
|
+
return kubeconfig.contexts.some((c) => c['name'] === service.context);
|
|
99
|
+
}
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
exports.checkIfContextExists = checkIfContextExists;
|
|
55
103
|
//# sourceMappingURL=validate.js.map
|
|
@@ -1,3 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createSubWorkContext = exports.createWorkContext = void 0;
|
|
4
|
+
function createWorkContext(build) {
|
|
5
|
+
return {
|
|
6
|
+
cwd: build.path,
|
|
7
|
+
namePrefix: [],
|
|
8
|
+
build,
|
|
9
|
+
workTree: { nodes: {}, services: {} },
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
exports.createWorkContext = createWorkContext;
|
|
13
|
+
function createSubWorkContext(context, options) {
|
|
14
|
+
const subBuildFile = context.build[options.type][options.name];
|
|
15
|
+
return {
|
|
16
|
+
build: subBuildFile,
|
|
17
|
+
workTree: context.workTree,
|
|
18
|
+
cwd: options.type === 'references' ? subBuildFile.path : context.cwd,
|
|
19
|
+
namePrefix: [...context.namePrefix, options.name],
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
exports.createSubWorkContext = createSubWorkContext;
|
|
3
23
|
//# sourceMappingURL=work-context.js.map
|