hammerkit 1.6.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/build.schema.json +59 -15
- package/dist/cache/backends/local-cache-backend.js +58 -1
- package/dist/cache/backends/registry/registry-client.js +264 -0
- package/dist/cache/backends/registry/registry-credentials.js +81 -0
- package/dist/cache/backends/registry/registry-reference.js +36 -0
- package/dist/cache/backends/registry-cache-backend.js +145 -0
- package/dist/cache/backends/s3-cache-backend.js +99 -46
- package/dist/cache/cache-backend-registry.js +2 -0
- package/dist/cache/cache-inventory.js +84 -0
- package/dist/cache/cache-sync.js +77 -0
- package/dist/cache/explain.js +214 -0
- package/dist/cache/last-resolved.js +48 -0
- package/dist/cache/read-only.js +15 -0
- package/dist/cache/retention.js +61 -0
- package/dist/cli.js +43 -0
- package/dist/docker/using-container.js +17 -1
- package/dist/executer/archive-task-entry.js +21 -0
- package/dist/executer/await-completed-dependencies.js +32 -14
- package/dist/executer/cache-metadata.js +9 -2
- package/dist/executer/docker-service.js +2 -1
- package/dist/executer/docker-task.js +18 -3
- package/dist/executer/dry-run.js +73 -0
- package/dist/executer/event-cache.js +6 -5
- package/dist/executer/execute-command.js +21 -3
- package/dist/executer/execute-docker.js +18 -2
- package/dist/executer/execute-work-service.js +10 -1
- package/dist/executer/execute-work-task.js +111 -26
- package/dist/executer/execute-work-tree.js +26 -1
- package/dist/executer/execution-steps.js +3 -8
- package/dist/executer/get-container-binds.js +13 -1
- package/dist/executer/get-scheduler-execute-result.js +4 -1
- package/dist/executer/lazy-resolver.js +15 -3
- package/dist/executer/reset-work-tree.js +2 -0
- package/dist/executer/run-summary.js +102 -0
- package/dist/executer/scheduler/enqueue-next.js +15 -60
- package/dist/executer/scheduler/state-key.js +78 -0
- package/dist/index.js +14 -1
- package/dist/kubernetes/apply.js +6 -7
- package/dist/kubernetes/await-running-state.js +100 -60
- package/dist/kubernetes/ensure-http-route.js +7 -10
- package/dist/kubernetes/ensure-namespace.js +9 -10
- package/dist/kubernetes/ensure-persistent-data.js +6 -5
- package/dist/kubernetes/get-service-ip.js +2 -2
- package/dist/kubernetes/kubernetes-instance.js +0 -4
- package/dist/kubernetes/remove-persistent-data.js +16 -6
- package/dist/kubernetes/resolve-pod-name.js +7 -7
- package/dist/log.js +16 -6
- package/dist/logging/live-logger.js +2 -1
- package/dist/optimizer/calculate-checksum.js +8 -2
- package/dist/optimizer/get-work-cache-stats.js +66 -16
- package/dist/optimizer/work-task-cache-description.js +34 -5
- package/dist/planner/project-root.js +26 -0
- package/dist/planner/utils/append-work-environment.js +1 -1
- package/dist/planner/utils/append-work-service.js +2 -1
- package/dist/planner/utils/append-work-task.js +7 -1
- package/dist/planner/utils/get-outputs-to-reset.js +20 -0
- package/dist/planner/utils/parse-work-generate.js +2 -2
- package/dist/planner/utils/parse-work-source.js +35 -30
- package/dist/planner/utils/portable-path.js +30 -0
- package/dist/planner/work-cache-id.js +2 -2
- package/dist/planner/work-graph-serializer.js +103 -0
- package/dist/planner/work-instance-id.js +15 -0
- package/dist/planner/work-runtime-docker.js +58 -15
- package/dist/planner/work-runtime-kubernetes.js +95 -45
- package/dist/planner/work-runtime-local.js +31 -8
- package/dist/planner/work-service-id.js +16 -4
- package/dist/program.js +235 -1
- package/dist/schema/build-file-base-task-schema.js +4 -0
- package/dist/schema/build-file-environment-schema-http-route.js +15 -0
- package/dist/schema/build-file-environment-schema.js +8 -2
- package/dist/schema/build-file-schema.js +1 -1
- package/dist/schema/cache-schema.js +21 -2
- package/dist/schema/duration-schema.js +18 -0
- package/dist/schema/envs-schema.js +1 -1
- package/dist/schema/reference-parser.js +3 -0
- package/dist/schema/size-schema.js +18 -0
- package/dist/schema/work-scope-parser.js +15 -2
- package/dist/utils/units.js +87 -0
- package/package.json +20 -9
- package/.agents/FEEDBACK.md +0 -74
- package/.agents/skills/before-commit/SKILL.md +0 -101
- package/.agents/skills/do-the-work/SKILL.md +0 -64
- package/.agents/skills/fix-ci/SKILL.md +0 -98
- package/.agents/skills/speckit-git-commit/SKILL.md +0 -53
- package/.agents/skills/speckit-git-feature/SKILL.md +0 -72
- package/.agents/skills/speckit-git-initialize/SKILL.md +0 -54
- package/.agents/skills/speckit-git-remote/SKILL.md +0 -50
- package/.agents/skills/speckit-git-validate/SKILL.md +0 -54
- package/.devcontainer/Dockerfile +0 -5
- package/.devcontainer/devcontainer.json +0 -40
- package/.gitbook.yaml +0 -5
- package/.specify/extensions/.registry +0 -37
- package/.specify/extensions/git/README.md +0 -100
- package/.specify/extensions/git/commands/speckit.git.commit.md +0 -48
- package/.specify/extensions/git/commands/speckit.git.feature.md +0 -67
- package/.specify/extensions/git/commands/speckit.git.initialize.md +0 -49
- package/.specify/extensions/git/commands/speckit.git.remote.md +0 -45
- package/.specify/extensions/git/commands/speckit.git.validate.md +0 -49
- package/.specify/extensions/git/config-template.yml +0 -62
- package/.specify/extensions/git/extension.yml +0 -140
- package/.specify/extensions/git/git-config.yml +0 -62
- package/.specify/extensions.yml +0 -149
- package/.specify/feature.json +0 -3
- package/.specify/init-options.json +0 -10
- package/.specify/integration.json +0 -15
- package/.specify/integrations/claude.manifest.json +0 -16
- package/.specify/integrations/speckit.manifest.json +0 -17
- package/.specify/memory/constitution.md +0 -162
- package/.specify/templates/checklist-template.md +0 -40
- package/.specify/templates/constitution-template.md +0 -50
- package/.specify/templates/plan-template.md +0 -113
- package/.specify/templates/spec-template.md +0 -131
- package/.specify/templates/tasks-template.md +0 -252
- package/.specify/workflows/speckit/workflow.yml +0 -77
- package/.specify/workflows/workflow-registry.json +0 -13
- package/AGENTS.md +0 -94
- package/Dockerfile +0 -32
- package/FOLLOWUPS.md +0 -34
- package/SUMMARY.md +0 -68
- package/VALUES.md +0 -53
- package/dist/cache/auto-pull.spec.js +0 -123
- package/dist/cache/backends/local-cache-backend.spec.js +0 -72
- package/dist/cache/backends/s3-cache-backend.spec.js +0 -118
- package/dist/cache/cache-backend-registry.spec.js +0 -22
- package/dist/cache/resolve-cache.spec.js +0 -52
- package/dist/cli.spec.js +0 -23
- package/dist/console/get-logger.spec.js +0 -23
- package/dist/docker/get-default-platform.spec.js +0 -29
- package/dist/docker/longest-common-prefix.spec.js +0 -26
- package/dist/docker/package.spec.js +0 -145
- package/dist/docker/remove-container.spec.js +0 -32
- package/dist/docker/using-container.spec.js +0 -90
- package/dist/environment/merge-environment-variables.spec.js +0 -24
- package/dist/environment/replace-env-variables.spec.js +0 -47
- package/dist/executer/abort.spec.js +0 -18
- package/dist/executer/environment-mock.spec.js +0 -22
- package/dist/executer/execute.spec.js +0 -51
- package/dist/executer/get-service-containers.spec.js +0 -59
- package/dist/executer/get-service-env-hints.spec.js +0 -65
- package/dist/executer/label-values.spec.js +0 -61
- package/dist/executer/lazy-resolver.spec.js +0 -20
- package/dist/executer/process-manager.spec.js +0 -54
- package/dist/executer/scheduler/enqueue-next.spec.js +0 -136
- package/dist/executer/state-resolver.spec.js +0 -37
- package/dist/executer/state.spec.js +0 -66
- package/dist/executer/states.spec.js +0 -14
- package/dist/file/get-file-context.spec.js +0 -178
- package/dist/file/move-files.spec.js +0 -48
- package/dist/kubernetes/ensure-http-route.spec.js +0 -70
- package/dist/kubernetes/ensure-ingress.js +0 -54
- package/dist/kubernetes/ensure-namespace.spec.js +0 -39
- package/dist/kubernetes/resolve-pod-name.spec.js +0 -81
- package/dist/log.spec.js +0 -131
- package/dist/logging/grouped-logger.spec.js +0 -84
- package/dist/logging/interactive-logger.spec.js +0 -57
- package/dist/logging/live-logger.spec.js +0 -37
- package/dist/logging/loggers.spec.js +0 -154
- package/dist/optimizer/calculate-checksum.spec.js +0 -34
- package/dist/optimizer/get-cache-directory.spec.js +0 -59
- package/dist/optimizer/get-work-cache-stats.spec.js +0 -79
- package/dist/optimizer/work-task-cache-description.spec.js +0 -45
- package/dist/parser/default-build-file.spec.js +0 -48
- package/dist/parser/parse-label-arguments.spec.js +0 -27
- package/dist/parser/read-build-file.spec.js +0 -89
- package/dist/parser/read-env-file.spec.js +0 -42
- package/dist/planner/utils/append-work-service.spec.js +0 -71
- package/dist/planner/utils/get-container-user.spec.js +0 -30
- package/dist/planner/utils/get-default-kube-config.spec.js +0 -11
- package/dist/planner/utils/normalize-path.spec.js +0 -24
- package/dist/planner/utils/parse-work-command.spec.js +0 -21
- package/dist/planner/utils/parse-work-generate.spec.js +0 -45
- package/dist/planner/utils/parse-work-mount.spec.js +0 -62
- package/dist/planner/utils/parse-work-mounts.spec.js +0 -19
- package/dist/planner/utils/parse-work-port.spec.js +0 -24
- package/dist/planner/utils/parse-work-ports.spec.js +0 -24
- package/dist/planner/utils/parse-work-source.spec.js +0 -58
- package/dist/planner/utils/parse-work-volume.spec.js +0 -18
- package/dist/planner/utils/plan-work-tasks.spec.js +0 -30
- package/dist/planner/utils/plan-work-volume.spec.js +0 -33
- package/dist/planner/utils/split-name.spec.js +0 -16
- package/dist/planner/utils/template-value.spec.js +0 -14
- package/dist/planner/validate.spec.js +0 -251
- package/dist/planner/work-cache-id.spec.js +0 -173
- package/dist/planner/work-runtime-local.spec.js +0 -193
- package/dist/program-commands.spec.js +0 -84
- package/dist/program.spec.js +0 -43
- package/dist/schema/build-file-environment-schema-ingress.js +0 -14
- package/dist/schema/build-file-schema.spec.js +0 -61
- package/dist/schema/doc-build-files.spec.js +0 -223
- package/dist/schema/parse-error.spec.js +0 -18
- package/dist/schema/reference-parser.spec.js +0 -83
- package/dist/schema/schema-parser.spec.js +0 -80
- package/dist/schema/type-guards.spec.js +0 -23
- package/dist/schema/work-scope-parser.spec.js +0 -66
- package/dist/service/update-service-status.spec.js +0 -27
- package/dist/testing/ensure-local-registry.js +0 -134
- package/dist/testing/example-test-suite.js +0 -63
- package/dist/testing/expect.js +0 -82
- package/dist/testing/get-test-suite.js +0 -9
- package/dist/testing/http-get.js +0 -21
- package/dist/testing/integration/cache.spec.js +0 -49
- package/dist/testing/integration/cancellation.spec.js +0 -45
- package/dist/testing/integration/clean.spec.js +0 -43
- package/dist/testing/integration/cmd.spec.js +0 -15
- package/dist/testing/integration/concurrency.spec.js +0 -19
- package/dist/testing/integration/docker-package-registry.spec.js +0 -44
- package/dist/testing/integration/docker-service-crash.spec.js +0 -36
- package/dist/testing/integration/docker.spec.js +0 -18
- package/dist/testing/integration/env.spec.js +0 -48
- package/dist/testing/integration/environment.spec.js +0 -97
- package/dist/testing/integration/error.spec.js +0 -19
- package/dist/testing/integration/export.spec.js +0 -22
- package/dist/testing/integration/extend.spec.js +0 -29
- package/dist/testing/integration/glob.spec.js +0 -40
- package/dist/testing/integration/include.spec.js +0 -31
- package/dist/testing/integration/invalid.spec.js +0 -17
- package/dist/testing/integration/invalid_loop.spec.js +0 -56
- package/dist/testing/integration/k8s-state-cache.spec.js +0 -41
- package/dist/testing/integration/kubernetes-service.spec.js +0 -148
- package/dist/testing/integration/kubernetes.spec.js +0 -99
- package/dist/testing/integration/labels.spec.js +0 -42
- package/dist/testing/integration/local.spec.js +0 -14
- package/dist/testing/integration/monorepo.spec.js +0 -15
- package/dist/testing/integration/multi-line.spec.js +0 -17
- package/dist/testing/integration/reference.spec.js +0 -21
- package/dist/testing/integration/services.spec.js +0 -38
- package/dist/testing/integration/store.spec.js +0 -52
- package/dist/testing/integration/unknown.spec.js +0 -28
- package/dist/testing/integration/validate.spec.js +0 -160
- package/dist/testing/integration/watch-dependency.spec.js +0 -33
- package/dist/testing/integration/watch.spec.js +0 -45
- package/dist/testing/requires-kubernetes.js +0 -18
- package/dist/testing/requires-linux-containers.js +0 -18
- package/dist/testing/requires-windows-containers.js +0 -18
- package/dist/testing/test-case.js +0 -75
- package/dist/testing/test-streams.js +0 -28
- package/dist/testing/test-suite-setup.js +0 -3
- package/dist/testing/test-suite.js +0 -3
- package/dist/testing/testing-timeout.js +0 -32
- package/dist/utils/abort-event.spec.js +0 -46
- package/dist/utils/buffer-context.spec.js +0 -38
- package/dist/utils/ci.spec.js +0 -53
- package/dist/utils/debouncer.spec.js +0 -58
- package/dist/utils/emitter.spec.js +0 -34
- package/dist/utils/empty-writable.spec.js +0 -18
- package/dist/utils/environment-config.spec.js +0 -26
- package/dist/utils/fail-never.spec.js +0 -9
- package/dist/utils/sleep.spec.js +0 -22
- package/dist/version.spec.js +0 -12
- package/specs/build-file/caches/spec.md +0 -114
- package/specs/build-file/environment-variables/spec.md +0 -82
- package/specs/build-file/includes/spec.md +0 -60
- package/specs/build-file/references/spec.md +0 -56
- package/specs/build-file/spec.md +0 -62
- package/specs/cli/clean/spec.md +0 -85
- package/specs/cli/down/spec.md +0 -85
- package/specs/cli/execute/spec.md +0 -101
- package/specs/cli/init/spec.md +0 -64
- package/specs/cli/ls/spec.md +0 -66
- package/specs/cli/package/spec.md +0 -110
- package/specs/cli/spec.md +0 -73
- package/specs/cli/store-restore/spec.md +0 -74
- package/specs/cli/up/spec.md +0 -80
- package/specs/cli/validate/spec.md +0 -70
- package/specs/labels/spec.md +0 -91
- package/specs/service/container/spec.md +0 -120
- package/specs/service/kubernetes/spec.md +0 -97
- package/specs/service/spec.md +0 -105
- package/specs/task/caching/spec.md +0 -107
- package/specs/task/container/spec.md +0 -118
- package/specs/task/dependencies/spec.md +0 -70
- package/specs/task/extending/spec.md +0 -74
- package/specs/task/kubernetes/spec.md +0 -125
- package/specs/task/needs/spec.md +0 -59
- package/specs/task/spec.md +0 -87
- package/specs/task/watching/spec.md +0 -69
|
@@ -0,0 +1,102 @@
|
|
|
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.printRunSummary = exports.formatDuration = exports.summarizeRun = void 0;
|
|
7
|
+
const colors_1 = __importDefault(require("colors"));
|
|
8
|
+
const plan_work_tasks_1 = require("../planner/utils/plan-work-tasks");
|
|
9
|
+
const log_1 = require("../log");
|
|
10
|
+
function statusOf(state) {
|
|
11
|
+
switch (state.type) {
|
|
12
|
+
case 'completed':
|
|
13
|
+
return state.skipped ? 'skipped' : state.cached ? 'cached' : 'executed';
|
|
14
|
+
case 'error':
|
|
15
|
+
case 'crash':
|
|
16
|
+
return 'failed';
|
|
17
|
+
default:
|
|
18
|
+
// canceled, or never started (pending/starting/ready/running left over from
|
|
19
|
+
// an aborted run) — all surface as cancelled/skipped.
|
|
20
|
+
return 'cancelled';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
// Derive the run summary purely from the final task states already on the work
|
|
24
|
+
// tree — nothing is re-run. Deterministically ordered by task name.
|
|
25
|
+
function summarizeRun(workTree, totalDuration) {
|
|
26
|
+
const tasks = [];
|
|
27
|
+
for (const task of (0, plan_work_tasks_1.iterateWorkTasks)(workTree)) {
|
|
28
|
+
const state = task.state.current;
|
|
29
|
+
const cause = state.type === 'completed' && state.missCauses?.length ? state.missCauses.join(', ') : undefined;
|
|
30
|
+
tasks.push({
|
|
31
|
+
taskId: task.id(),
|
|
32
|
+
taskName: task.name,
|
|
33
|
+
status: statusOf(state),
|
|
34
|
+
duration: state.type === 'completed' ? state.duration : 0,
|
|
35
|
+
cause,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
tasks.sort((a, b) => a.taskName.localeCompare(b.taskName));
|
|
39
|
+
const executed = tasks.filter((t) => t.status === 'executed').length;
|
|
40
|
+
const cached = tasks.filter((t) => t.status === 'cached').length;
|
|
41
|
+
const skipped = tasks.filter((t) => t.status === 'skipped').length;
|
|
42
|
+
const failed = tasks.filter((t) => t.status === 'failed').length;
|
|
43
|
+
const cancelled = tasks.filter((t) => t.status === 'cancelled').length;
|
|
44
|
+
const ran = executed + cached;
|
|
45
|
+
return {
|
|
46
|
+
tasks,
|
|
47
|
+
executed,
|
|
48
|
+
cached,
|
|
49
|
+
skipped,
|
|
50
|
+
failed,
|
|
51
|
+
cancelled,
|
|
52
|
+
cacheHitRatio: ran === 0 ? 0 : cached / ran,
|
|
53
|
+
totalDuration,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
exports.summarizeRun = summarizeRun;
|
|
57
|
+
function formatDuration(ms) {
|
|
58
|
+
if (ms < 1000) {
|
|
59
|
+
return `${ms}ms`;
|
|
60
|
+
}
|
|
61
|
+
return `${(ms / 1000).toFixed(1)}s`;
|
|
62
|
+
}
|
|
63
|
+
exports.formatDuration = formatDuration;
|
|
64
|
+
function colorStatus(status) {
|
|
65
|
+
const label = status.padEnd(9);
|
|
66
|
+
switch (status) {
|
|
67
|
+
case 'executed':
|
|
68
|
+
return colors_1.default.cyan(label);
|
|
69
|
+
case 'cached':
|
|
70
|
+
return colors_1.default.green(label);
|
|
71
|
+
case 'skipped':
|
|
72
|
+
return colors_1.default.grey(label);
|
|
73
|
+
case 'failed':
|
|
74
|
+
return colors_1.default.red(label);
|
|
75
|
+
case 'cancelled':
|
|
76
|
+
return colors_1.default.grey(label);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Bound the name column so a single very long task name cannot blow out the
|
|
80
|
+
// width on large graphs.
|
|
81
|
+
const MAX_NAME_WIDTH = 60;
|
|
82
|
+
function printRunSummary(environment, summary) {
|
|
83
|
+
(0, log_1.printTitle)(environment, 'Summary');
|
|
84
|
+
if (summary.tasks.length === 0) {
|
|
85
|
+
environment.stdout.write(' nothing ran\n');
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const nameWidth = Math.min(MAX_NAME_WIDTH, summary.tasks.reduce((max, t) => Math.max(max, t.taskName.length), 0));
|
|
89
|
+
for (const task of summary.tasks) {
|
|
90
|
+
const name = task.taskName.length > nameWidth ? `${task.taskName.slice(0, nameWidth - 1)}…` : task.taskName.padEnd(nameWidth);
|
|
91
|
+
const cause = task.cause ? ` ${colors_1.default.grey(task.cause)}` : '';
|
|
92
|
+
environment.stdout.write(` ${name} ${colorStatus(task.status)} ${colors_1.default.grey(formatDuration(task.duration))}${cause}\n`);
|
|
93
|
+
}
|
|
94
|
+
const ratio = Math.round(summary.cacheHitRatio * 100);
|
|
95
|
+
const skippedSuffix = summary.skipped > 0 ? `, ${summary.skipped} skipped` : '';
|
|
96
|
+
const failedSuffix = summary.failed > 0 ? `, ${summary.failed} failed` : '';
|
|
97
|
+
const cancelledSuffix = summary.cancelled > 0 ? `, ${summary.cancelled} cancelled` : '';
|
|
98
|
+
environment.stdout.write(` ${summary.executed} executed, ${summary.cached} cached${skippedSuffix}${failedSuffix}${cancelledSuffix} ` +
|
|
99
|
+
`(${ratio}% cache hit), ${formatDuration(summary.totalDuration)} total\n`);
|
|
100
|
+
}
|
|
101
|
+
exports.printRunSummary = printRunSummary;
|
|
102
|
+
//# sourceMappingURL=run-summary.js.map
|
|
@@ -1,91 +1,46 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.checkCacheState = void 0;
|
|
4
|
-
const get_work_cache_stats_1 = require("../../optimizer/get-work-cache-stats");
|
|
5
4
|
const work_item_1 = require("../../planner/work-item");
|
|
6
5
|
const get_cache_directory_1 = require("../../optimizer/get-cache-directory");
|
|
7
6
|
const cache_metadata_1 = require("../cache-metadata");
|
|
8
7
|
const work_task_cache_description_1 = require("../../optimizer/work-task-cache-description");
|
|
9
8
|
const log_1 = require("../../log");
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
const declared = item.data.caching;
|
|
13
|
-
if (declared.implicit) {
|
|
14
|
-
return { ...declared, method: fallbackMethod };
|
|
15
|
-
}
|
|
16
|
-
return declared;
|
|
17
|
-
}
|
|
18
|
-
// Fold a task's own state key together with the state keys of its dependencies.
|
|
19
|
-
// A change anywhere in the dependency subtree must change the resulting key, so
|
|
20
|
-
// that a downstream task is invalidated when an upstream source changes — even
|
|
21
|
-
// if the downstream task's own sources are untouched.
|
|
22
|
-
function combineStateKeys(ownKey, depKeys) {
|
|
23
|
-
if (depKeys.length === 0) {
|
|
24
|
-
return ownKey;
|
|
25
|
-
}
|
|
26
|
-
// Sort so the key is independent of dependency declaration order.
|
|
27
|
-
const sorted = [...depKeys].sort();
|
|
28
|
-
return (0, crypto_1.createHash)('md5')
|
|
29
|
-
.update([ownKey, ...sorted].join(','))
|
|
30
|
-
.digest('hex');
|
|
31
|
-
}
|
|
32
|
-
// Compute an item's effective state key from its source files plus the effective
|
|
33
|
-
// state keys of its dependencies, recursively. This is derived purely from the
|
|
34
|
-
// work tree and the filesystem, so it does not depend on scheduler/run state —
|
|
35
|
-
// important because checkCacheState runs before dependencies are awaited.
|
|
36
|
-
async function resolveEffectiveStateKey(item, defaultCacheMethod, environment, memo) {
|
|
37
|
-
const existing = memo.get(item.id());
|
|
38
|
-
if (existing !== undefined) {
|
|
39
|
-
return existing;
|
|
40
|
-
}
|
|
41
|
-
const resolved = resolveEffective(item, defaultCacheMethod);
|
|
42
|
-
// Always hash with a concrete method; `none` only disables the cache *check*
|
|
43
|
-
// for that task, its sources still influence what depends on it.
|
|
44
|
-
const method = resolved.method === 'none' ? defaultCacheMethod : resolved.method;
|
|
45
|
-
const stats = await (0, get_work_cache_stats_1.getWorkCacheStats)(item.data, environment);
|
|
46
|
-
const ownKey = (0, get_work_cache_stats_1.getStateKey)(stats, method);
|
|
47
|
-
const depKeys = [];
|
|
48
|
-
for (const dep of item.deps) {
|
|
49
|
-
depKeys.push(await resolveEffectiveStateKey(dep, defaultCacheMethod, environment, memo));
|
|
50
|
-
}
|
|
51
|
-
const combined = combineStateKeys(ownKey, depKeys);
|
|
52
|
-
memo.set(item.id(), combined);
|
|
53
|
-
return combined;
|
|
54
|
-
}
|
|
9
|
+
const state_key_1 = require("./state-key");
|
|
10
|
+
const work_instance_id_1 = require("../../planner/work-instance-id");
|
|
55
11
|
async function checkCacheState(item, defaultCacheMethod, environment) {
|
|
56
|
-
const resolved =
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
const memo = new Map();
|
|
60
|
-
const depKeys = [];
|
|
61
|
-
for (const dep of item.deps) {
|
|
62
|
-
depKeys.push(await resolveEffectiveStateKey(dep, defaultCacheMethod, environment, memo));
|
|
12
|
+
const { stateKey, stats: currentStats, resolved, provable, unmatched, } = await (0, state_key_1.computeStateKey)(item, defaultCacheMethod, environment);
|
|
13
|
+
for (const src of unmatched) {
|
|
14
|
+
item.status.write('warn', `src "${src.source}" matches no files`);
|
|
63
15
|
}
|
|
64
|
-
const stateKey = combineStateKeys(ownKey, depKeys);
|
|
65
16
|
if (resolved.method === 'none') {
|
|
66
17
|
item.status.write('debug', `${item.name} is skipping cache check, because caching is disabled`);
|
|
67
|
-
return { cached: false, stateKey, resolved };
|
|
18
|
+
return { cached: false, stateKey, resolved, provable };
|
|
19
|
+
}
|
|
20
|
+
if ((0, work_item_1.isWorkTaskItem)(item) && !provable) {
|
|
21
|
+
item.status.write('debug', `${item.name} always runs, it or one of its dependencies has no src files`);
|
|
22
|
+
return { cached: false, stateKey, resolved, provable };
|
|
68
23
|
}
|
|
69
24
|
if ((0, work_item_1.isWorkTaskItem)(item)) {
|
|
70
25
|
const runtimeStateKey = await item.runtime.currentStateKey(environment);
|
|
71
26
|
if (runtimeStateKey === stateKey) {
|
|
72
|
-
return { cached: true, stateKey, resolved };
|
|
27
|
+
return { cached: true, stateKey, resolved, provable };
|
|
73
28
|
}
|
|
74
29
|
try {
|
|
75
|
-
const cacheDir = (0, get_cache_directory_1.getCacheDirectory)(
|
|
30
|
+
const cacheDir = (0, get_cache_directory_1.getCacheDirectory)((0, work_instance_id_1.getWorkInstanceId)(item));
|
|
76
31
|
const pulled = await resolved.backend.pull(item.id(), stateKey, cacheDir, environment);
|
|
77
32
|
if (pulled) {
|
|
78
33
|
item.status.write('info', `${item.name} pulled from cache "${resolved.name}" (${resolved.backend.type})`);
|
|
79
34
|
await item.runtime.restore(environment, cacheDir);
|
|
80
|
-
await (0, cache_metadata_1.writeCacheMetadata)(environment, item
|
|
81
|
-
return { cached: true, stateKey, resolved };
|
|
35
|
+
await (0, cache_metadata_1.writeCacheMetadata)(environment, item, currentStats, (0, work_task_cache_description_1.getWorkTaskCacheDescription)(item));
|
|
36
|
+
return { cached: true, stateKey, resolved, provable };
|
|
82
37
|
}
|
|
83
38
|
}
|
|
84
39
|
catch (e) {
|
|
85
40
|
item.status.write('warn', `${item.name} failed to pull from cache "${resolved.name}": ${(0, log_1.getErrorMessage)(e)} — continuing with local execution`);
|
|
86
41
|
}
|
|
87
42
|
}
|
|
88
|
-
return { cached: false, stateKey, resolved };
|
|
43
|
+
return { cached: false, stateKey, resolved, provable };
|
|
89
44
|
}
|
|
90
45
|
exports.checkCacheState = checkCacheState;
|
|
91
46
|
//# sourceMappingURL=enqueue-next.js.map
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.computeStateKey = exports.combineStateKeys = exports.resolveEffective = void 0;
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
|
+
const get_work_cache_stats_1 = require("../../optimizer/get-work-cache-stats");
|
|
6
|
+
// The state-key engine is shared by the scheduler's hit/miss decision
|
|
7
|
+
// (`checkCacheState`) and the read-only cache-explain engine, so a prediction
|
|
8
|
+
// can never diverge from the decision it predicts — there is one implementation.
|
|
9
|
+
function resolveEffective(item, fallbackMethod) {
|
|
10
|
+
const declared = item.data.caching;
|
|
11
|
+
if (declared.implicit) {
|
|
12
|
+
return { ...declared, method: fallbackMethod };
|
|
13
|
+
}
|
|
14
|
+
return declared;
|
|
15
|
+
}
|
|
16
|
+
exports.resolveEffective = resolveEffective;
|
|
17
|
+
// A task whose inputs cannot be observed cannot be proven up to date, so it
|
|
18
|
+
// always runs, and so does everything depending on it (specs/task SC-001). That
|
|
19
|
+
// is a task that declares no `src` of its own — the sources it inherits from its
|
|
20
|
+
// dependencies say nothing about the files its own commands read — and a task
|
|
21
|
+
// whose `src` entries all match no file (a typo, a moved path). Services are not
|
|
22
|
+
// affected.
|
|
23
|
+
function isOwnProvable(item, unmatched) {
|
|
24
|
+
// unmatched ⊆ declared, so this is also false when nothing is declared
|
|
25
|
+
return unmatched.length < item.data.src.filter((src) => !src.inherited).length;
|
|
26
|
+
}
|
|
27
|
+
// Fold a task's own state key together with the state keys of its dependencies.
|
|
28
|
+
// A change anywhere in the dependency subtree must change the resulting key, so
|
|
29
|
+
// that a downstream task is invalidated when an upstream source changes — even
|
|
30
|
+
// if the downstream task's own sources are untouched.
|
|
31
|
+
function combineStateKeys(ownKey, depKeys) {
|
|
32
|
+
if (depKeys.length === 0) {
|
|
33
|
+
return ownKey;
|
|
34
|
+
}
|
|
35
|
+
// Sort so the key is independent of dependency declaration order.
|
|
36
|
+
const sorted = [...depKeys].sort();
|
|
37
|
+
return (0, crypto_1.createHash)('md5')
|
|
38
|
+
.update([ownKey, ...sorted].join(','))
|
|
39
|
+
.digest('hex');
|
|
40
|
+
}
|
|
41
|
+
exports.combineStateKeys = combineStateKeys;
|
|
42
|
+
// `none` only disables the cache *check* for a task; its sources still influence
|
|
43
|
+
// what depends on it, so a concrete method is always used for the hash itself.
|
|
44
|
+
function concreteMethod(resolved, defaultCacheMethod) {
|
|
45
|
+
return resolved.method === 'none' ? defaultCacheMethod : resolved.method;
|
|
46
|
+
}
|
|
47
|
+
// Compute an item's effective state key from its source files plus the effective
|
|
48
|
+
// state keys of its dependencies, recursively. This is derived purely from the
|
|
49
|
+
// work tree and the filesystem, so it does not depend on scheduler/run state —
|
|
50
|
+
// important because it runs before dependencies are awaited.
|
|
51
|
+
async function resolveEffectiveStateKey(item, defaultCacheMethod, environment, memo) {
|
|
52
|
+
const existing = memo.get(item.id());
|
|
53
|
+
if (existing !== undefined) {
|
|
54
|
+
return existing;
|
|
55
|
+
}
|
|
56
|
+
const { stateKey, provable } = await computeStateKey(item, defaultCacheMethod, environment, memo);
|
|
57
|
+
const effective = { stateKey, provable };
|
|
58
|
+
memo.set(item.id(), effective);
|
|
59
|
+
return effective;
|
|
60
|
+
}
|
|
61
|
+
// Compute the combined state key for a single item together with the source
|
|
62
|
+
// stats it was derived from, sharing one filesystem walk with callers that also
|
|
63
|
+
// need the stats (the scheduler, the explain engine).
|
|
64
|
+
async function computeStateKey(item, defaultCacheMethod, environment, memo = new Map()) {
|
|
65
|
+
const resolved = resolveEffective(item, defaultCacheMethod);
|
|
66
|
+
const { stats, unmatched } = await (0, get_work_cache_stats_1.getWorkItemCacheStats)(item, environment);
|
|
67
|
+
const ownKey = (0, get_work_cache_stats_1.getStateKey)(stats, concreteMethod(resolved, defaultCacheMethod));
|
|
68
|
+
const depKeys = [];
|
|
69
|
+
let provable = isOwnProvable(item, unmatched);
|
|
70
|
+
for (const dep of item.deps) {
|
|
71
|
+
const effective = await resolveEffectiveStateKey(dep, defaultCacheMethod, environment, memo);
|
|
72
|
+
depKeys.push(effective.stateKey);
|
|
73
|
+
provable = provable && effective.provable;
|
|
74
|
+
}
|
|
75
|
+
return { stateKey: combineStateKeys(ownKey, depKeys), stats, resolved, provable, unmatched };
|
|
76
|
+
}
|
|
77
|
+
exports.computeStateKey = computeStateKey;
|
|
78
|
+
//# sourceMappingURL=state-key.js.map
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,16 @@ const abortCtrl = new AbortController();
|
|
|
10
10
|
process.on('SIGINT', function () {
|
|
11
11
|
abortCtrl.abort();
|
|
12
12
|
});
|
|
13
|
+
let settled = false;
|
|
14
|
+
// A run that never settles (a task waiting on something that can't happen)
|
|
15
|
+
// lets the event loop drain, and Node then exits 0: CI would report success
|
|
16
|
+
// for a build that never finished. Fail loudly instead.
|
|
17
|
+
process.on('beforeExit', () => {
|
|
18
|
+
if (!settled) {
|
|
19
|
+
process.stderr.write('hammerkit stopped before the run finished\n');
|
|
20
|
+
process.exitCode = 1;
|
|
21
|
+
}
|
|
22
|
+
});
|
|
13
23
|
(0, run_program_1.runProgram)({
|
|
14
24
|
cwd: process.cwd(),
|
|
15
25
|
abortCtrl,
|
|
@@ -20,7 +30,10 @@ process.on('SIGINT', function () {
|
|
|
20
30
|
stdout: process.stdout,
|
|
21
31
|
stderr: process.stderr,
|
|
22
32
|
stdoutColumns: process.stdout.columns,
|
|
23
|
-
}, process.argv, false).
|
|
33
|
+
}, process.argv, false).then(() => {
|
|
34
|
+
settled = true;
|
|
35
|
+
}, () => {
|
|
36
|
+
settled = true;
|
|
24
37
|
process.exit(1);
|
|
25
38
|
});
|
|
26
39
|
//# sourceMappingURL=index.js.map
|
package/dist/kubernetes/apply.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.apply = exports.statusCodeOf = void 0;
|
|
4
|
+
// The client throws an ApiException carrying the HTTP status as `code`; watch
|
|
5
|
+
// errors carry it as `statusCode`.
|
|
4
6
|
function statusCodeOf(e) {
|
|
5
7
|
const err = e;
|
|
6
|
-
return err?.
|
|
8
|
+
return typeof err?.code === 'number' ? err.code : err?.statusCode;
|
|
7
9
|
}
|
|
8
10
|
exports.statusCodeOf = statusCodeOf;
|
|
9
11
|
async function apply(instance, spec) {
|
|
10
12
|
try {
|
|
11
13
|
await instance.objectApi.read(spec);
|
|
12
|
-
|
|
13
|
-
return response.body;
|
|
14
|
+
return await instance.objectApi.patch(spec);
|
|
14
15
|
}
|
|
15
16
|
catch (e) {
|
|
16
17
|
try {
|
|
17
|
-
|
|
18
|
-
return response.body;
|
|
18
|
+
return await instance.objectApi.create(spec);
|
|
19
19
|
}
|
|
20
20
|
catch (createError) {
|
|
21
21
|
// Two work items can apply the same object concurrently (e.g. a volume
|
|
@@ -23,8 +23,7 @@ async function apply(instance, spec) {
|
|
|
23
23
|
// lost the create race, the object now exists — read it back instead of
|
|
24
24
|
// failing the whole item.
|
|
25
25
|
if (statusCodeOf(createError) === 409) {
|
|
26
|
-
|
|
27
|
-
return response.body;
|
|
26
|
+
return await instance.objectApi.read(spec);
|
|
28
27
|
}
|
|
29
28
|
throw createError;
|
|
30
29
|
}
|
|
@@ -1,71 +1,111 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.awaitDeployRunningState = exports.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
});
|
|
3
|
+
exports.deleteJobAndWait = exports.awaitDeployRunningState = exports.deleteJob = exports.awaitJobCompletion = exports.awaitRunningState = void 0;
|
|
4
|
+
const abort_1 = require("../executer/abort");
|
|
5
|
+
const abort_event_1 = require("../utils/abort-event");
|
|
6
|
+
const apply_1 = require("./apply");
|
|
7
|
+
const sleep_1 = require("../utils/sleep");
|
|
8
|
+
// The waits below poll instead of using the client's Watch: Watch aborts every
|
|
9
|
+
// request after 30s, which a pod or deployment still pulling its image outlasts.
|
|
10
|
+
async function awaitRunningState(instance, env, name, phase, pollInterval = 1000) {
|
|
11
|
+
for (;;) {
|
|
12
|
+
const pod = await instance.coreApi.readNamespacedPod({ name, namespace: env.namespace });
|
|
13
|
+
const current = pod.status?.phase;
|
|
14
|
+
if (current === phase) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (current === 'Succeeded' || current === 'Failed') {
|
|
18
|
+
throw new Error(`pod ${name} ended in phase ${current} before reaching ${phase}`);
|
|
19
|
+
}
|
|
20
|
+
await (0, sleep_1.sleep)(pollInterval);
|
|
21
|
+
}
|
|
23
22
|
}
|
|
24
23
|
exports.awaitRunningState = awaitRunningState;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
24
|
+
// Wait for a job to finish by polling its status: resolves once it succeeded,
|
|
25
|
+
// rejects when it failed (its `Failed` condition, i.e. retries are exhausted).
|
|
26
|
+
// On abort the job is deleted — with its pods — and an AbortError is thrown, so
|
|
27
|
+
// a cancelled or timed-out task leaves nothing running on the cluster.
|
|
28
|
+
async function awaitJobCompletion(instance, env, name, abort, pollInterval = 1000) {
|
|
29
|
+
for (;;) {
|
|
30
|
+
if (abort.aborted) {
|
|
31
|
+
await deleteJob(instance, env, name);
|
|
32
|
+
throw new abort_1.AbortError();
|
|
33
|
+
}
|
|
34
|
+
const job = await instance.batchApi.readNamespacedJobStatus({ name, namespace: env.namespace });
|
|
35
|
+
const status = job.status;
|
|
36
|
+
if (status?.succeeded) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const failed = status?.conditions?.find((c) => c.type === 'Failed' && c.status === 'True');
|
|
40
|
+
if (failed) {
|
|
41
|
+
throw new Error(`job ${name} failed: ${failed.message ?? failed.reason ?? 'unknown reason'}`);
|
|
42
|
+
}
|
|
43
|
+
await sleep(pollInterval, abort);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.awaitJobCompletion = awaitJobCompletion;
|
|
47
|
+
function sleep(ms, abort) {
|
|
48
|
+
if (abort.aborted) {
|
|
49
|
+
return Promise.resolve();
|
|
50
|
+
}
|
|
51
|
+
return new Promise((resolve) => {
|
|
52
|
+
const timer = setTimeout(() => {
|
|
53
|
+
listener.close();
|
|
54
|
+
resolve();
|
|
55
|
+
}, ms);
|
|
56
|
+
// not aborted yet, so this callback can only fire later, after assignment
|
|
57
|
+
const listener = (0, abort_event_1.listenOnAbort)(abort, () => {
|
|
58
|
+
clearTimeout(timer);
|
|
59
|
+
resolve();
|
|
42
60
|
});
|
|
43
61
|
});
|
|
44
62
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
obj.status?.readyReplicas) ??
|
|
53
|
-
0 > 0) {
|
|
54
|
-
req.then((r) => r.abort());
|
|
55
|
-
resolve();
|
|
56
|
-
}
|
|
57
|
-
}, (err) => {
|
|
58
|
-
if (err && err.message === 'aborted') {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
if (err) {
|
|
62
|
-
reject(err);
|
|
63
|
-
}
|
|
64
|
-
else {
|
|
65
|
-
resolve();
|
|
66
|
-
}
|
|
63
|
+
async function deleteJob(instance, env, name) {
|
|
64
|
+
try {
|
|
65
|
+
await instance.batchApi.deleteNamespacedJob({
|
|
66
|
+
name,
|
|
67
|
+
namespace: env.namespace,
|
|
68
|
+
gracePeriodSeconds: 0,
|
|
69
|
+
propagationPolicy: 'Background',
|
|
67
70
|
});
|
|
68
|
-
}
|
|
71
|
+
}
|
|
72
|
+
catch (e) {
|
|
73
|
+
if ((0, apply_1.statusCodeOf)(e) !== 404) {
|
|
74
|
+
throw e;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
exports.deleteJob = deleteJob;
|
|
79
|
+
async function awaitDeployRunningState(instance, env, name, pollInterval = 1000) {
|
|
80
|
+
for (;;) {
|
|
81
|
+
const deployment = await instance.appsApi.readNamespacedDeployment({ name, namespace: env.namespace });
|
|
82
|
+
if ((deployment.status?.readyReplicas ?? 0) > 0) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
await (0, sleep_1.sleep)(pollInterval);
|
|
86
|
+
}
|
|
69
87
|
}
|
|
70
88
|
exports.awaitDeployRunningState = awaitDeployRunningState;
|
|
89
|
+
// Delete a job and wait until it is gone: its name is reused for the task's next
|
|
90
|
+
// command (and the next run with the same state), and creating it while the old
|
|
91
|
+
// one is still being deleted would pick up the old job.
|
|
92
|
+
async function deleteJobAndWait(instance, env, name, abort, pollInterval = 500) {
|
|
93
|
+
await deleteJob(instance, env, name);
|
|
94
|
+
for (;;) {
|
|
95
|
+
try {
|
|
96
|
+
await instance.batchApi.readNamespacedJob({ name, namespace: env.namespace });
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
if ((0, apply_1.statusCodeOf)(e) === 404) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
throw e;
|
|
103
|
+
}
|
|
104
|
+
if (abort.aborted) {
|
|
105
|
+
throw new abort_1.AbortError();
|
|
106
|
+
}
|
|
107
|
+
await sleep(pollInterval, abort);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
exports.deleteJobAndWait = deleteJobAndWait;
|
|
71
111
|
//# sourceMappingURL=await-running-state.js.map
|
|
@@ -5,15 +5,12 @@ const apply_1 = require("./apply");
|
|
|
5
5
|
const resources_1 = require("./resources");
|
|
6
6
|
exports.HTTP_ROUTE_API_VERSION = 'gateway.networking.k8s.io/v1';
|
|
7
7
|
exports.HTTP_ROUTE_KIND = 'HTTPRoute';
|
|
8
|
-
async function ensureHttpRoute(instance, env,
|
|
9
|
-
if (!ingress.gateway) {
|
|
10
|
-
throw new Error(`httproute for ${ingress.host} requires a "gateway" (the parent Gateway name)`);
|
|
11
|
-
}
|
|
8
|
+
async function ensureHttpRoute(instance, env, route, service) {
|
|
12
9
|
const resource = {
|
|
13
10
|
apiVersion: exports.HTTP_ROUTE_API_VERSION,
|
|
14
11
|
kind: exports.HTTP_ROUTE_KIND,
|
|
15
12
|
metadata: {
|
|
16
|
-
name:
|
|
13
|
+
name: route.host,
|
|
17
14
|
namespace: env.namespace,
|
|
18
15
|
labels: {
|
|
19
16
|
'hammerkit.dev/id': service.id(),
|
|
@@ -22,25 +19,25 @@ async function ensureHttpRoute(instance, env, ingress, service) {
|
|
|
22
19
|
spec: {
|
|
23
20
|
parentRefs: [
|
|
24
21
|
{
|
|
25
|
-
name:
|
|
26
|
-
...(
|
|
22
|
+
name: route.gateway,
|
|
23
|
+
...(route.gatewayNamespace ? { namespace: route.gatewayNamespace } : {}),
|
|
27
24
|
},
|
|
28
25
|
],
|
|
29
|
-
hostnames: [
|
|
26
|
+
hostnames: [route.host],
|
|
30
27
|
rules: [
|
|
31
28
|
{
|
|
32
29
|
matches: [
|
|
33
30
|
{
|
|
34
31
|
path: {
|
|
35
32
|
type: 'PathPrefix',
|
|
36
|
-
value:
|
|
33
|
+
value: route.path ?? '/',
|
|
37
34
|
},
|
|
38
35
|
},
|
|
39
36
|
],
|
|
40
37
|
backendRefs: [
|
|
41
38
|
{
|
|
42
39
|
name: (0, resources_1.getResourceName)(service),
|
|
43
|
-
port:
|
|
40
|
+
port: route.servicePort ?? service.data.ports[0].containerPort,
|
|
44
41
|
},
|
|
45
42
|
],
|
|
46
43
|
},
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ensureNamespace = void 0;
|
|
4
|
-
|
|
5
|
-
const err = e;
|
|
6
|
-
return err?.statusCode ?? err?.response?.statusCode ?? err?.body?.code;
|
|
7
|
-
}
|
|
4
|
+
const apply_1 = require("./apply");
|
|
8
5
|
/**
|
|
9
6
|
* Idempotently make sure `namespace` exists. hammerkit does not otherwise
|
|
10
7
|
* create namespaces — deployments/services/jobs are applied straight into
|
|
@@ -16,25 +13,27 @@ function statusCodeOf(e) {
|
|
|
16
13
|
*/
|
|
17
14
|
async function ensureNamespace(instance, namespace) {
|
|
18
15
|
try {
|
|
19
|
-
await instance.coreApi.readNamespace(namespace);
|
|
16
|
+
await instance.coreApi.readNamespace({ name: namespace });
|
|
20
17
|
return;
|
|
21
18
|
}
|
|
22
19
|
catch (e) {
|
|
23
|
-
if (statusCodeOf(e) !== 404) {
|
|
20
|
+
if ((0, apply_1.statusCodeOf)(e) !== 404) {
|
|
24
21
|
throw e;
|
|
25
22
|
}
|
|
26
23
|
}
|
|
27
24
|
try {
|
|
28
25
|
await instance.coreApi.createNamespace({
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
body: {
|
|
27
|
+
metadata: {
|
|
28
|
+
name: namespace,
|
|
29
|
+
labels: { 'hammerkit.dev/managed': 'true' },
|
|
30
|
+
},
|
|
32
31
|
},
|
|
33
32
|
});
|
|
34
33
|
}
|
|
35
34
|
catch (e) {
|
|
36
35
|
// another worker created it between our read and create
|
|
37
|
-
if (statusCodeOf(e) !== 409) {
|
|
36
|
+
if ((0, apply_1.statusCodeOf)(e) !== 409) {
|
|
38
37
|
throw e;
|
|
39
38
|
}
|
|
40
39
|
}
|