hammerkit 1.5.1 → 1.6.0-alpha.2
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.
- package/.agents/FEEDBACK.md +74 -0
- package/.agents/skills/before-commit/SKILL.md +101 -0
- package/.agents/skills/do-the-work/SKILL.md +64 -0
- package/.agents/skills/fix-ci/SKILL.md +98 -0
- package/.agents/skills/speckit-git-commit/SKILL.md +53 -0
- package/.agents/skills/speckit-git-feature/SKILL.md +72 -0
- package/.agents/skills/speckit-git-initialize/SKILL.md +54 -0
- package/.agents/skills/speckit-git-remote/SKILL.md +50 -0
- package/.agents/skills/speckit-git-validate/SKILL.md +54 -0
- package/.gitbook.yaml +5 -0
- package/.specify/extensions/.registry +37 -0
- package/.specify/extensions/git/README.md +100 -0
- package/.specify/extensions/git/commands/speckit.git.commit.md +48 -0
- package/.specify/extensions/git/commands/speckit.git.feature.md +67 -0
- package/.specify/extensions/git/commands/speckit.git.initialize.md +49 -0
- package/.specify/extensions/git/commands/speckit.git.remote.md +45 -0
- package/.specify/extensions/git/commands/speckit.git.validate.md +49 -0
- package/.specify/extensions/git/config-template.yml +62 -0
- package/.specify/extensions/git/extension.yml +140 -0
- package/.specify/extensions/git/git-config.yml +62 -0
- package/.specify/extensions.yml +149 -0
- package/.specify/feature.json +3 -0
- package/.specify/init-options.json +10 -0
- package/.specify/integration.json +15 -0
- package/.specify/integrations/claude.manifest.json +16 -0
- package/.specify/integrations/speckit.manifest.json +17 -0
- package/.specify/memory/constitution.md +162 -0
- package/.specify/templates/checklist-template.md +40 -0
- package/.specify/templates/constitution-template.md +50 -0
- package/.specify/templates/plan-template.md +113 -0
- package/.specify/templates/spec-template.md +131 -0
- package/.specify/templates/tasks-template.md +252 -0
- package/.specify/workflows/speckit/workflow.yml +77 -0
- package/.specify/workflows/workflow-registry.json +13 -0
- package/AGENTS.md +94 -0
- package/Dockerfile +3 -3
- package/FOLLOWUPS.md +34 -0
- package/README.md +9 -7
- package/SUMMARY.md +30 -5
- package/VALUES.md +53 -0
- package/build.schema.json +542 -408
- package/dist/cache/auto-pull.spec.js +123 -0
- package/dist/cache/backends/local-cache-backend.js +56 -0
- package/dist/cache/backends/local-cache-backend.spec.js +72 -0
- package/dist/cache/backends/s3-cache-backend.js +124 -0
- package/dist/cache/backends/s3-cache-backend.spec.js +118 -0
- package/dist/cache/cache-backend-registry.js +21 -0
- package/dist/cache/cache-backend-registry.spec.js +22 -0
- package/dist/cache/cache-backend.js +3 -0
- package/dist/cache/resolve-cache.js +60 -0
- package/dist/cache/resolve-cache.spec.js +52 -0
- package/dist/cli.js +112 -82
- package/dist/cli.spec.js +20 -2
- package/dist/console/get-logger.spec.js +23 -0
- package/dist/docker/get-default-platform.spec.js +29 -0
- package/dist/docker/longest-common-prefix.spec.js +26 -0
- package/dist/docker/package.js +283 -0
- package/dist/docker/package.spec.js +145 -0
- package/dist/docker/pull.js +4 -4
- package/dist/docker/remove-container.spec.js +32 -0
- package/dist/docker/stream.js +3 -3
- package/dist/docker/using-container.js +29 -11
- package/dist/docker/using-container.spec.js +90 -0
- package/dist/environment/merge-environment-variables.js +21 -0
- package/dist/environment/merge-environment-variables.spec.js +24 -0
- package/dist/environment/replace-env-variables.js +43 -10
- package/dist/environment/replace-env-variables.spec.js +47 -0
- package/dist/executer/abort.spec.js +18 -0
- package/dist/executer/await-completed-dependencies.js +56 -0
- package/dist/executer/cache-metadata.js +11 -0
- package/dist/executer/check-readiness.js +1 -1
- package/dist/{planner/work-node-port.js → executer/container-bind.js} +1 -1
- package/dist/executer/docker-service.js +110 -86
- package/dist/executer/docker-task.js +132 -0
- package/dist/executer/environment-mock.js +3 -4
- package/dist/executer/environment-mock.spec.js +22 -0
- package/dist/executer/event-cache.js +60 -127
- package/dist/executer/execute-command.js +4 -3
- package/dist/executer/execute-docker.js +32 -14
- package/dist/executer/execute-work-service.js +61 -0
- package/dist/executer/execute-work-task.js +107 -0
- package/dist/executer/execute-work-tree.js +27 -0
- package/dist/executer/execute.spec.js +14 -10
- package/dist/executer/execution-steps.js +47 -31
- package/dist/executer/get-container-binds.js +19 -0
- package/dist/executer/get-docker-executor.js +12 -12
- package/dist/executer/get-scheduler-down-result.js +12 -0
- package/dist/executer/get-scheduler-execute-result.js +28 -0
- package/dist/executer/get-scheduler-up-result.js +12 -0
- package/dist/executer/get-service-containers.js +14 -0
- package/dist/executer/get-service-containers.spec.js +59 -0
- package/dist/executer/get-service-env-hints.js +35 -0
- package/dist/executer/get-service-env-hints.spec.js +65 -0
- package/dist/executer/kubernetes-service.js +116 -48
- package/dist/executer/label-values.js +29 -46
- package/dist/executer/label-values.spec.js +61 -0
- package/dist/executer/lazy-resolver.js +16 -0
- package/dist/executer/lazy-resolver.spec.js +20 -0
- package/dist/executer/local-task.js +44 -0
- package/dist/executer/process-manager.js +16 -70
- package/dist/executer/process-manager.spec.js +39 -76
- package/dist/executer/reset-work-tree.js +30 -0
- package/dist/executer/scheduler/check-for-loop.js +17 -7
- package/dist/executer/scheduler/{scheduler-state.js → dependency-state.js} +1 -1
- package/dist/executer/scheduler/enqueue-next.js +83 -19
- package/dist/executer/scheduler/enqueue-next.spec.js +136 -0
- package/dist/executer/scheduler/{node-state.js → need-state.js} +1 -1
- package/dist/{parser/build-file.js → executer/scheduler/task-state.js} +1 -1
- package/dist/executer/set-user-permission.js +1 -1
- package/dist/executer/state-resolver.js +61 -0
- package/dist/executer/state-resolver.spec.js +37 -0
- package/dist/executer/state.js +37 -31
- package/dist/executer/state.spec.js +66 -0
- package/dist/executer/states.spec.js +14 -0
- package/dist/executer/watch-loop.js +68 -0
- package/dist/executer/watch-state-key.js +44 -0
- package/dist/executer/work-scope.js +1 -5
- package/dist/file/get-file-context.js +24 -3
- package/dist/file/get-file-context.spec.js +178 -0
- package/dist/file/move-files.js +2 -2
- package/dist/file/move-files.spec.js +48 -0
- package/dist/index.js +7 -8
- package/dist/json-schema.js +12 -0
- package/dist/kubernetes/apply.js +34 -0
- package/dist/kubernetes/await-running-state.js +71 -0
- package/dist/kubernetes/ensure-http-route.js +53 -0
- package/dist/kubernetes/ensure-http-route.spec.js +70 -0
- package/dist/kubernetes/ensure-ingress.js +54 -0
- package/dist/kubernetes/ensure-kubernetes-deployment-exists.js +105 -0
- package/dist/kubernetes/ensure-kubernetes-persistent-volume-claim-exists.js +40 -0
- package/dist/kubernetes/ensure-kubernetes-service-exists.js +36 -0
- package/dist/kubernetes/ensure-namespace.js +43 -0
- package/dist/kubernetes/ensure-namespace.spec.js +39 -0
- package/dist/kubernetes/ensure-persistent-data.js +158 -0
- package/dist/kubernetes/get-service-ip.js +11 -0
- package/dist/kubernetes/kubernetes-instance.js +48 -0
- package/dist/kubernetes/remove-persistent-data.js +19 -0
- package/dist/kubernetes/resolve-pod-name.js +42 -0
- package/dist/kubernetes/resolve-pod-name.spec.js +81 -0
- package/dist/kubernetes/resources.js +12 -0
- package/dist/kubernetes/restore-kubernetes-data.js +42 -0
- package/dist/kubernetes/store-kubernetes-data.js +39 -0
- package/dist/kubernetes/volumes.js +64 -0
- package/dist/log.js +69 -69
- package/dist/log.spec.js +131 -0
- package/dist/logging/grouped-logger.js +17 -15
- package/dist/logging/grouped-logger.spec.js +84 -0
- package/dist/logging/interactive-logger.js +1 -1
- package/dist/logging/interactive-logger.spec.js +57 -0
- package/dist/logging/live-logger.js +2 -2
- package/dist/logging/live-logger.spec.js +37 -0
- package/dist/logging/loggers.spec.js +154 -0
- package/dist/optimizer/calculate-checksum.spec.js +34 -0
- package/dist/optimizer/get-cache-directory.js +6 -6
- package/dist/optimizer/get-cache-directory.spec.js +59 -0
- package/dist/optimizer/get-work-cache-stats.js +53 -0
- package/dist/optimizer/get-work-cache-stats.spec.js +79 -0
- package/dist/{parser/build-file-task.js → optimizer/work-cache-stats.js} +1 -1
- package/dist/optimizer/work-task-cache-description.js +25 -0
- package/dist/optimizer/work-task-cache-description.spec.js +45 -0
- package/dist/parser/default-build-file.js +14 -7
- package/dist/parser/default-build-file.spec.js +48 -0
- package/dist/parser/parse-label-arguments.spec.js +27 -0
- package/dist/parser/read-build-file.js +2 -13
- package/dist/parser/read-build-file.spec.js +89 -0
- package/dist/parser/read-env-file.js +4 -5
- package/dist/parser/read-env-file.spec.js +42 -0
- package/dist/planner/utils/append-work-dependencies.js +55 -0
- package/dist/planner/utils/append-work-environment.js +22 -0
- package/dist/planner/utils/append-work-needs.js +18 -0
- package/dist/planner/utils/append-work-service.js +107 -0
- package/dist/planner/utils/append-work-service.spec.js +71 -0
- package/dist/planner/utils/append-work-task.js +81 -0
- package/dist/planner/utils/get-container-user.js +14 -0
- package/dist/planner/utils/get-container-user.spec.js +30 -0
- package/dist/planner/utils/get-default-kube-config.js +10 -0
- package/dist/planner/utils/get-default-kube-config.spec.js +11 -0
- package/dist/planner/utils/get-work-runtime.js +44 -0
- package/dist/planner/utils/normalize-path.js +1 -1
- package/dist/planner/utils/normalize-path.spec.js +24 -0
- package/dist/planner/utils/parse-work-command.js +80 -0
- package/dist/planner/utils/parse-work-command.spec.js +21 -0
- package/dist/planner/utils/parse-work-generate.js +38 -0
- package/dist/planner/utils/parse-work-generate.spec.js +45 -0
- package/dist/planner/utils/{parse-work-node-mount.js → parse-work-mount.js} +10 -7
- package/dist/planner/utils/{parse-work-node-mount.spec.js → parse-work-mount.spec.js} +14 -11
- package/dist/planner/utils/parse-work-mounts.js +13 -0
- package/dist/planner/utils/parse-work-mounts.spec.js +19 -0
- package/dist/planner/utils/{parse-work-node-port.js → parse-work-port.js} +11 -8
- package/dist/planner/utils/parse-work-port.spec.js +24 -0
- package/dist/planner/utils/parse-work-ports.js +10 -0
- package/dist/planner/utils/parse-work-ports.spec.js +24 -0
- package/dist/planner/utils/parse-work-source.js +72 -0
- package/dist/planner/utils/parse-work-source.spec.js +58 -0
- package/dist/planner/utils/parse-work-volume.js +45 -0
- package/dist/planner/utils/parse-work-volume.spec.js +18 -0
- package/dist/planner/utils/plan-work-tasks.js +41 -0
- package/dist/planner/utils/plan-work-tasks.spec.js +30 -0
- package/dist/planner/utils/plan-work-volume.js +1 -0
- package/dist/planner/utils/plan-work-volume.spec.js +33 -0
- package/dist/planner/utils/split-name.js +2 -2
- package/dist/planner/utils/split-name.spec.js +16 -0
- package/dist/planner/utils/template-value.js +1 -2
- package/dist/planner/utils/template-value.spec.js +14 -0
- package/dist/planner/validate.js +71 -38
- package/dist/planner/validate.spec.js +251 -0
- package/dist/planner/work-cache-id.js +12 -0
- package/dist/planner/work-cache-id.spec.js +173 -0
- package/dist/planner/work-command.js +3 -0
- package/dist/planner/work-environment.js +3 -0
- package/dist/planner/work-healthcheck.js +3 -0
- package/dist/planner/{work-node-status.js → work-item-status.js} +16 -62
- package/dist/{parser/build-file-service.js → planner/work-item-validation.js} +1 -1
- package/dist/planner/work-item.js +16 -0
- package/dist/{optimizer/work-node-cache-stats.js → planner/work-kubernetes-selector.js} +1 -1
- package/dist/planner/{work-nodes.js → work-port.js} +1 -1
- package/dist/planner/work-runtime-docker.js +224 -0
- package/dist/planner/work-runtime-kubernetes.js +264 -0
- package/dist/planner/work-runtime-local.js +109 -0
- package/dist/planner/work-runtime-local.spec.js +193 -0
- package/dist/planner/work-service-id.js +15 -5
- package/dist/planner/work-source.js +3 -0
- package/dist/planner/work-task.js +8 -0
- package/dist/program-commands.spec.js +84 -0
- package/dist/program.js +219 -73
- package/dist/program.spec.js +34 -11
- package/dist/run-program.js +28 -0
- package/dist/{executer/process.js → runtime/runtime.js} +1 -1
- package/dist/schema/build-file-base-task-schema.js +27 -0
- package/dist/schema/build-file-container-service-schema.js +28 -0
- package/dist/schema/build-file-container-task-schema.js +13 -0
- package/dist/schema/build-file-environment-schema-ingress.js +14 -0
- package/dist/schema/build-file-environment-schema.js +23 -0
- package/dist/schema/build-file-kubernetes-service-schema.js +17 -0
- package/dist/schema/build-file-kubernetes-service-selector-schema.js +9 -0
- package/dist/schema/build-file-local-platform-schema.js +9 -0
- package/dist/schema/build-file-local-task-schema.js +12 -0
- package/dist/schema/build-file-need-schema.js +12 -0
- package/dist/schema/build-file-schema.js +23 -0
- package/dist/schema/build-file-schema.spec.js +61 -0
- package/dist/schema/build-file-service-container-healthcheck.js +8 -0
- package/dist/schema/build-file-service-schema.js +15 -0
- package/dist/schema/build-file-task-command-schema.js +12 -0
- package/dist/schema/build-file-task-schema.js +12 -0
- package/dist/schema/build-file-volume-schema.js +14 -0
- package/dist/schema/cache-schema.js +31 -0
- package/dist/schema/doc-build-files.spec.js +223 -0
- package/dist/schema/envs-schema.js +6 -0
- package/dist/schema/labels-schema.js +6 -0
- package/dist/schema/parse-context.js +3 -0
- package/dist/schema/parse-error.js +12 -0
- package/dist/schema/parse-error.spec.js +18 -0
- package/dist/schema/reference-parser.js +209 -0
- package/dist/schema/reference-parser.spec.js +83 -0
- package/dist/schema/schema-parser.js +66 -0
- package/dist/schema/schema-parser.spec.js +80 -0
- package/dist/schema/type-guards.spec.js +23 -0
- package/dist/schema/work-scope-parser.js +77 -0
- package/dist/schema/work-scope-parser.spec.js +66 -0
- package/dist/service/update-service-status.js +11 -0
- package/dist/service/update-service-status.spec.js +27 -0
- package/dist/testing/ensure-local-registry.js +134 -0
- package/dist/testing/example-test-suite.js +16 -18
- package/dist/testing/expect.js +46 -22
- package/dist/testing/http-get.js +21 -0
- package/dist/testing/integration/cache.spec.js +13 -14
- package/dist/testing/integration/cancellation.spec.js +14 -9
- package/dist/testing/integration/clean.spec.js +14 -11
- package/dist/testing/integration/cmd.spec.js +1 -1
- package/dist/testing/integration/concurrency.spec.js +3 -3
- package/dist/testing/integration/docker-package-registry.spec.js +44 -0
- package/dist/testing/integration/docker-service-crash.spec.js +36 -0
- package/dist/testing/integration/docker.spec.js +4 -3
- package/dist/testing/integration/env.spec.js +9 -8
- package/dist/testing/integration/environment.spec.js +97 -0
- package/dist/testing/integration/error.spec.js +5 -4
- package/dist/testing/integration/export.spec.js +22 -0
- package/dist/testing/integration/extend.spec.js +9 -12
- package/dist/testing/integration/glob.spec.js +12 -20
- package/dist/testing/integration/include.spec.js +3 -3
- package/dist/testing/integration/invalid.spec.js +2 -3
- package/dist/testing/integration/invalid_loop.spec.js +49 -6
- package/dist/testing/integration/k8s-state-cache.spec.js +41 -0
- package/dist/testing/integration/kubernetes-service.spec.js +148 -0
- package/dist/testing/integration/kubernetes.spec.js +93 -9
- package/dist/testing/integration/labels.spec.js +6 -11
- package/dist/testing/integration/local.spec.js +1 -1
- package/dist/testing/integration/monorepo.spec.js +4 -4
- package/dist/testing/integration/multi-line.spec.js +3 -3
- package/dist/testing/integration/reference.spec.js +4 -5
- package/dist/testing/integration/services.spec.js +22 -4
- package/dist/testing/integration/store.spec.js +15 -16
- package/dist/testing/integration/unknown.spec.js +20 -18
- package/dist/testing/integration/validate.spec.js +143 -26
- package/dist/testing/integration/watch-dependency.spec.js +11 -8
- package/dist/testing/integration/watch.spec.js +15 -16
- package/dist/testing/requires-kubernetes.js +18 -0
- package/dist/testing/requires-linux-containers.js +18 -0
- package/dist/testing/requires-windows-containers.js +18 -0
- package/dist/testing/test-case.js +75 -0
- package/dist/testing/test-streams.js +28 -0
- package/dist/testing/testing-timeout.js +32 -0
- package/dist/utils/abort-event.js +10 -4
- package/dist/utils/abort-event.spec.js +46 -0
- package/dist/utils/buffer-context.js +44 -0
- package/dist/utils/buffer-context.spec.js +38 -0
- package/dist/utils/ci.spec.js +53 -0
- package/dist/utils/emitter.spec.js +34 -0
- package/dist/utils/empty-writable.spec.js +18 -0
- package/dist/utils/environment-config.js +4 -1
- package/dist/utils/environment-config.spec.js +26 -0
- package/dist/utils/fail-never.spec.js +9 -0
- package/dist/version.js +9 -0
- package/dist/version.spec.js +12 -0
- package/package.json +41 -23
- package/specs/build-file/caches/spec.md +114 -0
- package/specs/build-file/environment-variables/spec.md +82 -0
- package/specs/build-file/includes/spec.md +60 -0
- package/specs/build-file/references/spec.md +56 -0
- package/specs/build-file/spec.md +62 -0
- package/specs/cli/clean/spec.md +85 -0
- package/specs/cli/down/spec.md +85 -0
- package/specs/cli/execute/spec.md +101 -0
- package/specs/cli/init/spec.md +64 -0
- package/specs/cli/ls/spec.md +66 -0
- package/specs/cli/package/spec.md +110 -0
- package/specs/cli/spec.md +73 -0
- package/specs/cli/store-restore/spec.md +74 -0
- package/specs/cli/up/spec.md +80 -0
- package/specs/cli/validate/spec.md +70 -0
- package/specs/labels/spec.md +91 -0
- package/specs/service/container/spec.md +120 -0
- package/specs/service/kubernetes/spec.md +97 -0
- package/specs/service/spec.md +105 -0
- package/specs/task/caching/spec.md +107 -0
- package/specs/task/container/spec.md +118 -0
- package/specs/task/dependencies/spec.md +70 -0
- package/specs/task/extending/spec.md +74 -0
- package/specs/task/kubernetes/spec.md +125 -0
- package/specs/task/needs/spec.md +59 -0
- package/specs/task/spec.md +87 -0
- package/specs/task/watching/spec.md +69 -0
- package/dist/console/console-context-mock.js +0 -14
- package/dist/environment/get-process-env.js +0 -15
- package/dist/executer/create-scheduler-state.js +0 -32
- package/dist/executer/docker-node.js +0 -123
- package/dist/executer/hierarchy-scheduler.js +0 -94
- package/dist/executer/local-node.js +0 -57
- package/dist/executer/schedule.js +0 -137
- package/dist/executer/start-node.js +0 -67
- package/dist/executer/watch-node.js +0 -56
- package/dist/executer/watch-service.js +0 -54
- package/dist/file/get-file-context-mock.js +0 -187
- package/dist/file/get-file-context-mock.spec.js +0 -56
- package/dist/get-work-context.js +0 -29
- package/dist/optimizer/get-work-node-cache-stats.js +0 -104
- package/dist/optimizer/read-work-node-cache.js +0 -19
- package/dist/optimizer/work-node-cache-description.js +0 -32
- package/dist/optimizer/write-work-node-cache.js +0 -21
- package/dist/parser/build-file-task-command.js +0 -3
- package/dist/parser/build-file-task-platform.js +0 -3
- package/dist/parser/build-file-task-source.js +0 -3
- package/dist/parser/get-build-file.js +0 -9
- package/dist/parser/parse-boolean.js +0 -29
- package/dist/parser/parse-boolean.spec.js +0 -48
- package/dist/parser/parse-build-file-references.js +0 -35
- package/dist/parser/parse-build-file-services.js +0 -58
- package/dist/parser/parse-build-file-task-command.js +0 -36
- package/dist/parser/parse-build-file-task-source.js +0 -63
- package/dist/parser/parse-build-file.js +0 -125
- package/dist/parser/parse-context.js +0 -13
- package/dist/parser/parse-envs.js +0 -29
- package/dist/parser/parse-healthcheck.js +0 -28
- package/dist/parser/parse-service-selector.js +0 -39
- package/dist/parser/parse-string-array.js +0 -20
- package/dist/parser/parse-string-map.js +0 -30
- package/dist/parser/parse-string.js +0 -20
- package/dist/planner/utils/get-container-mounts.js +0 -24
- package/dist/planner/utils/parse-work-service-volume.js +0 -23
- package/dist/planner/utils/plan-work-command.js +0 -21
- package/dist/planner/utils/plan-work-dependency.js +0 -36
- package/dist/planner/utils/plan-work-node.js +0 -293
- package/dist/planner/utils/plan-work-nodes.js +0 -78
- package/dist/planner/utils/plan-work-tree.js +0 -15
- package/dist/planner/work-context.js +0 -23
- package/dist/planner/work-node-command.js +0 -3
- package/dist/planner/work-node-id.js +0 -12
- package/dist/planner/work-node-id.spec.js +0 -106
- package/dist/planner/work-node-path.js +0 -2
- package/dist/planner/work-node-source.js +0 -3
- package/dist/planner/work-node-validation.js +0 -3
- package/dist/planner/work-node.js +0 -8
- package/dist/planner/work-service-volume.js +0 -3
- package/dist/planner/work-services.js +0 -3
- package/dist/start-watch-processes.js +0 -28
- package/dist/testing/cli.js +0 -73
- package/dist/testing/create-build-file.js +0 -9
- package/dist/testing/get-logger.js +0 -23
- package/dist/testing/get-node.js +0 -12
- package/dist/testing/get-test-context.js +0 -19
- package/dist/testing/integration/program.spec.js +0 -25
- package/dist/testing/lazy.js +0 -17
- package/dist/testing/start-watch-processes.js +0 -29
- package/dist/testing/test-suite-options.js +0 -3
- package/dist/utils/abortable-function.js +0 -71
- package/logs/cache-console.log +0 -0
- package/logs/cache-status.log +0 -6
- package/logs/cache-stout.log +0 -0
- package/logs/cancellation-console.log +0 -0
- package/logs/cancellation-status.log +0 -3
- package/logs/cancellation-stout.log +0 -3
- package/logs/clean-console.log +0 -0
- package/logs/clean-status.log +0 -37
- package/logs/clean-stout.log +0 -95
- package/logs/cmd-console.log +0 -0
- package/logs/cmd-status.log +0 -8
- package/logs/cmd-stout.log +0 -9
- package/logs/concurrency-console.log +0 -0
- package/logs/concurrency-status.log +0 -14
- package/logs/concurrency-stout.log +0 -88
- package/logs/docker-console.log +0 -0
- package/logs/docker-status.log +0 -14
- package/logs/docker-stout.log +0 -39
- package/logs/env-console.log +0 -1
- package/logs/env-status.log +0 -1
- package/logs/env-stout.log +0 -0
- package/logs/error-console.log +0 -0
- package/logs/error-status.log +0 -10
- package/logs/error-stout.log +0 -36
- package/logs/extend-console.log +0 -0
- package/logs/extend-status.log +0 -1
- package/logs/extend-stout.log +0 -0
- package/logs/glob-console.log +0 -28
- package/logs/glob-status.log +0 -23
- package/logs/glob-stout.log +0 -52
- package/logs/hello-world-node-console.log +0 -0
- package/logs/hello-world-node-status.log +0 -37
- package/logs/hello-world-node-stout.log +0 -41
- package/logs/include-console.log +0 -0
- package/logs/include-status.log +0 -3
- package/logs/include-stout.log +0 -0
- package/logs/invalid-console.log +0 -0
- package/logs/invalid-status.log +0 -1
- package/logs/invalid-stout.log +0 -0
- package/logs/invalid_loop-console.log +0 -0
- package/logs/invalid_loop-status.log +0 -1
- package/logs/invalid_loop-stout.log +0 -11
- package/logs/labels-console.log +0 -0
- package/logs/labels-status.log +0 -1
- package/logs/labels-stout.log +0 -0
- package/logs/local-console.log +0 -0
- package/logs/local-status.log +0 -7
- package/logs/local-stout.log +0 -8
- package/logs/monorepo-console.log +0 -0
- package/logs/monorepo-status.log +0 -152
- package/logs/monorepo-stout.log +0 -2354
- package/logs/multi-line-console.log +0 -0
- package/logs/multi-line-status.log +0 -1
- package/logs/multi-line-stout.log +0 -0
- package/logs/reference-console.log +0 -0
- package/logs/reference-status.log +0 -5
- package/logs/reference-stout.log +0 -0
- package/logs/services-console.log +0 -0
- package/logs/services-status.log +0 -129
- package/logs/services-stout.log +0 -639
- package/logs/store-restore-console.log +0 -0
- package/logs/store-restore-status.log +0 -40
- package/logs/store-restore-stout.log +0 -97
- package/logs/unknown-console.log +0 -3
- package/logs/unknown-status.log +0 -1
- package/logs/unknown-stout.log +0 -0
- package/logs/validate-console.log +0 -0
- package/logs/validate-status.log +0 -2
- package/logs/validate-stout.log +0 -0
- package/logs/watch-console.log +0 -0
- package/logs/watch-dependency-console.log +0 -0
- package/logs/watch-dependency-status.log +0 -176
- package/logs/watch-dependency-stout.log +0 -779
- package/logs/watch-status.log +0 -100
- package/logs/watch-stout.log +0 -349
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ensureLocalRegistry = void 0;
|
|
7
|
+
const dockerode_1 = __importDefault(require("dockerode"));
|
|
8
|
+
const REGISTRY_NAME = 'hammerkit-test-registry';
|
|
9
|
+
const REGISTRY_IMAGE = 'registry:2';
|
|
10
|
+
// Small image with busybox wget, used to talk to the registry from the daemon's
|
|
11
|
+
// network (see why below). alpine is already pulled by the package suites.
|
|
12
|
+
const PROBE_IMAGE = 'alpine:3.19';
|
|
13
|
+
const MANAGED_PORT = Number(process.env.HAMMERKIT_TEST_REGISTRY_PORT) || 5000;
|
|
14
|
+
function registryAddressFromEnv() {
|
|
15
|
+
const fromEnv = process.env.REGISTRY;
|
|
16
|
+
if (!fromEnv) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const match = /^([^:]+):(\d+)$/.exec(fromEnv);
|
|
20
|
+
if (!match) {
|
|
21
|
+
throw new Error(`REGISTRY must be of the form host:port (got "${fromEnv}")`);
|
|
22
|
+
}
|
|
23
|
+
return { host: match[1], hostPort: parseInt(match[2], 10) };
|
|
24
|
+
}
|
|
25
|
+
async function ensureImage(docker, image) {
|
|
26
|
+
try {
|
|
27
|
+
await docker.getImage(image).inspect();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// not present locally — pull it below
|
|
32
|
+
}
|
|
33
|
+
await new Promise((resolve, reject) => {
|
|
34
|
+
docker.pull(image, (err, stream) => {
|
|
35
|
+
if (err || !stream) {
|
|
36
|
+
reject(err ?? new Error('no pull stream'));
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
docker.modem.followProgress(stream, (e) => (e ? reject(e) : resolve()));
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
// Run a throwaway container on the *host* network and return its exit code.
|
|
44
|
+
// The registry is reachable at 127.0.0.1:<port> from the daemon's network (see
|
|
45
|
+
// ensureLocalRegistry), but not necessarily from this (host) process — on Docker
|
|
46
|
+
// Desktop the daemon is in a VM — so registry HTTP is done from here instead.
|
|
47
|
+
async function runOnHostNet(docker, shellCmd) {
|
|
48
|
+
await ensureImage(docker, PROBE_IMAGE);
|
|
49
|
+
const container = await docker.createContainer({
|
|
50
|
+
Image: PROBE_IMAGE,
|
|
51
|
+
Cmd: ['sh', '-c', shellCmd],
|
|
52
|
+
HostConfig: { NetworkMode: 'host', AutoRemove: false },
|
|
53
|
+
});
|
|
54
|
+
try {
|
|
55
|
+
await container.start();
|
|
56
|
+
const res = await container.wait();
|
|
57
|
+
return res.StatusCode ?? 1;
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
await container.remove({ force: true }).catch(() => undefined);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Returns a docker registry suitable for `cli.package({ registry, push: true, ... })`.
|
|
65
|
+
*
|
|
66
|
+
* Resolution order:
|
|
67
|
+
* 1. `REGISTRY=host:port` env var (used by CI; just probed for liveness, never managed).
|
|
68
|
+
* 2. A managed `registry:2` container on the daemon's own network (host networking).
|
|
69
|
+
*
|
|
70
|
+
* Host networking matters: the daemon performs the push, and an HTTP push needs a
|
|
71
|
+
* `127.0.0.1`/`localhost` address (the only registries docker treats as insecure
|
|
72
|
+
* without daemon config). On Docker Desktop the daemon runs in a VM, so a
|
|
73
|
+
* host-*published* port is not reachable from it via 127.0.0.1 (`docker push
|
|
74
|
+
* 127.0.0.1:<published>` → connection refused). Putting the registry on the
|
|
75
|
+
* daemon's network makes 127.0.0.1:<port> resolve to it. Because this process
|
|
76
|
+
* (on the host) then can't see the registry, liveness and tag lookups run inside
|
|
77
|
+
* a throwaway container on the same network — see `listsTag`.
|
|
78
|
+
*
|
|
79
|
+
* Callers must invoke `cleanup()`. For the env-var case it is a no-op.
|
|
80
|
+
*/
|
|
81
|
+
async function ensureLocalRegistry(docker) {
|
|
82
|
+
const d = docker ?? new dockerode_1.default();
|
|
83
|
+
const fromEnv = registryAddressFromEnv();
|
|
84
|
+
let host;
|
|
85
|
+
let hostPort;
|
|
86
|
+
let cleanup = async () => undefined;
|
|
87
|
+
if (fromEnv) {
|
|
88
|
+
host = fromEnv.host;
|
|
89
|
+
hostPort = fromEnv.hostPort;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
host = '127.0.0.1';
|
|
93
|
+
hostPort = MANAGED_PORT;
|
|
94
|
+
await ensureImage(d, REGISTRY_IMAGE);
|
|
95
|
+
const existing = await d.listContainers({ all: true, filters: { name: [REGISTRY_NAME] } });
|
|
96
|
+
if (existing.length === 0) {
|
|
97
|
+
const container = await d.createContainer({
|
|
98
|
+
Image: REGISTRY_IMAGE,
|
|
99
|
+
name: REGISTRY_NAME,
|
|
100
|
+
Env: [`REGISTRY_HTTP_ADDR=0.0.0.0:${MANAGED_PORT}`],
|
|
101
|
+
HostConfig: { AutoRemove: true, NetworkMode: 'host' },
|
|
102
|
+
});
|
|
103
|
+
await container.start();
|
|
104
|
+
}
|
|
105
|
+
else if (existing[0].State !== 'running') {
|
|
106
|
+
await d.getContainer(existing[0].Id).start();
|
|
107
|
+
}
|
|
108
|
+
cleanup = async () => {
|
|
109
|
+
const c = (await d.listContainers({ all: true, filters: { name: [REGISTRY_NAME] } }))[0];
|
|
110
|
+
if (c) {
|
|
111
|
+
await d
|
|
112
|
+
.getContainer(c.Id)
|
|
113
|
+
.remove({ force: true })
|
|
114
|
+
.catch(() => undefined);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
const base = `http://${host}:${hostPort}`;
|
|
119
|
+
const reachable = await runOnHostNet(d, `for i in $(seq 1 60); do wget -q -O /dev/null ${base}/v2/ && exit 0; sleep 1; done; exit 1`);
|
|
120
|
+
if (reachable !== 0) {
|
|
121
|
+
throw new Error(`docker registry at ${host}:${hostPort} did not become reachable in time`);
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
host,
|
|
125
|
+
hostPort,
|
|
126
|
+
cleanup,
|
|
127
|
+
async listsTag(repository, tag) {
|
|
128
|
+
const code = await runOnHostNet(d, `wget -qO- ${base}/v2/${repository}/tags/list | grep -q '"${tag}"'`);
|
|
129
|
+
return code === 0;
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
exports.ensureLocalRegistry = ensureLocalRegistry;
|
|
134
|
+
//# sourceMappingURL=ensure-local-registry.js.map
|
|
@@ -3,14 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ExampleTestSuite = void 0;
|
|
4
4
|
const path_1 = require("path");
|
|
5
5
|
const get_file_context_1 = require("../file/get-file-context");
|
|
6
|
-
const
|
|
6
|
+
const work_item_status_1 = require("../planner/work-item-status");
|
|
7
7
|
const program_1 = require("../program");
|
|
8
|
-
const execute_docker_1 = require("../executer/execute-docker");
|
|
9
|
-
const fs_1 = require("fs");
|
|
10
8
|
const log_1 = require("../log");
|
|
9
|
+
const test_streams_1 = require("./test-streams");
|
|
11
10
|
class ExampleTestSuite {
|
|
12
11
|
constructor(exampleName, files) {
|
|
13
|
-
this.exampleName = exampleName;
|
|
14
12
|
this.files = files;
|
|
15
13
|
this.tests = [];
|
|
16
14
|
this.exampleDirectory = (0, path_1.join)(__dirname, '../../examples/', exampleName);
|
|
@@ -19,29 +17,23 @@ class ExampleTestSuite {
|
|
|
19
17
|
}
|
|
20
18
|
async close() {
|
|
21
19
|
for (const test of this.tests) {
|
|
20
|
+
test.close();
|
|
22
21
|
await this.file.remove(test.cwd);
|
|
23
22
|
}
|
|
24
23
|
}
|
|
25
24
|
async setup(scope) {
|
|
26
25
|
await this.file.remove(this.path);
|
|
27
26
|
await this.file.createDirectory(this.path);
|
|
28
|
-
const
|
|
29
|
-
const stdoutFile = (0, path_1.join)(logPath, this.exampleName + '-stout.log');
|
|
30
|
-
const statusFile = (0, path_1.join)(logPath, this.exampleName + '-status.log');
|
|
31
|
-
const consoleFile = (0, path_1.join)(logPath, this.exampleName + '-console.log');
|
|
32
|
-
await this.file.createDirectory(logPath);
|
|
33
|
-
await this.file.remove(stdoutFile);
|
|
34
|
-
await this.file.remove(statusFile);
|
|
35
|
-
await this.file.remove(consoleFile);
|
|
27
|
+
const statusStream = (0, test_streams_1.memoryStream)();
|
|
36
28
|
const environment = {
|
|
37
29
|
processEnvs: { ...process.env, ...(scope.envs ?? {}) },
|
|
38
30
|
abortCtrl: new AbortController(),
|
|
39
31
|
cwd: this.path,
|
|
40
32
|
file: this.file,
|
|
41
|
-
console: (0, log_1.consoleContext)((0,
|
|
42
|
-
status: (0,
|
|
43
|
-
|
|
44
|
-
|
|
33
|
+
console: (0, log_1.consoleContext)((0, test_streams_1.emptyStream)()),
|
|
34
|
+
status: (0, work_item_status_1.statusConsole)(statusStream.stream),
|
|
35
|
+
stdout: (0, test_streams_1.emptyStream)(),
|
|
36
|
+
stderr: (0, test_streams_1.emptyStream)(),
|
|
45
37
|
stdoutColumns: 80,
|
|
46
38
|
};
|
|
47
39
|
for (const file of this.files) {
|
|
@@ -50,11 +42,17 @@ class ExampleTestSuite {
|
|
|
50
42
|
const fileName = (0, path_1.join)(this.path, '.hammerkit.yaml');
|
|
51
43
|
this.tests.push({
|
|
52
44
|
cwd: this.path,
|
|
45
|
+
close() {
|
|
46
|
+
environment.abortCtrl.abort();
|
|
47
|
+
},
|
|
53
48
|
});
|
|
54
49
|
const cli = await (0, program_1.createCli)(fileName, environment, scope);
|
|
55
|
-
|
|
50
|
+
// clear the backend cache too: the default `local` backend persists under
|
|
51
|
+
// ~/.hammerkit/remote-cache outside the test's temp dir, so without this a
|
|
52
|
+
// prior run's result would leak in and make cache assertions flaky.
|
|
53
|
+
await cli.clean({ cache: true });
|
|
56
54
|
// reset cli clean stats
|
|
57
|
-
environment.status = (0,
|
|
55
|
+
environment.status = (0, work_item_status_1.statusConsole)(statusStream.stream);
|
|
58
56
|
return {
|
|
59
57
|
cli,
|
|
60
58
|
environment,
|
package/dist/testing/expect.js
CHANGED
|
@@ -1,24 +1,48 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.expectContainsLog = exports.expectLog = exports.expectSuccessfulResult = void 0;
|
|
4
|
-
const
|
|
3
|
+
exports.expectContainsLog = exports.expectLog = exports.expectSuccessfulResult = exports.expectSuccessfulExecution = void 0;
|
|
4
|
+
const plan_work_tasks_1 = require("../planner/utils/plan-work-tasks");
|
|
5
|
+
const get_scheduler_execute_result_1 = require("../executer/get-scheduler-execute-result");
|
|
6
|
+
const testing_timeout_1 = require("./testing-timeout");
|
|
7
|
+
async function expectSuccessfulExecution(exec, env) {
|
|
8
|
+
const badResult = new Promise((resolve) => {
|
|
9
|
+
exec.state.on('expected-status', (workTree) => {
|
|
10
|
+
if (env.abortCtrl.signal.aborted) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const hasErrorTask = Object.values(workTree.tasks).some((n) => n.state.current.type === 'error' || n.state.current.type === 'crash');
|
|
14
|
+
const hasErrorService = Object.values(workTree.services).some((n) => n.state.current.type === 'error' || n.state.current.type === 'end');
|
|
15
|
+
if (!hasErrorTask && !hasErrorService) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const stateResult = (0, get_scheduler_execute_result_1.getSchedulerExecuteResult)(workTree);
|
|
19
|
+
if (!stateResult.success) {
|
|
20
|
+
resolve(stateResult);
|
|
21
|
+
env.abortCtrl.abort();
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
const result = await Promise.race([badResult, (0, testing_timeout_1.testingTimeout)(exec)]);
|
|
26
|
+
await expectSuccessfulResult(result, env);
|
|
27
|
+
}
|
|
28
|
+
exports.expectSuccessfulExecution = expectSuccessfulExecution;
|
|
5
29
|
async function expectSuccessfulResult(result, env) {
|
|
6
30
|
if (!result.success) {
|
|
7
|
-
for (const
|
|
8
|
-
if (state.type !== 'completed') {
|
|
31
|
+
for (const task of (0, plan_work_tasks_1.iterateWorkTasks)(result.state)) {
|
|
32
|
+
if (task.state.current.type !== 'completed') {
|
|
9
33
|
expect({
|
|
10
|
-
|
|
11
|
-
status: state.type,
|
|
12
|
-
updates: Array.from(
|
|
13
|
-
logs: Array.from(
|
|
14
|
-
errorMessage: state.type === 'error' ? state.errorMessage : undefined,
|
|
15
|
-
needs:
|
|
34
|
+
cacheId: task.id(),
|
|
35
|
+
status: task.state.current.type,
|
|
36
|
+
updates: Array.from(task.status.read()).map((s) => `${s.level}: ${s.message}`),
|
|
37
|
+
logs: Array.from(task.status.logs()).map((l) => `${l.console}: ${l.message}`),
|
|
38
|
+
errorMessage: task.state.current.type === 'error' ? task.state.current.errorMessage : undefined,
|
|
39
|
+
needs: task.needs.map((need) => ({
|
|
16
40
|
name: need.name,
|
|
17
|
-
updates: Array.from(
|
|
18
|
-
logs: Array.from(
|
|
41
|
+
updates: Array.from(need.service.status.read()).map((s) => `${s.level}: ${s.message}`),
|
|
42
|
+
logs: Array.from(need.service.status.logs()).map((l) => `${l.console}: ${l.message}`),
|
|
19
43
|
})),
|
|
20
44
|
}).toEqual({
|
|
21
|
-
|
|
45
|
+
cacheId: task.id(),
|
|
22
46
|
status: 'completed',
|
|
23
47
|
});
|
|
24
48
|
}
|
|
@@ -31,22 +55,22 @@ async function expectSuccessfulResult(result, env) {
|
|
|
31
55
|
expect(errorStatus).toEqual([]);
|
|
32
56
|
}
|
|
33
57
|
exports.expectSuccessfulResult = expectSuccessfulResult;
|
|
34
|
-
function
|
|
35
|
-
const
|
|
36
|
-
if (!
|
|
37
|
-
throw new Error(`could not find
|
|
58
|
+
function getTaskState(state, name) {
|
|
59
|
+
const tasks = Object.values(state.tasks).find((n) => n.name === name);
|
|
60
|
+
if (!tasks) {
|
|
61
|
+
throw new Error(`could not find task ${name}`);
|
|
38
62
|
}
|
|
39
|
-
return
|
|
63
|
+
return tasks;
|
|
40
64
|
}
|
|
41
65
|
async function expectLog(result, env, name, message) {
|
|
42
|
-
const state =
|
|
43
|
-
const logs = Array.from(
|
|
66
|
+
const state = getTaskState(result.state, name);
|
|
67
|
+
const logs = Array.from(state.status.logs()).map((n) => n.message);
|
|
44
68
|
expect(logs).toContain(message);
|
|
45
69
|
}
|
|
46
70
|
exports.expectLog = expectLog;
|
|
47
71
|
async function expectContainsLog(result, env, name, message) {
|
|
48
|
-
const state =
|
|
49
|
-
const logs =
|
|
72
|
+
const state = getTaskState(result.state, name);
|
|
73
|
+
const logs = state.status.logs();
|
|
50
74
|
for (const log of logs) {
|
|
51
75
|
if (log.message.indexOf(message) >= 0) {
|
|
52
76
|
return;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.httpGet = void 0;
|
|
4
|
+
const http_1 = require("http");
|
|
5
|
+
function httpGet(host, port, path, timeoutMs = 10000) {
|
|
6
|
+
return new Promise((resolve, reject) => {
|
|
7
|
+
const req = (0, http_1.request)({ host, port, path, method: 'GET', timeout: timeoutMs }, (res) => {
|
|
8
|
+
const chunks = [];
|
|
9
|
+
res.on('data', (chunk) => chunks.push(chunk));
|
|
10
|
+
res.on('end', () => resolve({ status: res.statusCode ?? 0, body: Buffer.concat(chunks).toString('utf8') }));
|
|
11
|
+
res.on('error', reject);
|
|
12
|
+
});
|
|
13
|
+
req.on('error', reject);
|
|
14
|
+
req.on('timeout', () => {
|
|
15
|
+
req.destroy(new Error(`timeout after ${timeoutMs}ms`));
|
|
16
|
+
});
|
|
17
|
+
req.end();
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
exports.httpGet = httpGet;
|
|
21
|
+
//# sourceMappingURL=http-get.js.map
|
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
require("jest-extended");
|
|
4
|
-
const write_work_node_cache_1 = require("../../optimizer/write-work-node-cache");
|
|
5
3
|
const expect_1 = require("../expect");
|
|
6
4
|
const get_test_suite_1 = require("../get-test-suite");
|
|
7
5
|
const path_1 = require("path");
|
|
8
6
|
const enqueue_next_1 = require("../../executer/scheduler/enqueue-next");
|
|
9
7
|
const read_build_file_1 = require("../../parser/read-build-file");
|
|
8
|
+
const requires_linux_containers_1 = require("../requires-linux-containers");
|
|
10
9
|
describe('cache', () => {
|
|
11
10
|
const suite = (0, get_test_suite_1.getTestSuite)('cache', ['.hammerkit.yaml', 'package.json', 'package-lock.json']);
|
|
12
11
|
afterAll(() => suite.close());
|
|
13
12
|
async function testCache(action, expectInvalidate) {
|
|
14
13
|
const setupBefore = await suite.setup({ taskName: 'example' });
|
|
15
|
-
const
|
|
16
|
-
await (0,
|
|
14
|
+
const result = await setupBefore.cli.exec().start();
|
|
15
|
+
await (0, expect_1.expectSuccessfulResult)(result, setupBefore.environment);
|
|
17
16
|
await action(setupBefore.environment);
|
|
18
17
|
const setupAfter = await suite.setup({ taskName: 'example' });
|
|
19
|
-
const
|
|
20
|
-
const checksumUpToDate = await (0, enqueue_next_1.checkCacheState)(
|
|
21
|
-
const modifyDateUpToDate = await (0, enqueue_next_1.checkCacheState)(
|
|
18
|
+
const task = setupAfter.cli.task('example');
|
|
19
|
+
const checksumUpToDate = await (0, enqueue_next_1.checkCacheState)(task, 'checksum', setupAfter.environment);
|
|
20
|
+
const modifyDateUpToDate = await (0, enqueue_next_1.checkCacheState)(task, 'modify-date', setupAfter.environment);
|
|
22
21
|
if (expectInvalidate) {
|
|
23
22
|
expect(checksumUpToDate.cached).toBeFalsy();
|
|
24
23
|
expect(modifyDateUpToDate.cached).toBeFalsy();
|
|
@@ -28,23 +27,23 @@ describe('cache', () => {
|
|
|
28
27
|
expect(modifyDateUpToDate.cached).toBeTruthy();
|
|
29
28
|
}
|
|
30
29
|
}
|
|
31
|
-
it('should run invalid cache on src file change', async () => {
|
|
30
|
+
it('should run invalid cache on src file change', (0, requires_linux_containers_1.requiresLinuxContainers)(async () => {
|
|
32
31
|
await testCache(async (environment) => {
|
|
33
32
|
await environment.file.appendFile((0, path_1.join)(environment.cwd, 'package.json'), '\n');
|
|
34
33
|
}, true);
|
|
35
|
-
});
|
|
36
|
-
it('should mount generations of dependant tasks', async () => {
|
|
34
|
+
}));
|
|
35
|
+
it('should mount generations of dependant tasks', (0, requires_linux_containers_1.requiresLinuxContainers)(async () => {
|
|
37
36
|
const { cli, environment } = await suite.setup({ taskName: 'dependant' });
|
|
38
|
-
const result = await cli.
|
|
37
|
+
const result = await cli.runExec();
|
|
39
38
|
await (0, expect_1.expectSuccessfulResult)(result, environment);
|
|
40
39
|
await (0, expect_1.expectLog)(result, environment, `dependant`, 'node_modules');
|
|
41
|
-
});
|
|
42
|
-
it('should invalid cache on image change', async () => {
|
|
40
|
+
}));
|
|
41
|
+
it('should invalid cache on image change', (0, requires_linux_containers_1.requiresLinuxContainers)(async () => {
|
|
43
42
|
await testCache(async (environment) => {
|
|
44
43
|
const buildFile = await (0, read_build_file_1.read)('.hammerkit.yaml', environment);
|
|
45
44
|
buildFile.tasks['example'].image = '15.0.0';
|
|
46
45
|
await (0, read_build_file_1.write)('.hammerkit.yaml', buildFile, environment);
|
|
47
46
|
}, true);
|
|
48
|
-
});
|
|
47
|
+
}));
|
|
49
48
|
});
|
|
50
49
|
//# sourceMappingURL=cache.spec.js.map
|
|
@@ -2,22 +2,24 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const path_1 = require("path");
|
|
4
4
|
const get_test_suite_1 = require("../get-test-suite");
|
|
5
|
+
const requires_linux_containers_1 = require("../requires-linux-containers");
|
|
5
6
|
describe('cancellation', () => {
|
|
6
7
|
const suite = (0, get_test_suite_1.getTestSuite)('cancellation', ['.hammerkit.yaml']);
|
|
7
8
|
afterAll(() => suite.close());
|
|
8
9
|
async function testAbort(taskName, expectedState) {
|
|
9
10
|
const { cli, environment } = await suite.setup({ taskName });
|
|
10
|
-
const exec = await cli.
|
|
11
|
-
const abortNode = Object.values(exec.state.current.
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
const exec = await cli.exec({ logMode: 'live' });
|
|
12
|
+
const abortNode = Object.values(exec.state.current.tasks).find((n) => n.data.name.startsWith('long_'));
|
|
13
|
+
expect_toBeDefined(abortNode);
|
|
14
|
+
exec.state.on('check-status', (evt) => {
|
|
15
|
+
if (evt.tasks[abortNode.name].state.current.type === 'running') {
|
|
14
16
|
environment.abortCtrl.abort();
|
|
15
17
|
}
|
|
16
18
|
});
|
|
17
19
|
const result = await exec.start();
|
|
18
20
|
expect(result.success).toBeFalsy();
|
|
19
21
|
if (abortNode) {
|
|
20
|
-
expect(
|
|
22
|
+
expect(abortNode.state.current.type).toEqual(expectedState);
|
|
21
23
|
}
|
|
22
24
|
else {
|
|
23
25
|
expect(abortNode).toBeDefined();
|
|
@@ -30,11 +32,14 @@ describe('cancellation', () => {
|
|
|
30
32
|
it('should cancel local task', async () => {
|
|
31
33
|
await testAbort('long_running_local', 'canceled');
|
|
32
34
|
});
|
|
33
|
-
it('should cancel docker task', async () => {
|
|
35
|
+
it('should cancel docker task', (0, requires_linux_containers_1.requiresLinuxContainers)(async () => {
|
|
34
36
|
await testAbort('long_running_docker', 'canceled');
|
|
35
|
-
});
|
|
36
|
-
it('should cancel docker task with dependencies', async () => {
|
|
37
|
+
}));
|
|
38
|
+
it('should cancel docker task with dependencies', (0, requires_linux_containers_1.requiresLinuxContainers)(async () => {
|
|
37
39
|
await testAbort('docker_cancel', 'canceled');
|
|
38
|
-
});
|
|
40
|
+
}));
|
|
39
41
|
});
|
|
42
|
+
function expect_toBeDefined(arg) {
|
|
43
|
+
expect(arg).toBeDefined();
|
|
44
|
+
}
|
|
40
45
|
//# sourceMappingURL=cancellation.spec.js.map
|
|
@@ -6,35 +6,38 @@ const expect_1 = require("../expect");
|
|
|
6
6
|
const get_test_suite_1 = require("../get-test-suite");
|
|
7
7
|
const get_docker_executor_1 = require("../../executer/get-docker-executor");
|
|
8
8
|
const plan_work_volume_1 = require("../../planner/utils/plan-work-volume");
|
|
9
|
+
const execute_docker_1 = require("../../executer/execute-docker");
|
|
10
|
+
const requires_linux_containers_1 = require("../requires-linux-containers");
|
|
9
11
|
describe('clean', () => {
|
|
10
12
|
const suite = (0, get_test_suite_1.getTestSuite)('clean', ['.hammerkit.yaml', 'package.json']);
|
|
11
13
|
afterAll(() => suite.close());
|
|
12
14
|
it('should clean generated outputs locally', async () => {
|
|
13
15
|
const { cli, environment } = await suite.setup({ taskName: 'example' });
|
|
14
|
-
const result = await cli.
|
|
16
|
+
const result = await cli.runExec({ cacheDefault: 'none' });
|
|
15
17
|
await (0, expect_1.expectSuccessfulResult)(result, environment);
|
|
16
18
|
const outputPath = (0, path_1.join)(suite.path, 'node_modules');
|
|
17
19
|
expect((0, fs_1.existsSync)(outputPath)).toBeTruthy();
|
|
18
20
|
await cli.clean();
|
|
19
21
|
expect((0, fs_1.existsSync)(outputPath)).toBeFalsy();
|
|
20
22
|
});
|
|
21
|
-
it('should clean generated outputs in containers', async () => {
|
|
23
|
+
it('should clean generated outputs in containers', (0, requires_linux_containers_1.requiresLinuxContainers)(async () => {
|
|
22
24
|
const { cli, environment } = await suite.setup({ taskName: 'docker:example' });
|
|
23
|
-
const result = await cli.
|
|
25
|
+
const result = await cli.runExec({ cacheDefault: 'none' });
|
|
24
26
|
await (0, expect_1.expectSuccessfulResult)(result, environment);
|
|
27
|
+
const docker = (0, execute_docker_1.getContainerCli)({ type: 'docker' });
|
|
25
28
|
const outputPath = (0, path_1.join)(suite.path, 'node_modules');
|
|
26
29
|
const volumeName = (0, plan_work_volume_1.getVolumeName)(outputPath);
|
|
27
|
-
expect(await (0, get_docker_executor_1.existsVolume)(
|
|
30
|
+
expect(await (0, get_docker_executor_1.existsVolume)(docker, volumeName)).toBeTruthy();
|
|
28
31
|
await cli.clean();
|
|
29
|
-
expect(await (0, get_docker_executor_1.existsVolume)(
|
|
30
|
-
});
|
|
31
|
-
it('should clean and restore created data in volumes', async () => {
|
|
32
|
+
expect(await (0, get_docker_executor_1.existsVolume)(docker, volumeName)).toBeFalsy();
|
|
33
|
+
}));
|
|
34
|
+
it('should clean and restore created data in volumes', (0, requires_linux_containers_1.requiresLinuxContainers)(async () => {
|
|
32
35
|
const { cli, environment } = await suite.setup({ taskName: 'example:service' });
|
|
33
|
-
const result = await cli.
|
|
36
|
+
const result = await cli.runExec();
|
|
34
37
|
await (0, expect_1.expectSuccessfulResult)(result, environment);
|
|
35
|
-
await cli.clean(
|
|
36
|
-
const resultAfterClean = await cli.
|
|
38
|
+
await cli.clean();
|
|
39
|
+
const resultAfterClean = await cli.runExec();
|
|
37
40
|
await (0, expect_1.expectSuccessfulResult)(resultAfterClean, environment);
|
|
38
|
-
});
|
|
41
|
+
}));
|
|
39
42
|
});
|
|
40
43
|
//# sourceMappingURL=clean.spec.js.map
|
|
@@ -7,7 +7,7 @@ describe('cmd', () => {
|
|
|
7
7
|
afterAll(() => suite.close());
|
|
8
8
|
it('should run with path arg', async () => {
|
|
9
9
|
const { cli, environment } = await suite.setup({ taskName: 'example' });
|
|
10
|
-
const result = await cli.
|
|
10
|
+
const result = await cli.runExec();
|
|
11
11
|
await (0, expect_1.expectSuccessfulResult)(result, environment);
|
|
12
12
|
await (0, expect_1.expectContainsLog)(result, environment, `example`, 'README.md');
|
|
13
13
|
});
|
|
@@ -7,9 +7,9 @@ describe('concurrency', () => {
|
|
|
7
7
|
afterAll(() => suite.close());
|
|
8
8
|
it('should run with concurrency lower than total tasks', async () => {
|
|
9
9
|
const { cli, environment } = await suite.setup({ taskName: 'example' });
|
|
10
|
-
const exec = cli.
|
|
11
|
-
exec.state.on((state) => {
|
|
12
|
-
const runningNodes = Object.values(state.
|
|
10
|
+
const exec = await cli.exec({ workers: 1 });
|
|
11
|
+
exec.state.on('check-status', (state) => {
|
|
12
|
+
const runningNodes = Object.values(state.tasks).filter((n) => n.state.current.type === 'running');
|
|
13
13
|
expect(runningNodes.length).toBeLessThanOrEqual(1);
|
|
14
14
|
});
|
|
15
15
|
const result = await exec.start();
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const test_case_1 = require("../test-case");
|
|
4
|
+
const ensure_local_registry_1 = require("../ensure-local-registry");
|
|
5
|
+
const requires_linux_containers_1 = require("../requires-linux-containers");
|
|
6
|
+
describe('docker/package against a local registry', () => {
|
|
7
|
+
let registry;
|
|
8
|
+
beforeAll((0, requires_linux_containers_1.requiresLinuxContainers)(async () => {
|
|
9
|
+
registry = await (0, ensure_local_registry_1.ensureLocalRegistry)();
|
|
10
|
+
}));
|
|
11
|
+
afterAll(async () => {
|
|
12
|
+
if (registry && process.env.HAMMERKIT_KEEP_REGISTRY !== 'true') {
|
|
13
|
+
await registry.cleanup();
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
it('pushes a built service image and the registry lists its tag', (0, requires_linux_containers_1.requiresLinuxContainers)(async () => {
|
|
17
|
+
const repository = `pkg-${Date.now()}`;
|
|
18
|
+
const testCase = (0, test_case_1.createTestCase)('docker-package-registry', {
|
|
19
|
+
'.hammerkit.yaml': {
|
|
20
|
+
services: {
|
|
21
|
+
[repository]: {
|
|
22
|
+
image: 'alpine:3.19',
|
|
23
|
+
labels: { app: 'svc' },
|
|
24
|
+
cmd: 'sh -c "echo hi && sleep 3600"',
|
|
25
|
+
src: ['hello.txt'],
|
|
26
|
+
ports: ['8080'],
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
'hello.txt': 'hi from hammerkit',
|
|
31
|
+
});
|
|
32
|
+
await testCase.cli({ filterLabels: { app: ['svc'] } }, async (cli) => {
|
|
33
|
+
await cli.package({
|
|
34
|
+
registry: `${registry.host}:${registry.hostPort}`,
|
|
35
|
+
push: true,
|
|
36
|
+
overrideUser: false,
|
|
37
|
+
username: null,
|
|
38
|
+
password: null,
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
expect(await registry.listsTag(repository, 'latest')).toBe(true);
|
|
42
|
+
}), 180000);
|
|
43
|
+
});
|
|
44
|
+
//# sourceMappingURL=docker-package-registry.spec.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const test_case_1 = require("../test-case");
|
|
4
|
+
const requires_linux_containers_1 = require("../requires-linux-containers");
|
|
5
|
+
/**
|
|
6
|
+
* Regression for the crash detection in docker-service.ts: a container that
|
|
7
|
+
* exits while the runtime is waiting on abort must surface as
|
|
8
|
+
* `{ type: 'end', reason: 'crash' }` instead of being silently 'terminated'.
|
|
9
|
+
*/
|
|
10
|
+
describe('docker service crash detection', () => {
|
|
11
|
+
const testCase = (0, test_case_1.createTestCase)('docker-service-crash', {
|
|
12
|
+
'.hammerkit.yaml': {
|
|
13
|
+
services: {
|
|
14
|
+
flaky: {
|
|
15
|
+
image: 'alpine:3.19',
|
|
16
|
+
// command exits with non-zero after a short delay
|
|
17
|
+
cmd: 'sh -c "sleep 1 && exit 17"',
|
|
18
|
+
ports: [':9000'],
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
it('reports crash when the container exits while running', (0, requires_linux_containers_1.requiresLinuxContainers)(async () => {
|
|
24
|
+
await testCase.cli({}, async (cli) => {
|
|
25
|
+
// daemon=false so docker-service.ts awaits container.wait() instead of
|
|
26
|
+
// returning as soon as the service is 'running'
|
|
27
|
+
await cli.runUp({ daemon: false });
|
|
28
|
+
const service = cli.service('flaky');
|
|
29
|
+
expect(service.state.current.type).toBe('end');
|
|
30
|
+
if (service.state.current.type === 'end') {
|
|
31
|
+
expect(service.state.current.reason).toBe('crash');
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}), 90000);
|
|
35
|
+
});
|
|
36
|
+
//# sourceMappingURL=docker-service-crash.spec.js.map
|
|
@@ -2,15 +2,16 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const expect_1 = require("../expect");
|
|
4
4
|
const get_test_suite_1 = require("../get-test-suite");
|
|
5
|
+
const requires_linux_containers_1 = require("../requires-linux-containers");
|
|
5
6
|
describe('docker', () => {
|
|
6
7
|
const suite = (0, get_test_suite_1.getTestSuite)('docker', ['.hammerkit.yaml']);
|
|
7
8
|
afterAll(() => suite.close());
|
|
8
|
-
it('should pull docker image', async () => {
|
|
9
|
+
it('should pull docker image', (0, requires_linux_containers_1.requiresLinuxContainers)(async () => {
|
|
9
10
|
const { cli, environment } = await suite.setup({ taskName: 'example' });
|
|
10
|
-
const result = await cli.
|
|
11
|
+
const result = await cli.runExec();
|
|
11
12
|
await (0, expect_1.expectSuccessfulResult)(result, environment);
|
|
12
13
|
await (0, expect_1.expectLog)(result, environment, `example`, '7.19.1');
|
|
13
14
|
await (0, expect_1.expectLog)(result, environment, `example`, 'v16.6.0');
|
|
14
|
-
});
|
|
15
|
+
}));
|
|
15
16
|
});
|
|
16
17
|
//# sourceMappingURL=docker.spec.js.map
|