hammerkit 1.5.1 → 1.6.0-alpha.1

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 (480) hide show
  1. package/.agents/FEEDBACK.md +74 -0
  2. package/.agents/skills/before-commit/SKILL.md +101 -0
  3. package/.agents/skills/do-the-work/SKILL.md +64 -0
  4. package/.agents/skills/fix-ci/SKILL.md +98 -0
  5. package/.agents/skills/speckit-git-commit/SKILL.md +53 -0
  6. package/.agents/skills/speckit-git-feature/SKILL.md +72 -0
  7. package/.agents/skills/speckit-git-initialize/SKILL.md +54 -0
  8. package/.agents/skills/speckit-git-remote/SKILL.md +50 -0
  9. package/.agents/skills/speckit-git-validate/SKILL.md +54 -0
  10. package/.gitbook.yaml +5 -0
  11. package/.specify/extensions/.registry +37 -0
  12. package/.specify/extensions/git/README.md +100 -0
  13. package/.specify/extensions/git/commands/speckit.git.commit.md +48 -0
  14. package/.specify/extensions/git/commands/speckit.git.feature.md +67 -0
  15. package/.specify/extensions/git/commands/speckit.git.initialize.md +49 -0
  16. package/.specify/extensions/git/commands/speckit.git.remote.md +45 -0
  17. package/.specify/extensions/git/commands/speckit.git.validate.md +49 -0
  18. package/.specify/extensions/git/config-template.yml +62 -0
  19. package/.specify/extensions/git/extension.yml +140 -0
  20. package/.specify/extensions/git/git-config.yml +62 -0
  21. package/.specify/extensions.yml +149 -0
  22. package/.specify/feature.json +3 -0
  23. package/.specify/init-options.json +10 -0
  24. package/.specify/integration.json +15 -0
  25. package/.specify/integrations/claude.manifest.json +16 -0
  26. package/.specify/integrations/speckit.manifest.json +17 -0
  27. package/.specify/memory/constitution.md +162 -0
  28. package/.specify/templates/checklist-template.md +40 -0
  29. package/.specify/templates/constitution-template.md +50 -0
  30. package/.specify/templates/plan-template.md +113 -0
  31. package/.specify/templates/spec-template.md +131 -0
  32. package/.specify/templates/tasks-template.md +252 -0
  33. package/.specify/workflows/speckit/workflow.yml +77 -0
  34. package/.specify/workflows/workflow-registry.json +13 -0
  35. package/AGENTS.md +94 -0
  36. package/Dockerfile +3 -3
  37. package/FOLLOWUPS.md +34 -0
  38. package/README.md +9 -7
  39. package/SUMMARY.md +30 -5
  40. package/VALUES.md +53 -0
  41. package/build.schema.json +542 -408
  42. package/dist/cache/auto-pull.spec.js +123 -0
  43. package/dist/cache/backends/local-cache-backend.js +56 -0
  44. package/dist/cache/backends/local-cache-backend.spec.js +72 -0
  45. package/dist/cache/backends/s3-cache-backend.js +124 -0
  46. package/dist/cache/backends/s3-cache-backend.spec.js +118 -0
  47. package/dist/cache/cache-backend-registry.js +21 -0
  48. package/dist/cache/cache-backend-registry.spec.js +22 -0
  49. package/dist/cache/cache-backend.js +3 -0
  50. package/dist/cache/resolve-cache.js +60 -0
  51. package/dist/cache/resolve-cache.spec.js +52 -0
  52. package/dist/cli.js +112 -82
  53. package/dist/cli.spec.js +20 -2
  54. package/dist/console/get-logger.spec.js +23 -0
  55. package/dist/docker/get-default-platform.spec.js +29 -0
  56. package/dist/docker/longest-common-prefix.spec.js +26 -0
  57. package/dist/docker/package.js +283 -0
  58. package/dist/docker/package.spec.js +145 -0
  59. package/dist/docker/pull.js +4 -4
  60. package/dist/docker/remove-container.spec.js +32 -0
  61. package/dist/docker/stream.js +3 -3
  62. package/dist/docker/using-container.js +29 -11
  63. package/dist/docker/using-container.spec.js +90 -0
  64. package/dist/environment/merge-environment-variables.js +21 -0
  65. package/dist/environment/merge-environment-variables.spec.js +24 -0
  66. package/dist/environment/replace-env-variables.js +43 -10
  67. package/dist/environment/replace-env-variables.spec.js +47 -0
  68. package/dist/executer/abort.spec.js +18 -0
  69. package/dist/executer/await-completed-dependencies.js +56 -0
  70. package/dist/executer/cache-metadata.js +11 -0
  71. package/dist/executer/check-readiness.js +1 -1
  72. package/dist/{planner/work-node-port.js → executer/container-bind.js} +1 -1
  73. package/dist/executer/docker-service.js +110 -86
  74. package/dist/executer/docker-task.js +132 -0
  75. package/dist/executer/environment-mock.js +3 -4
  76. package/dist/executer/environment-mock.spec.js +22 -0
  77. package/dist/executer/event-cache.js +60 -127
  78. package/dist/executer/execute-command.js +4 -3
  79. package/dist/executer/execute-docker.js +32 -14
  80. package/dist/executer/execute-work-service.js +61 -0
  81. package/dist/executer/execute-work-task.js +107 -0
  82. package/dist/executer/execute-work-tree.js +27 -0
  83. package/dist/executer/execute.spec.js +14 -10
  84. package/dist/executer/execution-steps.js +47 -31
  85. package/dist/executer/get-container-binds.js +19 -0
  86. package/dist/executer/get-docker-executor.js +12 -12
  87. package/dist/executer/get-scheduler-down-result.js +12 -0
  88. package/dist/executer/get-scheduler-execute-result.js +28 -0
  89. package/dist/executer/get-scheduler-up-result.js +12 -0
  90. package/dist/executer/get-service-containers.js +14 -0
  91. package/dist/executer/get-service-containers.spec.js +59 -0
  92. package/dist/executer/get-service-env-hints.js +35 -0
  93. package/dist/executer/get-service-env-hints.spec.js +65 -0
  94. package/dist/executer/kubernetes-service.js +116 -48
  95. package/dist/executer/label-values.js +29 -46
  96. package/dist/executer/label-values.spec.js +61 -0
  97. package/dist/executer/lazy-resolver.js +16 -0
  98. package/dist/executer/lazy-resolver.spec.js +20 -0
  99. package/dist/executer/local-task.js +44 -0
  100. package/dist/executer/process-manager.js +16 -70
  101. package/dist/executer/process-manager.spec.js +39 -76
  102. package/dist/executer/reset-work-tree.js +30 -0
  103. package/dist/executer/scheduler/check-for-loop.js +17 -7
  104. package/dist/executer/scheduler/{scheduler-state.js → dependency-state.js} +1 -1
  105. package/dist/executer/scheduler/enqueue-next.js +83 -19
  106. package/dist/executer/scheduler/enqueue-next.spec.js +136 -0
  107. package/dist/executer/scheduler/{node-state.js → need-state.js} +1 -1
  108. package/dist/{parser/build-file.js → executer/scheduler/task-state.js} +1 -1
  109. package/dist/executer/set-user-permission.js +1 -1
  110. package/dist/executer/state-resolver.js +61 -0
  111. package/dist/executer/state-resolver.spec.js +37 -0
  112. package/dist/executer/state.js +37 -31
  113. package/dist/executer/state.spec.js +66 -0
  114. package/dist/executer/states.spec.js +14 -0
  115. package/dist/executer/watch-loop.js +68 -0
  116. package/dist/executer/watch-state-key.js +44 -0
  117. package/dist/executer/work-scope.js +1 -5
  118. package/dist/file/get-file-context.js +24 -3
  119. package/dist/file/get-file-context.spec.js +178 -0
  120. package/dist/file/move-files.js +2 -2
  121. package/dist/file/move-files.spec.js +48 -0
  122. package/dist/index.js +7 -8
  123. package/dist/json-schema.js +12 -0
  124. package/dist/kubernetes/apply.js +34 -0
  125. package/dist/kubernetes/await-running-state.js +71 -0
  126. package/dist/kubernetes/ensure-http-route.js +53 -0
  127. package/dist/kubernetes/ensure-http-route.spec.js +70 -0
  128. package/dist/kubernetes/ensure-ingress.js +54 -0
  129. package/dist/kubernetes/ensure-kubernetes-deployment-exists.js +105 -0
  130. package/dist/kubernetes/ensure-kubernetes-persistent-volume-claim-exists.js +40 -0
  131. package/dist/kubernetes/ensure-kubernetes-service-exists.js +36 -0
  132. package/dist/kubernetes/ensure-namespace.js +43 -0
  133. package/dist/kubernetes/ensure-namespace.spec.js +39 -0
  134. package/dist/kubernetes/ensure-persistent-data.js +158 -0
  135. package/dist/kubernetes/get-service-ip.js +11 -0
  136. package/dist/kubernetes/kubernetes-instance.js +48 -0
  137. package/dist/kubernetes/remove-persistent-data.js +19 -0
  138. package/dist/kubernetes/resolve-pod-name.js +42 -0
  139. package/dist/kubernetes/resolve-pod-name.spec.js +81 -0
  140. package/dist/kubernetes/resources.js +12 -0
  141. package/dist/kubernetes/restore-kubernetes-data.js +42 -0
  142. package/dist/kubernetes/store-kubernetes-data.js +39 -0
  143. package/dist/kubernetes/volumes.js +64 -0
  144. package/dist/log.js +69 -69
  145. package/dist/log.spec.js +131 -0
  146. package/dist/logging/grouped-logger.js +17 -15
  147. package/dist/logging/grouped-logger.spec.js +84 -0
  148. package/dist/logging/interactive-logger.js +1 -1
  149. package/dist/logging/interactive-logger.spec.js +57 -0
  150. package/dist/logging/live-logger.js +2 -2
  151. package/dist/logging/live-logger.spec.js +37 -0
  152. package/dist/logging/loggers.spec.js +154 -0
  153. package/dist/optimizer/calculate-checksum.spec.js +34 -0
  154. package/dist/optimizer/get-cache-directory.js +6 -6
  155. package/dist/optimizer/get-cache-directory.spec.js +59 -0
  156. package/dist/optimizer/get-work-cache-stats.js +53 -0
  157. package/dist/optimizer/get-work-cache-stats.spec.js +79 -0
  158. package/dist/{parser/build-file-task.js → optimizer/work-cache-stats.js} +1 -1
  159. package/dist/optimizer/work-task-cache-description.js +25 -0
  160. package/dist/optimizer/work-task-cache-description.spec.js +45 -0
  161. package/dist/parser/default-build-file.js +14 -7
  162. package/dist/parser/default-build-file.spec.js +48 -0
  163. package/dist/parser/parse-label-arguments.spec.js +27 -0
  164. package/dist/parser/read-build-file.js +2 -13
  165. package/dist/parser/read-build-file.spec.js +89 -0
  166. package/dist/parser/read-env-file.js +4 -5
  167. package/dist/parser/read-env-file.spec.js +42 -0
  168. package/dist/planner/utils/append-work-dependencies.js +55 -0
  169. package/dist/planner/utils/append-work-environment.js +22 -0
  170. package/dist/planner/utils/append-work-needs.js +18 -0
  171. package/dist/planner/utils/append-work-service.js +107 -0
  172. package/dist/planner/utils/append-work-service.spec.js +71 -0
  173. package/dist/planner/utils/append-work-task.js +81 -0
  174. package/dist/planner/utils/get-container-user.js +14 -0
  175. package/dist/planner/utils/get-container-user.spec.js +30 -0
  176. package/dist/planner/utils/get-default-kube-config.js +10 -0
  177. package/dist/planner/utils/get-default-kube-config.spec.js +11 -0
  178. package/dist/planner/utils/get-work-runtime.js +44 -0
  179. package/dist/planner/utils/normalize-path.js +1 -1
  180. package/dist/planner/utils/normalize-path.spec.js +24 -0
  181. package/dist/planner/utils/parse-work-command.js +80 -0
  182. package/dist/planner/utils/parse-work-command.spec.js +21 -0
  183. package/dist/planner/utils/parse-work-generate.js +38 -0
  184. package/dist/planner/utils/parse-work-generate.spec.js +45 -0
  185. package/dist/planner/utils/{parse-work-node-mount.js → parse-work-mount.js} +10 -7
  186. package/dist/planner/utils/{parse-work-node-mount.spec.js → parse-work-mount.spec.js} +14 -11
  187. package/dist/planner/utils/parse-work-mounts.js +13 -0
  188. package/dist/planner/utils/parse-work-mounts.spec.js +19 -0
  189. package/dist/planner/utils/{parse-work-node-port.js → parse-work-port.js} +11 -8
  190. package/dist/planner/utils/parse-work-port.spec.js +24 -0
  191. package/dist/planner/utils/parse-work-ports.js +10 -0
  192. package/dist/planner/utils/parse-work-ports.spec.js +24 -0
  193. package/dist/planner/utils/parse-work-source.js +72 -0
  194. package/dist/planner/utils/parse-work-source.spec.js +58 -0
  195. package/dist/planner/utils/parse-work-volume.js +45 -0
  196. package/dist/planner/utils/parse-work-volume.spec.js +18 -0
  197. package/dist/planner/utils/plan-work-tasks.js +41 -0
  198. package/dist/planner/utils/plan-work-tasks.spec.js +30 -0
  199. package/dist/planner/utils/plan-work-volume.js +1 -0
  200. package/dist/planner/utils/plan-work-volume.spec.js +33 -0
  201. package/dist/planner/utils/split-name.js +2 -2
  202. package/dist/planner/utils/split-name.spec.js +16 -0
  203. package/dist/planner/utils/template-value.js +1 -2
  204. package/dist/planner/utils/template-value.spec.js +14 -0
  205. package/dist/planner/validate.js +71 -38
  206. package/dist/planner/validate.spec.js +251 -0
  207. package/dist/planner/work-cache-id.js +12 -0
  208. package/dist/planner/work-cache-id.spec.js +173 -0
  209. package/dist/planner/work-command.js +3 -0
  210. package/dist/planner/work-environment.js +3 -0
  211. package/dist/planner/work-healthcheck.js +3 -0
  212. package/dist/planner/{work-node-status.js → work-item-status.js} +16 -62
  213. package/dist/{parser/build-file-service.js → planner/work-item-validation.js} +1 -1
  214. package/dist/planner/work-item.js +16 -0
  215. package/dist/{optimizer/work-node-cache-stats.js → planner/work-kubernetes-selector.js} +1 -1
  216. package/dist/planner/{work-nodes.js → work-port.js} +1 -1
  217. package/dist/planner/work-runtime-docker.js +224 -0
  218. package/dist/planner/work-runtime-kubernetes.js +264 -0
  219. package/dist/planner/work-runtime-local.js +109 -0
  220. package/dist/planner/work-runtime-local.spec.js +193 -0
  221. package/dist/planner/work-service-id.js +15 -5
  222. package/dist/planner/work-source.js +3 -0
  223. package/dist/planner/work-task.js +8 -0
  224. package/dist/program-commands.spec.js +84 -0
  225. package/dist/program.js +219 -73
  226. package/dist/program.spec.js +34 -11
  227. package/dist/run-program.js +28 -0
  228. package/dist/{executer/process.js → runtime/runtime.js} +1 -1
  229. package/dist/schema/build-file-base-task-schema.js +27 -0
  230. package/dist/schema/build-file-container-service-schema.js +28 -0
  231. package/dist/schema/build-file-container-task-schema.js +13 -0
  232. package/dist/schema/build-file-environment-schema-ingress.js +14 -0
  233. package/dist/schema/build-file-environment-schema.js +23 -0
  234. package/dist/schema/build-file-kubernetes-service-schema.js +17 -0
  235. package/dist/schema/build-file-kubernetes-service-selector-schema.js +9 -0
  236. package/dist/schema/build-file-local-platform-schema.js +9 -0
  237. package/dist/schema/build-file-local-task-schema.js +12 -0
  238. package/dist/schema/build-file-need-schema.js +12 -0
  239. package/dist/schema/build-file-schema.js +23 -0
  240. package/dist/schema/build-file-schema.spec.js +61 -0
  241. package/dist/schema/build-file-service-container-healthcheck.js +8 -0
  242. package/dist/schema/build-file-service-schema.js +15 -0
  243. package/dist/schema/build-file-task-command-schema.js +12 -0
  244. package/dist/schema/build-file-task-schema.js +12 -0
  245. package/dist/schema/build-file-volume-schema.js +14 -0
  246. package/dist/schema/cache-schema.js +31 -0
  247. package/dist/schema/doc-build-files.spec.js +223 -0
  248. package/dist/schema/envs-schema.js +6 -0
  249. package/dist/schema/labels-schema.js +6 -0
  250. package/dist/schema/parse-context.js +3 -0
  251. package/dist/schema/parse-error.js +12 -0
  252. package/dist/schema/parse-error.spec.js +18 -0
  253. package/dist/schema/reference-parser.js +209 -0
  254. package/dist/schema/reference-parser.spec.js +83 -0
  255. package/dist/schema/schema-parser.js +66 -0
  256. package/dist/schema/schema-parser.spec.js +80 -0
  257. package/dist/schema/type-guards.spec.js +23 -0
  258. package/dist/schema/work-scope-parser.js +77 -0
  259. package/dist/schema/work-scope-parser.spec.js +66 -0
  260. package/dist/service/update-service-status.js +11 -0
  261. package/dist/service/update-service-status.spec.js +27 -0
  262. package/dist/testing/ensure-local-registry.js +134 -0
  263. package/dist/testing/example-test-suite.js +16 -18
  264. package/dist/testing/expect.js +46 -22
  265. package/dist/testing/http-get.js +21 -0
  266. package/dist/testing/integration/cache.spec.js +13 -14
  267. package/dist/testing/integration/cancellation.spec.js +14 -9
  268. package/dist/testing/integration/clean.spec.js +14 -11
  269. package/dist/testing/integration/cmd.spec.js +1 -1
  270. package/dist/testing/integration/concurrency.spec.js +3 -3
  271. package/dist/testing/integration/docker-package-registry.spec.js +44 -0
  272. package/dist/testing/integration/docker-service-crash.spec.js +36 -0
  273. package/dist/testing/integration/docker.spec.js +4 -3
  274. package/dist/testing/integration/env.spec.js +9 -8
  275. package/dist/testing/integration/environment.spec.js +97 -0
  276. package/dist/testing/integration/error.spec.js +5 -4
  277. package/dist/testing/integration/export.spec.js +22 -0
  278. package/dist/testing/integration/extend.spec.js +9 -12
  279. package/dist/testing/integration/glob.spec.js +12 -20
  280. package/dist/testing/integration/include.spec.js +3 -3
  281. package/dist/testing/integration/invalid.spec.js +2 -3
  282. package/dist/testing/integration/invalid_loop.spec.js +49 -6
  283. package/dist/testing/integration/k8s-state-cache.spec.js +41 -0
  284. package/dist/testing/integration/kubernetes-service.spec.js +148 -0
  285. package/dist/testing/integration/kubernetes.spec.js +93 -9
  286. package/dist/testing/integration/labels.spec.js +6 -11
  287. package/dist/testing/integration/local.spec.js +1 -1
  288. package/dist/testing/integration/monorepo.spec.js +4 -4
  289. package/dist/testing/integration/multi-line.spec.js +3 -3
  290. package/dist/testing/integration/reference.spec.js +4 -5
  291. package/dist/testing/integration/services.spec.js +22 -4
  292. package/dist/testing/integration/store.spec.js +15 -16
  293. package/dist/testing/integration/unknown.spec.js +20 -18
  294. package/dist/testing/integration/validate.spec.js +143 -26
  295. package/dist/testing/integration/watch-dependency.spec.js +11 -8
  296. package/dist/testing/integration/watch.spec.js +15 -16
  297. package/dist/testing/requires-kubernetes.js +18 -0
  298. package/dist/testing/requires-linux-containers.js +18 -0
  299. package/dist/testing/requires-windows-containers.js +18 -0
  300. package/dist/testing/test-case.js +75 -0
  301. package/dist/testing/test-streams.js +28 -0
  302. package/dist/testing/testing-timeout.js +32 -0
  303. package/dist/utils/abort-event.js +10 -4
  304. package/dist/utils/abort-event.spec.js +46 -0
  305. package/dist/utils/buffer-context.js +44 -0
  306. package/dist/utils/buffer-context.spec.js +38 -0
  307. package/dist/utils/ci.spec.js +53 -0
  308. package/dist/utils/emitter.spec.js +34 -0
  309. package/dist/utils/empty-writable.spec.js +18 -0
  310. package/dist/utils/environment-config.js +4 -1
  311. package/dist/utils/environment-config.spec.js +26 -0
  312. package/dist/utils/fail-never.spec.js +9 -0
  313. package/dist/version.js +9 -0
  314. package/dist/version.spec.js +12 -0
  315. package/package.json +41 -23
  316. package/specs/build-file/caches/spec.md +114 -0
  317. package/specs/build-file/environment-variables/spec.md +82 -0
  318. package/specs/build-file/includes/spec.md +60 -0
  319. package/specs/build-file/references/spec.md +56 -0
  320. package/specs/build-file/spec.md +62 -0
  321. package/specs/cli/clean/spec.md +85 -0
  322. package/specs/cli/down/spec.md +85 -0
  323. package/specs/cli/execute/spec.md +101 -0
  324. package/specs/cli/init/spec.md +64 -0
  325. package/specs/cli/ls/spec.md +66 -0
  326. package/specs/cli/package/spec.md +110 -0
  327. package/specs/cli/spec.md +73 -0
  328. package/specs/cli/store-restore/spec.md +74 -0
  329. package/specs/cli/up/spec.md +80 -0
  330. package/specs/cli/validate/spec.md +70 -0
  331. package/specs/labels/spec.md +91 -0
  332. package/specs/service/container/spec.md +120 -0
  333. package/specs/service/kubernetes/spec.md +97 -0
  334. package/specs/service/spec.md +105 -0
  335. package/specs/task/caching/spec.md +107 -0
  336. package/specs/task/container/spec.md +118 -0
  337. package/specs/task/dependencies/spec.md +70 -0
  338. package/specs/task/extending/spec.md +74 -0
  339. package/specs/task/kubernetes/spec.md +125 -0
  340. package/specs/task/needs/spec.md +59 -0
  341. package/specs/task/spec.md +87 -0
  342. package/specs/task/watching/spec.md +69 -0
  343. package/dist/console/console-context-mock.js +0 -14
  344. package/dist/environment/get-process-env.js +0 -15
  345. package/dist/executer/create-scheduler-state.js +0 -32
  346. package/dist/executer/docker-node.js +0 -123
  347. package/dist/executer/hierarchy-scheduler.js +0 -94
  348. package/dist/executer/local-node.js +0 -57
  349. package/dist/executer/schedule.js +0 -137
  350. package/dist/executer/start-node.js +0 -67
  351. package/dist/executer/watch-node.js +0 -56
  352. package/dist/executer/watch-service.js +0 -54
  353. package/dist/file/get-file-context-mock.js +0 -187
  354. package/dist/file/get-file-context-mock.spec.js +0 -56
  355. package/dist/get-work-context.js +0 -29
  356. package/dist/optimizer/get-work-node-cache-stats.js +0 -104
  357. package/dist/optimizer/read-work-node-cache.js +0 -19
  358. package/dist/optimizer/work-node-cache-description.js +0 -32
  359. package/dist/optimizer/write-work-node-cache.js +0 -21
  360. package/dist/parser/build-file-task-command.js +0 -3
  361. package/dist/parser/build-file-task-platform.js +0 -3
  362. package/dist/parser/build-file-task-source.js +0 -3
  363. package/dist/parser/get-build-file.js +0 -9
  364. package/dist/parser/parse-boolean.js +0 -29
  365. package/dist/parser/parse-boolean.spec.js +0 -48
  366. package/dist/parser/parse-build-file-references.js +0 -35
  367. package/dist/parser/parse-build-file-services.js +0 -58
  368. package/dist/parser/parse-build-file-task-command.js +0 -36
  369. package/dist/parser/parse-build-file-task-source.js +0 -63
  370. package/dist/parser/parse-build-file.js +0 -125
  371. package/dist/parser/parse-context.js +0 -13
  372. package/dist/parser/parse-envs.js +0 -29
  373. package/dist/parser/parse-healthcheck.js +0 -28
  374. package/dist/parser/parse-service-selector.js +0 -39
  375. package/dist/parser/parse-string-array.js +0 -20
  376. package/dist/parser/parse-string-map.js +0 -30
  377. package/dist/parser/parse-string.js +0 -20
  378. package/dist/planner/utils/get-container-mounts.js +0 -24
  379. package/dist/planner/utils/parse-work-service-volume.js +0 -23
  380. package/dist/planner/utils/plan-work-command.js +0 -21
  381. package/dist/planner/utils/plan-work-dependency.js +0 -36
  382. package/dist/planner/utils/plan-work-node.js +0 -293
  383. package/dist/planner/utils/plan-work-nodes.js +0 -78
  384. package/dist/planner/utils/plan-work-tree.js +0 -15
  385. package/dist/planner/work-context.js +0 -23
  386. package/dist/planner/work-node-command.js +0 -3
  387. package/dist/planner/work-node-id.js +0 -12
  388. package/dist/planner/work-node-id.spec.js +0 -106
  389. package/dist/planner/work-node-path.js +0 -2
  390. package/dist/planner/work-node-source.js +0 -3
  391. package/dist/planner/work-node-validation.js +0 -3
  392. package/dist/planner/work-node.js +0 -8
  393. package/dist/planner/work-service-volume.js +0 -3
  394. package/dist/planner/work-services.js +0 -3
  395. package/dist/start-watch-processes.js +0 -28
  396. package/dist/testing/cli.js +0 -73
  397. package/dist/testing/create-build-file.js +0 -9
  398. package/dist/testing/get-logger.js +0 -23
  399. package/dist/testing/get-node.js +0 -12
  400. package/dist/testing/get-test-context.js +0 -19
  401. package/dist/testing/integration/program.spec.js +0 -25
  402. package/dist/testing/lazy.js +0 -17
  403. package/dist/testing/start-watch-processes.js +0 -29
  404. package/dist/testing/test-suite-options.js +0 -3
  405. package/dist/utils/abortable-function.js +0 -71
  406. package/logs/cache-console.log +0 -0
  407. package/logs/cache-status.log +0 -6
  408. package/logs/cache-stout.log +0 -0
  409. package/logs/cancellation-console.log +0 -0
  410. package/logs/cancellation-status.log +0 -3
  411. package/logs/cancellation-stout.log +0 -3
  412. package/logs/clean-console.log +0 -0
  413. package/logs/clean-status.log +0 -37
  414. package/logs/clean-stout.log +0 -95
  415. package/logs/cmd-console.log +0 -0
  416. package/logs/cmd-status.log +0 -8
  417. package/logs/cmd-stout.log +0 -9
  418. package/logs/concurrency-console.log +0 -0
  419. package/logs/concurrency-status.log +0 -14
  420. package/logs/concurrency-stout.log +0 -88
  421. package/logs/docker-console.log +0 -0
  422. package/logs/docker-status.log +0 -14
  423. package/logs/docker-stout.log +0 -39
  424. package/logs/env-console.log +0 -1
  425. package/logs/env-status.log +0 -1
  426. package/logs/env-stout.log +0 -0
  427. package/logs/error-console.log +0 -0
  428. package/logs/error-status.log +0 -10
  429. package/logs/error-stout.log +0 -36
  430. package/logs/extend-console.log +0 -0
  431. package/logs/extend-status.log +0 -1
  432. package/logs/extend-stout.log +0 -0
  433. package/logs/glob-console.log +0 -28
  434. package/logs/glob-status.log +0 -23
  435. package/logs/glob-stout.log +0 -52
  436. package/logs/hello-world-node-console.log +0 -0
  437. package/logs/hello-world-node-status.log +0 -37
  438. package/logs/hello-world-node-stout.log +0 -41
  439. package/logs/include-console.log +0 -0
  440. package/logs/include-status.log +0 -3
  441. package/logs/include-stout.log +0 -0
  442. package/logs/invalid-console.log +0 -0
  443. package/logs/invalid-status.log +0 -1
  444. package/logs/invalid-stout.log +0 -0
  445. package/logs/invalid_loop-console.log +0 -0
  446. package/logs/invalid_loop-status.log +0 -1
  447. package/logs/invalid_loop-stout.log +0 -11
  448. package/logs/labels-console.log +0 -0
  449. package/logs/labels-status.log +0 -1
  450. package/logs/labels-stout.log +0 -0
  451. package/logs/local-console.log +0 -0
  452. package/logs/local-status.log +0 -7
  453. package/logs/local-stout.log +0 -8
  454. package/logs/monorepo-console.log +0 -0
  455. package/logs/monorepo-status.log +0 -152
  456. package/logs/monorepo-stout.log +0 -2354
  457. package/logs/multi-line-console.log +0 -0
  458. package/logs/multi-line-status.log +0 -1
  459. package/logs/multi-line-stout.log +0 -0
  460. package/logs/reference-console.log +0 -0
  461. package/logs/reference-status.log +0 -5
  462. package/logs/reference-stout.log +0 -0
  463. package/logs/services-console.log +0 -0
  464. package/logs/services-status.log +0 -129
  465. package/logs/services-stout.log +0 -639
  466. package/logs/store-restore-console.log +0 -0
  467. package/logs/store-restore-status.log +0 -40
  468. package/logs/store-restore-stout.log +0 -97
  469. package/logs/unknown-console.log +0 -3
  470. package/logs/unknown-status.log +0 -1
  471. package/logs/unknown-stout.log +0 -0
  472. package/logs/validate-console.log +0 -0
  473. package/logs/validate-status.log +0 -2
  474. package/logs/validate-stout.log +0 -0
  475. package/logs/watch-console.log +0 -0
  476. package/logs/watch-dependency-console.log +0 -0
  477. package/logs/watch-dependency-status.log +0 -176
  478. package/logs/watch-dependency-stout.log +0 -779
  479. package/logs/watch-status.log +0 -100
  480. package/logs/watch-stout.log +0 -349
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.removePersistentData = void 0;
4
+ async function removePersistentData(instance, kubernetes, task) {
5
+ const configmaps = await instance.coreApi.listNamespacedConfigMap(kubernetes.namespace, undefined, undefined, undefined, undefined, `hammerkit.dev/id=${task.id()}`);
6
+ for (const configMap of configmaps.body.items) {
7
+ if (configMap.metadata?.name) {
8
+ await instance.coreApi.deleteNamespacedConfigMap(configMap.metadata.name, kubernetes.namespace);
9
+ }
10
+ }
11
+ const pvcs = await instance.coreApi.listNamespacedPersistentVolumeClaim(kubernetes.namespace, undefined, undefined, undefined, undefined, `hammerkit.dev/id=${task.id()}`);
12
+ for (const pvc of pvcs.body.items) {
13
+ if (pvc.metadata?.name) {
14
+ await instance.coreApi.deleteNamespacedPersistentVolumeClaim(pvc.metadata.name, kubernetes.namespace);
15
+ }
16
+ }
17
+ }
18
+ exports.removePersistentData = removePersistentData;
19
+ //# sourceMappingURL=remove-persistent-data.js.map
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolvePodName = void 0;
4
+ function formatSelector(matchLabels) {
5
+ return Object.entries(matchLabels)
6
+ .map(([k, v]) => `${k}=${v}`)
7
+ .join(',');
8
+ }
9
+ async function findReadyPod(coreApi, namespace, labelSelector) {
10
+ const pods = await coreApi.listNamespacedPod(namespace, undefined, undefined, undefined, undefined, labelSelector);
11
+ const ready = pods.body.items.find((p) => p.status?.conditions?.some((c) => c.type === 'Ready' && c.status === 'True'));
12
+ const pod = ready ?? pods.body.items[0];
13
+ if (!pod?.metadata?.name) {
14
+ throw new Error(`no pod found for selector ${labelSelector} in namespace ${namespace}`);
15
+ }
16
+ return pod.metadata.name;
17
+ }
18
+ async function resolvePodName(coreApi, appsApi, namespace, selector) {
19
+ const type = selector.type.toLowerCase();
20
+ if (type === 'pod') {
21
+ return selector.name;
22
+ }
23
+ if (type === 'service') {
24
+ const svc = await coreApi.readNamespacedService(selector.name, namespace);
25
+ const matchLabels = svc.body.spec?.selector;
26
+ if (!matchLabels || Object.keys(matchLabels).length === 0) {
27
+ throw new Error(`service ${selector.name} has no selector`);
28
+ }
29
+ return findReadyPod(coreApi, namespace, formatSelector(matchLabels));
30
+ }
31
+ if (type === 'deployment') {
32
+ const deploy = await appsApi.readNamespacedDeployment(selector.name, namespace);
33
+ const matchLabels = deploy.body.spec?.selector?.matchLabels;
34
+ if (!matchLabels) {
35
+ throw new Error(`deployment ${selector.name} has no matchLabels`);
36
+ }
37
+ return findReadyPod(coreApi, namespace, formatSelector(matchLabels));
38
+ }
39
+ throw new Error(`unsupported selector type ${selector.type}`);
40
+ }
41
+ exports.resolvePodName = resolvePodName;
42
+ //# sourceMappingURL=resolve-pod-name.js.map
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const resolve_pod_name_1 = require("./resolve-pod-name");
4
+ function podBody(items) {
5
+ return {
6
+ body: {
7
+ items: items.map((p) => ({
8
+ metadata: { name: p.name },
9
+ status: {
10
+ conditions: [{ type: 'Ready', status: p.ready ? 'True' : 'False' }],
11
+ },
12
+ })),
13
+ },
14
+ };
15
+ }
16
+ function makeCoreApi(opts = {}) {
17
+ return {
18
+ readNamespacedService: vi.fn().mockResolvedValue({ body: { spec: { selector: opts.service?.selector } } }),
19
+ listNamespacedPod: vi.fn().mockResolvedValue(podBody(opts.pods ?? [])),
20
+ };
21
+ }
22
+ function makeAppsApi(opts = {}) {
23
+ return {
24
+ readNamespacedDeployment: vi
25
+ .fn()
26
+ .mockResolvedValue({ body: { spec: { selector: { matchLabels: opts.deployment?.matchLabels } } } }),
27
+ };
28
+ }
29
+ describe('resolvePodName', () => {
30
+ it('returns the name directly for selector type "pod"', async () => {
31
+ const core = makeCoreApi();
32
+ const apps = makeAppsApi();
33
+ await expect((0, resolve_pod_name_1.resolvePodName)(core, apps, 'ns', { type: 'pod', name: 'my-pod' })).resolves.toBe('my-pod');
34
+ expect(core.listNamespacedPod).not.toHaveBeenCalled();
35
+ });
36
+ it('resolves a service to a ready pod', async () => {
37
+ const core = makeCoreApi({
38
+ service: { selector: { app: 'api' } },
39
+ pods: [
40
+ { name: 'api-old', ready: false },
41
+ { name: 'api-new', ready: true },
42
+ ],
43
+ });
44
+ const apps = makeAppsApi();
45
+ await expect((0, resolve_pod_name_1.resolvePodName)(core, apps, 'ns', { type: 'service', name: 'api' })).resolves.toBe('api-new');
46
+ expect(core.listNamespacedPod).toHaveBeenCalledWith('ns', undefined, undefined, undefined, undefined, 'app=api');
47
+ });
48
+ it('falls back to the first pod if none are ready', async () => {
49
+ const core = makeCoreApi({
50
+ service: { selector: { app: 'api' } },
51
+ pods: [
52
+ { name: 'api-1', ready: false },
53
+ { name: 'api-2', ready: false },
54
+ ],
55
+ });
56
+ const apps = makeAppsApi();
57
+ await expect((0, resolve_pod_name_1.resolvePodName)(core, apps, 'ns', { type: 'service', name: 'api' })).resolves.toBe('api-1');
58
+ });
59
+ it('resolves a deployment via matchLabels', async () => {
60
+ const core = makeCoreApi({ pods: [{ name: 'p', ready: true }] });
61
+ const apps = makeAppsApi({ deployment: { matchLabels: { 'hammerkit.dev/id': 'x' } } });
62
+ await expect((0, resolve_pod_name_1.resolvePodName)(core, apps, 'ns', { type: 'deployment', name: 'api' })).resolves.toBe('p');
63
+ expect(core.listNamespacedPod).toHaveBeenCalledWith('ns', undefined, undefined, undefined, undefined, 'hammerkit.dev/id=x');
64
+ });
65
+ it('throws when a service has no selector', async () => {
66
+ const core = makeCoreApi({ service: { selector: undefined } });
67
+ const apps = makeAppsApi();
68
+ await expect((0, resolve_pod_name_1.resolvePodName)(core, apps, 'ns', { type: 'service', name: 'api' })).rejects.toThrow(/no selector/);
69
+ });
70
+ it('throws when no pods match', async () => {
71
+ const core = makeCoreApi({ service: { selector: { app: 'api' } }, pods: [] });
72
+ const apps = makeAppsApi();
73
+ await expect((0, resolve_pod_name_1.resolvePodName)(core, apps, 'ns', { type: 'service', name: 'api' })).rejects.toThrow(/no pod found/);
74
+ });
75
+ it('rejects unsupported selector types', async () => {
76
+ const core = makeCoreApi();
77
+ const apps = makeAppsApi();
78
+ await expect((0, resolve_pod_name_1.resolvePodName)(core, apps, 'ns', { type: 'statefulset', name: 'x' })).rejects.toThrow(/unsupported selector type/);
79
+ });
80
+ });
81
+ //# sourceMappingURL=resolve-pod-name.spec.js.map
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.removeInvalidCharacters = exports.getResourceName = void 0;
4
+ function getResourceName(item, suffix) {
5
+ return removeInvalidCharacters(item.name) + '-' + item.id() + (suffix ?? '');
6
+ }
7
+ exports.getResourceName = getResourceName;
8
+ function removeInvalidCharacters(val) {
9
+ return val.replace(/:/g, '-').replace(/\./g, '-');
10
+ }
11
+ exports.removeInvalidCharacters = removeInvalidCharacters;
12
+ //# sourceMappingURL=resources.js.map
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.restoreKubernetesData = void 0;
4
+ const event_cache_1 = require("../executer/event-cache");
5
+ const log_1 = require("../log");
6
+ const path_1 = require("path");
7
+ const volumes_1 = require("./volumes");
8
+ const ensure_persistent_data_1 = require("./ensure-persistent-data");
9
+ async function restoreKubernetesData(work, kubernetes, instance, environment, path) {
10
+ const persistence = await (0, volumes_1.getKubernetesPersistence)(work);
11
+ await (0, ensure_persistent_data_1.getPodForPersistence)(instance, kubernetes, work, persistence, 'write', async (name) => {
12
+ for (const generatedArchive of (0, event_cache_1.getArchivePaths)(work.data, path)) {
13
+ if (!(await environment.file.exists(generatedArchive.filename))) {
14
+ continue;
15
+ }
16
+ const targetPath = `/dev/hammerkit/${work.id()}/${(0, path_1.basename)(generatedArchive.path)}`;
17
+ const res = await instance.exec.exec(kubernetes.namespace, name, 'volume', ['tar', 'xzf', '-', '-C', targetPath], process.stdout, process.stderr, environment.file.readStream(generatedArchive.filename), false, (status) => {
18
+ work.status.write('debug', `upload ${generatedArchive.filename} to ${name}: ${status}`);
19
+ });
20
+ await new Promise((resolve, reject) => {
21
+ try {
22
+ res.on('open', () => {
23
+ work.status.write('debug', `start upload of ${generatedArchive.filename} to ${name}:${targetPath}`);
24
+ });
25
+ res.on('error', (err) => {
26
+ work.status.write('error', `error during upload of ${generatedArchive.filename} to ${name}: ${(0, log_1.getErrorMessage)(err)}`);
27
+ reject(err);
28
+ });
29
+ res.on('close', () => {
30
+ work.status.write('debug', `uploaded ${generatedArchive.filename} to ${name}:${targetPath}`);
31
+ resolve();
32
+ });
33
+ }
34
+ catch (e) {
35
+ reject(e);
36
+ }
37
+ });
38
+ }
39
+ });
40
+ }
41
+ exports.restoreKubernetesData = restoreKubernetesData;
42
+ //# sourceMappingURL=restore-kubernetes-data.js.map
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.storeKubernetesData = void 0;
4
+ const log_1 = require("../log");
5
+ const event_cache_1 = require("../executer/event-cache");
6
+ const volumes_1 = require("./volumes");
7
+ const ensure_persistent_data_1 = require("./ensure-persistent-data");
8
+ async function storeKubernetesData(work, kubernetes, instance, environment, path) {
9
+ const persistence = await (0, volumes_1.getKubernetesPersistence)(work);
10
+ await (0, ensure_persistent_data_1.getPodForPersistence)(instance, kubernetes, work, persistence, 'read', async (name) => {
11
+ for (const generatedArchive of (0, event_cache_1.getArchivePaths)(work.data, path)) {
12
+ const writerStream = environment.file.createWriteStream(generatedArchive.filename);
13
+ const res = await instance.exec.exec(kubernetes.namespace, name, 'volume', ['tar', 'zcf', '-', '-C', generatedArchive.path, '.'], writerStream, process.stderr, null, false, (status) => {
14
+ work.status.write('debug', `archive ${generatedArchive.path} of ${name}: ${status}`);
15
+ writerStream.close();
16
+ });
17
+ await new Promise((resolve, reject) => {
18
+ try {
19
+ res.on('open', () => {
20
+ work.status.write('debug', `start download ${generatedArchive.path} of ${name}`);
21
+ });
22
+ res.on('error', (err) => {
23
+ work.status.write('error', `download during upload ${generatedArchive.path} of ${name}: ${(0, log_1.getErrorMessage)(err)}`);
24
+ reject(err);
25
+ });
26
+ res.on('close', () => {
27
+ work.status.write('debug', `downloaded ${generatedArchive.path} of ${name}`);
28
+ resolve();
29
+ });
30
+ }
31
+ catch (e) {
32
+ reject(e);
33
+ }
34
+ });
35
+ }
36
+ });
37
+ }
38
+ exports.storeKubernetesData = storeKubernetesData;
39
+ //# sourceMappingURL=store-kubernetes-data.js.map
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.appendVolume = exports.getKubernetesPersistence = exports.getVolumeName = void 0;
4
+ const path_1 = require("path");
5
+ function getVolumeName(service) {
6
+ return 'hammerkit-' + service.id();
7
+ }
8
+ exports.getVolumeName = getVolumeName;
9
+ async function getKubernetesPersistence(work) {
10
+ const persistence = { volumes: [], sources: [], mounts: [], initCommands: [] };
11
+ for (const mount of work.data.mounts) {
12
+ appendVolume(work, persistence, mount.containerPath, mount.localPath, mount.isFile, true);
13
+ }
14
+ for (const src of work.data.src) {
15
+ if (src.inherited) {
16
+ continue;
17
+ }
18
+ appendVolume(work, persistence, src.absolutePath, src.absolutePath, src.isFile, true); // TODO matcher
19
+ }
20
+ if (work.data.type === 'container-task') {
21
+ for (const generate of work.data.generates) {
22
+ appendVolume(generate.inherited ?? work, persistence, generate.path, null, false, !!generate.inherited);
23
+ }
24
+ }
25
+ else {
26
+ for (const volume of work.data.volumes) {
27
+ appendVolume(volume.inherited ?? work, persistence, volume.containerPath, null, false, !!volume.inherited);
28
+ }
29
+ }
30
+ return persistence;
31
+ }
32
+ exports.getKubernetesPersistence = getKubernetesPersistence;
33
+ function appendVolume(sourceWork, persistence, containerPath, localPath, isFile, readOnly) {
34
+ const volumeName = getVolumeName(sourceWork);
35
+ const existVolume = persistence.volumes.some((v) => v.name === volumeName);
36
+ if (!existVolume) {
37
+ persistence.volumes.push({
38
+ name: volumeName,
39
+ persistentVolumeClaim: {
40
+ claimName: volumeName,
41
+ },
42
+ });
43
+ }
44
+ persistence.mounts.push({
45
+ mount: {
46
+ readOnly,
47
+ mountPath: containerPath,
48
+ name: volumeName,
49
+ subPath: (0, path_1.basename)(containerPath),
50
+ },
51
+ uploadPath: `/dev/hammerkit/${sourceWork.id()}`,
52
+ cwd: isFile ? (0, path_1.dirname)(containerPath) : containerPath,
53
+ });
54
+ if (localPath) {
55
+ persistence.sources.push({
56
+ localPath: localPath,
57
+ matcher: () => true, // TODO
58
+ containerPath,
59
+ stateKey: '', // TODO
60
+ });
61
+ }
62
+ }
63
+ exports.appendVolume = appendVolume;
64
+ //# sourceMappingURL=volumes.js.map
package/dist/log.js CHANGED
@@ -3,9 +3,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.showCursor = exports.hideCursor = exports.writeWorkTreeStatus = exports.formatDate = exports.writeNodeLogToConsole = exports.getNodeName = exports.getNodeNameLengthForWorkTree = exports.getNodeNameLength = exports.printTitle = exports.printItem = exports.printProperty = exports.getNodeNameLengthForSchedulerState = exports.printWorkTreeResult = exports.getType = exports.isVerbose = exports.consoleContext = exports.getErrorMessage = exports.getLogLevel = exports.getLogs = void 0;
6
+ exports.showCursor = exports.hideCursor = exports.writeWorkTreeStatus = exports.formatDate = exports.writeWorkItemLogToConsole = exports.getNodeName = exports.getMaxNameLength = exports.printTitle = exports.printItem = exports.printProperty = exports.getWorkItemMaxLength = exports.printWorkTreeResult = exports.getType = exports.isVerbose = exports.consoleContext = exports.getErrorMessage = exports.getLogLevel = exports.getLogs = void 0;
7
7
  const readline_1 = require("readline");
