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.
Files changed (177) hide show
  1. package/.devcontainer/Dockerfile +5 -0
  2. package/.devcontainer/devcontainer.json +40 -0
  3. package/README.md +13 -86
  4. package/SUMMARY.md +43 -0
  5. package/build.schema.json +56 -2
  6. package/dist/cli.js +97 -0
  7. package/dist/cli.spec.js +5 -0
  8. package/dist/console/console-context-mock.js +11 -0
  9. package/dist/console/get-logger.js +23 -0
  10. package/dist/docker/pull.js +5 -5
  11. package/dist/docker/remove-container.js +21 -0
  12. package/dist/docker/stream.js +14 -10
  13. package/dist/docker/using-container.js +28 -0
  14. package/dist/environment/get-process-env.js +4 -4
  15. package/dist/environment/replace-env-variables.js +2 -3
  16. package/dist/executer/abort.js +13 -0
  17. package/dist/executer/check-readiness.js +25 -0
  18. package/dist/executer/create-scheduler-state.js +32 -0
  19. package/dist/executer/docker-node.js +123 -0
  20. package/dist/executer/docker-service.js +113 -0
  21. package/dist/executer/environment-mock.js +17 -0
  22. package/dist/executer/event-cache.js +165 -0
  23. package/dist/executer/execute-command.js +42 -0
  24. package/dist/executer/execute-docker.js +58 -194
  25. package/dist/executer/execute.spec.js +37 -37
  26. package/dist/executer/execution-steps.js +57 -0
  27. package/dist/executer/get-docker-executor.js +6 -100
  28. package/dist/executer/hierarchy-scheduler.js +94 -0
  29. package/dist/executer/kubernetes-service.js +64 -0
  30. package/dist/executer/label-values.js +65 -0
  31. package/dist/executer/local-node.js +57 -0
  32. package/dist/executer/print-container-options.js +17 -0
  33. package/dist/{logging/log-strategy.js → executer/process-item.js} +1 -1
  34. package/dist/executer/process-listener.js +3 -0
  35. package/dist/executer/process-manager.js +111 -0
  36. package/dist/executer/process-manager.spec.js +91 -0
  37. package/dist/executer/{executor.js → process.js} +1 -1
  38. package/dist/executer/{execute-result.js → readonly-state.js} +1 -1
  39. package/dist/executer/schedule.js +139 -0
  40. package/dist/executer/scheduler/check-for-loop.js +21 -0
  41. package/dist/executer/scheduler/enqueue-next.js +27 -0
  42. package/dist/{testing/test-context.js → executer/scheduler/node-state.js} +1 -1
  43. package/dist/executer/scheduler/scheduler-result.js +3 -0
  44. package/dist/executer/scheduler/scheduler-state.js +3 -0
  45. package/dist/executer/scheduler/service-state.js +3 -0
  46. package/dist/executer/service-dns.js +6 -0
  47. package/dist/executer/set-user-permission.js +16 -0
  48. package/dist/executer/start-node.js +59 -0
  49. package/dist/executer/state-listener.js +3 -0
  50. package/dist/executer/state.js +49 -0
  51. package/dist/executer/states.js +4 -159
  52. package/dist/executer/watch-node.js +57 -0
  53. package/dist/executer/watch-service.js +54 -0
  54. package/dist/executer/work-scope.js +10 -0
  55. package/dist/file/get-file-context-mock.spec.js +5 -5
  56. package/dist/file/get-file-context.js +41 -18
  57. package/dist/file/move-files.js +1 -1
  58. package/dist/get-work-context.js +29 -0
  59. package/dist/index.js +8 -4
  60. package/dist/log.js +192 -50
  61. package/dist/logging/grouped-logger.js +31 -19
  62. package/dist/logging/interactive-logger.js +20 -23
  63. package/dist/logging/live-logger.js +7 -17
  64. package/dist/optimizer/calculate-checksum.js +1 -1
  65. package/dist/optimizer/get-cache-directory.js +8 -13
  66. package/dist/optimizer/get-work-node-cache-stats.js +68 -21
  67. package/dist/optimizer/read-work-node-cache.js +2 -2
  68. package/dist/optimizer/work-node-cache-description.js +12 -11
  69. package/dist/optimizer/write-work-node-cache.js +9 -8
  70. package/dist/{executer/execution-context.js → parser/build-file-service.js} +1 -1
  71. package/dist/{optimizer → parser}/cache-method.js +0 -0
  72. package/dist/parser/get-build-file.js +1 -1
  73. package/dist/parser/parse-boolean.js +29 -0
  74. package/dist/parser/parse-boolean.spec.js +48 -0
  75. package/dist/parser/parse-build-file-references.js +2 -2
  76. package/dist/parser/parse-build-file-services.js +58 -0
  77. package/dist/parser/parse-build-file-task-command.js +6 -5
  78. package/dist/parser/parse-build-file-task-source.js +5 -5
  79. package/dist/parser/parse-build-file.js +27 -15
  80. package/dist/parser/parse-context.js +13 -0
  81. package/dist/parser/parse-envs.js +4 -3
  82. package/dist/parser/parse-healthcheck.js +28 -0
  83. package/dist/parser/parse-label-arguments.js +23 -0
  84. package/dist/parser/parse-service-selector.js +39 -0
  85. package/dist/parser/parse-string-array.js +6 -5
  86. package/dist/parser/parse-string-map.js +30 -0
  87. package/dist/parser/parse-string.js +20 -0
  88. package/dist/parser/read-build-file.js +16 -5
  89. package/dist/parser/read-env-file.js +3 -3
  90. package/dist/planner/utils/get-container-mounts.js +24 -0
  91. package/dist/planner/utils/normalize-path.js +17 -0
  92. package/dist/planner/utils/parse-work-node-mount.js +3 -14
  93. package/dist/planner/utils/parse-work-node-mount.spec.js +10 -10
  94. package/dist/planner/utils/parse-work-service-volume.js +21 -0
  95. package/dist/planner/utils/plan-work-command.js +1 -1
  96. package/dist/planner/utils/plan-work-dependency.js +17 -5
  97. package/dist/planner/utils/plan-work-node.js +203 -128
  98. package/dist/planner/utils/plan-work-nodes.js +59 -14
  99. package/dist/planner/utils/plan-work-tree.js +8 -4
  100. package/dist/planner/utils/plan-work-volume.js +25 -0
  101. package/dist/planner/validate.js +56 -8
  102. package/dist/planner/work-context.js +20 -0
  103. package/dist/planner/work-mount.js +3 -0
  104. package/dist/planner/work-node-id.js +4 -4
  105. package/dist/planner/work-node-id.spec.js +11 -8
  106. package/dist/planner/work-node-path.js +0 -1
  107. package/dist/planner/work-node-status.js +121 -18
  108. package/dist/planner/work-node.js +3 -3
  109. package/dist/planner/work-service-id.js +13 -0
  110. package/dist/planner/work-service-volume.js +3 -0
  111. package/dist/planner/work-service.js +6 -0
  112. package/dist/planner/work-services.js +3 -0
  113. package/dist/planner/work-volume.js +3 -0
  114. package/dist/program.js +155 -90
  115. package/dist/program.spec.js +20 -0
  116. package/dist/start-watch-processes.js +28 -0
  117. package/dist/testing/cli.js +73 -0
  118. package/dist/testing/create-build-file.js +1 -1
  119. package/dist/testing/example-test-suite.js +54 -0
  120. package/dist/testing/expect.js +30 -18
  121. package/dist/testing/get-logger.js +23 -0
  122. package/dist/testing/get-node.js +2 -2
  123. package/dist/testing/get-test-context.js +5 -3
  124. package/dist/testing/get-test-suite.js +2 -50
  125. package/dist/testing/integration/cache.spec.js +25 -28
  126. package/dist/testing/integration/cancellation.spec.js +19 -21
  127. package/dist/testing/integration/clean.spec.js +25 -28
  128. package/dist/testing/integration/cmd.spec.js +5 -8
  129. package/dist/testing/integration/concurrency.spec.js +8 -17
  130. package/dist/testing/integration/docker.spec.js +6 -9
  131. package/dist/testing/integration/env.spec.js +27 -34
  132. package/dist/testing/integration/error.spec.js +5 -9
  133. package/dist/testing/integration/extend.spec.js +32 -0
  134. package/dist/testing/integration/glob.spec.js +35 -28
  135. package/dist/testing/integration/include.spec.js +17 -16
  136. package/dist/testing/integration/invalid.spec.js +3 -2
  137. package/dist/testing/integration/invalid_loop.spec.js +13 -0
  138. package/dist/testing/integration/kubernetes.spec.js +15 -0
  139. package/dist/testing/integration/labels.spec.js +47 -0
  140. package/dist/testing/integration/local.spec.js +4 -7
  141. package/dist/testing/integration/monorepo.spec.js +5 -9
  142. package/dist/testing/integration/multi-line.spec.js +4 -4
  143. package/dist/testing/integration/program.spec.js +3 -10
  144. package/dist/testing/integration/reference.spec.js +10 -13
  145. package/dist/testing/integration/services.spec.js +14 -0
  146. package/dist/testing/integration/store.spec.js +42 -38
  147. package/dist/testing/integration/unknown.spec.js +4 -4
  148. package/dist/testing/integration/validate.spec.js +4 -4
  149. package/dist/testing/integration/watch.spec.js +34 -33
  150. package/dist/testing/lazy.js +17 -0
  151. package/dist/testing/start-watch-processes.js +29 -0
  152. package/dist/testing/test-suite-setup.js +3 -0
  153. package/dist/utils/abort-event.js +14 -1
  154. package/dist/utils/abortable-function.js +71 -0
  155. package/dist/utils/debouncer.spec.js +8 -8
  156. package/dist/utils/environment-config.js +13 -0
  157. package/dist/utils/fail-never.js +1 -1
  158. package/dist/utils/sleep.spec.js +3 -3
  159. package/package.json +24 -21
  160. package/dist/console/get-console-context-mock.js +0 -33
  161. package/dist/executer/clean.js +0 -17
  162. package/dist/executer/execute-local.js +0 -59
  163. package/dist/executer/execute.js +0 -139
  164. package/dist/executer/execution-context-event.js +0 -3
  165. package/dist/executer/execution-context-mock.js +0 -3
  166. package/dist/executer/executor-mock.js +0 -61
  167. package/dist/executer/get-environment-mock.js +0 -16
  168. package/dist/executer/get-execution-context-mock.js +0 -18
  169. package/dist/executer/get-local-executor.js +0 -56
  170. package/dist/executer/restore.js +0 -19
  171. package/dist/executer/store.js +0 -19
  172. package/dist/logging/get-logger.js +0 -23
  173. package/dist/logging/message-to-console.js +0 -16
  174. package/dist/optimizer/optimize.js +0 -32
  175. package/dist/optimizer/work-node-description.js +0 -12
  176. package/dist/planner/utils/find-build-task.js +0 -18
  177. package/dist/testing/create-work-tree.js +0 -11
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getCli = exports.isCliService = exports.isCliTask = void 0;
4
+ const plan_work_nodes_1 = require("../planner/utils/plan-work-nodes");
5
+ const create_scheduler_state_1 = require("../executer/create-scheduler-state");
6
+ const ci_1 = require("../utils/ci");
7
+ const get_logger_1 = require("./get-logger");
8
+ const hierarchy_scheduler_1 = require("../executer/hierarchy-scheduler");
9
+ const event_cache_1 = require("../executer/event-cache");
10
+ const validate_1 = require("../planner/validate");
11
+ const start_watch_processes_1 = require("./start-watch-processes");
12
+ const process_manager_1 = require("../executer/process-manager");
13
+ const isCliTask = (val) => val.type === 'task';
14
+ exports.isCliTask = isCliTask;
15
+ const isCliService = (val) => val.type === 'service';
16
+ exports.isCliService = isCliService;
17
+ function getCli(workTree, environment) {
18
+ return {
19
+ execWatch(options) {
20
+ const processManager = new process_manager_1.ProcessManager(environment, options?.workers ?? 0);
21
+ const state = (0, create_scheduler_state_1.createSchedulerState)({
22
+ services: workTree.services,
23
+ nodes: workTree.nodes,
24
+ watch: options?.watch ?? false,
25
+ logMode: options?.logMode ?? ci_1.isCI ? 'live' : 'interactive',
26
+ cacheMethod: options?.cacheDefault ?? 'checksum',
27
+ });
28
+ const logMode = options?.logMode ?? (ci_1.isCI ? 'live' : 'interactive');
29
+ const logger = (0, get_logger_1.getLogger)(logMode, state, environment);
30
+ if (options?.watch) {
31
+ (0, start_watch_processes_1.startWatchProcesses)(state, processManager, environment);
32
+ }
33
+ return {
34
+ state,
35
+ start: async () => {
36
+ const result = await (0, hierarchy_scheduler_1.schedule)(processManager, state, environment);
37
+ await logger.complete(result, environment);
38
+ return result;
39
+ },
40
+ };
41
+ },
42
+ async exec(options) {
43
+ return this.execWatch(options).start();
44
+ },
45
+ async clean() {
46
+ await (0, event_cache_1.cleanCache)(workTree, environment);
47
+ },
48
+ async restore(path) {
49
+ await (0, event_cache_1.restoreCache)(path, workTree, environment);
50
+ },
51
+ async store(path) {
52
+ await (0, event_cache_1.storeCache)(path, workTree, environment);
53
+ },
54
+ ls() {
55
+ return [
56
+ ...Array.from((0, plan_work_nodes_1.iterateWorkServices)(workTree.services)).map((item) => ({ item, type: 'service' })),
57
+ ...Array.from((0, plan_work_nodes_1.iterateWorkNodes)(workTree.nodes)).map((item) => ({ item, type: 'task' })),
58
+ ];
59
+ },
60
+ validate() {
61
+ return (0, validate_1.validate)(workTree, environment);
62
+ },
63
+ node(name) {
64
+ const node = Object.values(workTree.nodes).find((n) => n.name == name);
65
+ if (!node) {
66
+ throw new Error(`unable to find node ${name}`);
67
+ }
68
+ return node;
69
+ },
70
+ };
71
+ }
72
+ exports.getCli = getCli;
73
+ //# sourceMappingURL=cli.js.map
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createBuildFile = void 0;
4
4
  const parse_build_file_1 = require("../parser/parse-build-file");
