hammerkit 1.5.0-alpha.1 → 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 (131) 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 +30 -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 +25 -3
  23. package/dist/planner/utils/parse-work-service-volume.js +2 -0
  24. package/dist/planner/utils/plan-work-dependency.js +4 -1
  25. package/dist/planner/utils/plan-work-node.js +27 -6
  26. package/dist/planner/utils/plan-work-volume.js +2 -0
  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/integration/cache.spec.js +3 -3
  31. package/dist/testing/integration/cancellation.spec.js +1 -1
  32. package/dist/testing/integration/clean.spec.js +1 -1
  33. package/dist/testing/integration/cmd.spec.js +1 -1
  34. package/dist/testing/integration/concurrency.spec.js +1 -1
  35. package/dist/testing/integration/docker.spec.js +1 -1
  36. package/dist/testing/integration/env.spec.js +1 -1
  37. package/dist/testing/integration/error.spec.js +1 -1
  38. package/dist/testing/integration/extend.spec.js +2 -2
  39. package/dist/testing/integration/glob.spec.js +1 -1
  40. package/dist/testing/integration/include.spec.js +1 -1
  41. package/dist/testing/integration/invalid.spec.js +1 -1
  42. package/dist/testing/integration/invalid_loop.spec.js +1 -1
  43. package/dist/testing/integration/kubernetes.spec.js +1 -1
  44. package/dist/testing/integration/labels.spec.js +1 -1
  45. package/dist/testing/integration/local.spec.js +1 -1
  46. package/dist/testing/integration/monorepo.spec.js +1 -1
  47. package/dist/testing/integration/multi-line.spec.js +1 -1
  48. package/dist/testing/integration/reference.spec.js +1 -1
  49. package/dist/testing/integration/services.spec.js +7 -1
  50. package/dist/testing/integration/store.spec.js +2 -2
  51. package/dist/testing/integration/unknown.spec.js +1 -1
  52. package/dist/testing/integration/validate.spec.js +1 -1
  53. package/dist/testing/integration/watch-dependency.spec.js +30 -0
  54. package/dist/testing/integration/watch.spec.js +1 -1
  55. package/dist/utils/empty-writable.js +13 -0
  56. package/logs/cache-console.log +0 -0
  57. package/logs/cache-status.log +6 -0
  58. package/logs/cache-stout.log +0 -0
  59. package/logs/cancellation-console.log +0 -0
  60. package/logs/cancellation-status.log +3 -0
  61. package/logs/cancellation-stout.log +3 -0
  62. package/logs/clean-console.log +0 -0
  63. package/logs/clean-status.log +37 -0
  64. package/logs/clean-stout.log +95 -0
  65. package/logs/cmd-console.log +0 -0
  66. package/logs/cmd-status.log +8 -0
  67. package/logs/cmd-stout.log +9 -0
  68. package/logs/concurrency-console.log +0 -0
  69. package/logs/concurrency-status.log +14 -0
  70. package/logs/concurrency-stout.log +88 -0
  71. package/logs/docker-console.log +0 -0
  72. package/logs/docker-status.log +14 -0
  73. package/logs/docker-stout.log +39 -0
  74. package/logs/env-console.log +1 -0
  75. package/logs/env-status.log +1 -0
  76. package/logs/env-stout.log +0 -0
  77. package/logs/error-console.log +0 -0
  78. package/logs/error-status.log +10 -0
  79. package/logs/error-stout.log +36 -0
  80. package/logs/extend-console.log +0 -0
  81. package/logs/extend-status.log +1 -0
  82. package/logs/extend-stout.log +0 -0
  83. package/logs/glob-console.log +28 -0
  84. package/logs/glob-status.log +23 -0
  85. package/logs/glob-stout.log +52 -0
  86. package/logs/hello-world-node-console.log +0 -0
  87. package/logs/hello-world-node-status.log +37 -0
  88. package/logs/hello-world-node-stout.log +41 -0
  89. package/logs/include-console.log +0 -0
  90. package/logs/include-status.log +3 -0
  91. package/logs/include-stout.log +0 -0
  92. package/logs/invalid-console.log +0 -0
  93. package/logs/invalid-status.log +1 -0
  94. package/logs/invalid-stout.log +0 -0
  95. package/logs/invalid_loop-console.log +0 -0
  96. package/logs/invalid_loop-status.log +1 -0
  97. package/logs/invalid_loop-stout.log +11 -0
  98. package/logs/labels-console.log +0 -0
  99. package/logs/labels-status.log +1 -0
  100. package/logs/labels-stout.log +0 -0
  101. package/logs/local-console.log +0 -0
  102. package/logs/local-status.log +7 -0
  103. package/logs/local-stout.log +8 -0
  104. package/logs/monorepo-console.log +0 -0
  105. package/logs/monorepo-status.log +152 -0
  106. package/logs/monorepo-stout.log +2354 -0
  107. package/logs/multi-line-console.log +0 -0
  108. package/logs/multi-line-status.log +1 -0
  109. package/logs/multi-line-stout.log +0 -0
  110. package/logs/reference-console.log +0 -0
  111. package/logs/reference-status.log +5 -0
  112. package/logs/reference-stout.log +0 -0
  113. package/logs/services-console.log +0 -0
  114. package/logs/services-status.log +129 -0
  115. package/logs/services-stout.log +639 -0
  116. package/logs/store-restore-console.log +0 -0
  117. package/logs/store-restore-status.log +40 -0
  118. package/logs/store-restore-stout.log +97 -0
  119. package/logs/unknown-console.log +3 -0
  120. package/logs/unknown-status.log +1 -0
  121. package/logs/unknown-stout.log +0 -0
  122. package/logs/validate-console.log +0 -0
  123. package/logs/validate-status.log +2 -0
  124. package/logs/validate-stout.log +0 -0
  125. package/logs/watch-console.log +0 -0
  126. package/logs/watch-dependency-console.log +0 -0
  127. package/logs/watch-dependency-status.log +176 -0
  128. package/logs/watch-dependency-stout.log +779 -0
  129. package/logs/watch-status.log +100 -0
  130. package/logs/watch-stout.log +349 -0
  131. 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
