hammerkit 1.11.0 → 1.11.3
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/dist/executer/await-completed-dependencies.js +11 -5
- package/dist/executer/execute-work-task.js +3 -3
- package/dist/executer/execute-work-tree.js +14 -11
- package/dist/planner/utils/append-work-service.js +2 -1
- package/dist/planner/utils/parse-work-volume.js +5 -2
- package/dist/program.js +1 -1
- package/package.json +1 -1
|
@@ -16,12 +16,18 @@ async function awaitRequirement(svc, abort, options = { untilAllDone: false }) {
|
|
|
16
16
|
return Promise.race([ready, allDone]);
|
|
17
17
|
}
|
|
18
18
|
exports.awaitRequirement = awaitRequirement;
|
|
19
|
-
// Resolve true once any dependent
|
|
20
|
-
//
|
|
21
|
-
//
|
|
19
|
+
// Resolve true once any dependent needs this task's outputs — a task that is
|
|
20
|
+
// `ready` (it missed the cache and is about to run), a service that is
|
|
21
|
+
// `starting` (a task needing it runs) — and false once every dependent
|
|
22
|
+
// finished without needing it: tasks that were cache hits or skipped, services
|
|
23
|
+
// that never started.
|
|
22
24
|
async function awaitDependentNeed(dependents, abort) {
|
|
23
|
-
const ready = Promise.race(dependents.map((dependent) => (0,
|
|
24
|
-
|
|
25
|
+
const ready = Promise.race(dependents.map((dependent) => (0, work_item_1.isWorkTaskItem)(dependent)
|
|
26
|
+
? (0, state_resolver_1.awaitState)('await-dependent', dependent.state, (s) => s.type === 'ready', abort)
|
|
27
|
+
: (0, state_resolver_1.awaitState)('await-dependent', dependent.state, (s) => s.type === 'starting' || s.type === 'ready' || s.type === 'running', abort))).then(() => true);
|
|
28
|
+
const allDone = Promise.all(dependents.map((dependent) => (0, work_item_1.isWorkTaskItem)(dependent)
|
|
29
|
+
? (0, state_resolver_1.awaitState)('await-dependent-done', dependent.state, (s) => s.type === 'completed' || s.type === 'error' || s.type === 'crash' || s.type === 'canceled', abort)
|
|
30
|
+
: (0, state_resolver_1.awaitState)('await-dependent-done', dependent.state, (s) => s.type === 'end' || s.type === 'error' || s.type === 'canceled', abort))).then(() => false);
|
|
25
31
|
return Promise.race([ready, allDone]);
|
|
26
32
|
}
|
|
27
33
|
exports.awaitDependentNeed = awaitDependentNeed;
|
|
@@ -38,14 +38,14 @@ function onlyGroupsCacheHits(work) {
|
|
|
38
38
|
work.deps.every((dep) => dep.state.current.type === 'completed' && dep.state.current.cached));
|
|
39
39
|
}
|
|
40
40
|
async function executeWorkTask(work, environment, options,
|
|
41
|
-
// when set, the task was not requested and only runs if one of these
|
|
42
|
-
// depending on it
|
|
41
|
+
// when set, the task was not requested and only runs if one of these items
|
|
42
|
+
// depending on it needs it (see executeWorkTree)
|
|
43
43
|
dependents = null) {
|
|
44
44
|
try {
|
|
45
45
|
if (dependents) {
|
|
46
46
|
const needed = await (0, await_completed_dependencies_1.awaitDependentNeed)(dependents, environment.abortCtrl.signal);
|
|
47
47
|
if (!needed) {
|
|
48
|
-
work.status.write('debug', `${work.name} skipped,
|
|
48
|
+
work.status.write('debug', `${work.name} skipped, nothing depending on it had to run`);
|
|
49
49
|
work.state.set({ type: 'completed', cached: false, skipped: true, duration: 0, stateKey: '' });
|
|
50
50
|
return;
|
|
51
51
|
}
|
|
@@ -51,26 +51,29 @@ function mirrorServicesToInitViews(work) {
|
|
|
51
51
|
});
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
-
// For every task that may be skipped when nothing needs it, the tasks
|
|
55
|
-
// run that depend on it. Requested tasks always run;
|
|
56
|
-
//
|
|
54
|
+
// For every task that may be skipped when nothing needs it, the tasks and
|
|
55
|
+
// services in this run that depend on it. Requested tasks always run; a
|
|
56
|
+
// service's dependency runs once the service starts. Everything runs in watch
|
|
57
|
+
// mode, under `up` and with skipping turned off.
|
|
57
58
|
function skippableDependents(work, options) {
|
|
58
59
|
const result = new Map();
|
|
59
60
|
if (options.type !== 'execute' || !options.skipDeps || options.watch || !work.requested) {
|
|
60
61
|
return result;
|
|
61
62
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
// a dependency of nothing in the run (its service needs no one here) has no
|
|
64
|
+
// dependents left, and is skipped
|
|
65
|
+
for (const task of (0, plan_work_tasks_1.iterateWorkTasks)(work)) {
|
|
66
|
+
if (!work.requested.includes(task.name) && !(0, execute_init_task_1.findInitOf)(task)) {
|
|
67
|
+
result.set(task.name, []);
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
const items = [...(0, plan_work_tasks_1.iterateWorkTasks)(work), ...(0, plan_work_tasks_1.iterateWorkServices)(work)];
|
|
71
|
+
for (const item of items) {
|
|
72
|
+
for (const dep of item.deps) {
|
|
73
|
+
if (work.requested.includes(dep.name)) {
|
|
71
74
|
continue;
|
|
72
75
|
}
|
|
73
|
-
result.set(dep.name, [...(result.get(dep.name) ?? []),
|
|
76
|
+
result.set(dep.name, [...(result.get(dep.name) ?? []), item]);
|
|
74
77
|
}
|
|
75
78
|
}
|
|
76
79
|
return result;
|
|
@@ -139,7 +139,8 @@ function appendServiceInit(workTree, service, item, environment, context) {
|
|
|
139
139
|
task.needs.push({ name: item.name, service: view });
|
|
140
140
|
}
|
|
141
141
|
removeRequirer(item, task.name);
|
|
142
|
-
|
|
142
|
+
// explicit, so neither the default method nor `--cache` turns it back on
|
|
143
|
+
task.data.caching = { ...task.data.caching, method: 'none', implicit: false };
|
|
143
144
|
if (task.data.timeout === null) {
|
|
144
145
|
task.data.timeout = getInitTimeout(undefined, environment);
|
|
145
146
|
}
|
|
@@ -6,7 +6,10 @@ const plan_work_volume_1 = require("./plan-work-volume");
|
|
|
6
6
|
const template_value_1 = require("./template-value");
|
|
7
7
|
function parseWorkVolume(cwd, volume, envs) {
|
|
8
8
|
if (typeof volume === 'string') {
|
|
9
|
-
|
|
9
|
+
// `$NAME` references resolve first, as in mounts, so a value holding a
|
|
10
|
+
// colon can't break the name:path split
|
|
11
|
+
const value = (0, template_value_1.templateValue)(volume, envs);
|
|
12
|
+
const parts = value.split(':');
|
|
10
13
|
if (parts.length === 2) {
|
|
11
14
|
return parseVolume(cwd, parts[0], parts[1], false);
|
|
12
15
|
}
|
|
@@ -14,7 +17,7 @@ function parseWorkVolume(cwd, volume, envs) {
|
|
|
14
17
|
return parseVolume(cwd, parts[0], parts[1], parts[2] === 'ro');
|
|
15
18
|
}
|
|
16
19
|
else {
|
|
17
|
-
throw new Error(`invalid volume ${
|
|
20
|
+
throw new Error(`invalid volume ${value}`);
|
|
18
21
|
}
|
|
19
22
|
}
|
|
20
23
|
else {
|
package/dist/program.js
CHANGED
|
@@ -508,7 +508,7 @@ async function getProgram(environment, argv) {
|
|
|
508
508
|
.addOption(new commander_1.Option('--dry-run', 'print the execution plan with predicted cache hits/misses without running').default(false))
|
|
509
509
|
.addOption(new commander_1.Option('--cache-read-only', `restore from cache backends but never push to them (or set ${read_only_1.CACHE_READ_ONLY_ENV}=1)`).default(false))
|
|
510
510
|
.addOption(new commander_1.Option('--timeout <duration>', 'fail tasks without their own timeout after this long (e.g. 10m)').argParser(units_1.parseDuration))
|
|
511
|
-
.addOption(new commander_1.Option('--no-skip-deps', 'run dependencies even when
|
|
511
|
+
.addOption(new commander_1.Option('--no-skip-deps', 'run dependencies even when nothing needing them has to run'))
|
|
512
512
|
.action(async (task, options) => {
|
|
513
513
|
try {
|
|
514
514
|
// For machine-readable JSON, suppress the human progress logger (which
|
package/package.json
CHANGED