hammerkit 1.5.0-alpha.0 → 1.5.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 (132) hide show
  1. package/Dockerfile +1 -1
  2. package/build.schema.json +338 -161
  3. package/dist/executer/docker-service.js +1 -1
  4. package/dist/executer/environment-mock.js +6 -3
  5. package/dist/executer/event-cache.js +2 -6
  6. package/dist/executer/execute-docker.js +1 -1
  7. package/dist/executer/execute.spec.js +1 -1
  8. package/dist/executer/execution-steps.js +10 -1
  9. package/dist/executer/get-docker-executor.js +34 -7
  10. package/dist/executer/schedule.js +4 -6
  11. package/dist/executer/start-node.js +11 -3
  12. package/dist/executer/watch-node.js +0 -1
  13. package/dist/index.js +5 -2
  14. package/dist/log.js +35 -30
  15. package/dist/logging/grouped-logger.js +2 -2
  16. package/dist/logging/interactive-logger.js +3 -3
  17. package/dist/logging/live-logger.js +1 -1
  18. package/dist/optimizer/get-work-node-cache-stats.js +8 -2
  19. package/dist/optimizer/work-node-cache-description.js +1 -1
  20. package/dist/parser/default-build-file.js +22 -0
  21. package/dist/parser/parse-build-file-references.js +13 -2
  22. package/dist/parser/parse-build-file.js +37 -3
  23. package/dist/planner/utils/parse-work-service-volume.js +2 -0
  24. package/dist/planner/utils/plan-work-dependency.js +5 -8
  25. package/dist/planner/utils/plan-work-node.js +29 -8
  26. package/dist/planner/utils/plan-work-volume.js +7 -1
  27. package/dist/planner/work-node-status.js +2 -1
  28. package/dist/program.js +23 -22
  29. package/dist/testing/example-test-suite.js +17 -6
  30. package/dist/testing/expect.js +5 -0
  31. package/dist/testing/integration/cache.spec.js +3 -3
  32. package/dist/testing/integration/cancellation.spec.js +1 -1
  33. package/dist/testing/integration/clean.spec.js +1 -1
  34. package/dist/testing/integration/cmd.spec.js +1 -1
  35. package/dist/testing/integration/concurrency.spec.js +1 -1
  36. package/dist/testing/integration/docker.spec.js +1 -1
  37. package/dist/testing/integration/env.spec.js +1 -1
  38. package/dist/testing/integration/error.spec.js +1 -1
  39. package/dist/testing/integration/extend.spec.js +2 -2
  40. package/dist/testing/integration/glob.spec.js +1 -1
  41. package/dist/testing/integration/include.spec.js +1 -1
  42. package/dist/testing/integration/invalid.spec.js +1 -1
  43. package/dist/testing/integration/invalid_loop.spec.js +1 -1
  44. package/dist/testing/integration/kubernetes.spec.js +1 -1
  45. package/dist/testing/integration/labels.spec.js +1 -1
  46. package/dist/testing/integration/local.spec.js +1 -1
  47. package/dist/testing/integration/monorepo.spec.js +1 -1
  48. package/dist/testing/integration/multi-line.spec.js +1 -1
  49. package/dist/testing/integration/reference.spec.js +1 -1
  50. package/dist/testing/integration/services.spec.js +7 -1
  51. package/dist/testing/integration/store.spec.js +2 -2
  52. package/dist/testing/integration/unknown.spec.js +1 -1
  53. package/dist/testing/integration/validate.spec.js +1 -1
  54. package/dist/testing/integration/watch-dependency.spec.js +30 -0
  55. package/dist/testing/integration/watch.spec.js +1 -1
  56. package/dist/utils/empty-writable.js +13 -0
  57. package/logs/cache-console.log +0 -0
  58. package/logs/cache-status.log +6 -0
  59. package/logs/cache-stout.log +0 -0
  60. package/logs/cancellation-console.log +0 -0
  61. package/logs/cancellation-status.log +3 -0
  62. package/logs/cancellation-stout.log +3 -0
  63. package/logs/clean-console.log +0 -0
  64. package/logs/clean-status.log +37 -0
  65. package/logs/clean-stout.log +95 -0
  66. package/logs/cmd-console.log +0 -0
  67. package/logs/cmd-status.log +8 -0
  68. package/logs/cmd-stout.log +9 -0
  69. package/logs/concurrency-console.log +0 -0
  70. package/logs/concurrency-status.log +14 -0
  71. package/logs/concurrency-stout.log +88 -0
  72. package/logs/docker-console.log +0 -0
  73. package/logs/docker-status.log +14 -0
  74. package/logs/docker-stout.log +39 -0
  75. package/logs/env-console.log +1 -0
  76. package/logs/env-status.log +1 -0
  77. package/logs/env-stout.log +0 -0
  78. package/logs/error-console.log +0 -0
  79. package/logs/error-status.log +10 -0
  80. package/logs/error-stout.log +36 -0
  81. package/logs/extend-console.log +0 -0
  82. package/logs/extend-status.log +1 -0
  83. package/logs/extend-stout.log +0 -0
  84. package/logs/glob-console.log +28 -0
  85. package/logs/glob-status.log +23 -0
  86. package/logs/glob-stout.log +52 -0
  87. package/logs/hello-world-node-console.log +0 -0
  88. package/logs/hello-world-node-status.log +37 -0
  89. package/logs/hello-world-node-stout.log +41 -0
  90. package/logs/include-console.log +0 -0
  91. package/logs/include-status.log +3 -0
  92. package/logs/include-stout.log +0 -0
  93. package/logs/invalid-console.log +0 -0
  94. package/logs/invalid-status.log +1 -0
  95. package/logs/invalid-stout.log +0 -0
  96. package/logs/invalid_loop-console.log +0 -0
  97. package/logs/invalid_loop-status.log +1 -0
  98. package/logs/invalid_loop-stout.log +11 -0
  99. package/logs/labels-console.log +0 -0
  100. package/logs/labels-status.log +1 -0
  101. package/logs/labels-stout.log +0 -0
  102. package/logs/local-console.log +0 -0
  103. package/logs/local-status.log +7 -0
  104. package/logs/local-stout.log +8 -0
  105. package/logs/monorepo-console.log +0 -0
  106. package/logs/monorepo-status.log +152 -0
  107. package/logs/monorepo-stout.log +2354 -0
  108. package/logs/multi-line-console.log +0 -0
  109. package/logs/multi-line-status.log +1 -0
  110. package/logs/multi-line-stout.log +0 -0
  111. package/logs/reference-console.log +0 -0
  112. package/logs/reference-status.log +5 -0
  113. package/logs/reference-stout.log +0 -0
  114. package/logs/services-console.log +0 -0
  115. package/logs/services-status.log +129 -0
  116. package/logs/services-stout.log +639 -0
  117. package/logs/store-restore-console.log +0 -0
  118. package/logs/store-restore-status.log +40 -0
  119. package/logs/store-restore-stout.log +97 -0
  120. package/logs/unknown-console.log +3 -0
  121. package/logs/unknown-status.log +1 -0
  122. package/logs/unknown-stout.log +0 -0
  123. package/logs/validate-console.log +0 -0
  124. package/logs/validate-status.log +2 -0
  125. package/logs/validate-stout.log +0 -0
  126. package/logs/watch-console.log +0 -0
  127. package/logs/watch-dependency-console.log +0 -0
  128. package/logs/watch-dependency-status.log +176 -0
  129. package/logs/watch-dependency-stout.log +779 -0
  130. package/logs/watch-status.log +100 -0
  131. package/logs/watch-stout.log +349 -0
  132. package/package.json +1 -1