8
- const plan_work_nodes_1 = require("./planner/utils/plan-work-nodes");
8
+ const plan_work_tasks_1 = require("./planner/utils/plan-work-tasks");
9
9
  const colors_1 = __importDefault(require("colors"));
10
10
  const fail_never_1 = require("./utils/fail-never");
11
11
  function getLogs(chunk) {
@@ -66,50 +66,59 @@ function getType(type) {
66
66
  }
67
67
  exports.getType = getType;
68
68
  async function printWorkTreeResult(schedulerState, env) {
69
- const maxNodeNameLength = getNodeNameLengthForSchedulerState(schedulerState);
69
+ const maxNodeNameLength = getWorkItemMaxLength(schedulerState);
70
70
  for (const log of env.status.read()) {
71
71
  if (exports.isVerbose || (log.type === 'status' && log.level === 'error')) {
72
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
- for (const state of (0, plan_work_nodes_1.iterateWorkServices)(schedulerState.service)) {
76
- if (state.type === 'end' && state.reason === 'crash') {
77
- const message = `${getType('service')} ${getNodeName(state.service.name, maxNodeNameLength)}`;
78
- for (const log of env.status.service(state.service).logs()) {
75
+ for (const service of (0, plan_work_tasks_1.iterateWorkServices)(schedulerState)) {
76
+ if (service.state.current.type === 'end' && service.state.current.reason === 'crash') {
77
+ const message = `${getType('service')} ${getNodeName(service.name, maxNodeNameLength)}`;
78
+ for (const log of service.status.logs()) {
79
79
  env.stdout.write(`${formatDate(log.date)} ${message} - ${log.console}: ${log.message}\n`);
80
80
  }
81
81
  }
82
+ else if (service.state.current.type === 'running') {
83
+ const message = `${getType('service')} ${getNodeName(service.name, maxNodeNameLength)}`;
84
+ if (service.state.current.remote) {
85
+ env.stdout.write(`${formatDate(new Date())} ${message} - already started\n`);
86
+ }
87
+ else {
88
+ env.stdout.write(`${formatDate(new Date())} ${message} - sucessfull started\n`);
89
+ }
90
+ }
82
91
  }
83
- for (const state of (0, plan_work_nodes_1.iterateWorkNodes)(schedulerState.node)) {
84
- if (state.type === 'error' || state.type === 'crash') {
85
- const message = `${getType('task')} ${getNodeName(state.node.name, maxNodeNameLength)}`;
86
- for (const log of env.status.task(state.node).logs()) {
92
+ for (const task of (0, plan_work_tasks_1.iterateWorkTasks)(schedulerState)) {
93
+ if (task.state.current.type === 'error' || task.state.current.type === 'crash') {
94
+ const message = `${getType('task')} ${getNodeName(task.name, maxNodeNameLength)}`;
95
+ for (const log of task.status.logs()) {
87
96
  env.stdout.write(`${formatDate(log.date)} ${message} - ${log.console}: ${log.message}\n`);
88
97
  }
89
98
  }
90
99
  }
91
- for (const state of (0, plan_work_nodes_1.iterateWorkServices)(schedulerState.service)) {
92
- let message = `${formatDate(new Date())} ${getType('service')} ${getNodeName(state.service.name, maxNodeNameLength)} - ${getStateText(state)}`;
93
- if (state.type === 'end') {
94
- if (state.reason === 'crash') {
100
+ for (const service of (0, plan_work_tasks_1.iterateWorkServices)(schedulerState)) {
101
+ let message = `${formatDate(new Date())} ${getType('service')} ${getNodeName(service.name, maxNodeNameLength)} - ${getStateText(service.state.current)}`;
102
+ if (service.state.current.type === 'end') {
103
+ if (service.state.current.reason === 'crash') {
95
104
  message += ` crashed`;
96
105
  }
97
106
  env.stdout.write(`${message}\n`);
98
107
  }
99
108
  }
100
- for (const state of (0, plan_work_nodes_1.iterateWorkNodes)(schedulerState.node)) {
101
- let message = `${formatDate(new Date())} ${getType('task')} ${getNodeName(state.node.name, maxNodeNameLength)} - ${getStateText(state)}`;
102
- if (state.type === 'completed') {
103
- message += ` in ${state.duration}ms`;
104
- if (state.cached) {
109
+ for (const task of (0, plan_work_tasks_1.iterateWorkTasks)(schedulerState)) {
110
+ let message = `${formatDate(new Date())} ${getType('task')} ${getNodeName(task.name, maxNodeNameLength)} - ${getStateText(task.state.current)}`;
111
+ if (task.state.current.type === 'completed') {
112
+ message += ` in ${task.state.current.duration}ms`;
113
+ if (task.state.current.cached) {
105
114
  message += ' [CACHED]';
106
115
  }
107
116
  }
108
- if (state.type === 'crash') {
109
- message += ` exited with ${state.exitCode}`;
117
+ if (task.state.current.type === 'crash') {
118
+ message += ` exited with ${task.state.current.exitCode}`;
110
119
  }
111
- if (state.type === 'error') {
112
- message += ` with message ${state.errorMessage}`;
120
+ if (task.state.current.type === 'error') {
121
+ message += ` with message ${task.state.current.errorMessage}`;
113
122
  }
114
123
  env.stdout.write(`${message}\n`);
115
124
  }
@@ -142,21 +151,21 @@ function getStateText(state) {
142
151
  return colors_1.default.blue(state.type);
143
152
  }
144
153
  else {
145
- (0, fail_never_1.failNever)(state, 'unknown node state');
154
+ (0, fail_never_1.failNever)(state, 'unknown task state');
146
155
  }
147
156
  }
148
- function getNodeNameLengthForSchedulerState(schedulerState) {
157
+ function getWorkItemMaxLength(schedulerState) {
149
158
  function* Names() {
150
- for (const node of (0, plan_work_nodes_1.iterateWorkNodes)(schedulerState.node)) {
151
- yield node.node.name;
159
+ for (const task of (0, plan_work_tasks_1.iterateWorkTasks)(schedulerState)) {
160
+ yield task.name;
152
161
  }
153
- for (const service of (0, plan_work_nodes_1.iterateWorkServices)(schedulerState.service)) {
154
- yield service.service.name;
162
+ for (const service of (0, plan_work_tasks_1.iterateWorkServices)(schedulerState)) {
163
+ yield service.name;
155
164
  }
156
165
  }
157
- return getNodeNameLength(Names);
166
+ return getMaxNameLength(Names);
158
167
  }
159
- exports.getNodeNameLengthForSchedulerState = getNodeNameLengthForSchedulerState;
168
+ exports.getWorkItemMaxLength = getWorkItemMaxLength;
160
169
  function printProperty(env, name, value) {
161
170
  env.stdout.write(` ${colors_1.default.grey(`${name}:`)} ${value}\n`);
162
171
  }
@@ -169,7 +178,7 @@ function printTitle(env, name) {
169
178
  env.stdout.write(`${colors_1.default.bgWhite(name + ':\n')}`);
170
179
  }
171
180
  exports.printTitle = printTitle;
172
- function getNodeNameLength(names) {
181
+ function getMaxNameLength(names) {
173
182
  let maxNodeNameLength = 0;
174
183
  for (const name of names()) {
175
184
  if (name.length > maxNodeNameLength) {
@@ -178,24 +187,12 @@ function getNodeNameLength(names) {
178
187
  }
179
188
  return maxNodeNameLength;
180
189
  }
181
- exports.getNodeNameLength = getNodeNameLength;
182
- function getNodeNameLengthForWorkTree(nodes, services) {
183
- function* Names() {
184
- for (const node of (0, plan_work_nodes_1.iterateWorkNodes)(nodes)) {
185
- yield node.node.name;
186
- }
187
- for (const service of (0, plan_work_nodes_1.iterateWorkServices)(services)) {
188
- yield service.service.name;
189
- }
190
- }
191
- return getNodeNameLength(Names);
192
- }
193
- exports.getNodeNameLengthForWorkTree = getNodeNameLengthForWorkTree;
190
+ exports.getMaxNameLength = getMaxNameLength;
194
191
  function getNodeName(name, maxNodeNameLength) {
195
192
  return colors_1.default.white(name) + ' '.repeat(Math.max(0, maxNodeNameLength - name.length));
196
193
  }
197
194
  exports.getNodeName = getNodeName;
198
- function writeNodeLogToConsole(env, log, maxNodeNameLength) {
195
+ function writeWorkItemLogToConsole(env, log, maxNodeNameLength) {
199
196
  if (log.type === 'status') {
200
197
  if (log.level === 'debug' && !exports.isVerbose) {
201
198
  return;
@@ -208,7 +205,7 @@ function writeNodeLogToConsole(env, log, maxNodeNameLength) {
208
205
  : `${getLogLevel(log.level)} - ${log.message}`;
209
206
  env.stdout.write(`${formatDate(log.date)} ${colors_1.default.grey(log.context.type + ':')} ${getNodeName(log.context.name, maxNodeNameLength)} - ${log.date.toLocaleTimeString()} - ${content}\n`);
210
207
  }
211
- exports.writeNodeLogToConsole = writeNodeLogToConsole;
208
+ exports.writeWorkItemLogToConsole = writeWorkItemLogToConsole;
212
209
  function formatDate(date) {
213
210
  return colors_1.default.grey(`[${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date
214
211
  .getDay()
@@ -224,23 +221,26 @@ function formatDate(date) {
224
221
  exports.formatDate = formatDate;
225
222
  function writeWorkTreeStatus(schedulerState, env, ticker) {
226
223
  (0, readline_1.clearScreenDown)(env.stdout);
227
- const maxNodeNameLength = getNodeNameLengthForSchedulerState(schedulerState);
224
+ const maxNodeNameLength = getWorkItemMaxLength(schedulerState);
228
225
  let count = 0;
229
- for (const state of (0, plan_work_nodes_1.iterateWorkServices)(schedulerState.service)) {
230
- let message = `${getType('service')} ${getNodeName(state.service.name, maxNodeNameLength)} - ${getStateText(state)}`;
231
- const currentMessage = env.status.service(state.service).current();
226
+ for (const service of (0, plan_work_tasks_1.iterateWorkServices)(schedulerState)) {
227
+ let message = `${getType('service')} ${getNodeName(service.name, maxNodeNameLength)} - ${getStateText(service.state.current)}`;
228
+ if (service.state.current.type === 'running' && service.state.current.remote) {
229
+ message += ` [REMOTE]`;
230
+ }
231
+ const currentMessage = service.status.currentLog();
232
232
  if (currentMessage) {
233
233
  message += ` ${currentMessage.message}`;
234
234
  }
235
235
  count += printWithTruncate(env, message);
236
236
  }
237
- for (const state of (0, plan_work_nodes_1.iterateWorkNodes)(schedulerState.node)) {
238
- let message = `${getType('task')} ${getNodeName(state.node.name, maxNodeNameLength)} - ${getStateText(state)}`;
239
- if (state.type === 'pending') {
240
- const totalDepCount = state.node.deps.length;
241
- const totalServiceCount = state.node.needs.length;
242
- const completedDepCount = state.node.deps.filter((d) => schedulerState.node[d.id]?.type === 'completed').length;
243
- const runningServiceCount = state.node.needs.filter((n) => schedulerState.service[n.id]?.type === 'ready').length;
237
+ for (const task of (0, plan_work_tasks_1.iterateWorkTasks)(schedulerState)) {
238
+ let message = `${getType('task')} ${getNodeName(task.name, maxNodeNameLength)} - ${getStateText(task.state.current)}`;
239
+ if (task.state.current.type === 'pending') {
240
+ const totalDepCount = task.deps.length;
241
+ const totalServiceCount = task.needs.length;
242
+ const completedDepCount = task.deps.filter((d) => d.state.current.type === 'completed').length;
243
+ const runningServiceCount = task.needs.filter((n) => n.service.state.current.type === 'ready').length;
244
244
  if (totalDepCount > 0 && completedDepCount !== totalDepCount) {
245
245
  message += ` | ${colors_1.default.grey(` awaiting dependencies (${completedDepCount}/${totalDepCount})`)}`;
246
246
  }
@@ -248,28 +248,28 @@ function writeWorkTreeStatus(schedulerState, env, ticker) {
248
248
  message += ` | ${colors_1.default.grey(` awaiting service (${runningServiceCount}/${totalServiceCount})`)}`;
249
249
  }
250
250
  }
251
- if (state.type === 'starting' || state.type === 'ready') {
251
+ if (task.state.current.type === 'starting' || task.state.current.type === 'ready') {
252
252
  message += ` | ${spinner[ticker % spinner.length]}`;
253
- const currentMessage = env.status.task(state.node).current();
253
+ const currentMessage = task.status.current();
254
254
  if (currentMessage) {
255
255
  message += ` ${currentMessage.message}`;
256
256
  }
257
257
  }
258
- else if (state.type === 'running') {
258
+ else if (task.state.current.type === 'running') {
259
259
  message += ` | ${spinner[ticker % spinner.length]}`;
260
- const currentMessage = env.status.task(state.node).currentLog();
260
+ const currentMessage = task.status.currentLog();
261
261
  if (currentMessage) {
262
262
  message += ` ${currentMessage.message}`;
263
263
  }
264
264
  }
265
- else if (state.type === 'completed') {
266
- message += ` in ${state.duration}ms`;
267
- if (state.cached) {
265
+ else if (task.state.current.type === 'completed') {
266
+ message += ` in ${task.state.current.duration}ms`;
267
+ if (task.state.current.cached) {
268
268
  message += ' [CACHED]';
269
269
  }
270
270
  }
271
- else if (state.type === 'error') {
272
- message += ` ${state.errorMessage}`;
271
+ else if (task.state.current.type === 'error') {
272
+ message += ` ${task.state.current.errorMessage}`;
273
273
  }
274
274
  count += printWithTruncate(env, message);
275
275
  }
@@ -290,7 +290,7 @@ function printWithTruncate(env, message) {
290
290
  let index = 0;
291
291
  do {
292
292
  const newLineCount = countChar(message, '\n');
293
- env.stdout.write(`${message.substr(index, env.stdoutColumns)}\n`);
293
+ env.stdout.write(`${message.substring(index, index + env.stdoutColumns)}\n`);
294
294
  index += env.stdoutColumns;
295
295
  lineCount++;
296
296
  lineCount += newLineCount;