5
5
  function createBuildFile(env, buildFile) {
6
- return parse_build_file_1.parseBuildFile(`${env.cwd}/build.yaml`, {}, buildFile, env);
6
+ return (0, parse_build_file_1.parseBuildFile)(`${env.cwd}/build.yaml`, {}, buildFile, env);
7
7
  }
8
8
  exports.createBuildFile = createBuildFile;
9
9
  //# sourceMappingURL=create-build-file.js.map
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ExampleTestSuite = void 0;
4
+ const path_1 = require("path");
5
+ const get_file_context_1 = require("../file/get-file-context");
6
+ const console_context_mock_1 = require("../console/console-context-mock");
7
+ const work_node_status_1 = require("../planner/work-node-status");
8
+ const program_1 = require("../program");
9
+ const execute_docker_1 = require("../executer/execute-docker");
10
+ class ExampleTestSuite {
11
+ constructor(exampleName, files) {
12
+ this.files = files;
13
+ this.tests = [];
14
+ this.exampleDirectory = (0, path_1.join)(__dirname, '../../examples/', exampleName);
15
+ this.path = (0, path_1.join)(process.cwd(), 'temp', exampleName);
16
+ this.file = (0, get_file_context_1.getFileContext)(this.path);
17
+ }
18
+ async close() {
19
+ for (const test of this.tests) {
20
+ await this.file.remove(test.cwd);
21
+ }
22
+ }
23
+ async setup(scope) {
24
+ await this.file.remove(this.path);
25
+ await this.file.createDirectory(this.path);
26
+ const environment = {
27
+ processEnvs: { ...process.env, ...(scope.envs ?? {}) },
28
+ abortCtrl: new AbortController(),
29
+ cwd: this.path,
30
+ file: this.file,
31
+ console: (0, console_context_mock_1.consoleContextMock)(),
32
+ status: (0, work_node_status_1.statusConsole)(),
33
+ docker: (0, execute_docker_1.getContainerCli)(),
34
+ };
35
+ for (const file of this.files) {
36
+ await this.file.copy((0, path_1.join)(this.exampleDirectory, file), (0, path_1.join)(this.path, file));
37
+ }
38
+ const fileName = (0, path_1.join)(this.path, 'build.yaml');
39
+ this.tests.push({
40
+ cwd: this.path,
41
+ });
42
+ const cli = await (0, program_1.createCli)(fileName, environment, scope);
43
+ await cli.clean({ service: true });
44
+ // reset cli clean stats
45
+ environment.console = (0, console_context_mock_1.consoleContextMock)();
46
+ environment.status = (0, work_node_status_1.statusConsole)();
47
+ return {
48
+ cli,
49
+ environment,
50
+ };
51
+ }
52
+ }
53
+ exports.ExampleTestSuite = ExampleTestSuite;
54
+ //# sourceMappingURL=example-test-suite.js.map
@@ -1,17 +1,24 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.expectContainsLog = exports.expectLog = exports.expectSuccessfulResult = void 0;
4
- async function expectSuccessfulResult(result) {
4
+ const plan_work_nodes_1 = require("../planner/utils/plan-work-nodes");
5
+ async function expectSuccessfulResult(result, env) {
5
6
  if (!result.success) {
6
- for (const nodeId of Object.keys(result.nodes)) {
7
- const node = result.nodes[nodeId];
8
- if (node.state.type === 'failed') {
7
+ for (const state of (0, plan_work_nodes_1.iterateWorkNodes)(result.state.node)) {
8
+ if (state.type !== 'completed') {
9
9
  expect({
10
- nodeId,
11
- status: node.state.type,
12
- logs: await node.console.read(),
10
+ nodeId: state.node.id,
11
+ status: state.type,
12
+ updates: Array.from(env.status.task(state.node).read()).map((s) => `${s.level}: ${s.message}`),
13
+ logs: Array.from(env.status.task(state.node).logs()).map((l) => `${l.console}: ${l.message}`),
14
+ errorMessage: state.type === 'error' ? state.errorMessage : undefined,
15
+ needs: state.node.needs.map((need) => ({
16
+ name: need.name,
17
+ updates: Array.from(env.status.service(need).read()).map((s) => `${s.level}: ${s.message}`),
18
+ logs: Array.from(env.status.service(need).logs()).map((l) => `${l.console}: ${l.message}`),
19
+ })),
13
20
  }).toEqual({
14
- nodeId,
21
+ nodeId: state.node.id,
15
22
  status: 'completed',
16
23
  });
17
24
  }
@@ -19,23 +26,28 @@ async function expectSuccessfulResult(result) {
19
26
  }
20
27
  }
21
28
  exports.expectSuccessfulResult = expectSuccessfulResult;
22
- function getNode(result, name) {
23
- const node = Object.values(result.nodes).find((n) => n.name === name);
29
+ function getNodeState(state, name) {
30
+ const node = Object.values(state.node).find((n) => n.node.name === name);
24
31
  if (!node) {
25
32
  throw new Error(`could not find node ${name}`);
26
33
  }
27
34
  return node;
28
35
  }
29
- async function expectLog(result, name, message) {
30
- const node = getNode(result, name);
31
- const logs = await node.console.read();
32
- expect(logs.map((l) => l.message)).toContain(message);
36
+ async function expectLog(result, env, name, message) {
37
+ const state = getNodeState(result.state, name);
38
+ const logs = Array.from(env.status.task(state.node).logs()).map((n) => n.message);
39
+ expect(logs).toContain(message);
33
40
  }
34
41
  exports.expectLog = expectLog;
35
- async function expectContainsLog(result, name, message) {
36
- const node = getNode(result, name);
37
- const logs = await node.console.read();
38
- expect(logs.some((l) => l.message.indexOf(message))).toBeTruthy();
42
+ async function expectContainsLog(result, env, name, message) {
43
+ const state = getNodeState(result.state, name);
44
+ const logs = env.status.task(state.node).logs();
45
+ for (const log of logs) {
46
+ if (log.message.indexOf(message) >= 0) {
47
+ return;
48
+ }
49
+ }
50
+ expect(Array.from(logs)).toContain(message);
39
51
  }
40
52
  exports.expectContainsLog = expectContainsLog;
41
53
  //# sourceMappingURL=expect.js.map
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getLogger = void 0;
4
+ const grouped_logger_1 = require("../logging/grouped-logger");
5
+ const live_logger_1 = require("../logging/live-logger");
6
+ const interactive_logger_1 = require("../logging/interactive-logger");
7
+ const fail_never_1 = require("../utils/fail-never");
8
+ function getLogger(mode, state, env) {
9
+ if (mode === 'grouped') {
10
+ return (0, grouped_logger_1.groupedLogger)(state, env);
11
+ }
12
+ else if (mode === 'live') {
13
+ return (0, live_logger_1.liveLogger)(state, env);
14
+ }
15
+ else if (mode === 'interactive') {
16
+ return (0, interactive_logger_1.interactiveLogger)(state, env);
17
+ }
18
+ else {
19
+ (0, fail_never_1.failNever)(mode, 'unknown log mode');
20
+ }
21
+ }
22
+ exports.getLogger = getLogger;
23
+ //# sourceMappingURL=get-logger.js.map
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getNode = void 0;
4
- function getNode(buildFile, workTree, taskName) {
5
- const node = Object.values(workTree.nodes).find((n) => n.name === taskName);
4
+ function getNode(buildFile, nodes, taskName) {
5
+ const node = Object.values(nodes).find((n) => n.name === taskName);
6
6
  if (!node) {
7
7
  throw new Error(`could not find node ${taskName}`);
8
8
  }
@@ -2,14 +2,16 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getTestContext = void 0;
4
4
  const get_file_context_1 = require("../file/get-file-context");
5
- const get_console_context_mock_1 = require("../console/get-console-context-mock");
5
+ const work_node_status_1 = require("../planner/work-node-status");
6
+ const log_1 = require("../log");
6
7
  function getTestContext(cwd) {
7
8
  const context = {
8
9
  processEnvs: { ...process.env },
9
10
  abortCtrl: new AbortController(),
10
11
  cwd,
11
- file: get_file_context_1.getFileContext(),
12
- console: get_console_context_mock_1.getConsoleContextMock(),
12
+ file: (0, get_file_context_1.getFileContext)(cwd),
13
+ console: (0, log_1.consoleContext)(),
14
+ status: (0, work_node_status_1.statusConsole)(),
13
15
  };
14
16
  return context;
15
17
  }
@@ -1,57 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getTestSuite = void 0;
4
- const path_1 = require("path");
5
- const get_build_file_1 = require("../parser/get-build-file");
6
- const get_docker_executor_1 = require("../executer/get-docker-executor");
7
- const get_console_context_mock_1 = require("../console/get-console-context-mock");
8
- const get_file_context_1 = require("../file/get-file-context");
9
- const emitter_1 = require("../utils/emitter");
10
- const clean_1 = require("../executer/clean");
11
- const plan_work_nodes_1 = require("../planner/utils/plan-work-nodes");
4
+ const example_test_suite_1 = require("./example-test-suite");
12
5
  function getTestSuite(exampleName, files) {
13
- const exampleDirectory = path_1.join(__dirname, '../../examples/', exampleName);
14
- const testDirectory = path_1.join(process.cwd(), 'temp', exampleName);
15
- const file = get_file_context_1.getFileContext();
16
- const tests = [];
17
- return {
18
- async close() {
19
- for (const test of tests) {
20
- await file.remove(test.cwd);
21
- }
22
- },
23
- async setup(executionOptions) {
24
- const context = {
25
- processEnvs: { ...process.env },
26
- abortCtrl: new AbortController(),
27
- cwd: testDirectory,
28
- file,
29
- console: get_console_context_mock_1.getConsoleContextMock(),
30
- };
31
- await file.remove(testDirectory);
32
- await file.createDirectory(testDirectory);
33
- for (const file of files) {
34
- await context.file.copy(path_1.join(exampleDirectory, file), path_1.join(testDirectory, file));
35
- }
36
- const fileName = path_1.join(testDirectory, 'build.yaml');
37
- const buildFile = await get_build_file_1.getBuildFile(fileName, context);
38
- const workNodes = plan_work_nodes_1.planWorkNodes(buildFile);
39
- const executor = get_docker_executor_1.getDockerExecutor();
40
- await clean_1.clean(workNodes, context, executor);
41
- const executionContext = {
42
- environment: context,
43
- watch: executionOptions?.watch ?? false,
44
- cacheMethod: executionOptions?.cacheMethod ?? 'checksum',
45
- workers: executionOptions?.workers ?? 0,
46
- events: emitter_1.emitter(),
47
- executor,
48
- };
49
- tests.push({
50
- cwd: testDirectory,
51
- });
52
- return { buildFile, context, executionContext };
53
- },
54
- };
6
+ return new example_test_suite_1.ExampleTestSuite(exampleName, files);
55
7
  }
56
8
  exports.getTestSuite = getTestSuite;
57
9
  //# sourceMappingURL=get-test-suite.js.map
@@ -3,50 +3,47 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  require("jest-extended");
4
4
  const write_work_node_cache_1 = require("../../optimizer/write-work-node-cache");
5
5
  const expect_1 = require("../expect");
6
- const plan_work_tree_1 = require("../../planner/utils/plan-work-tree");
7
- const execute_1 = require("../../executer/execute");
8
- const optimize_1 = require("../../optimizer/optimize");
9
6
  const get_test_suite_1 = require("../get-test-suite");
10
7
  const path_1 = require("path");
11
- const get_node_1 = require("../get-node");
12
- const work_node_id_1 = require("../../planner/work-node-id");
8
+ const enqueue_next_1 = require("../../executer/scheduler/enqueue-next");
9
+ const read_build_file_1 = require("../../parser/read-build-file");
13
10
  describe('cache', () => {
14
- const suite = get_test_suite_1.getTestSuite('cache', ['build.yaml', 'package.json', 'package-lock.json']);
11
+ const suite = (0, get_test_suite_1.getTestSuite)('cache', ['build.yaml', 'package.json', 'package-lock.json']);
15
12
  afterAll(() => suite.close());
16
13
  async function testCache(action, expectInvalidate) {
17
- const { buildFile, context, executionContext } = await suite.setup();
18
- const workTree = plan_work_tree_1.planWorkTree(buildFile, 'example');
19
- expect(workTree.nodes).toContainKey(workTree.rootNode.id);
20
- await write_work_node_cache_1.writeWorkNodeCache(workTree.nodes[workTree.rootNode.id], context);
21
- await action(buildFile, workTree, executionContext);
22
- await optimize_1.optimize(workTree, executionContext);
14
+ const setupBefore = await suite.setup({ taskName: 'example' });
15
+ const nodeBefore = setupBefore.cli.node('example');
16
+ await (0, write_work_node_cache_1.writeWorkNodeCache)(nodeBefore, setupBefore.environment);
17
+ await action(setupBefore.environment);
18
+ const setupAfter = await suite.setup({ taskName: 'example' });
19
+ const node = setupAfter.cli.node('example');
20
+ const checksumUpToDate = await (0, enqueue_next_1.checkCacheState)(node, 'checksum', setupAfter.environment);
21
+ const modifyDateUpToDate = await (0, enqueue_next_1.checkCacheState)(node, 'modify-date', setupAfter.environment);
23
22
  if (expectInvalidate) {
24
- expect(workTree.nodes[workTree.rootNode.id].status.state.type).toEqual('pending');
23
+ expect(checksumUpToDate.cached).toBeFalsy();
24
+ expect(modifyDateUpToDate.cached).toBeFalsy();
25
25
  }
26
26
  else {
27
- expect(workTree.nodes[workTree.rootNode.id].status.state.type).toEqual('completed');
27
+ expect(checksumUpToDate.cached).toBeTruthy();
28
+ expect(modifyDateUpToDate.cached).toBeTruthy();
28
29
  }
29
30
  }
30
31
  it('should run invalid cache on src file change', async () => {
31
- await testCache(async (buildFile, workTree, context) => {
32
- await context.environment.file.appendFile(path_1.join(context.environment.cwd, 'package.json'), '\n');
32
+ await testCache(async (environment) => {
33
+ await environment.file.appendFile((0, path_1.join)(environment.cwd, 'package.json'), '\n');
33
34
  }, true);
34
35
  });
35
36
  it('should mount generations of dependant tasks', async () => {
36
- const { buildFile, executionContext } = await suite.setup();
37
- const workTree = plan_work_tree_1.planWorkTree(buildFile, 'dependant');
38
- const result = await execute_1.execute(workTree, executionContext);
39
- await expect_1.expectSuccessfulResult(result);
40
- await expect_1.expectLog(result, `dependant`, 'node_modules');
37
+ const { cli, environment } = await suite.setup({ taskName: 'dependant' });
38
+ const result = await cli.exec();
39
+ await (0, expect_1.expectSuccessfulResult)(result, environment);
40
+ await (0, expect_1.expectLog)(result, environment, `dependant`, 'node_modules');
41
41
  });
42
42
  it('should invalid cache on image change', async () => {
43
- await testCache(async (buildFile, workTree) => {
44
- const node = get_node_1.getNode(buildFile, workTree, 'example');
45
- node.image = '15.0.0';
46
- node.mergedTask.image = '15.0.0';
47
- delete workTree.nodes[node.id];
48
- node.id = work_node_id_1.getWorkNodeId(node.cwd, node.mergedTask, node.mergedDeps);
49
- workTree.nodes[node.id] = node;
43
+ await testCache(async (environment) => {
44
+ const buildFile = await (0, read_build_file_1.read)('build.yaml', environment);
45
+ buildFile.tasks['example'].image = '15.0.0';
46
+ await (0, read_build_file_1.write)('build.yaml', buildFile, environment);
50
47
  }, true);
51
48
  });
52
49
  });
@@ -1,42 +1,40 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const path_1 = require("path");
4
- const plan_work_tree_1 = require("../../planner/utils/plan-work-tree");
5
4
  const get_test_suite_1 = require("../get-test-suite");
6
- const execute_1 = require("../../executer/execute");
7
5
  describe('cancellation', () => {
8
- const suite = get_test_suite_1.getTestSuite('cancellation', ['build.yaml']);
6
+ const suite = (0, get_test_suite_1.getTestSuite)('cancellation', ['build.yaml']);
9
7
  afterAll(() => suite.close());
10
8
  async function testAbort(taskName, expectedState) {
11
- const { buildFile, context, executionContext } = await suite.setup();
12
- const workTree = plan_work_tree_1.planWorkTree(buildFile, taskName);
13
- executionContext.events.on((evt) => {
14
- if (evt.newState.type === 'running' && !executionContext.environment.abortCtrl.signal.aborted) {
15
- evt.workTree.nodes[evt.nodeId].status.console.on((log) => {
16
- if (log.message.startsWith('execute cmd ')) {
17
- setTimeout(() => {
18
- executionContext.environment.abortCtrl.abort();
19
- }, 2000);
20
- }
21
- });
9
+ const { cli, environment } = await suite.setup({ taskName });
10
+ const exec = await cli.execWatch({ logMode: 'live' });
11
+ const abortNode = Object.values(exec.state.current.node).find((n) => n.node.name.startsWith('long_'));
12
+ exec.processManager.on((evt) => {
13
+ if (evt.type === 'started' && evt.context.id === abortNode?.node.id) {
14
+ environment.abortCtrl.abort();
22
15
  }
23
16
  });
24
- const result = await execute_1.execute(workTree, executionContext);
17
+ const result = await exec.start();
25
18
  expect(result.success).toBeFalsy();
26
- expect(result.nodes[workTree.rootNode.id].state.type).toEqual(expectedState);
27
- expect(await context.file.exists(path_1.join(buildFile.path, 'test'))).toBeFalsy();
19
+ if (abortNode) {
20
+ expect(result.state.node[abortNode.node.id].type).toEqual(expectedState);
21
+ }
22
+ else {
23
+ expect(abortNode).toBeDefined();
24
+ }
25
+ expect(await environment.file.exists((0, path_1.join)(suite.path, 'test'))).toBeFalsy();
28
26
  }
29
27
  it('should cancel local task with dependencies', async () => {
30
- await testAbort('local_cancel', 'aborted');
28
+ await testAbort('local_cancel', 'canceled');
31
29
  });
32
30
  it('should cancel local task', async () => {
33
- await testAbort('long_running_local', 'aborted');
31
+ await testAbort('long_running_local', 'canceled');
34
32
  });
35
33
  it('should cancel docker task', async () => {
36
- await testAbort('long_running_docker', 'aborted');
34
+ await testAbort('long_running_docker', 'canceled');
37
35
  });
38
36
  it('should cancel docker task with dependencies', async () => {
39
- await testAbort('local_cancel', 'aborted');
37
+ await testAbort('docker_cancel', 'canceled');
40
38
  });
41
39
  });
42
40
  //# sourceMappingURL=cancellation.spec.js.map
@@ -3,41 +3,38 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const path_1 = require("path");
4
4
  const fs_1 = require("fs");
5
5
  const expect_1 = require("../expect");
6
- const plan_work_tree_1 = require("../../planner/utils/plan-work-tree");
7
- const clean_1 = require("../../executer/clean");
8
6
  const get_test_suite_1 = require("../get-test-suite");
9
- const execute_1 = require("../../executer/execute");
10
- const get_local_executor_1 = require("../../executer/get-local-executor");
11
- const execute_docker_1 = require("../../executer/execute-docker");
12
7
  const get_docker_executor_1 = require("../../executer/get-docker-executor");
8
+ const plan_work_volume_1 = require("../../planner/utils/plan-work-volume");
13
9
  describe('clean', () => {
14
- const suite = get_test_suite_1.getTestSuite('clean', ['build.yaml', 'package.json']);
10
+ const suite = (0, get_test_suite_1.getTestSuite)('clean', ['build.yaml', 'package.json']);
15
11
  afterAll(() => suite.close());
16
12
  it('should clean generated outputs locally', async () => {
17
- const { buildFile, context, executionContext } = await suite.setup();
18
- executionContext.executor = get_local_executor_1.getLocalExecutor();
19
- executionContext.cacheMethod = 'none';
20
- const workTree = plan_work_tree_1.planWorkTree(buildFile, 'example');
21
- const result = await execute_1.execute(workTree, executionContext);
22
- await expect_1.expectSuccessfulResult(result);
23
- const outputPath = path_1.join(buildFile.path, 'node_modules');
24
- expect(fs_1.existsSync(outputPath)).toBeTruthy();
25
- await clean_1.clean(workTree.nodes, context, executionContext.executor);
26
- expect(fs_1.existsSync(outputPath)).toBeFalsy();
13
+ const { cli, environment } = await suite.setup({ taskName: 'example' });
14
+ const result = await cli.exec({ cacheDefault: 'none' });
15
+ await (0, expect_1.expectSuccessfulResult)(result, environment);
16
+ const outputPath = (0, path_1.join)(suite.path, 'node_modules');
17
+ expect((0, fs_1.existsSync)(outputPath)).toBeTruthy();
18
+ await cli.clean();
19
+ expect((0, fs_1.existsSync)(outputPath)).toBeFalsy();
27
20
  });
28
21
  it('should clean generated outputs in containers', async () => {
29
- const { buildFile, context, executionContext } = await suite.setup();
30
- executionContext.executor = get_docker_executor_1.getDockerExecutor();
31
- executionContext.cacheMethod = 'none';
32
- const workTree = plan_work_tree_1.planWorkTree(buildFile, 'example');
33
- const result = await execute_1.execute(workTree, executionContext);
34
- await expect_1.expectSuccessfulResult(result);
35
- const outputPath = path_1.join(buildFile.path, 'node_modules');
36
- const volumeName = execute_docker_1.getVolumeName(outputPath);
37
- const docker = execute_docker_1.getDocker();
38
- expect(await get_docker_executor_1.existsVolume(docker, volumeName)).toBeTruthy();
39
- await clean_1.clean(workTree.nodes, context, executionContext.executor);
40
- expect(await get_docker_executor_1.existsVolume(docker, volumeName)).toBeFalsy();
22
+ const { cli, environment } = await suite.setup({ taskName: 'docker:example' });
23
+ const result = await cli.exec({ cacheDefault: 'none' });
24
+ await (0, expect_1.expectSuccessfulResult)(result, environment);
25
+ const outputPath = (0, path_1.join)(suite.path, 'node_modules');
26
+ const volumeName = (0, plan_work_volume_1.getVolumeName)(outputPath);
27
+ expect(await (0, get_docker_executor_1.existsVolume)(environment, volumeName)).toBeTruthy();
28
+ await cli.clean();
29
+ expect(await (0, get_docker_executor_1.existsVolume)(environment, volumeName)).toBeFalsy();
30
+ });
31
+ it('should clean and restore created data in volumes', async () => {
32
+ const { cli, environment } = await suite.setup({ taskName: 'example:service' });
33
+ const result = await cli.exec();
34
+ await (0, expect_1.expectSuccessfulResult)(result, environment);
35
+ await cli.clean({ service: true });
36
+ const resultAfterClean = await cli.exec();
37
+ await (0, expect_1.expectSuccessfulResult)(resultAfterClean, environment);
41
38
  });
42
39
  });
43
40
  //# sourceMappingURL=clean.spec.js.map
@@ -1,18 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const expect_1 = require("../expect");
4
- const plan_work_tree_1 = require("../../planner/utils/plan-work-tree");
5
4
  const get_test_suite_1 = require("../get-test-suite");
6
- const execute_1 = require("../../executer/execute");
7
5
  describe('cmd', () => {
8
- const suite = get_test_suite_1.getTestSuite('cmd', ['build.yaml', 'sub/README.md']);
6
+ const suite = (0, get_test_suite_1.getTestSuite)('cmd', ['build.yaml', 'sub/README.md']);
9
7
  afterAll(() => suite.close());
10
8
  it('should run with path arg', async () => {
11
- const { buildFile, executionContext } = await suite.setup();
12
- const workTree = plan_work_tree_1.planWorkTree(buildFile, 'example');
13
- const result = await execute_1.execute(workTree, executionContext);
14
- await expect_1.expectSuccessfulResult(result);
15
- await expect_1.expectContainsLog(result, `example`, 'README.md');
9
+ const { cli, environment } = await suite.setup({ taskName: 'example' });
10
+ const result = await cli.exec();
11
+ await (0, expect_1.expectSuccessfulResult)(result, environment);
12
+ await (0, expect_1.expectContainsLog)(result, environment, `example`, 'README.md');
16
13
  });
17
14
  });
18
15
  //# sourceMappingURL=cmd.spec.js.map
@@ -1,28 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const expect_1 = require("../expect");
4
- const plan_work_tree_1 = require("../../planner/utils/plan-work-tree");
5
4
  const get_test_suite_1 = require("../get-test-suite");
6
- const execute_1 = require("../../executer/execute");
7
5
  describe('concurrency', () => {
8
- const suite = get_test_suite_1.getTestSuite('concurrency', ['build.yaml']);
6
+ const suite = (0, get_test_suite_1.getTestSuite)('concurrency', ['build.yaml']);
9
7
  afterAll(() => suite.close());
10
8
  it('should run with concurrency lower than total tasks', async () => {
11
- const { buildFile, executionContext } = await suite.setup();
12
- executionContext.workers = 1;
13
- let concurrentRunners = 0;
14
- executionContext.events.on((evt) => {
15
- if (evt.newState.type === 'running') {
16
- concurrentRunners++;
17
- }
18
- else if (evt.newState.type === 'failed' || evt.newState.type === 'completed') {
19
- concurrentRunners--;
20
- }
21
- expect(concurrentRunners).toBeLessThanOrEqual(1);
9
+ const { cli, environment } = await suite.setup({ taskName: 'example' });
10
+ const exec = cli.execWatch({ workers: 1 });
11
+ exec.state.on((state) => {
12
+ const runningNodes = Object.values(state.node).filter((n) => n.type === 'running');
13
+ expect(runningNodes.length).toBeLessThanOrEqual(1);
22
14
  });
23
- const workTree = plan_work_tree_1.planWorkTree(buildFile, 'example');
24
- const result = await execute_1.execute(workTree, executionContext);
25
- await expect_1.expectSuccessfulResult(result);
15
+ const result = await exec.start();
16
+ await (0, expect_1.expectSuccessfulResult)(result, environment);
26
17
  });
27
18
  });
28
19
  //# sourceMappingURL=concurrency.spec.js.map
@@ -1,19 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const expect_1 = require("../expect");
4
- const plan_work_tree_1 = require("../../planner/utils/plan-work-tree");
5
4
  const get_test_suite_1 = require("../get-test-suite");
6
- const execute_1 = require("../../executer/execute");
7
5
  describe('docker', () => {
8
- const suite = get_test_suite_1.getTestSuite('docker', ['build.yaml']);
6
+ const suite = (0, get_test_suite_1.getTestSuite)('docker', ['build.yaml']);
9
7
  afterAll(() => suite.close());
10
8
  it('should pull docker image', async () => {
11
- const { buildFile, executionContext } = await suite.setup();
12
- const workTree = plan_work_tree_1.planWorkTree(buildFile, 'example');
13
- const result = await execute_1.execute(workTree, executionContext);
14
- await expect_1.expectSuccessfulResult(result);
15
- await expect_1.expectLog(result, `example`, '7.19.1');
16
- await expect_1.expectLog(result, `example`, 'v16.6.0');
9
+ const { cli, environment } = await suite.setup({ taskName: 'example' });
10
+ const result = await cli.exec();
11
+ await (0, expect_1.expectSuccessfulResult)(result, environment);
12
+ await (0, expect_1.expectLog)(result, environment, `example`, '7.19.1');
13
+ await (0, expect_1.expectLog)(result, environment, `example`, 'v16.6.0');
17
14
  });
18
15
  });
19
16
  //# sourceMappingURL=docker.spec.js.map