- }, 3000);
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,7 +195,7 @@ 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
199
  if (log.type === 'status') {
200
200
  if (log.level === 'debug' && !exports.isVerbose) {
201
201
  return;
@@ -206,7 +206,7 @@ function writeNodeLogToConsole(log, maxNodeNameLength) {
206
206
  ? colors_1.default.white(log.message)
207
207
  : colors_1.default.red(log.message)
208
208
  : `${getLogLevel(log.level)} - ${log.message}`;
209
- 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`);
210
210
  }
211
211
  exports.writeNodeLogToConsole = writeNodeLogToConsole;
212
212
  function formatDate(date) {
@@ -223,7 +223,7 @@ function formatDate(date) {
223
223
  }
224
224
  exports.formatDate = formatDate;
225
225
  function writeWorkTreeStatus(schedulerState, env, ticker) {
226
- (0, readline_1.clearScreenDown)(process.stdout);
226
+ (0, readline_1.clearScreenDown)(env.stdout);
227
227
  const maxNodeNameLength = getNodeNameLengthForSchedulerState(schedulerState);
228
228
  let count = 0;
229
229
  for (const state of (0, plan_work_nodes_1.iterateWorkServices)(schedulerState.service)) {
@@ -232,7 +232,7 @@ function writeWorkTreeStatus(schedulerState, env, ticker) {
232
232
  if (currentMessage) {
233
233
  message += ` ${currentMessage.message}`;
234
234
  }
235
- count += printWithTruncate(message);
235
+ count += printWithTruncate(env, message);
236
236
  }
237
237
  for (const state of (0, plan_work_nodes_1.iterateWorkNodes)(schedulerState.node)) {
238
238
  let message = `${getType('task')} ${getNodeName(state.node.name, maxNodeNameLength)} - ${getStateText(state)}`;
@@ -271,9 +271,9 @@ function writeWorkTreeStatus(schedulerState, env, ticker) {
271
271
  else if (state.type === 'error') {
272
272
  message += ` ${state.errorMessage}`;
273
273
  }
274
- count += printWithTruncate(message);
274
+ count += printWithTruncate(env, message);
275
275
  }
276
- (0, readline_1.moveCursor)(process.stdout, 0, -1 * count);
276
+ (0, readline_1.moveCursor)(env.stdout, 0, -1 * count);
277
277
  }
278
278
  exports.writeWorkTreeStatus = writeWorkTreeStatus;
279
279
  function countChar(message, char) {
@@ -285,24 +285,24 @@ function countChar(message, char) {
285
285
  }
286
286
  return result;
287
287
  }
288
- function printWithTruncate(message) {
288
+ function printWithTruncate(env, message) {
289
289
  let lineCount = 0;
290
290
  let index = 0;
291
291
  do {
292
292
  const newLineCount = countChar(message, '\n');
293
- process.stdout.write(`${message.substr(index, process.stdout.columns)}\n`);
294
- index += process.stdout.columns;
293
+ env.stdout.write(`${message.substr(index, env.stdoutColumns)}\n`);
294
+ index += env.stdoutColumns;
295
295
  lineCount++;
296
296
  lineCount += newLineCount;
297
297
  } while (index < message.length);
298
298
  return lineCount;
299
299
  }
300
- function hideCursor() {
301
- process.stdout.write('\x1B[?25l');
300
+ function hideCursor(env) {
301
+ env.stdout.write('\x1B[?25l');
302
302
  }
303
303
  exports.hideCursor = hideCursor;
304
- function showCursor() {
305
- process.stdout.write('\x1B[?25h');
304
+ function showCursor(env) {
305
+ env.stdout.write('\x1B[?25h');
306
306
  }
307
307
  exports.showCursor = showCursor;
308
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,6 +10,7 @@ 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
16
  const validTaskKeys = [
@@ -22,8 +23,8 @@ const validTaskKeys = [
22
23
  'description',
23
24
  'extend',
24
25
  'cmds',
25
- 'watch',
26
26
  'continuous',
27
+ 'cache',
27
28
  ];
28
29
  const validDockerTaskKeys = ['image', 'mounts', 'ports', 'shell', ...validTaskKeys];
29
30
  async function parseBuildFile(fileName, files, input, context) {
@@ -74,7 +75,7 @@ async function parseBuildFile(fileName, files, input, context) {
74
75
  mounts: (0, parse_string_array_1.parseStringArray)(ctx, 'mounts', value.mounts),
75
76
  src: (0, parse_build_file_task_source_1.parseBuildFileTaskSource)(ctx, value.src, context),
76
77
  deps: (0, parse_string_array_1.parseStringArray)(ctx, 'deps', value.deps),
77
- generates: (0, parse_string_array_1.parseStringArray)(ctx, 'generates', value.generates),
78
+ generates: parseGenerateArray(ctx, 'generates', value.generates),
78
79
  description: (0, parse_string_1.parseString)(ctx, 'description', value.description, true)?.trim() ?? null,
79
80
  labels: (0, parse_string_map_1.parseStringMap)(ctx, 'labels', value.labels),
80
81
  image: value.image || null,
@@ -91,7 +92,7 @@ async function parseBuildFile(fileName, files, input, context) {
91
92
  return map;
92
93
  }, {}),
93
94
  platform: null,
94
- cache: value.caching || null,
95
+ cache: value.cache || null,
95
96
  };
96
97
  if (Object.keys(result.tasks[key].unknownProps).length > 0) {
97
98
  context.console.warn(`unknown props ${Object.keys(result.tasks[key].unknownProps)} for ${key} in ${fileName}`);
@@ -100,4 +101,25 @@ async function parseBuildFile(fileName, files, input, context) {
100
101
  return result;
101
102
  }
102
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
+ }
103
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
@@ -22,7 +22,10 @@ function planWorkDependency(deps, node) {
22
22
  if ((0, work_node_1.isContainerWorkNode)(depNode) && (0, work_node_1.isContainerWorkNode)(node)) {
23
23
  for (const volume of depNode.volumes) {
24
24
  if (!node.volumes.some((v) => v.name === volume.name)) {
25
- node.volumes.push(volume);
25
+ node.volumes.push({
26
+ ...volume,
27
+ inherited: true,
28
+ });
26
29
  }
27
30
  }
28
31
  }