@@ -21,7 +21,7 @@ async function startContainer(status, container) {
21
21
  return new Promise((resolve, reject) => {
22
22
  const handle = setTimeout(() => {
23
23
  status.write('warn', 'start of container is potentially stuck on start');
24
- }, 1000);
24
+ }, 10000);
25
25
  container
26
26
  .start()
27
27
  .then(() => {
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const get_test_suite_1 = require("../testing/get-test-suite");
4
4
  const expect_1 = require("../testing/expect");
5
5
  describe('execute', () => {
6
- const suite = (0, get_test_suite_1.getTestSuite)('hello-world-node', ['build.yaml', 'package.json', 'index.js']);
6
+ const suite = (0, get_test_suite_1.getTestSuite)('hello-world-node', ['.hammerkit.yaml', 'package.json', 'index.js']);
7
7
  afterAll(() => suite.close());
8
8
  it('should restart watching task if once completed', async () => {
9
9
  const { cli, environment } = await suite.setup({ taskName: 'api' });
@@ -19,7 +19,16 @@ exports.pullImage = pullImage;
19
19
  async function prepareVolume(node, environment) {
20
20
  if ((0, work_node_1.isContainerWorkNode)(node) || (0, work_service_1.isContainerWorkService)(node)) {
21
21
  for (const volume of node.volumes) {
22
- await (0, get_docker_executor_1.ensureVolumeExists)(environment, volume.name);
22
+ if (volume.resetOnChange && !volume.inherited) {
23
+ const scopedConsole = environment.status.from(node);
24
+ scopedConsole.write('debug', 'recreate volume');
25
+ await (0, get_docker_executor_1.recreateVolume)(environment, scopedConsole, volume.name);
26
+ }
27
+ else {
28
+ const scopedConsole = environment.status.from(node);
29
+ scopedConsole.write('debug', 'ensure volume exists');
30
+ await (0, get_docker_executor_1.ensureVolumeExists)(environment, scopedConsole, volume.name);
31
+ }
23
32
  }
24
33
  }
25
34
  }
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ensureVolumeExists = exports.existsVolume = void 0;
3
+ exports.recreateVolume = exports.removeVolume = exports.createVolume = exports.ensureVolumeExists = exports.existsVolume = void 0;
4
+ const log_1 = require("../log");
4
5
  async function existsVolume(environment, volumeName) {
5
6
  try {
6
7
  const volume = await environment.docker.getVolume(volumeName);
@@ -11,15 +12,41 @@ async function existsVolume(environment, volumeName) {
11
12
  }
12
13
  }
13
14
  exports.existsVolume = existsVolume;
14
- async function ensureVolumeExists(environment, volumeName) {
15
+ async function ensureVolumeExists(environment, scopedConsole, volumeName) {
15
16
  const volumeExists = await existsVolume(environment, volumeName);
16
17
  if (!volumeExists) {
17
- await environment.docker.createVolume({
18
- Name: volumeName,
19
- Driver: 'local',
20
- Labels: { app: 'hammerkit' },
21
- });
18
+ await createVolume(environment, scopedConsole, volumeName);
19
+ }
20
+ else {
21
+ scopedConsole.write('debug', 'volume exists ' + volumeName);
22
22
  }
23
23
  }
24
24
  exports.ensureVolumeExists = ensureVolumeExists;
25
+ async function createVolume(environment, scopedConsole, volumeName) {
26
+ scopedConsole.write('debug', 'create volume ' + volumeName);
27
+ await environment.docker.createVolume({
28
+ Name: volumeName,
29
+ Driver: 'local',
30
+ Labels: { app: 'hammerkit' },
31
+ });
32
+ }
33
+ exports.createVolume = createVolume;
34
+ async function removeVolume(environment, scopedConsole, volumeName) {
35
+ try {
36
+ const volume = await environment.docker.getVolume(volumeName);
37
+ scopedConsole.write('debug', 'remove volume ' + volumeName);
38
+ await volume.remove({ force: true });
39
+ return true;
40
+ }
41
+ catch (e) {
42
+ scopedConsole.write('warn', `removing volume ${volumeName} failed: ${(0, log_1.getErrorMessage)(e)}`);
43
+ return false;
44
+ }
45
+ }
46
+ exports.removeVolume = removeVolume;
47
+ async function recreateVolume(environment, scopedConsole, volumeName) {
48
+ await removeVolume(environment, scopedConsole, volumeName);
49
+ await createVolume(environment, scopedConsole, volumeName);
50
+ }
51
+ exports.recreateVolume = recreateVolume;
25
52
  //# sourceMappingURL=get-docker-executor.js.map
@@ -31,9 +31,8 @@ async function schedule(processManager, state, environment) {
31
31
  type: 'task',
32
32
  name: nodeState.node.name,
33
33
  id: nodeState.node.id + '-cache',
34
- }, async () => {
35
- // TODO abort improvement
36
- await (0, start_node_1.startNode)(nodeState, state, environment);
34
+ }, async (abort) => {
35
+ await (0, start_node_1.startNode)(nodeState, state, environment, abort.signal);
37
36
  });
38
37
  }
39
38
  else if (nodeState.type === 'ready') {
@@ -65,9 +64,8 @@ async function schedule(processManager, state, environment) {
65
64
  type: 'service',
66
65
  name: pendingNeed.service.name,
67
66
  id: pendingNeed.service.id + '-cache',
68
- }, async () => {
69
- // TODO abort improvement
70
- await (0, start_node_1.startService)(pendingNeed.service, state, environment);
67
+ }, async (abort) => {
68
+ await (0, start_node_1.startService)(pendingNeed.service, state, environment, abort.signal);
71
69
  });
72
70
  }
73
71
  continue;
@@ -5,9 +5,12 @@ const enqueue_next_1 = require("./scheduler/enqueue-next");
5
5
  const states_1 = require("./states");
6
6
  const work_service_1 = require("../planner/work-service");
7
7
  const get_work_node_cache_stats_1 = require("../optimizer/get-work-node-cache-stats");
8
- async function startNode(node, state, environment) {
8
+ async function startNode(node, state, environment, abortSignal) {
9
9
  const cacheState = await (0, enqueue_next_1.checkCacheState)(node.node, state.current.cacheMethod, environment);
10
10
  const currentState = state.current.node[node.node.id];
11
+ if (abortSignal.aborted) {
12
+ return;
13
+ }
11
14
  if (!!currentState.stateKey && currentState.stateKey !== cacheState.stateKey) {
12
15
  const status = environment.status.task(node.node);
13
16
  status.write('debug', `cache check for ${node.node.name} no longer valid, skipping result`);
@@ -32,12 +35,17 @@ async function startNode(node, state, environment) {
32
35
  }
33
36
  }
34
37
  exports.startNode = startNode;
35
- async function startService(service, state, environment) {
38
+ async function startService(service, state, environment, abortSignal) {
39
+ const currentStats = await (0, get_work_node_cache_stats_1.getServiceNodeCacheStats)(service, environment);
40
+ const stateKey = (0, get_work_node_cache_stats_1.getStateKey)(currentStats, state.current.cacheMethod);
41
+ if (abortSignal.aborted) {
42
+ return;
43
+ }
36
44
  if (!(0, work_service_1.isContainerWorkService)(service)) {
37
45
  state.patchService({
38
46
  type: 'ready',
39
47
  service,
40
- stateKey: '', // TODO statekey from kube config
48
+ stateKey,
41
49
  });
42
50
  return;
43
51
  }
@@ -26,7 +26,6 @@ function watchNode(node, state, processManager, environment) {
26
26
  node,
27
27
  stateKey: currentFileState.stateKey,
28
28
  });
29
- // TODO set dependants as pending
30
29
  }, 100);
31
30
  const fileWatchers = [];
32
31
  const sources = [];
package/dist/index.js CHANGED
@@ -6,6 +6,7 @@ const log_1 = require("./log");
6
6
  const get_file_context_1 = require("./file/get-file-context");
7
7
  const work_node_status_1 = require("./planner/work-node-status");
8
8
  const execute_docker_1 = require("./executer/execute-docker");
9
+ const empty_writable_1 = require("./utils/empty-writable");
9
10
  const abortCtrl = new AbortController();
10
11
  process.on('SIGINT', function () {
11
12
  abortCtrl.abort();
@@ -15,9 +16,11 @@ process.on('SIGINT', function () {
15
16
  abortCtrl,
16
17
  processEnvs: process.env,
17
18
  file: (0, get_file_context_1.getFileContext)(process.cwd()),
18
- console: (0, log_1.consoleContext)(),
19
- status: (0, work_node_status_1.statusConsole)(),
19
+ console: (0, log_1.consoleContext)(process.stdout),
20
+ status: (0, work_node_status_1.statusConsole)((0, empty_writable_1.emptyWritable)()),
20
21
  docker: (0, execute_docker_1.getContainerCli)(),
22
+ stdout: process.stdout,
23
+ stdoutColumns: process.stdout.columns,
21
24
  }, process.argv).then(({ program, args }) => {
22
25
  return program.parseAsync(args);
23
26
  });
package/dist/log.js CHANGED
@@ -40,24 +40,24 @@ function getErrorMessage(e) {
40
40
  }
41
41
  }
42
42
  exports.getErrorMessage = getErrorMessage;
43
- function consoleContext() {
43
+ function consoleContext(stream) {
44
44
  return {
45
45
  debug(message) {
46
- process.stdout.write(`${formatDate(new Date())} ${getType('cli')} ${getLogLevel('debug')}: ${message}\n`);
46
+ stream.write(`${formatDate(new Date())} ${getType('cli')} ${getLogLevel('debug')}: ${message}\n`);
47
47
  },
48
48
  error(message) {
49
- process.stdout.write(`${formatDate(new Date())} ${getType('cli')} ${getLogLevel('error')}: ${message}\n`);
49
+ stream.write(`${formatDate(new Date())} ${getType('cli')} ${getLogLevel('error')}: ${message}\n`);
50
50
  },
51
51
  info(message) {
52
- process.stdout.write(`${formatDate(new Date())} ${getType('cli')} ${getLogLevel('info')}: ${message}\n`);
52
+ stream.write(`${formatDate(new Date())} ${getType('cli')} ${getLogLevel('info')}: ${message}\n`);
53
53
  },
54
54
  warn(message) {
55
- process.stdout.write(`${formatDate(new Date())} ${getType('cli')} ${getLogLevel('warn')}: ${message}\n`);
55
+ stream.write(`${formatDate(new Date())} ${getType('cli')} ${getLogLevel('warn')}: ${message}\n`);
56
56
  },
57
57
  };
58
58
  }
59
59
  exports.consoleContext = consoleContext;
60
- exports.isVerbose = process.argv.some((a) => a === '--verbose');
60
+ exports.isVerbose = process.argv.some((a) => a === '--verbose') || process.env['VERBOSE'] === 'true';
61
61
  const typeLength = ['service', 'task', 'cli']
62
62
  .map((s) => s.length)
63
63
  .reduce((max, current) => (max > current ? max : current), 0);
@@ -69,14 +69,14 @@ async function printWorkTreeResult(schedulerState, env) {
69
69
  const maxNodeNameLength = getNodeNameLengthForSchedulerState(schedulerState);
70
70
  for (const log of env.status.read()) {
71
71
  if (exports.isVerbose || (log.type === 'status' && log.level === 'error')) {
72
- process.stdout.write(`${formatDate(log.date)} ${getType(log.context.type)} ${getNodeName(log.context.name, maxNodeNameLength)} - ${colors_1.default.white(log.message)}\n`);
72
+ env.stdout.write(`${formatDate(log.date)} ${getType(log.context.type)} ${getNodeName(log.context.name, maxNodeNameLength)} - ${colors_1.default.white(log.message)}\n`);
73
73
  }
74
74
  }
75
75
  for (const state of (0, plan_work_nodes_1.iterateWorkServices)(schedulerState.service)) {
76
76
  if (state.type === 'end' && state.reason === 'crash') {
77
77
  const message = `${getType('service')} ${getNodeName(state.service.name, maxNodeNameLength)}`;
78
78
  for (const log of env.status.service(state.service).logs()) {
79
- process.stdout.write(`${formatDate(log.date)} ${message} - ${log.console}: ${log.message}\n`);
79
+ env.stdout.write(`${formatDate(log.date)} ${message} - ${log.console}: ${log.message}\n`);
80
80
  }
81
81
  }
82
82
  }
@@ -84,7 +84,7 @@ async function printWorkTreeResult(schedulerState, env) {
84
84
  if (state.type === 'error' || state.type === 'crash') {
85
85
  const message = `${getType('task')} ${getNodeName(state.node.name, maxNodeNameLength)}`;
86
86
  for (const log of env.status.task(state.node).logs()) {
87
- process.stdout.write(`${formatDate(log.date)} ${message} - ${log.console}: ${log.message}\n`);
87
+ env.stdout.write(`${formatDate(log.date)} ${message} - ${log.console}: ${log.message}\n`);
88
88
  }
89
89
  }
90
90
  }
@@ -94,7 +94,7 @@ async function printWorkTreeResult(schedulerState, env) {
94
94
  if (state.reason === 'crash') {
95
95
  message += ` crashed`;
96
96
  }
97
- process.stdout.write(`${message}\n`);
97
+ env.stdout.write(`${message}\n`);
98
98
  }
99
99
  }
100
100
  for (const state of (0, plan_work_nodes_1.iterateWorkNodes)(schedulerState.node)) {
@@ -111,7 +111,7 @@ async function printWorkTreeResult(schedulerState, env) {
111
111
  if (state.type === 'error') {
112
112
  message += ` with message ${state.errorMessage}`;
113
113
  }
114
- process.stdout.write(`${message}\n`);
114
+ env.stdout.write(`${message}\n`);
115
115
  }
116
116
  }
117
117
  exports.printWorkTreeResult = printWorkTreeResult;
@@ -157,16 +157,16 @@ function getNodeNameLengthForSchedulerState(schedulerState) {
157
157
  return getNodeNameLength(Names);
158
158
  }
159
159
  exports.getNodeNameLengthForSchedulerState = getNodeNameLengthForSchedulerState;
160
- function printProperty(name, value) {
161
- process.stdout.write(` ${colors_1.default.grey(`${name}:`)} ${value}\n`);
160
+ function printProperty(env, name, value) {
161
+ env.stdout.write(` ${colors_1.default.grey(`${name}:`)} ${value}\n`);
162
162
  }
163
163
  exports.printProperty = printProperty;
164
- function printItem(item) {
165
- process.stdout.write(`• ${item.name}${item.description ? `: ${colors_1.default.white(item.description)}` : ''}\n`);
164
+ function printItem(env, item) {
165
+ env.stdout.write(`• ${item.name}${item.description ? `: ${colors_1.default.white(item.description)}` : ''}\n`);
166
166
  }
167
167
  exports.printItem = printItem;
168
- function printTitle(name) {
169
- process.stdout.write(`${colors_1.default.bgWhite(name + ':\n')}`);
168
+ function printTitle(env, name) {
169
+ env.stdout.write(`${colors_1.default.bgWhite(name + ':\n')}`);
170
170
  }
171
171
  exports.printTitle = printTitle;
172
172
  function getNodeNameLength(names) {
@@ -195,13 +195,18 @@ function getNodeName(name, maxNodeNameLength) {
195
195
  return colors_1.default.white(name) + ' '.repeat(Math.max(0, maxNodeNameLength - name.length));
196
196
  }
197
197
  exports.getNodeName = getNodeName;
198
- function writeNodeLogToConsole(log, maxNodeNameLength) {
198
+ function writeNodeLogToConsole(env, log, maxNodeNameLength) {
199
+ if (log.type === 'status') {
200
+ if (log.level === 'debug' && !exports.isVerbose) {
201
+ return;
202
+ }
203
+ }
199
204
  const content = log.type === 'console'
200
205
  ? log.console === 'stdout'
201
206
  ? colors_1.default.white(log.message)
202
207
  : colors_1.default.red(log.message)
203
208
  : `${getLogLevel(log.level)} - ${log.message}`;
204
- process.stdout.write(`${formatDate(log.date)} ${colors_1.default.grey(log.context.type + ':')} ${getNodeName(log.context.name, maxNodeNameLength)} - ${log.date.toLocaleTimeString()} - ${content}\n`);
209
+ env.stdout.write(`${formatDate(log.date)} ${colors_1.default.grey(log.context.type + ':')} ${getNodeName(log.context.name, maxNodeNameLength)} - ${log.date.toLocaleTimeString()} - ${content}\n`);
205
210
  }
206
211
  exports.writeNodeLogToConsole = writeNodeLogToConsole;
207
212
  function formatDate(date) {
@@ -218,7 +223,7 @@ function formatDate(date) {
218
223
  }
219
224
  exports.formatDate = formatDate;
220
225
  function writeWorkTreeStatus(schedulerState, env, ticker) {
221
- (0, readline_1.clearScreenDown)(process.stdout);
226
+ (0, readline_1.clearScreenDown)(env.stdout);
222
227
  const maxNodeNameLength = getNodeNameLengthForSchedulerState(schedulerState);
223
228
  let count = 0;
224
229
  for (const state of (0, plan_work_nodes_1.iterateWorkServices)(schedulerState.service)) {
@@ -227,7 +232,7 @@ function writeWorkTreeStatus(schedulerState, env, ticker) {
227
232
  if (currentMessage) {
228
233
  message += ` ${currentMessage.message}`;
229
234
  }
230
- count += printWithTruncate(message);
235
+ count += printWithTruncate(env, message);
231
236
  }
232
237
  for (const state of (0, plan_work_nodes_1.iterateWorkNodes)(schedulerState.node)) {
233
238
  let message = `${getType('task')} ${getNodeName(state.node.name, maxNodeNameLength)} - ${getStateText(state)}`;
@@ -266,9 +271,9 @@ function writeWorkTreeStatus(schedulerState, env, ticker) {
266
271
  else if (state.type === 'error') {
267
272
  message += ` ${state.errorMessage}`;
268
273
  }
269
- count += printWithTruncate(message);
274
+ count += printWithTruncate(env, message);
270
275
  }
271
- (0, readline_1.moveCursor)(process.stdout, 0, -1 * count);
276
+ (0, readline_1.moveCursor)(env.stdout, 0, -1 * count);
272
277
  }
273
278
  exports.writeWorkTreeStatus = writeWorkTreeStatus;
274
279
  function countChar(message, char) {
@@ -280,24 +285,24 @@ function countChar(message, char) {
280
285
  }
281
286
  return result;
282
287
  }
283
- function printWithTruncate(message) {
288
+ function printWithTruncate(env, message) {
284
289
  let lineCount = 0;
285
290
  let index = 0;
286
291
  do {
287
292
  const newLineCount = countChar(message, '\n');
288
- process.stdout.write(`${message.substr(index, process.stdout.columns)}\n`);
289
- index += process.stdout.columns;
293
+ env.stdout.write(`${message.substr(index, env.stdoutColumns)}\n`);
294
+ index += env.stdoutColumns;
290
295
  lineCount++;
291
296
  lineCount += newLineCount;
292
297
  } while (index < message.length);
293
298
  return lineCount;
294
299
  }
295
- function hideCursor() {
296
- process.stdout.write('\x1B[?25l');
300
+ function hideCursor(env) {
301
+ env.stdout.write('\x1B[?25l');
297
302
  }
298
303
  exports.hideCursor = hideCursor;
299
- function showCursor() {
300
- process.stdout.write('\x1B[?25h');
304
+ function showCursor(env) {
305
+ env.stdout.write('\x1B[?25h');
301
306
  }
302
307
  exports.showCursor = showCursor;
303
308
  //# sourceMappingURL=log.js.map
@@ -15,7 +15,7 @@ function groupedLogger(state, env) {
15
15
  if (node.type === 'crash' || node.type === 'error' || node.type === 'completed') {
16
16
  completedNodes.push(node.node.id);
17
17
  for (const log of env.status.task(node.node).read()) {
18
- (0, log_1.writeNodeLogToConsole)(log, maxNodeNameLength);
18
+ (0, log_1.writeNodeLogToConsole)(env, log, maxNodeNameLength);
19
19
  }
20
20
  }
21
21
  }
@@ -26,7 +26,7 @@ function groupedLogger(state, env) {
26
26
  if (service.type === 'end') {
27
27
  completedServices.push(service.service.id);
28
28
  for (const log of env.status.service(service.service).read()) {
29
- (0, log_1.writeNodeLogToConsole)(log, maxNodeNameLength);
29
+ (0, log_1.writeNodeLogToConsole)(env, log, maxNodeNameLength);
30
30
  }
31
31
  }
32
32
  }
@@ -16,7 +16,7 @@ function interactiveLogger(state, env) {
16
16
  setTimeout(tickerFn, 100);
17
17
  }
18
18
  };
19
- (0, log_1.hideCursor)();
19
+ (0, log_1.hideCursor)(env);
20
20
  tickerFn();
21
21
  state.on((currentState) => {
22
22
  (0, log_1.writeWorkTreeStatus)(currentState, env, count);
@@ -24,9 +24,9 @@ function interactiveLogger(state, env) {
24
24
  return {
25
25
  async complete(evt, env) {
26
26
  running = false;
27
- (0, readline_1.clearScreenDown)(process.stdout);
27
+ (0, readline_1.clearScreenDown)(env.stdout);
28
28
  await (0, log_1.printWorkTreeResult)(evt.state, env);
29
- (0, log_1.showCursor)();
29
+ (0, log_1.showCursor)(env);
30
30
  },
31
31
  };
32
32
  }
@@ -5,7 +5,7 @@ const log_1 = require("../log");
5
5
  function liveLogger(state, env) {
6
6
  const maxNodeNameLength = (0, log_1.getNodeNameLengthForWorkTree)(state.current.node, state.current.service);
7
7
  env.status.on((log) => {
8
- (0, log_1.writeNodeLogToConsole)(log, maxNodeNameLength);
8
+ (0, log_1.writeNodeLogToConsole)(env, log, maxNodeNameLength);
9
9
  });
10
10
  return {
11
11
  async complete(evt, env) {
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getStateKey = exports.getCacheState = exports.getWorkNodeCacheStats = exports.getServiceNodeCacheStats = void 0;
4
4
  const calculate_checksum_1 = require("./calculate-checksum");
5
5
  const path_1 = require("path");
6
+ const work_service_1 = require("../planner/work-service");
6
7
  const crypto_1 = require("crypto");
7
8
  async function addWorkNodeCacheStats(result, cwd, path, matcher, context) {
8
9
  const exists = await context.file.exists(path);
@@ -47,8 +48,13 @@ async function getServiceNodeCacheStats(cache, environment) {
47
48
  const result = {
48
49
  files: {},
49
50
  };
50
- for (const mount of cache.mounts) {
51
- await addWorkServiceCacheStats(result, mount.localPath, environment);
51
+ if ((0, work_service_1.isContainerWorkService)(cache)) {
52
+ for (const mount of cache.mounts) {
53
+ await addWorkServiceCacheStats(result, mount.localPath, environment);
54
+ }
55
+ }
56
+ else {
57
+ await addWorkServiceCacheStats(result, cache.kubeconfig, environment);
52
58
  }
53
59
  return result;
54
60
  }
@@ -7,7 +7,7 @@ function getWorkNodeCacheDescription(task) {
7
7
  shell: task.shell ?? undefined,
8
8
  image: task.image ?? undefined,
9
9
  platform: task.image ? 'container' : (0, os_1.platform)(),
10
- generates: task.generates.sort() ?? undefined,
10
+ generates: task.generates.map((g) => g.path).sort() ?? undefined,
11
11
  src: task.src.map((s) => s.relativePath).sort() ?? undefined,
12
12
  deps: task.deps.map((d) => d.name).sort() ?? undefined,
13
13
  envs: Object.keys(task.envs)
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getDefaultBuildFilename = void 0;
4
+ const path_1 = require("path");
5
+ async function getDefaultBuildFilename(folder, env) {
6
+ const fileNames = ['.hammerkit.yaml', '.hammerkit.yml', 'build.yaml'];
7
+ const existingFiles = [];
8
+ for (const fileName of fileNames) {
9
+ if (await env.file.exists((0, path_1.join)(folder, fileName))) {
10
+ existingFiles.push(fileName);
11
+ }
12
+ }
13
+ if (existingFiles.length > 1) {
14
+ env.console.warn(`multiple hammerkit files ${existingFiles.join(', ')} in ${folder}`);
15
+ }
16
+ if (existingFiles.length > 0) {
17
+ return existingFiles[0];
18
+ }
19
+ return fileNames[0];
20
+ }
21
+ exports.getDefaultBuildFilename = getDefaultBuildFilename;
22
+ //# sourceMappingURL=default-build-file.js.map
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseBuildFileReferences = void 0;
4
4
  const path_1 = require("path");
5
5
  const read_build_file_1 = require("./read-build-file");
6
+ const default_build_file_1 = require("./default-build-file");
6
7
  async function parseBuildFileReferences(type, fileName, files, refs, context) {
7
8
  if (!refs) {
8
9
  return {};
@@ -14,9 +15,19 @@ async function parseBuildFileReferences(type, fileName, files, refs, context) {
14
15
  for (const [key, value] of Object.entries(refs || {})) {
15
16
  const referenceFileName = (0, path_1.join)((0, path_1.dirname)(fileName), value);
16
17
  if (!(await context.file.exists(referenceFileName))) {
17
- throw new Error(`${fileName} ${type} ${key} not found`);
18
+ throw new Error(`${fileName} ${type} ${key} ${referenceFileName} not found`);
19
+ }
20
+ const stats = await context.file.stats(referenceFileName);
21
+ if (stats.type === 'directory') {
22
+ const defaultReferenceFileName = (0, path_1.join)(referenceFileName, await (0, default_build_file_1.getDefaultBuildFilename)(referenceFileName, context));
23
+ if (!(await context.file.exists(defaultReferenceFileName))) {
24
+ throw new Error(`${fileName} ${type} ${key} ${defaultReferenceFileName} not found in ${referenceFileName}`);
25
+ }
26
+ result[key] = await (0, read_build_file_1.readBuildFile)(defaultReferenceFileName, files, context);
27
+ }
28
+ else {
29
+ result[key] = await (0, read_build_file_1.readBuildFile)(referenceFileName, files, context);
18
30
  }
19
- result[key] = await (0, read_build_file_1.readBuildFile)(referenceFileName, files, context);
20
31
  }
21
32
  return result;
22
33
  }
@@ -10,9 +10,22 @@ const parse_build_file_task_source_1 = require("./parse-build-file-task-source")
10
10
  const parse_build_file_task_command_1 = require("./parse-build-file-task-command");
11
11
  const parse_build_file_services_1 = require("./parse-build-file-services");
12
12
  const parse_string_map_1 = require("./parse-string-map");
13
+ const parse_context_1 = require("./parse-context");
13
14
  const parse_string_1 = require("./parse-string");
14
15
  const parse_boolean_1 = require("./parse-boolean");
15
- const validTaskKeys = ['envs', 'src', 'needs', 'deps', 'generates', 'labels', 'description', 'extend', 'cmds', 'watch'];
16
+ const validTaskKeys = [
17
+ 'envs',
18
+ 'src',
19
+ 'needs',
20
+ 'deps',
21
+ 'generates',
22
+ 'labels',
23
+ 'description',
24
+ 'extend',
25
+ 'cmds',
26
+ 'continuous',
27
+ 'cache',
28
+ ];
16
29
  const validDockerTaskKeys = ['image', 'mounts', 'ports', 'shell', ...validTaskKeys];
17
30
  async function parseBuildFile(fileName, files, input, context) {
18
31
  const result = {
@@ -62,7 +75,7 @@ async function parseBuildFile(fileName, files, input, context) {
62
75
  mounts: (0, parse_string_array_1.parseStringArray)(ctx, 'mounts', value.mounts),
63
76
  src: (0, parse_build_file_task_source_1.parseBuildFileTaskSource)(ctx, value.src, context),
64
77
  deps: (0, parse_string_array_1.parseStringArray)(ctx, 'deps', value.deps),
65
- generates: (0, parse_string_array_1.parseStringArray)(ctx, 'generates', value.generates),
78
+ generates: parseGenerateArray(ctx, 'generates', value.generates),
66
79
  description: (0, parse_string_1.parseString)(ctx, 'description', value.description, true)?.trim() ?? null,
67
80
  labels: (0, parse_string_map_1.parseStringMap)(ctx, 'labels', value.labels),
68
81
  image: value.image || null,
@@ -79,7 +92,7 @@ async function parseBuildFile(fileName, files, input, context) {
79
92
  return map;
80
93
  }, {}),
81
94
  platform: null,
82
- cache: value.caching || null,
95
+ cache: value.cache || null,
83
96
  };
84
97
  if (Object.keys(result.tasks[key].unknownProps).length > 0) {
85
98
  context.console.warn(`unknown props ${Object.keys(result.tasks[key].unknownProps)} for ${key} in ${fileName}`);
@@ -88,4 +101,25 @@ async function parseBuildFile(fileName, files, input, context) {
88
101
  return result;
89
102
  }
90
103
  exports.parseBuildFile = parseBuildFile;
104
+ function parseGenerateArray(ctx, valueName, value) {
105
+ if (!value) {
106
+ return null;
107
+ }
108
+ if (value instanceof Array) {
109
+ return value.map((v, i) => {
110
+ if (typeof v === 'string') {
111
+ return v;
112
+ }
113
+ else {
114
+ return {
115
+ path: (0, parse_string_1.parseString)(ctx, `generate[${i}].path`, v.path, false),
116
+ resetOnChange: (0, parse_boolean_1.parseBoolean)(ctx, `generate[${i}].resetOnChange`, v.resetOnChange, true) || false,
117
+ };
118
+ }
119
+ });
120
+ }
121
+ else {
122
+ throw new Error(`${(0, parse_context_1.parseContextDescription)(ctx)} ${valueName} needs to be a string array`);
123
+ }
124
+ }
91
125
  //# sourceMappingURL=parse-build-file.js.map
@@ -15,7 +15,9 @@ exports.parseWorkServiceVolume = parseWorkServiceVolume;
15
15
  function parseVolume(cwd, name, containerPath) {
16
16
  return {
17
17
  name,
18
+ resetOnChange: false,
18
19
  containerPath: (0, normalize_path_1.normalizePath)(cwd, cwd, containerPath),
20
+ inherited: false,
19
21
  };
20
22
  }
21
23
  //# sourceMappingURL=parse-work-service-volume.js.map
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.planWorkDependency = void 0;
4
4
  const work_node_1 = require("../work-node");
5
- const plan_work_volume_1 = require("./plan-work-volume");
6
5
  function planWorkDependency(deps, node) {
7
6
  for (const depNode of deps) {
8
7
  if (node.deps.some((d) => d.id === depNode.id)) {
@@ -20,14 +19,12 @@ function planWorkDependency(deps, node) {
20
19
  }
21
20
  }
22
21
  }
23
- for (const generate of depNode.generates) {
24
- if (!node.generates.some((g) => g.path === generate.path)) {
25
- node.generates.push({ path: generate.path, inherited: true });
26
- if ((0, work_node_1.isContainerWorkNode)(node)) {
27
- const name = (0, plan_work_volume_1.getVolumeName)(generate.path);
22
+ if ((0, work_node_1.isContainerWorkNode)(depNode) && (0, work_node_1.isContainerWorkNode)(node)) {
23
+ for (const volume of depNode.volumes) {
24
+ if (!node.volumes.some((v) => v.name === volume.name)) {
28
25
  node.volumes.push({
29
- name,
30
- containerPath: generate.path,
26
+ ...volume,
27
+ inherited: true,
31
28
  });
32
29
  }
33
30
  }