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,69 @@
|
|
|
1
|
+
# Feature Specification: Task: Watching
|
|
2
|
+
|
|
3
|
+
**Feature Branch**: `001-current-state-specs`
|
|
4
|
+
|
|
5
|
+
**Created**: 2026-05-30
|
|
6
|
+
|
|
7
|
+
**Status**: Current State (reverse-specified from docs, hammerkit 1.6.0)
|
|
8
|
+
|
|
9
|
+
**Input**: Existing behavior documented in `docs/task/watching.md`
|
|
10
|
+
|
|
11
|
+
## User Scenarios & Testing *(mandatory)*
|
|
12
|
+
|
|
13
|
+
### User Story 1 - Restart a task automatically on source file changes (Priority: P1)
|
|
14
|
+
|
|
15
|
+
A developer runs an API server task and wants it to restart whenever the source code changes. They run `hammerkit <task> --watch`. Hammerkit watches the task's declared `src` files and folders; when a change is detected it restarts the task.
|
|
16
|
+
|
|
17
|
+
**Why this priority**: Watch mode is the primary developer-experience feature for iterative development workflows.
|
|
18
|
+
|
|
19
|
+
**Independent Test**: Start a task with `--watch` and a `src` folder; modify a file in the folder and observe that the task process is terminated and restarted.
|
|
20
|
+
|
|
21
|
+
**Acceptance Scenarios**:
|
|
22
|
+
|
|
23
|
+
1. **Given** a task with `src` defined and the `--watch` flag, **When** a file in `src` changes, **Then** hammerkit terminates the running task and restarts it.
|
|
24
|
+
2. **Given** a task with `src` defined and the `--watch` flag, **When** no files change, **Then** the task continues running without interruption.
|
|
25
|
+
|
|
26
|
+
### User Story 2 - Mark a self-managing task as continuous (Priority: P2)
|
|
27
|
+
|
|
28
|
+
A developer uses Angular CLI's `ng serve` which handles its own file watching and incremental rebuilding internally. They mark the task with `continuous: true`. When watch mode is active, hammerkit does not watch the `src` directory for that task, allowing the tool to manage its own restart cycle.
|
|
29
|
+
|
|
30
|
+
**Why this priority**: Self-managing tasks (Angular, webpack --watch, etc.) would otherwise be redundantly restarted by hammerkit on top of their own internal watching, causing conflicts.
|
|
31
|
+
|
|
32
|
+
**Independent Test**: Mark a task `continuous: true` and run with `--watch`; modify a source file and verify hammerkit does NOT restart the task process (the task handles its own reload).
|
|
33
|
+
|
|
34
|
+
**Acceptance Scenarios**:
|
|
35
|
+
|
|
36
|
+
1. **Given** a task with `continuous: true` and the `--watch` flag, **When** a file in `src` changes, **Then** hammerkit does NOT restart the task process.
|
|
37
|
+
2. **Given** a task with `continuous: true` but WITHOUT `--watch`, **When** the task is run normally, **Then** the `continuous` flag has no visible effect on single-run behavior.
|
|
38
|
+
3. **Given** a mix of continuous and non-continuous tasks in watch mode, **When** a source file for the non-continuous task changes, **Then** only the non-continuous task is restarted.
|
|
39
|
+
|
|
40
|
+
### Edge Cases
|
|
41
|
+
|
|
42
|
+
- A task without `src` declared has nothing to watch; behavior with `--watch` and no `src` is not specified (assumed to run once and stay alive without restart triggers).
|
|
43
|
+
- `continuous: true` only suppresses hammerkit-level file watching; it does not affect how the task's process itself behaves.
|
|
44
|
+
- Watch mode with a container task follows the same restart semantics as a local task.
|
|
45
|
+
|
|
46
|
+
## Requirements *(mandatory)*
|
|
47
|
+
|
|
48
|
+
### Functional Requirements
|
|
49
|
+
|
|
50
|
+
- **FR-001**: The system MUST support a `--watch` CLI flag on the execute command.
|
|
51
|
+
- **FR-002**: When `--watch` is active, the system MUST monitor the `src` files and folders of a task for changes.
|
|
52
|
+
- **FR-003**: When a change is detected in watched sources, the system MUST terminate the running task process and restart it.
|
|
53
|
+
- **FR-004**: The system MUST accept a `continuous: true` field on a task.
|
|
54
|
+
- **FR-005**: When a task has `continuous: true` and watch mode is active, the system MUST NOT watch the task's `src` for changes or restart it.
|
|
55
|
+
|
|
56
|
+
## Success Criteria *(mandatory)*
|
|
57
|
+
|
|
58
|
+
### Measurable Outcomes
|
|
59
|
+
|
|
60
|
+
- **SC-001**: Modifying a source file of a watched non-continuous task causes the task to restart within a reasonable detection window.
|
|
61
|
+
- **SC-002**: Modifying a source file of a watched continuous task does NOT cause hammerkit to restart that task process.
|
|
62
|
+
- **SC-003**: A task without `continuous: true` runs and restarts under `--watch` as expected.
|
|
63
|
+
|
|
64
|
+
## Assumptions
|
|
65
|
+
|
|
66
|
+
- Watch mode monitors the same `src` paths used for caching; the two features share source declarations.
|
|
67
|
+
- The file-system polling or event mechanism used for watching is an implementation detail not described in the docs.
|
|
68
|
+
- `continuous: true` is intended for tasks that have their own internal watch loop (e.g., webpack, ng serve, jest --watch).
|
|
69
|
+
- Watch mode operates for the lifetime of the hammerkit process; Ctrl-C stops watching and terminates all running tasks.
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.consoleContextMock = void 0;
|
|
4
|
-
/* eslint-disable @typescript-eslint/no-empty-function */
|
|
5
|
-
function consoleContextMock() {
|
|
6
|
-
return {
|
|
7
|
-
warn() { },
|
|
8
|
-
info() { },
|
|
9
|
-
error() { },
|
|
10
|
-
debug() { },
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
exports.consoleContextMock = consoleContextMock;
|
|
14
|
-
//# sourceMappingURL=console-context-mock.js.map
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.extendHostVariables = void 0;
|
|
4
|
-
function extendHostVariables(envs, ctx) {
|
|
5
|
-
const result = { ...envs };
|
|
6
|
-
for (const key of ['PATH']) {
|
|
7
|
-
const value = ctx.processEnvs[key];
|
|
8
|
-
if (!result[key] && value) {
|
|
9
|
-
result[key] = value;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
return result;
|
|
13
|
-
}
|
|
14
|
-
exports.extendHostVariables = extendHostVariables;
|
|
15
|
-
//# sourceMappingURL=get-process-env.js.map
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createSchedulerState = void 0;
|
|
4
|
-
const plan_work_nodes_1 = require("../planner/utils/plan-work-nodes");
|
|
5
|
-
const check_for_loop_1 = require("./scheduler/check-for-loop");
|
|
6
|
-
const state_1 = require("./state");
|
|
7
|
-
function createSchedulerState(input) {
|
|
8
|
-
const state = {
|
|
9
|
-
service: {},
|
|
10
|
-
node: {},
|
|
11
|
-
cacheMethod: input.cacheMethod,
|
|
12
|
-
watch: input.watch,
|
|
13
|
-
};
|
|
14
|
-
for (const node of (0, plan_work_nodes_1.iterateWorkNodes)(input.nodes)) {
|
|
15
|
-
state.node[node.id] = {
|
|
16
|
-
type: 'pending',
|
|
17
|
-
node: node,
|
|
18
|
-
stateKey: null,
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
for (const service of (0, plan_work_nodes_1.iterateWorkServices)(input.services)) {
|
|
22
|
-
state.service[service.id] = {
|
|
23
|
-
type: 'pending',
|
|
24
|
-
service,
|
|
25
|
-
stateKey: null,
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
(0, check_for_loop_1.checkForLoop)(state);
|
|
29
|
-
return new state_1.State(state);
|
|
30
|
-
}
|
|
31
|
-
exports.createSchedulerState = createSchedulerState;
|
|
32
|
-
//# sourceMappingURL=create-scheduler-state.js.map
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.dockerNode = void 0;
|
|
4
|
-
const service_dns_1 = require("./service-dns");
|
|
5
|
-
const execute_docker_1 = require("./execute-docker");
|
|
6
|
-
const abort_1 = require("./abort");
|
|
7
|
-
const write_work_node_cache_1 = require("../optimizer/write-work-node-cache");
|
|
8
|
-
const log_1 = require("../log");
|
|
9
|
-
const states_1 = require("./states");
|
|
10
|
-
const execution_steps_1 = require("./execution-steps");
|
|
11
|
-
const using_container_1 = require("../docker/using-container");
|
|
12
|
-
const print_container_options_1 = require("./print-container-options");
|
|
13
|
-
function buildCreateOptions(node, serviceContainers) {
|
|
14
|
-
const links = [];
|
|
15
|
-
const hosts = [];
|
|
16
|
-
for (const need of node.needs) {
|
|
17
|
-
const dns = serviceContainers[need.id];
|
|
18
|
-
if ((0, service_dns_1.isHostServiceDns)(dns)) {
|
|
19
|
-
hosts.push(`${need.name}:${dns.host}`);
|
|
20
|
-
}
|
|
21
|
-
else {
|
|
22
|
-
if (!dns.containerId) {
|
|
23
|
-
throw new Error(`service ${need.name} is not running`);
|
|
24
|
-
}
|
|
25
|
-
links.push(`${dns.containerId}:${need.name}`);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return {
|
|
29
|
-
Image: node.image,
|
|
30
|
-
Tty: true,
|
|
31
|
-
Entrypoint: node.shell,
|
|
32
|
-
Cmd: ['-c', 'sleep 3600'],
|
|
33
|
-
Env: Object.keys(node.envs).map((k) => `${k}=${node.envs[k]}`),
|
|
34
|
-
WorkingDir: (0, execute_docker_1.convertToPosixPath)(node.cwd),
|
|
35
|
-
Labels: { app: 'hammerkit', 'hammerkit-id': node.id, 'hammerkit-type': 'task' },
|
|
36
|
-
HostConfig: {
|
|
37
|
-
Binds: [
|
|
38
|
-
...node.mounts.map((v) => `${v.localPath}:${(0, execute_docker_1.convertToPosixPath)(v.containerPath)}`),
|
|
39
|
-
...node.volumes.map((v) => `${v.name}:${(0, execute_docker_1.convertToPosixPath)(v.containerPath)}`),
|
|
40
|
-
],
|
|
41
|
-
PortBindings: node.ports.reduce((map, port) => {
|
|
42
|
-
map[`${port.containerPort}/tcp`] = [{ HostPort: `${port.hostPort}` }];
|
|
43
|
-
return map;
|
|
44
|
-
}, {}),
|
|
45
|
-
ExtraHosts: hosts,
|
|
46
|
-
Links: links,
|
|
47
|
-
AutoRemove: true,
|
|
48
|
-
},
|
|
49
|
-
ExposedPorts: node.ports.reduce((map, port) => {
|
|
50
|
-
map[`${port.containerPort}/tcp`] = {};
|
|
51
|
-
return map;
|
|
52
|
-
}, {}),
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
function dockerNode(node, stateKey, serviceContainers, state, environment) {
|
|
56
|
-
return async (abort, started) => {
|
|
57
|
-
const status = environment.status.task(node);
|
|
58
|
-
status.write('info', `execute ${node.name} in container`);
|
|
59
|
-
try {
|
|
60
|
-
await (0, execution_steps_1.prepareMounts)(node, environment);
|
|
61
|
-
(0, abort_1.checkForAbort)(abort.signal);
|
|
62
|
-
await (0, execution_steps_1.pullImage)(node, environment);
|
|
63
|
-
(0, abort_1.checkForAbort)(abort.signal);
|
|
64
|
-
await (0, execution_steps_1.prepareVolume)(node, environment);
|
|
65
|
-
(0, abort_1.checkForAbort)(abort.signal);
|
|
66
|
-
const containerOptions = buildCreateOptions(node, serviceContainers);
|
|
67
|
-
(0, print_container_options_1.printContainerOptions)(status, containerOptions);
|
|
68
|
-
const success = await (0, using_container_1.usingContainer)(environment, node, containerOptions, async (container) => {
|
|
69
|
-
await (0, execution_steps_1.setUserPermissions)(node, container, environment);
|
|
70
|
-
for (const cmd of node.cmds) {
|
|
71
|
-
(0, abort_1.checkForAbort)(abort.signal);
|
|
72
|
-
status.write('info', `execute cmd "${cmd.cmd}" in container`);
|
|
73
|
-
const result = await (0, execute_docker_1.execCommand)(status, environment, container, (0, execute_docker_1.convertToPosixPath)(cmd.path), [node.shell, '-c', cmd.cmd], node.user, undefined, abort.signal);
|
|
74
|
-
if (result.type === 'timeout') {
|
|
75
|
-
throw new Error(`command ${cmd.cmd} timed out`);
|
|
76
|
-
}
|
|
77
|
-
if (result.type === 'canceled') {
|
|
78
|
-
throw new abort_1.AbortError();
|
|
79
|
-
}
|
|
80
|
-
if (result.result.ExitCode !== 0) {
|
|
81
|
-
state.patchNode({
|
|
82
|
-
node,
|
|
83
|
-
stateKey,
|
|
84
|
-
type: 'crash',
|
|
85
|
-
exitCode: result.result.ExitCode ?? 1,
|
|
86
|
-
}, stateKey);
|
|
87
|
-
return false;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
return true;
|
|
91
|
-
});
|
|
92
|
-
if (success) {
|
|
93
|
-
await (0, write_work_node_cache_1.writeWorkNodeCache)(node, environment);
|
|
94
|
-
state.patchNode({
|
|
95
|
-
node,
|
|
96
|
-
stateKey,
|
|
97
|
-
type: 'completed',
|
|
98
|
-
cached: false,
|
|
99
|
-
duration: (0, states_1.getDuration)(started),
|
|
100
|
-
}, stateKey);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
catch (e) {
|
|
104
|
-
if (e instanceof abort_1.AbortError) {
|
|
105
|
-
state.patchNode({
|
|
106
|
-
node,
|
|
107
|
-
stateKey,
|
|
108
|
-
type: 'canceled',
|
|
109
|
-
}, stateKey);
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
state.patchNode({
|
|
113
|
-
node,
|
|
114
|
-
stateKey,
|
|
115
|
-
type: 'error',
|
|
116
|
-
errorMessage: (0, log_1.getErrorMessage)(e),
|
|
117
|
-
}, stateKey);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
exports.dockerNode = dockerNode;
|
|
123
|
-
//# sourceMappingURL=docker-node.js.map
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.schedule = void 0;
|
|
4
|
-
const work_service_1 = require("../planner/work-service");
|
|
5
|
-
const docker_service_1 = require("./docker-service");
|
|
6
|
-
const kubernetes_service_1 = require("./kubernetes-service");
|
|
7
|
-
const work_node_1 = require("../planner/work-node");
|
|
8
|
-
const docker_node_1 = require("./docker-node");
|
|
9
|
-
const local_node_1 = require("./local-node");
|
|
10
|
-
const work_node_status_1 = require("../planner/work-node-status");
|
|
11
|
-
async function schedule(processManager, state, environment) {
|
|
12
|
-
state.on((currentState) => {
|
|
13
|
-
for (const [, nodeState] of Object.entries(currentState.node)) {
|
|
14
|
-
if (nodeState.type === 'pending') {
|
|
15
|
-
const endedNeeds = nodeState.node.needs
|
|
16
|
-
.map((need) => currentState.service[need.id])
|
|
17
|
-
.filter((service) => service.type === 'end');
|
|
18
|
-
if (endedNeeds.length > 0) {
|
|
19
|
-
state.patchNode({
|
|
20
|
-
type: 'canceled',
|
|
21
|
-
node: nodeState.node,
|
|
22
|
-
});
|
|
23
|
-
continue;
|
|
24
|
-
}
|
|
25
|
-
const pendingNeeds = nodeState.node.needs
|
|
26
|
-
.map((need) => currentState.service[need.id])
|
|
27
|
-
.filter((service) => service.type === 'pending');
|
|
28
|
-
const hasOpenDeps = nodeState.node.deps.some((dep) => currentState.node[dep.id].type !== 'completed');
|
|
29
|
-
if (hasOpenDeps) {
|
|
30
|
-
continue;
|
|
31
|
-
}
|
|
32
|
-
if (pendingNeeds.length > 0) {
|
|
33
|
-
// TODO do not start, if needs are cached
|
|
34
|
-
for (const pendingNeed of pendingNeeds) {
|
|
35
|
-
const ctx = (0, work_node_status_1.logContext)('service', pendingNeed.service);
|
|
36
|
-
state.patchService({
|
|
37
|
-
type: 'running',
|
|
38
|
-
service: pendingNeed.service,
|
|
39
|
-
abortController: processManager.background(ctx, (0, work_service_1.isContainerWorkService)(pendingNeed.service)
|
|
40
|
-
? (0, docker_service_1.dockerService)(pendingNeed.service, state, environment)
|
|
41
|
-
: (0, kubernetes_service_1.kubernetesService)(pendingNeed.service, state, environment)),
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
continue;
|
|
45
|
-
}
|
|
46
|
-
const hasNotReadyNeeds = nodeState.node.needs.some((need) => currentState.service[need.id].type !== 'ready');
|
|
47
|
-
if (hasNotReadyNeeds) {
|
|
48
|
-
continue;
|
|
49
|
-
}
|
|
50
|
-
const serviceContainers = {};
|
|
51
|
-
for (const need of nodeState.node.needs) {
|
|
52
|
-
const serviceState = currentState.service[need.id];
|
|
53
|
-
if (serviceState.type === 'ready') {
|
|
54
|
-
serviceContainers[need.id] = serviceState.dns;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
const ctx = (0, work_node_status_1.logContext)('task', nodeState.node);
|
|
58
|
-
state.patchNode({
|
|
59
|
-
type: 'starting',
|
|
60
|
-
node: nodeState.node,
|
|
61
|
-
started: new Date(),
|
|
62
|
-
abortController: (0, work_node_1.isContainerWorkNode)(nodeState.node)
|
|
63
|
-
? processManager.task(ctx, (0, docker_node_1.dockerNode)(nodeState.node, serviceContainers, state, environment))
|
|
64
|
-
: processManager.task(ctx, (0, local_node_1.localNode)(nodeState.node, state, environment)),
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
for (const [serviceId, serviceState] of Object.entries(currentState.service)) {
|
|
69
|
-
if (serviceState.type !== 'ready' && serviceState.type !== 'running') {
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
let hasNeed = false;
|
|
73
|
-
for (const nodeState of Object.values(currentState.node)) {
|
|
74
|
-
if (nodeState.type === 'running' || nodeState.type === 'starting' || nodeState.type === 'pending') {
|
|
75
|
-
if (nodeState.node.needs.some((n) => n.id === serviceId)) {
|
|
76
|
-
hasNeed = true;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
if (!hasNeed) {
|
|
81
|
-
environment.status.service(serviceState.service).write('info', 'stop unused service');
|
|
82
|
-
serviceState.abortController.abort();
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
await processManager.onComplete();
|
|
87
|
-
const success = !Object.values(state.current.node).some((n) => n.type !== 'completed');
|
|
88
|
-
return {
|
|
89
|
-
state: state.current,
|
|
90
|
-
success,
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
exports.schedule = schedule;
|
|
94
|
-
//# sourceMappingURL=hierarchy-scheduler.js.map
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.localNode = void 0;
|
|
4
|
-
const abort_1 = require("./abort");
|
|
5
|
-
const execute_command_1 = require("./execute-command");
|
|
6
|
-
const write_work_node_cache_1 = require("../optimizer/write-work-node-cache");
|
|
7
|
-
const log_1 = require("../log");
|
|
8
|
-
const states_1 = require("./states");
|
|
9
|
-
function localNode(node, stateKey, state, environment) {
|
|
10
|
-
return async (abort, started) => {
|
|
11
|
-
const status = environment.status.task(node);
|
|
12
|
-
status.write('info', `execute ${node.name} locally`);
|
|
13
|
-
try {
|
|
14
|
-
for (const cmd of node.cmds) {
|
|
15
|
-
(0, abort_1.checkForAbort)(abort.signal);
|
|
16
|
-
status.write('info', `execute cmd "${cmd.cmd}" locally`);
|
|
17
|
-
const exitCode = await (0, execute_command_1.executeCommand)(status, abort.signal, cmd.path, cmd.cmd, node.envs);
|
|
18
|
-
if (exitCode !== 0) {
|
|
19
|
-
state.patchNode({
|
|
20
|
-
type: 'crash',
|
|
21
|
-
node,
|
|
22
|
-
exitCode,
|
|
23
|
-
stateKey,
|
|
24
|
-
}, stateKey);
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
await (0, write_work_node_cache_1.writeWorkNodeCache)(node, environment);
|
|
29
|
-
state.patchNode({
|
|
30
|
-
type: 'completed',
|
|
31
|
-
node: node,
|
|
32
|
-
cached: false,
|
|
33
|
-
stateKey,
|
|
34
|
-
duration: (0, states_1.getDuration)(started),
|
|
35
|
-
}, stateKey);
|
|
36
|
-
}
|
|
37
|
-
catch (e) {
|
|
38
|
-
if (e instanceof abort_1.AbortError) {
|
|
39
|
-
state.patchNode({
|
|
40
|
-
type: 'canceled',
|
|
41
|
-
node,
|
|
42
|
-
stateKey,
|
|
43
|
-
}, stateKey);
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
46
|
-
state.patchNode({
|
|
47
|
-
type: 'error',
|
|
48
|
-
node,
|
|
49
|
-
stateKey,
|
|
50
|
-
errorMessage: (0, log_1.getErrorMessage)(e),
|
|
51
|
-
}, stateKey);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
exports.localNode = localNode;
|
|
57
|
-
//# sourceMappingURL=local-node.js.map
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.schedule = void 0;
|
|
4
|
-
const work_service_1 = require("../planner/work-service");
|
|
5
|
-
const docker_service_1 = require("./docker-service");
|
|
6
|
-
const kubernetes_service_1 = require("./kubernetes-service");
|
|
7
|
-
const work_node_1 = require("../planner/work-node");
|
|
8
|
-
const docker_node_1 = require("./docker-node");
|
|
9
|
-
const local_node_1 = require("./local-node");
|
|
10
|
-
const work_node_status_1 = require("../planner/work-node-status");
|
|
11
|
-
const start_watch_processes_1 = require("../start-watch-processes");
|
|
12
|
-
const start_node_1 = require("./start-node");
|
|
13
|
-
async function schedule(processManager, state, environment) {
|
|
14
|
-
if (state.current.watch) {
|
|
15
|
-
(0, start_watch_processes_1.startWatchProcesses)(state, processManager, environment);
|
|
16
|
-
}
|
|
17
|
-
state.on((currentState) => {
|
|
18
|
-
for (const [, nodeState] of Object.entries(currentState.node)) {
|
|
19
|
-
if (nodeState.type === 'pending') {
|
|
20
|
-
const hasOpenDeps = nodeState.node.deps.some((dep) => currentState.node[dep.id].type !== 'completed');
|
|
21
|
-
if (hasOpenDeps) {
|
|
22
|
-
continue;
|
|
23
|
-
}
|
|
24
|
-
state.patchNode({
|
|
25
|
-
type: 'starting',
|
|
26
|
-
node: nodeState.node,
|
|
27
|
-
started: new Date(),
|
|
28
|
-
stateKey: null,
|
|
29
|
-
}, nodeState.stateKey);
|
|
30
|
-
processManager.background({
|
|
31
|
-
type: 'task',
|
|
32
|
-
name: nodeState.node.name,
|
|
33
|
-
id: nodeState.node.id + '-cache',
|
|
34
|
-
}, async (abort) => {
|
|
35
|
-
await (0, start_node_1.startNode)(nodeState, state, environment, abort.signal);
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
else if (nodeState.type === 'ready') {
|
|
39
|
-
const endedNeeds = nodeState.node.needs
|
|
40
|
-
.map((need) => currentState.service[need.id])
|
|
41
|
-
.filter((service) => service.type === 'end' || service.type === 'canceled');
|
|
42
|
-
if (endedNeeds.length > 0) {
|
|
43
|
-
state.patchNode({
|
|
44
|
-
type: 'error',
|
|
45
|
-
node: nodeState.node,
|
|
46
|
-
stateKey: nodeState.stateKey,
|
|
47
|
-
errorMessage: endedNeeds
|
|
48
|
-
.map((n) => `service ${n.service.name} ${n.type === 'end' ? 'has ended ' + n.reason : 'was canceled'}`)
|
|
49
|
-
.join(', '),
|
|
50
|
-
}, nodeState.stateKey);
|
|
51
|
-
continue;
|
|
52
|
-
}
|
|
53
|
-
const pendingNeeds = nodeState.node.needs
|
|
54
|
-
.map((need) => currentState.service[need.id])
|
|
55
|
-
.filter((service) => service.type === 'pending');
|
|
56
|
-
if (pendingNeeds.length > 0) {
|
|
57
|
-
for (const pendingNeed of pendingNeeds) {
|
|
58
|
-
state.patchService({
|
|
59
|
-
type: 'starting',
|
|
60
|
-
service: pendingNeed.service,
|
|
61
|
-
stateKey: null,
|
|
62
|
-
});
|
|
63
|
-
processManager.background({
|
|
64
|
-
type: 'service',
|
|
65
|
-
name: pendingNeed.service.name,
|
|
66
|
-
id: pendingNeed.service.id + '-cache',
|
|
67
|
-
}, async (abort) => {
|
|
68
|
-
await (0, start_node_1.startService)(pendingNeed.service, state, environment, abort.signal);
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
const hasNotReadyNeeds = nodeState.node.needs.some((need) => currentState.service[need.id].type !== 'running');
|
|
74
|
-
if (hasNotReadyNeeds) {
|
|
75
|
-
continue;
|
|
76
|
-
}
|
|
77
|
-
const serviceContainers = {};
|
|
78
|
-
for (const need of nodeState.node.needs) {
|
|
79
|
-
const serviceState = currentState.service[need.id];
|
|
80
|
-
if (serviceState.type === 'running') {
|
|
81
|
-
serviceContainers[need.id] = serviceState.dns;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
state.patchNode({
|
|
85
|
-
type: 'running',
|
|
86
|
-
node: nodeState.node,
|
|
87
|
-
stateKey: nodeState.stateKey,
|
|
88
|
-
started: nodeState.started,
|
|
89
|
-
}, nodeState.stateKey);
|
|
90
|
-
const ctx = (0, work_node_status_1.logContext)('task', nodeState.node);
|
|
91
|
-
if ((0, work_node_1.isContainerWorkNode)(nodeState.node)) {
|
|
92
|
-
processManager.task(ctx, (0, docker_node_1.dockerNode)(nodeState.node, nodeState.stateKey, serviceContainers, state, environment));
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
processManager.task(ctx, (0, local_node_1.localNode)(nodeState.node, nodeState.stateKey, state, environment));
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
for (const [serviceId, serviceState] of Object.entries(currentState.service)) {
|
|
100
|
-
if (serviceState.type === 'ready') {
|
|
101
|
-
const ctx = (0, work_node_status_1.logContext)('service', serviceState.service);
|
|
102
|
-
state.patchService({
|
|
103
|
-
type: 'starting',
|
|
104
|
-
service: serviceState.service,
|
|
105
|
-
stateKey: serviceState.stateKey,
|
|
106
|
-
});
|
|
107
|
-
processManager.background(ctx, (0, work_service_1.isContainerWorkService)(serviceState.service)
|
|
108
|
-
? (0, docker_service_1.dockerService)(serviceState.service, serviceState.stateKey, state, environment)
|
|
109
|
-
: (0, kubernetes_service_1.kubernetesService)(serviceState.service, serviceState.stateKey, state, environment));
|
|
110
|
-
}
|
|
111
|
-
if (serviceState.type !== 'ready' && serviceState.type !== 'running') {
|
|
112
|
-
continue;
|
|
113
|
-
}
|
|
114
|
-
let hasNeed = false;
|
|
115
|
-
for (const nodeState of Object.values(currentState.node)) {
|
|
116
|
-
if (nodeState.type === 'running' || nodeState.type === 'starting' || nodeState.type === 'pending') {
|
|
117
|
-
if (nodeState.node.needs.some((n) => n.id === serviceId)) {
|
|
118
|
-
hasNeed = true;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
if (!hasNeed) {
|
|
123
|
-
const ctx = (0, work_node_status_1.logContext)('service', serviceState.service);
|
|
124
|
-
environment.status.service(serviceState.service).write('info', 'stop unused service');
|
|
125
|
-
processManager.abort(ctx);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
await processManager.onComplete();
|
|
130
|
-
const success = !Object.values(state.current.node).some((n) => n.type !== 'completed');
|
|
131
|
-
return {
|
|
132
|
-
state: state.current,
|
|
133
|
-
success,
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
exports.schedule = schedule;
|
|
137
|
-
//# sourceMappingURL=schedule.js.map
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.startService = exports.startNode = void 0;
|
|
4
|
-
const enqueue_next_1 = require("./scheduler/enqueue-next");
|
|
5
|
-
const states_1 = require("./states");
|
|
6
|
-
const work_service_1 = require("../planner/work-service");
|
|
7
|
-
const get_work_node_cache_stats_1 = require("../optimizer/get-work-node-cache-stats");
|
|
8
|
-
async function startNode(node, state, environment, abortSignal) {
|
|
9
|
-
const cacheState = await (0, enqueue_next_1.checkCacheState)(node.node, state.current.cacheMethod, environment);
|
|
10
|
-
const currentState = state.current.node[node.node.id];
|
|
11
|
-
if (abortSignal.aborted) {
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
if (!!currentState.stateKey && currentState.stateKey !== cacheState.stateKey) {
|
|
15
|
-
const status = environment.status.task(node.node);
|
|
16
|
-
status.write('debug', `cache check for ${node.node.name} no longer valid, skipping result`);
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
if (cacheState.cached) {
|
|
20
|
-
state.patchNode({
|
|
21
|
-
type: 'completed',
|
|
22
|
-
node: node.node,
|
|
23
|
-
cached: true,
|
|
24
|
-
stateKey: cacheState.stateKey,
|
|
25
|
-
duration: currentState.type === 'starting' ? (0, states_1.getDuration)(currentState.started) : 0,
|
|
26
|
-
}, node.stateKey);
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
state.patchNode({
|
|
30
|
-
type: 'ready',
|
|
31
|
-
node: node.node,
|
|
32
|
-
stateKey: cacheState.stateKey,
|
|
33
|
-
started: currentState.type === 'starting' ? currentState.started : new Date(),
|
|
34
|
-
}, node.stateKey);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
exports.startNode = startNode;
|
|
38
|
-
async function startService(service, state, environment, abortSignal) {
|
|
39
|
-
const currentStats = await (0, get_work_node_cache_stats_1.getServiceNodeCacheStats)(service, environment);
|
|
40
|
-
const stateKey = (0, get_work_node_cache_stats_1.getStateKey)(currentStats, state.current.cacheMethod);
|
|
41
|
-
if (abortSignal.aborted) {
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
if (!(0, work_service_1.isContainerWorkService)(service)) {
|
|
45
|
-
state.patchService({
|
|
46
|
-
type: 'ready',
|
|
47
|
-
service,
|
|
48
|
-
stateKey,
|
|
49
|
-
});
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
const fileStats = await (0, get_work_node_cache_stats_1.getServiceNodeCacheStats)(service, environment);
|
|
53
|
-
const fileStateKey = (0, get_work_node_cache_stats_1.getStateKey)(fileStats, 'checksum');
|
|
54
|
-
const currentState = state.current.service[service.id];
|
|
55
|
-
if (!!currentState.stateKey && currentState.stateKey !== fileStateKey) {
|
|
56
|
-
const status = environment.status.service(service);
|
|
57
|
-
status.write('debug', `cache check for ${service.name} no longer valid, skipping result`);
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
state.patchService({
|
|
61
|
-
type: 'ready',
|
|
62
|
-
service,
|
|
63
|
-
stateKey: fileStateKey,
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
exports.startService = startService;
|
|
67
|
-
//# sourceMappingURL=start-node.js.map
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.watchNode = void 0;
|
|
4
|
-
const get_work_node_cache_stats_1 = require("../optimizer/get-work-node-cache-stats");
|
|
5
|
-
const debouncer_1 = require("../utils/debouncer");
|
|
6
|
-
const path_1 = require("path");
|
|
7
|
-
const abort_event_1 = require("../utils/abort-event");
|
|
8
|
-
function watchNode(node, state, processManager, environment) {
|
|
9
|
-
return async (abort) => {
|
|
10
|
-
const status = environment.status.task(node);
|
|
11
|
-
let currentState = await (0, get_work_node_cache_stats_1.getWorkNodeCacheStats)(node, environment);
|
|
12
|
-
const debouncer = new debouncer_1.Debouncer(async () => {
|
|
13
|
-
if (environment.abortCtrl.signal.aborted) {
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
const newStats = await (0, get_work_node_cache_stats_1.getWorkNodeCacheStats)(node, environment);
|
|
17
|
-
const currentFileState = (0, get_work_node_cache_stats_1.getCacheState)(status, { name: node.name, caching: node.caching ?? state.current.cacheMethod }, currentState, newStats);
|
|
18
|
-
currentState = newStats;
|
|
19
|
-
const currentNodeState = state.current.node[node.id];
|
|
20
|
-
if (currentNodeState.stateKey === currentFileState.stateKey) {
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
status.write('debug', `source changed for node ${node.name}, restart process`);
|
|
24
|
-
state.resetNode({
|
|
25
|
-
type: 'pending',
|
|
26
|
-
node,
|
|
27
|
-
stateKey: currentFileState.stateKey,
|
|
28
|
-
});
|
|
29
|
-
}, 100);
|
|
30
|
-
const fileWatchers = [];
|
|
31
|
-
const sources = [];
|
|
32
|
-
for (const src of node.src) {
|
|
33
|
-
status.write('debug', `watch ${src.absolutePath} source`);
|
|
34
|
-
const watcher = environment.file.watch(src.absolutePath, async (fileName) => {
|
|
35
|
-
const absoluteFileName = (0, path_1.join)(src.absolutePath, fileName);
|
|
36
|
-
if (src.matcher(absoluteFileName, node.cwd)) {
|
|
37
|
-
status.write('debug', `source ${absoluteFileName} change for watched task ${node.name}`);
|
|
38
|
-
debouncer.bounce();
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
sources.push(src.absolutePath);
|
|
42
|
-
fileWatchers.push(watcher);
|
|
43
|
-
}
|
|
44
|
-
await (0, abort_event_1.waitOnAbort)(abort.signal);
|
|
45
|
-
debouncer.clear();
|
|
46
|
-
for (const watcher of fileWatchers) {
|
|
47
|
-
watcher.close();
|
|
48
|
-
}
|
|
49
|
-
return {
|
|
50
|
-
type: 'node-watch-canceled',
|
|
51
|
-
node,
|
|
52
|
-
};
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
exports.watchNode = watchNode;
|
|
56
|
-
//# sourceMappingURL=watch-node.js.map
|