hammerkit 1.9.2 → 1.11.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/build.schema.json +52 -1
- package/dist/cache/backends/registry/registry-client.js +19 -4
- package/dist/cli.js +1 -0
- package/dist/docker/pull.js +38 -1
- package/dist/environment/replace-env-variables.js +53 -22
- package/dist/executer/container-secrets.js +59 -0
- package/dist/executer/deadline.js +29 -0
- package/dist/executer/docker-service.js +58 -38
- package/dist/executer/docker-task.js +37 -23
- package/dist/executer/execute-init-task.js +100 -0
- package/dist/executer/execute-work-service.js +30 -1
- package/dist/executer/execute-work-task.js +4 -25
- package/dist/executer/execute-work-tree.js +28 -2
- package/dist/executer/get-container-binds.js +8 -4
- package/dist/executer/local-task.js +6 -1
- package/dist/kubernetes/ensure-kubernetes-deployment-exists.js +13 -7
- package/dist/kubernetes/secrets.js +83 -0
- package/dist/kubernetes/volumes.js +1 -1
- package/dist/optimizer/work-task-cache-description.js +6 -0
- package/dist/parse-set-arguments.js +38 -0
- package/dist/planner/service-definition.js +40 -0
- package/dist/planner/utils/append-work-dependencies.js +2 -0
- package/dist/planner/utils/append-work-needs.js +7 -0
- package/dist/planner/utils/append-work-service.js +67 -1
- package/dist/planner/utils/append-work-task.js +6 -0
- package/dist/planner/utils/parse-work-generate.js +4 -2
- package/dist/planner/utils/parse-work-mount.js +7 -3
- package/dist/planner/utils/parse-work-volume.js +8 -3
- package/dist/planner/utils/plan-work-volume.js +1 -0
- package/dist/planner/utils/service-hostname.js +15 -0
- package/dist/planner/utils/template-value.js +1 -1
- package/dist/planner/work-item-status.js +3 -1
- package/dist/planner/work-runtime-docker.js +8 -0
- package/dist/planner/work-runtime-kubernetes.js +40 -6
- package/dist/planner/work-secret.js +83 -0
- package/dist/program.js +9 -1
- package/dist/schema/build-file-base-task-schema.js +2 -0
- package/dist/schema/build-file-container-service-schema.js +5 -0
- package/dist/schema/build-file-secret-schema.js +22 -0
- package/dist/schema/build-file-volume-schema.js +3 -1
- package/dist/schema/reference-parser.js +14 -0
- package/dist/schema/work-scope-parser.js +30 -5
- package/dist/utils/redact.js +29 -0
- package/package.json +1 -1
|
@@ -73,6 +73,7 @@ async function parseReferences(ctx, mainScope, environment) {
|
|
|
73
73
|
scope: file,
|
|
74
74
|
needs: [],
|
|
75
75
|
deps: [],
|
|
76
|
+
init: null,
|
|
76
77
|
envs: serviceEnvs,
|
|
77
78
|
};
|
|
78
79
|
}
|
|
@@ -86,6 +87,7 @@ async function parseReferences(ctx, mainScope, environment) {
|
|
|
86
87
|
for (const service of Object.values(reference.services)) {
|
|
87
88
|
resolveDeps(reference, service, service.scope, service.schema);
|
|
88
89
|
resolveNeeds(reference, service, service.scope, service.schema);
|
|
90
|
+
resolveInit(reference, service);
|
|
89
91
|
}
|
|
90
92
|
reference.caches = (0, resolve_cache_1.withBuiltinCaches)(declaredCaches);
|
|
91
93
|
return reference;
|
|
@@ -142,6 +144,18 @@ function resolveDeps(reference, taskOrService, scope, schema) {
|
|
|
142
144
|
});
|
|
143
145
|
}
|
|
144
146
|
}
|
|
147
|
+
function resolveInit(reference, service) {
|
|
148
|
+
if ((0, build_file_service_schema_1.isBuildFileKubernetesServiceSchema)(service.schema) || !service.schema.init) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const initTask = findTask(reference, service.scope, service.schema.init, null);
|
|
152
|
+
service.init = {
|
|
153
|
+
task: initTask.task,
|
|
154
|
+
type: initTask.type,
|
|
155
|
+
cwd: initTask.type === 'include' ? service.cwd : initTask.task.cwd,
|
|
156
|
+
relativeName: service.schema.init,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
145
159
|
function resolveNeeds(reference, taskOrService, scope, schema) {
|
|
146
160
|
if ((0, build_file_service_schema_1.isBuildFileKubernetesServiceSchema)(schema)) {
|
|
147
161
|
return;
|
|
@@ -37,22 +37,42 @@ function getWorkContext(context, scope, environment) {
|
|
|
37
37
|
workTree.environment = filteredWorkTree.environment;
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
// everything is planned before the run is narrowed: planning a service adds
|
|
41
|
+
// its init task's need on it, which narrowing follows
|
|
42
|
+
const tasks = Object.values(context.tasks).map((task) => (0, append_work_task_1.appendWorkTask)(workTree, task.cwd, task, environment, context));
|
|
43
|
+
const services = Object.values(context.services).map((service) => (0, append_work_service_1.appendWorkService)(workTree, service, environment, context));
|
|
44
|
+
for (const item of tasks) {
|
|
42
45
|
if (matchesTaskWorkScope(item, scope)) {
|
|
43
46
|
requested.push(item.name);
|
|
44
47
|
applyTask(filteredWorkTree, item);
|
|
45
48
|
}
|
|
46
49
|
}
|
|
47
|
-
for (const
|
|
48
|
-
const item = (0, append_work_service_1.appendWorkService)(workTree, service, environment, context);
|
|
50
|
+
for (const item of services) {
|
|
49
51
|
if (matchesServiceWorkScope(item.data, scope)) {
|
|
50
52
|
applyService(filteredWorkTree, item);
|
|
51
53
|
}
|
|
52
54
|
}
|
|
55
|
+
keepRequirersInScope(filteredWorkTree);
|
|
53
56
|
return filteredWorkTree;
|
|
54
57
|
}
|
|
55
58
|
exports.getWorkContext = getWorkContext;
|
|
59
|
+
// The whole build file is planned first, so a shared service lists every task
|
|
60
|
+
// and service that needs it. Those outside this run never start or end, and a
|
|
61
|
+
// service waiting for them to finish would keep the run open forever.
|
|
62
|
+
function keepRequirersInScope(workTree) {
|
|
63
|
+
const inScope = new Set([
|
|
64
|
+
...Object.values(workTree.tasks),
|
|
65
|
+
...Object.values(workTree.services),
|
|
66
|
+
]);
|
|
67
|
+
for (const service of Object.values(workTree.services)) {
|
|
68
|
+
service.requiredBy = service.requiredBy.filter((required) => inScope.has(required));
|
|
69
|
+
// an init task asked for alone is what its service starts for
|
|
70
|
+
const init = service.data.type === 'container-service' ? service.data.init : null;
|
|
71
|
+
if (init && workTree.requested?.length === 1 && workTree.requested[0] === init.task.name) {
|
|
72
|
+
service.requiredBy.push(init.task);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
56
76
|
function applyTask(workTree, item) {
|
|
57
77
|
if (workTree.tasks[item.name]) {
|
|
58
78
|
return;
|
|
@@ -60,12 +80,17 @@ function applyTask(workTree, item) {
|
|
|
60
80
|
workTree.tasks[item.name] = item;
|
|
61
81
|
applyNeedsAndDeps(workTree, item);
|
|
62
82
|
}
|
|
63
|
-
function applyService(workTree,
|
|
83
|
+
function applyService(workTree, need) {
|
|
84
|
+
const item = (0, append_work_service_1.getPlannedService)(need);
|
|
64
85
|
if (workTree.services[item.name]) {
|
|
65
86
|
return;
|
|
66
87
|
}
|
|
67
88
|
workTree.services[item.name] = item;
|
|
68
89
|
applyNeedsAndDeps(workTree, item);
|
|
90
|
+
// a service in the run brings its init task, which runs once it is healthy
|
|
91
|
+
if (item.data.type === 'container-service' && item.data.init) {
|
|
92
|
+
applyTask(workTree, item.data.init.task);
|
|
93
|
+
}
|
|
69
94
|
}
|
|
70
95
|
function applyNeedsAndDeps(workTree, item) {
|
|
71
96
|
for (const dep of item.deps) {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.redact = exports.registerSecretValue = void 0;
|
|
4
|
+
// Secret values hammerkit has read, masked in everything it logs, including the
|
|
5
|
+
// output it streams from a task or service. Logs are per line, so each line of
|
|
6
|
+
// a multi-line value (a key file) is masked on its own. Values shorter than
|
|
7
|
+
// MIN_LENGTH are left alone: masking them would mangle unrelated output.
|
|
8
|
+
const MIN_LENGTH = 4;
|
|
9
|
+
const MASK = '***';
|
|
10
|
+
const values = new Set();
|
|
11
|
+
function registerSecretValue(value) {
|
|
12
|
+
for (const candidate of [value, ...value.split(/\r?\n/)]) {
|
|
13
|
+
const trimmed = candidate.trim();
|
|
14
|
+
if (trimmed.length >= MIN_LENGTH) {
|
|
15
|
+
values.add(trimmed);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.registerSecretValue = registerSecretValue;
|
|
20
|
+
function redact(message) {
|
|
21
|
+
if (values.size === 0) {
|
|
22
|
+
return message;
|
|
23
|
+
}
|
|
24
|
+
// longest first, so a value containing another is masked as a whole
|
|
25
|
+
const sorted = [...values].sort((a, b) => b.length - a.length);
|
|
26
|
+
return sorted.reduce((result, value) => result.split(value).join(MASK), message);
|
|
27
|
+
}
|
|
28
|
+
exports.redact = redact;
|
|
29
|
+
//# sourceMappingURL=redact.js.map
|
package/package.json
CHANGED