hammerkit 1.6.0 → 1.7.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 (256) hide show
  1. package/README.md +4 -4
  2. package/build.schema.json +49 -2
  3. package/dist/cache/backends/local-cache-backend.js +58 -1
  4. package/dist/cache/backends/registry/registry-client.js +264 -0
  5. package/dist/cache/backends/registry/registry-credentials.js +81 -0
  6. package/dist/cache/backends/registry/registry-reference.js +36 -0
  7. package/dist/cache/backends/registry-cache-backend.js +145 -0
  8. package/dist/cache/backends/s3-cache-backend.js +99 -46
  9. package/dist/cache/cache-backend-registry.js +2 -0
  10. package/dist/cache/cache-inventory.js +84 -0
  11. package/dist/cache/cache-sync.js +77 -0
  12. package/dist/cache/explain.js +214 -0
  13. package/dist/cache/last-resolved.js +48 -0
  14. package/dist/cache/read-only.js +15 -0
  15. package/dist/cache/retention.js +61 -0
  16. package/dist/cli.js +43 -0
  17. package/dist/docker/using-container.js +5 -1
  18. package/dist/executer/archive-task-entry.js +21 -0
  19. package/dist/executer/await-completed-dependencies.js +32 -14
  20. package/dist/executer/cache-metadata.js +9 -2
  21. package/dist/executer/docker-service.js +2 -1
  22. package/dist/executer/docker-task.js +2 -1
  23. package/dist/executer/dry-run.js +73 -0
  24. package/dist/executer/event-cache.js +6 -5
  25. package/dist/executer/execute-command.js +21 -3
  26. package/dist/executer/execute-work-service.js +10 -1
  27. package/dist/executer/execute-work-task.js +95 -25
  28. package/dist/executer/execute-work-tree.js +26 -1
  29. package/dist/executer/get-scheduler-execute-result.js +4 -1
  30. package/dist/executer/lazy-resolver.js +15 -3
  31. package/dist/executer/reset-work-tree.js +2 -0
  32. package/dist/executer/run-summary.js +102 -0
  33. package/dist/executer/scheduler/enqueue-next.js +15 -60
  34. package/dist/executer/scheduler/state-key.js +78 -0
  35. package/dist/kubernetes/await-running-state.js +73 -19
  36. package/dist/log.js +16 -6
  37. package/dist/logging/live-logger.js +2 -1
  38. package/dist/optimizer/calculate-checksum.js +8 -2
  39. package/dist/optimizer/get-work-cache-stats.js +66 -16
  40. package/dist/optimizer/work-task-cache-description.js +34 -5
  41. package/dist/planner/project-root.js +26 -0
  42. package/dist/planner/utils/append-work-service.js +2 -1
  43. package/dist/planner/utils/append-work-task.js +7 -1
  44. package/dist/planner/utils/parse-work-source.js +35 -30
  45. package/dist/planner/utils/portable-path.js +30 -0
  46. package/dist/planner/work-cache-id.js +2 -2
  47. package/dist/planner/work-graph-serializer.js +103 -0
  48. package/dist/planner/work-instance-id.js +15 -0
  49. package/dist/planner/work-runtime-docker.js +53 -15
  50. package/dist/planner/work-runtime-kubernetes.js +35 -3
  51. package/dist/planner/work-runtime-local.js +9 -3
  52. package/dist/planner/work-service-id.js +16 -4
  53. package/dist/program.js +235 -1
  54. package/dist/schema/build-file-base-task-schema.js +4 -0
  55. package/dist/schema/cache-schema.js +21 -2
  56. package/dist/schema/duration-schema.js +18 -0
  57. package/dist/schema/reference-parser.js +3 -0
  58. package/dist/schema/size-schema.js +18 -0
  59. package/dist/schema/work-scope-parser.js +15 -2
  60. package/dist/utils/units.js +87 -0
  61. package/package.json +12 -1
  62. package/.agents/FEEDBACK.md +0 -74
  63. package/.agents/skills/before-commit/SKILL.md +0 -101
  64. package/.agents/skills/do-the-work/SKILL.md +0 -64
  65. package/.agents/skills/fix-ci/SKILL.md +0 -98
  66. package/.agents/skills/speckit-git-commit/SKILL.md +0 -53
  67. package/.agents/skills/speckit-git-feature/SKILL.md +0 -72
  68. package/.agents/skills/speckit-git-initialize/SKILL.md +0 -54
  69. package/.agents/skills/speckit-git-remote/SKILL.md +0 -50
  70. package/.agents/skills/speckit-git-validate/SKILL.md +0 -54
  71. package/.devcontainer/Dockerfile +0 -5
  72. package/.devcontainer/devcontainer.json +0 -40
  73. package/.gitbook.yaml +0 -5
  74. package/.specify/extensions/.registry +0 -37
  75. package/.specify/extensions/git/README.md +0 -100
  76. package/.specify/extensions/git/commands/speckit.git.commit.md +0 -48
  77. package/.specify/extensions/git/commands/speckit.git.feature.md +0 -67
  78. package/.specify/extensions/git/commands/speckit.git.initialize.md +0 -49
  79. package/.specify/extensions/git/commands/speckit.git.remote.md +0 -45
  80. package/.specify/extensions/git/commands/speckit.git.validate.md +0 -49
  81. package/.specify/extensions/git/config-template.yml +0 -62
  82. package/.specify/extensions/git/extension.yml +0 -140
  83. package/.specify/extensions/git/git-config.yml +0 -62
  84. package/.specify/extensions.yml +0 -149
  85. package/.specify/feature.json +0 -3
  86. package/.specify/init-options.json +0 -10
  87. package/.specify/integration.json +0 -15
  88. package/.specify/integrations/claude.manifest.json +0 -16
  89. package/.specify/integrations/speckit.manifest.json +0 -17
  90. package/.specify/memory/constitution.md +0 -162
  91. package/.specify/templates/checklist-template.md +0 -40
  92. package/.specify/templates/constitution-template.md +0 -50
  93. package/.specify/templates/plan-template.md +0 -113
  94. package/.specify/templates/spec-template.md +0 -131
  95. package/.specify/templates/tasks-template.md +0 -252
  96. package/.specify/workflows/speckit/workflow.yml +0 -77
  97. package/.specify/workflows/workflow-registry.json +0 -13
  98. package/AGENTS.md +0 -94
  99. package/Dockerfile +0 -32
  100. package/FOLLOWUPS.md +0 -34
  101. package/SUMMARY.md +0 -68
  102. package/VALUES.md +0 -53
  103. package/dist/cache/auto-pull.spec.js +0 -123
  104. package/dist/cache/backends/local-cache-backend.spec.js +0 -72
  105. package/dist/cache/backends/s3-cache-backend.spec.js +0 -118
  106. package/dist/cache/cache-backend-registry.spec.js +0 -22
  107. package/dist/cache/resolve-cache.spec.js +0 -52
  108. package/dist/cli.spec.js +0 -23
  109. package/dist/console/get-logger.spec.js +0 -23
  110. package/dist/docker/get-default-platform.spec.js +0 -29
  111. package/dist/docker/longest-common-prefix.spec.js +0 -26
  112. package/dist/docker/package.spec.js +0 -145
  113. package/dist/docker/remove-container.spec.js +0 -32
  114. package/dist/docker/using-container.spec.js +0 -90
  115. package/dist/environment/merge-environment-variables.spec.js +0 -24
  116. package/dist/environment/replace-env-variables.spec.js +0 -47
  117. package/dist/executer/abort.spec.js +0 -18
  118. package/dist/executer/environment-mock.spec.js +0 -22
  119. package/dist/executer/execute.spec.js +0 -51
  120. package/dist/executer/get-service-containers.spec.js +0 -59
  121. package/dist/executer/get-service-env-hints.spec.js +0 -65
  122. package/dist/executer/label-values.spec.js +0 -61
  123. package/dist/executer/lazy-resolver.spec.js +0 -20
  124. package/dist/executer/process-manager.spec.js +0 -54
  125. package/dist/executer/scheduler/enqueue-next.spec.js +0 -136
  126. package/dist/executer/state-resolver.spec.js +0 -37
  127. package/dist/executer/state.spec.js +0 -66
  128. package/dist/executer/states.spec.js +0 -14
  129. package/dist/file/get-file-context.spec.js +0 -178
  130. package/dist/file/move-files.spec.js +0 -48
  131. package/dist/kubernetes/ensure-http-route.spec.js +0 -70
  132. package/dist/kubernetes/ensure-namespace.spec.js +0 -39
  133. package/dist/kubernetes/resolve-pod-name.spec.js +0 -81
  134. package/dist/log.spec.js +0 -131
  135. package/dist/logging/grouped-logger.spec.js +0 -84
  136. package/dist/logging/interactive-logger.spec.js +0 -57
  137. package/dist/logging/live-logger.spec.js +0 -37
  138. package/dist/logging/loggers.spec.js +0 -154
  139. package/dist/optimizer/calculate-checksum.spec.js +0 -34
  140. package/dist/optimizer/get-cache-directory.spec.js +0 -59
  141. package/dist/optimizer/get-work-cache-stats.spec.js +0 -79
  142. package/dist/optimizer/work-task-cache-description.spec.js +0 -45
  143. package/dist/parser/default-build-file.spec.js +0 -48
  144. package/dist/parser/parse-label-arguments.spec.js +0 -27
  145. package/dist/parser/read-build-file.spec.js +0 -89
  146. package/dist/parser/read-env-file.spec.js +0 -42
  147. package/dist/planner/utils/append-work-service.spec.js +0 -71
  148. package/dist/planner/utils/get-container-user.spec.js +0 -30
  149. package/dist/planner/utils/get-default-kube-config.spec.js +0 -11
  150. package/dist/planner/utils/normalize-path.spec.js +0 -24
  151. package/dist/planner/utils/parse-work-command.spec.js +0 -21
  152. package/dist/planner/utils/parse-work-generate.spec.js +0 -45
  153. package/dist/planner/utils/parse-work-mount.spec.js +0 -62
  154. package/dist/planner/utils/parse-work-mounts.spec.js +0 -19
  155. package/dist/planner/utils/parse-work-port.spec.js +0 -24
  156. package/dist/planner/utils/parse-work-ports.spec.js +0 -24
  157. package/dist/planner/utils/parse-work-source.spec.js +0 -58
  158. package/dist/planner/utils/parse-work-volume.spec.js +0 -18
  159. package/dist/planner/utils/plan-work-tasks.spec.js +0 -30
  160. package/dist/planner/utils/plan-work-volume.spec.js +0 -33
  161. package/dist/planner/utils/split-name.spec.js +0 -16
  162. package/dist/planner/utils/template-value.spec.js +0 -14
  163. package/dist/planner/validate.spec.js +0 -251
  164. package/dist/planner/work-cache-id.spec.js +0 -173
  165. package/dist/planner/work-runtime-local.spec.js +0 -193
  166. package/dist/program-commands.spec.js +0 -84
  167. package/dist/program.spec.js +0 -43
  168. package/dist/schema/build-file-schema.spec.js +0 -61
  169. package/dist/schema/doc-build-files.spec.js +0 -223
  170. package/dist/schema/parse-error.spec.js +0 -18
  171. package/dist/schema/reference-parser.spec.js +0 -83
  172. package/dist/schema/schema-parser.spec.js +0 -80
  173. package/dist/schema/type-guards.spec.js +0 -23
  174. package/dist/schema/work-scope-parser.spec.js +0 -66
  175. package/dist/service/update-service-status.spec.js +0 -27
  176. package/dist/testing/ensure-local-registry.js +0 -134
  177. package/dist/testing/example-test-suite.js +0 -63
  178. package/dist/testing/expect.js +0 -82
  179. package/dist/testing/get-test-suite.js +0 -9
  180. package/dist/testing/http-get.js +0 -21
  181. package/dist/testing/integration/cache.spec.js +0 -49
  182. package/dist/testing/integration/cancellation.spec.js +0 -45
  183. package/dist/testing/integration/clean.spec.js +0 -43
  184. package/dist/testing/integration/cmd.spec.js +0 -15
  185. package/dist/testing/integration/concurrency.spec.js +0 -19
  186. package/dist/testing/integration/docker-package-registry.spec.js +0 -44
  187. package/dist/testing/integration/docker-service-crash.spec.js +0 -36
  188. package/dist/testing/integration/docker.spec.js +0 -18
  189. package/dist/testing/integration/env.spec.js +0 -48
  190. package/dist/testing/integration/environment.spec.js +0 -97
  191. package/dist/testing/integration/error.spec.js +0 -19
  192. package/dist/testing/integration/export.spec.js +0 -22
  193. package/dist/testing/integration/extend.spec.js +0 -29
  194. package/dist/testing/integration/glob.spec.js +0 -40
  195. package/dist/testing/integration/include.spec.js +0 -31
  196. package/dist/testing/integration/invalid.spec.js +0 -17
  197. package/dist/testing/integration/invalid_loop.spec.js +0 -56
  198. package/dist/testing/integration/k8s-state-cache.spec.js +0 -41
  199. package/dist/testing/integration/kubernetes-service.spec.js +0 -148
  200. package/dist/testing/integration/kubernetes.spec.js +0 -99
  201. package/dist/testing/integration/labels.spec.js +0 -42
  202. package/dist/testing/integration/local.spec.js +0 -14
  203. package/dist/testing/integration/monorepo.spec.js +0 -15
  204. package/dist/testing/integration/multi-line.spec.js +0 -17
  205. package/dist/testing/integration/reference.spec.js +0 -21
  206. package/dist/testing/integration/services.spec.js +0 -38
  207. package/dist/testing/integration/store.spec.js +0 -52
  208. package/dist/testing/integration/unknown.spec.js +0 -28
  209. package/dist/testing/integration/validate.spec.js +0 -160
  210. package/dist/testing/integration/watch-dependency.spec.js +0 -33
  211. package/dist/testing/integration/watch.spec.js +0 -45
  212. package/dist/testing/requires-kubernetes.js +0 -18
  213. package/dist/testing/requires-linux-containers.js +0 -18
  214. package/dist/testing/requires-windows-containers.js +0 -18
  215. package/dist/testing/test-case.js +0 -75
  216. package/dist/testing/test-streams.js +0 -28
  217. package/dist/testing/test-suite-setup.js +0 -3
  218. package/dist/testing/test-suite.js +0 -3
  219. package/dist/testing/testing-timeout.js +0 -32
  220. package/dist/utils/abort-event.spec.js +0 -46
  221. package/dist/utils/buffer-context.spec.js +0 -38
  222. package/dist/utils/ci.spec.js +0 -53
  223. package/dist/utils/debouncer.spec.js +0 -58
  224. package/dist/utils/emitter.spec.js +0 -34
  225. package/dist/utils/empty-writable.spec.js +0 -18
  226. package/dist/utils/environment-config.spec.js +0 -26
  227. package/dist/utils/fail-never.spec.js +0 -9
  228. package/dist/utils/sleep.spec.js +0 -22
  229. package/dist/version.spec.js +0 -12
  230. package/specs/build-file/caches/spec.md +0 -114
  231. package/specs/build-file/environment-variables/spec.md +0 -82
  232. package/specs/build-file/includes/spec.md +0 -60
  233. package/specs/build-file/references/spec.md +0 -56
  234. package/specs/build-file/spec.md +0 -62
  235. package/specs/cli/clean/spec.md +0 -85
  236. package/specs/cli/down/spec.md +0 -85
  237. package/specs/cli/execute/spec.md +0 -101
  238. package/specs/cli/init/spec.md +0 -64
  239. package/specs/cli/ls/spec.md +0 -66
  240. package/specs/cli/package/spec.md +0 -110
  241. package/specs/cli/spec.md +0 -73
  242. package/specs/cli/store-restore/spec.md +0 -74
  243. package/specs/cli/up/spec.md +0 -80
  244. package/specs/cli/validate/spec.md +0 -70
  245. package/specs/labels/spec.md +0 -91
  246. package/specs/service/container/spec.md +0 -120
  247. package/specs/service/kubernetes/spec.md +0 -97
  248. package/specs/service/spec.md +0 -105
  249. package/specs/task/caching/spec.md +0 -107
  250. package/specs/task/container/spec.md +0 -118
  251. package/specs/task/dependencies/spec.md +0 -70
  252. package/specs/task/extending/spec.md +0 -74
  253. package/specs/task/kubernetes/spec.md +0 -125
  254. package/specs/task/needs/spec.md +0 -59
  255. package/specs/task/spec.md +0 -87
  256. package/specs/task/watching/spec.md +0 -69
@@ -1,148 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const requires_kubernetes_1 = require("../requires-kubernetes");
4
- const test_case_1 = require("../test-case");
5
- const client_node_1 = require("@kubernetes/client-node");
6
- const http_1 = require("http");
7
- // Exercises src/executer/kubernetes-service.ts end-to-end: hammerkit's
8
- // `kubernetes-service` type opens a local TCP server (one per published port)
9
- // that tunnels via the k8s API to a pod. We deploy nginx directly with the k8s
10
- // client, then point a hammerkit kubernetes-service at it, drive the lifecycle
11
- // (load kubeconfig -> resolve pod -> listen -> state `running`) and actually
12
- // HTTP-GET the forwarded port to prove data flows through to the pod.
13
- const RUN_ID = (process.env.HAMMERKIT_TEST_RUN_ID ?? 'local').slice(0, 30);
14
- const NS = `hammerkit-k8s-svc-${RUN_ID}`;
15
- const CTX = process.env.CLUSTER_NAME || 'docker-desktop';
16
- const HOST_PORT = 28080;
17
- const DEPLOY_NAME = 'nginx';
18
- function makeClients() {
19
- const kc = new client_node_1.KubeConfig();
20
- kc.loadFromDefault();
21
- kc.setCurrentContext(CTX);
22
- return {
23
- coreApi: kc.makeApiClient(client_node_1.CoreV1Api),
24
- appsApi: kc.makeApiClient(client_node_1.AppsV1Api),
25
- };
26
- }
27
- async function ensureNamespace(coreApi) {
28
- try {
29
- await coreApi.readNamespace(NS);
30
- return;
31
- }
32
- catch {
33
- /* missing */
34
- }
35
- try {
36
- await coreApi.createNamespace({ metadata: { name: NS } });
37
- }
38
- catch {
39
- /* racing creator */
40
- }
41
- }
42
- async function applyNginx(coreApi, appsApi) {
43
- await appsApi.deleteNamespacedDeployment(DEPLOY_NAME, NS).catch(() => undefined);
44
- await appsApi.createNamespacedDeployment(NS, {
45
- metadata: { name: DEPLOY_NAME, labels: { app: DEPLOY_NAME } },
46
- spec: {
47
- replicas: 1,
48
- selector: { matchLabels: { app: DEPLOY_NAME } },
49
- template: {
50
- metadata: { labels: { app: DEPLOY_NAME } },
51
- spec: {
52
- containers: [{ name: DEPLOY_NAME, image: 'nginx:1.25-alpine', ports: [{ containerPort: 80 }] }],
53
- },
54
- },
55
- },
56
- });
57
- const deadline = Date.now() + 90000;
58
- while (Date.now() < deadline) {
59
- const pods = await coreApi.listNamespacedPod(NS, undefined, undefined, undefined, undefined, `app=${DEPLOY_NAME}`);
60
- const ready = pods.body.items.some((p) => p.status?.conditions?.some((c) => c.type === 'Ready' && c.status === 'True'));
61
- if (ready)
62
- return;
63
- await new Promise((r) => setTimeout(r, 1000));
64
- }
65
- throw new Error(`nginx pod in ${NS} did not become ready in time`);
66
- }
67
- async function waitFor(predicate, timeoutMs, intervalMs = 200) {
68
- const deadline = Date.now() + timeoutMs;
69
- while (Date.now() < deadline) {
70
- if (predicate())
71
- return;
72
- await new Promise((r) => setTimeout(r, intervalMs));
73
- }
74
- throw new Error('waitFor: predicate never became true');
75
- }
76
- function httpGet(host, port, path) {
77
- return new Promise((resolve, reject) => {
78
- const req = (0, http_1.request)({ host, port, path, method: 'GET', timeout: 5000 }, (res) => {
79
- let body = '';
80
- res.on('data', (c) => (body += c));
81
- res.on('end', () => resolve({ status: res.statusCode ?? 0, body }));
82
- });
83
- req.on('error', reject);
84
- req.on('timeout', () => {
85
- req.destroy();
86
- reject(new Error('http timeout'));
87
- });
88
- req.end();
89
- });
90
- }
91
- describe('kubernetes-service (port-forward)', () => {
92
- const suite = (0, test_case_1.createTestCase)('k8s-service-forward', {
93
- '.hammerkit.yaml': {
94
- services: {
95
- nginx: {
96
- context: CTX,
97
- namespace: NS,
98
- selector: { type: 'deployment', name: DEPLOY_NAME },
99
- ports: [`${HOST_PORT}:80`],
100
- },
101
- },
102
- environments: {
103
- default: {
104
- kubernetes: { context: CTX, namespace: NS },
105
- },
106
- },
107
- },
108
- });
109
- beforeAll((0, requires_kubernetes_1.requiresKubernetes)(async () => {
110
- const { coreApi, appsApi } = makeClients();
111
- await ensureNamespace(coreApi);
112
- await applyNginx(coreApi, appsApi);
113
- }), 120000);
114
- afterAll(async () => {
115
- try {
116
- const { coreApi } = makeClients();
117
- await coreApi.deleteNamespace(NS).catch(() => undefined);
118
- }
119
- catch {
120
- /* no cluster available */
121
- }
122
- });
123
- it('forwards a kubernetes-service to a pod and tears down on abort', (0, requires_kubernetes_1.requiresKubernetes)(async () => {
124
- await suite.cli({}, async (cli, env) => {
125
- const exec = cli.up({ logMode: 'live' });
126
- const done = exec.start();
127
- try {
128
- // state transitions to `running` only after the forward server's
129
- // listen() resolves — proves loadKubeConfig + resolvePodName + the
130
- // TCP listener setup all completed against a live cluster.
131
- await waitFor(() => exec.state.current.services['nginx']?.state.current.type === 'running', 30000);
132
- // and an actual byte round-trip through the forward confirms the
133
- // per-connection portForward path (createServer callback) works too.
134
- const res = await httpGet('127.0.0.1', HOST_PORT, '/');
135
- expect(res.status).toBe(200);
136
- expect(res.body).toMatch(/nginx/i);
137
- }
138
- finally {
139
- env.abortCtrl.abort();
140
- await done;
141
- }
142
- // abort triggers the finally block in kubernetesService: forwards close,
143
- // state advances to `end`.
144
- expect(exec.state.current.services['nginx']?.state.current.type).toBe('end');
145
- });
146
- }), 120000);
147
- });
148
- //# sourceMappingURL=kubernetes-service.spec.js.map
@@ -1,99 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const requires_kubernetes_1 = require("../requires-kubernetes");
4
- const test_case_1 = require("../test-case");
5
- describe('kubernetes', () => {
6
- const suite = (0, test_case_1.createTestCase)('kubernetes', {
7
- '.hammerkit.yaml': {
8
- services: {
9
- postgres: {
10
- image: 'postgres:12-alpine',
11
- envs: {
12
- POSTGRES_USER: 'postgres',
13
- POSTGRES_DB: 'demo',
14
- POSTGRES_PASSWORD: '123456',
15
- },
16
- volumes: ['data:/var/lib/postgresql/data'],
17
- ports: [':5432'],
18
- },
19
- api: {
20
- image: 'node:16.6.0-alpine',
21
- deps: ['install'],
22
- needs: ['postgres'],
23
- ports: [':3000'],
24
- labels: {
25
- app: 'example',
26
- },
27
- src: ['index.js'],
28
- cmd: 'node index.js',
29
- },
30
- },
31
- tasks: {
32
- install: {
33
- image: 'node:16.6.0-alpine',
34
- src: ['package.json'],
35
- generates: ['node_modules'],
36
- cmds: ['npm install'],
37
- },
38
- },
39
- environments: {
40
- default: {
41
- kubernetes: {
42
- namespace: `hammerkit-k8s-${(process.env.HAMMERKIT_TEST_RUN_ID ?? 'local').slice(0, 40)}`,
43
- context: process.env.CLUSTER_NAME || 'docker-desktop',
44
- },
45
- },
46
- },
47
- },
48
- 'index.js': `const { Pool } = require('pg')
49
- const { createServer } = require('http')
50
-
51
- const pool = new Pool({
52
- connectionString: 'postgres://api:123456@postgres:5432/api',
53
- })
54
-
55
- pool.on('error', () => {
56
- console.error('pool has connection error')
57
- })
58
-
59
- const server = createServer(async function (req, res) {
60
- let client
61
- try {
62
- client = await pool.connect()
63
- const queryResult = await client.query('SELECT $1::text as message', ['Hello world from PG!'])
64
-
65
- res.writeHead(200)
66
- res.end(queryResult.rows[0].message)
67
- } catch (e) {
68
- res.writeHead(500)
69
- res.end(e.message)
70
- } finally {
71
- client?.release()
72
- }
73
- })
74
-
75
- process.on('SIGINT', async function () {
76
- server.close()
77
- await pool.end()
78
- })
79
-
80
- server.listen(3000, () => {
81
- console.log(\`Server is running on http://0.0.0.0:3000\`)
82
- })
83
- `,
84
- 'package.json': `{
85
- "name": "example-with-service",
86
- "version": "1.0.0",
87
- "dependencies": {
88
- "pg": "^8.7.1"
89
- }
90
- }
91
- `,
92
- });
93
- it('should create deployment', (0, requires_kubernetes_1.requiresKubernetes)(async () => {
94
- await suite.cli({}, async (cli) => {
95
- await cli.runUp({ daemon: true });
96
- });
97
- }));
98
- });
99
- //# sourceMappingURL=kubernetes.spec.js.map
@@ -1,42 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const get_test_suite_1 = require("../get-test-suite");
4
- describe('local', () => {
5
- const suite = (0, get_test_suite_1.getTestSuite)('labels', ['.hammerkit.yaml']);
6
- afterAll(() => suite.close());
7
- it('should run only run labeled task with app=bar and dependencies', async () => {
8
- const { cli } = await suite.setup({
9
- filterLabels: { app: ['bar'] },
10
- });
11
- expectNodes(cli.ls(), ['bar', 'base']);
12
- });
13
- it('should not run labeled task with app=foo and dependencies', async () => {
14
- const { cli } = await suite.setup({
15
- filterLabels: { app: ['foo'] },
16
- });
17
- expectNodes(cli.ls(), ['foo', 'base']);
18
- });
19
- it('should exclude foo labeled tasks', async () => {
20
- const { cli } = await suite.setup({
21
- excludeLabels: { app: ['foo'] },
22
- });
23
- expectNodes(cli.ls(), ['bar', 'base']);
24
- });
25
- it('should exclude base labeled tasks', async () => {
26
- const { cli } = await suite.setup({
27
- excludeLabels: { app: ['base'] },
28
- });
29
- expectNodes(cli.ls(), []);
30
- });
31
- it('should run tasks with label app=bar or app=foo', async () => {
32
- const { cli } = await suite.setup({
33
- filterLabels: { app: ['foo', 'bar'] },
34
- });
35
- expectNodes(cli.ls(), ['foo', 'bar', 'base']);
36
- });
37
- });
38
- function expectNodes(items, expectedNames) {
39
- const itemNames = items.map((n) => n.item.name);
40
- expect([...itemNames].sort()).toEqual([...expectedNames].sort());
41
- }
42
- //# sourceMappingURL=labels.spec.js.map
@@ -1,14 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const expect_1 = require("../expect");
4
- const get_test_suite_1 = require("../get-test-suite");
5
- describe('local', () => {
6
- const suite = (0, get_test_suite_1.getTestSuite)('local', ['.hammerkit.yaml']);
7
- afterAll(() => suite.close());
8
- it('should run local task', async () => {
9
- const { cli, environment } = await suite.setup({ taskName: 'example' });
10
- const result = await cli.runExec();
11
- await (0, expect_1.expectSuccessfulResult)(result, environment);
12
- });
13
- });
14
- //# sourceMappingURL=local.spec.js.map
@@ -1,15 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const expect_1 = require("../expect");
4
- const get_test_suite_1 = require("../get-test-suite");
5
- const requires_linux_containers_1 = require("../requires-linux-containers");
6
- describe('monorepo', () => {
7
- const suite = (0, get_test_suite_1.getTestSuite)('monorepo', ['.hammerkit.yaml', 'projects', 'build.npm.yaml', 'build.tsc.yaml']);
8
- afterAll(() => suite.close());
9
- it('should build and clean monorepo', (0, requires_linux_containers_1.requiresLinuxContainers)(async () => {
10
- const { cli, environment } = await suite.setup({ taskName: 'build' });
11
- await (0, expect_1.expectSuccessfulExecution)(cli.exec(), environment);
12
- await cli.clean();
13
- }), 900000);
14
- });
15
- //# sourceMappingURL=monorepo.spec.js.map
@@ -1,17 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const get_test_suite_1 = require("../get-test-suite");
4
- describe('multi-line', () => {
5
- const suite = (0, get_test_suite_1.getTestSuite)('multi-line', ['.hammerkit.yaml']);
6
- afterAll(() => suite.close());
7
- it('should get multi lines', async () => {
8
- const { cli } = await suite.setup({ taskName: 'example' });
9
- const task = cli.task('example');
10
- expect((task.data.cmds || []).map((c) => c.cmd)).toEqual([
11
- 'some very long cmd continues on line 2',
12
- 'some other very long cmd continues on line 2',
13
- ]);
14
- expect(task.data.description).toEqual('Test multiline description');
15
- });
16
- });
17
- //# sourceMappingURL=multi-line.spec.js.map
@@ -1,21 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const expect_1 = require("../expect");
4
- const get_test_suite_1 = require("../get-test-suite");
5
- describe('reference', () => {
6
- const suite = (0, get_test_suite_1.getTestSuite)('reference', ['.hammerkit.yaml', 'foo']);
7
- afterAll(() => suite.close());
8
- it('should run included task', async () => {
9
- const { cli, environment } = await suite.setup({ taskName: 'example' });
10
- const result = await cli.runExec();
11
- await (0, expect_1.expectSuccessfulResult)(result, environment);
12
- await (0, expect_1.expectLog)(result, environment, `foo:bar`, 'foobar');
13
- await (0, expect_1.expectLog)(result, environment, `example`, 'hammertime');
14
- });
15
- it('should list task with references tasks nested', async () => {
16
- const { cli } = await suite.setup({});
17
- const workItems = cli.ls();
18
- expect(workItems.map((t) => t.item.name)).toEqual(['foo:bardb', 'example', 'foo:bar', 'foo:sub:sub']);
19
- });
20
- });
21
- //# sourceMappingURL=reference.spec.js.map
@@ -1,38 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const get_test_suite_1 = require("../get-test-suite");
4
- const expect_1 = require("../expect");
5
- const testing_timeout_1 = require("../testing-timeout");
6
- const requires_linux_containers_1 = require("../requires-linux-containers");
7
- describe('services', () => {
8
- const suite = (0, get_test_suite_1.getTestSuite)('services', [
9
- 'index.js',
10
- 'server.js',
11
- 'config.json',
12
- 'package.json',
13
- 'package-lock.json',
14
- '.hammerkit.yaml',
15
- ]);
16
- afterAll(() => suite.close());
17
- it('should run with needed service', (0, requires_linux_containers_1.requiresLinuxContainers)(async () => {
18
- const { cli, environment } = await suite.setup({});
19
- const result = await (0, testing_timeout_1.testingTimeout)(cli.up({ daemon: true }), 120000);
20
- await (0, expect_1.expectSuccessfulResult)(result, environment);
21
- }), 900000);
22
- it('should start needs of service', (0, requires_linux_containers_1.requiresLinuxContainers)(async () => {
23
- const { cli, environment } = await suite.setup({ taskName: 'test' });
24
- const result = await (0, testing_timeout_1.testingTimeout)(cli.exec(), 120000);
25
- await (0, expect_1.expectSuccessfulResult)(result, environment);
26
- }), 900000);
27
- it('should start services up', (0, requires_linux_containers_1.requiresLinuxContainers)(async () => {
28
- const { cli } = await suite.setup({
29
- filterLabels: { task: ['dev'] },
30
- excludeLabels: {},
31
- });
32
- const upResult = await (0, testing_timeout_1.testingTimeout)(cli.up({ daemon: true }));
33
- expect(upResult.success).toBe(true);
34
- const downResult = await cli.runDown();
35
- expect(downResult.success).toBe(true);
36
- }), 900000);
37
- });
38
- //# sourceMappingURL=services.spec.js.map
@@ -1,52 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const path_1 = require("path");
4
- const get_test_suite_1 = require("../get-test-suite");
5
- const fs_1 = require("fs");
6
- const expect_1 = require("../expect");
7
- const requires_linux_containers_1 = require("../requires-linux-containers");
8
- describe('store/restore', () => {
9
- const suite = (0, get_test_suite_1.getTestSuite)('store-restore', ['.hammerkit.yaml', 'package.json']);
10
- afterAll(() => suite.close());
11
- it('should clean and restore created outputs locally', async () => {
12
- const { cli, environment } = await suite.setup({ taskName: 'example' });
13
- const generatedPath = (0, path_1.join)(environment.cwd, 'node_modules');
14
- const cacheStoragePath = (0, path_1.join)(environment.cwd, 'storage');
15
- expect((0, fs_1.existsSync)(generatedPath)).toBeFalsy();
16
- expect((0, fs_1.existsSync)(cacheStoragePath)).toBeFalsy();
17
- const result = await cli.runExec({});
18
- await (0, expect_1.expectSuccessfulResult)(result, environment);
19
- expect((0, fs_1.existsSync)(generatedPath)).toBeTruthy();
20
- expect((0, fs_1.existsSync)(cacheStoragePath)).toBeFalsy();
21
- await cli.store(cacheStoragePath);
22
- expect((0, fs_1.existsSync)(cacheStoragePath)).toBeTruthy();
23
- await cli.clean();
24
- expect((0, fs_1.existsSync)(generatedPath)).toBeFalsy();
25
- await cli.restore(cacheStoragePath);
26
- expect((0, fs_1.existsSync)(generatedPath)).toBeTruthy();
27
- const execAfterRestore = await cli.runExec();
28
- await (0, expect_1.expectSuccessfulResult)(execAfterRestore, environment);
29
- const taskState = execAfterRestore.state.tasks['example'];
30
- expect(taskState.state.current.type).toBe('completed');
31
- if (taskState.state.current.type === 'completed') {
32
- expect(taskState.state.current.cached).toBeTruthy();
33
- }
34
- });
35
- it('should clean and restore created outputs in container', (0, requires_linux_containers_1.requiresLinuxContainers)(async () => {
36
- const { cli, environment } = await suite.setup({ taskName: 'example:docker' });
37
- const cacheStoragePath = (0, path_1.join)(environment.cwd, 'storage');
38
- const firstExecResult = await cli.runExec();
39
- await (0, expect_1.expectSuccessfulResult)(firstExecResult, environment);
40
- await cli.store(cacheStoragePath);
41
- await cli.clean();
42
- await cli.restore(cacheStoragePath);
43
- const execAfterRestore = await cli.runExec();
44
- await (0, expect_1.expectSuccessfulResult)(execAfterRestore, environment);
45
- const taskState = execAfterRestore.state.tasks['example:docker'];
46
- expect(taskState.state.current.type).toBe('completed');
47
- if (taskState.state.current.type === 'completed') {
48
- expect(taskState.state.current.cached).toBeTruthy();
49
- }
50
- }), 900000);
51
- });
52
- //# sourceMappingURL=store.spec.js.map
@@ -1,28 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const test_case_1 = require("../test-case");
4
- const parse_error_1 = require("../../schema/parse-error");
5
- describe('unknown', () => {
6
- it('should validate unknown props', async () => {
7
- const testCase = (0, test_case_1.createTestCase)('wrong-cmd', {
8
- '.hammerkit.yaml': {
9
- example: {
10
- cmd: ['echo wrong cmd'],
11
- },
12
- },
13
- });
14
- await expect(testCase.cli({ taskName: 'example' })).rejects.toThrow(parse_error_1.ParseError);
15
- });
16
- it('should validate unknown container props for local tasks', async () => {
17
- const testCase = (0, test_case_1.createTestCase)('wrong-cmd', {
18
- '.hammerkit.yaml': {
19
- example: {
20
- cmds: ['echo hello'],
21
- mounts: ['/.npm:/.npm'],
22
- },
23
- },
24
- });
25
- await expect(testCase.cli({ taskName: 'example' })).rejects.toThrow(parse_error_1.ParseError);
26
- });
27
- });
28
- //# sourceMappingURL=unknown.spec.js.map
@@ -1,160 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const test_case_1 = require("../test-case");
4
- describe('validate', () => {
5
- async function validateTask(testCase, name, expectedErrors) {
6
- await testCase.cli({ taskName: name }, async (cli) => {
7
- let i = 0;
8
- for await (const message of cli.validate()) {
9
- expect(message.message).toEqual(expectedErrors[i++]);
10
- }
11
- expect(i).toEqual(expectedErrors.length);
12
- });
13
- }
14
- it('should validate local task', async () => {
15
- const testCase = (0, test_case_1.createTestCase)('valid_local_task', {
16
- '.hammerkit.yaml': {
17
- tasks: {
18
- valid_local_task: {
19
- description: 'build code',
20
- cmds: ['make'],
21
- },
22
- },
23
- },
24
- });
25
- await validateTask(testCase, 'valid_local_task', []);
26
- });
27
- it('should validate container task', async () => {
28
- const testCase = (0, test_case_1.createTestCase)('valid_container_task', {
29
- '.hammerkit.yaml': {
30
- tasks: {
31
- valid_container_task: {
32
- image: 'alpine',
33
- description: 'build code',
34
- cmds: ['make'],
35
- mounts: ['/.kube:/.kube'],
36
- },
37
- },
38
- },
39
- });
40
- await validateTask(testCase, 'valid_container_task', []);
41
- });
42
- it('should warn about tasks without description', async () => {
43
- const testCase = (0, test_case_1.createTestCase)('missing_doc', {
44
- '.hammerkit.yaml': {
45
- tasks: {
46
- missing_doc: {
47
- image: 'alpine',
48
- cmds: ['make'],
49
- mounts: ['/.kube:/.kube'],
50
- },
51
- },
52
- },
53
- });
54
- await validateTask(testCase, 'missing_doc', ['missing description']);
55
- });
56
- it('should detect empty tasks without cmds', async () => {
57
- const testCase = (0, test_case_1.createTestCase)('missing_cmd', {
58
- '.hammerkit.yaml': {
59
- tasks: {
60
- missing_cmd: {
61
- image: 'alpine',
62
- description: 'build code',
63
- mounts: ['/.kube:/.kube'],
64
- },
65
- },
66
- },
67
- });
68
- await validateTask(testCase, 'missing_cmd', ['task is empty']);
69
- });
70
- it('should allow only deps without cmds', async () => {
71
- const testCase = (0, test_case_1.createTestCase)('dep_only', {
72
- '.hammerkit.yaml': {
73
- tasks: {
74
- build: {
75
- cmds: ['make'],
76
- description: 'build code',
77
- },
78
- dep_only: {
79
- image: 'alpine',
80
- description: 'deps',
81
- deps: ['build'],
82
- },
83
- },
84
- },
85
- });
86
- await validateTask(testCase, 'dep_only', []);
87
- });
88
- it('should detect loop in dep', async () => {
89
- const testCase = (0, test_case_1.createTestCase)('loop_with_dep', {
90
- '.hammerkit.yaml': {
91
- tasks: {
92
- loop_with_dep: {
93
- image: 'alpine',
94
- description: 'build code',
95
- cmds: ['make'],
96
- deps: ['loop_with_dep'],
97
- },
98
- },
99
- },
100
- });
101
- await validateTask(testCase, 'loop_with_dep', ['task cycle detected loop_with_dep -> loop_with_dep']);
102
- });
103
- it('should detect loop in refs', async () => {
104
- const testCase = (0, test_case_1.createTestCase)('loop_with_refs', {
105
- '.hammerkit.yaml': {
106
- tasks: {
107
- loop_with_refs: {
108
- image: 'alpine',
109
- description: 'build code',
110
- cmds: ['make'],
111
- deps: ['ref:loop_with_refs'],
112
- },
113
- },
114
- references: { ref: '.hammerkit2.yaml' },
115
- },
116
- '.hammerkit2.yaml': {
117
- tasks: {
118
- loop_with_refs: {
119
- deps: ['ref:loop_with_refs'],
120
- image: 'alpine',
121
- description: 'build code',
122
- cmds: ['make 2'],
123
- },
124
- },
125
- references: { ref: '.hammerkit.yaml' },
126
- },
127
- });
128
- await validateTask(testCase, 'loop_with_refs', [
129
- 'task cycle detected loop_with_refs -> ref:loop_with_refs -> loop_with_refs',
130
- ]);
131
- });
132
- it('should detect loop over multiple tasks', async () => {
133
- const testCase = (0, test_case_1.createTestCase)('loop_with_multiple_tasks', {
134
- '.hammerkit.yaml': {
135
- tasks: {
136
- first: {
137
- image: 'alpine',
138
- description: 'build code',
139
- cmds: ['make 1'],
140
- deps: ['second'],
141
- },
142
- second: {
143
- image: 'alpine',
144
- description: 'build code',
145
- cmds: ['make 2'],
146
- deps: ['third'],
147
- },
148
- third: {
149
- image: 'alpine',
150
- description: 'build code',
151
- cmds: ['make 3'],
152
- deps: ['first'],
153
- },
154
- },
155
- },
156
- });
157
- await validateTask(testCase, 'first', ['task cycle detected first -> second -> third -> first']);
158
- });
159
- });
160
- //# sourceMappingURL=validate.spec.js.map