hammerkit 1.26.0 → 1.27.0-next.10
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/build.schema.json +62 -1
- package/dist/cache/backends/local-cache-backend.js +10 -2
- package/dist/cache/backends/registry-cache-backend.js +2 -2
- package/dist/cache/explain.js +13 -11
- package/dist/cli.js +3 -0
- package/dist/docker/item-network.js +471 -0
- package/dist/docker/pull.js +4 -2
- package/dist/docker/remove-orphaned-containers.js +13 -6
- package/dist/environment/replace-env-variables.js +8 -6
- package/dist/executer/await-completed-dependencies.js +2 -1
- package/dist/executer/check-readiness.js +2 -2
- package/dist/executer/docker-service.js +24 -13
- package/dist/executer/docker-task.js +18 -29
- package/dist/executer/event-cache.js +24 -2
- package/dist/executer/execute-command.js +18 -5
- package/dist/executer/execute-docker.js +4 -1
- package/dist/executer/execution-steps.js +33 -7
- package/dist/executer/get-docker-executor.js +14 -7
- package/dist/executer/scheduler/enqueue-next.js +17 -3
- package/dist/executer/watch-loop.js +2 -2
- package/dist/executer/watch-state-key.js +1 -1
- package/dist/file/within-root.js +42 -0
- package/dist/harness/connect.js +99 -0
- package/dist/harness/format.js +73 -0
- package/dist/harness/mcp-command.js +59 -0
- package/dist/harness/mcp.js +432 -0
- package/dist/harness/opencode.js +492 -0
- package/dist/harness/pi.js +217 -0
- package/dist/harness/sandbox-client.js +411 -0
- package/dist/index.js +33 -36
- package/dist/kubernetes/apply.js +42 -1
- package/dist/kubernetes/await-running-state.js +33 -1
- package/dist/kubernetes/claim-layout.js +71 -0
- package/dist/kubernetes/ensure-http-route.js +1 -1
- package/dist/kubernetes/ensure-kubernetes-deployment-exists.js +46 -28
- package/dist/kubernetes/ensure-kubernetes-persistent-volume-claim-exists.js +132 -5
- package/dist/kubernetes/ensure-kubernetes-service-exists.js +27 -11
- package/dist/kubernetes/ensure-persistent-data.js +75 -24
- package/dist/kubernetes/get-service-ip.js +16 -2
- package/dist/kubernetes/job-placement.js +99 -0
- package/dist/kubernetes/job-secrets.js +320 -0
- package/dist/kubernetes/kept-claims.js +203 -0
- package/dist/kubernetes/kubernetes-instance.js +10 -2
- package/dist/kubernetes/network-gate.js +71 -0
- package/dist/kubernetes/network-policy.js +583 -0
- package/dist/kubernetes/remove-persistent-data.js +3 -1
- package/dist/kubernetes/resources.js +37 -4
- package/dist/kubernetes/restore-kubernetes-data.js +28 -7
- package/dist/kubernetes/secrets.js +7 -9
- package/dist/kubernetes/store-kubernetes-data.js +1 -1
- package/dist/kubernetes/volumes.js +104 -12
- package/dist/log.js +1 -1
- package/dist/main.js +41 -0
- package/dist/network/egress-proxy.js +407 -0
- package/dist/network/port-relay.js +35 -0
- package/dist/optimizer/get-work-cache-stats.js +16 -0
- package/dist/optimizer/work-task-cache-description.js +5 -2
- package/dist/planner/service-definition.js +5 -0
- package/dist/planner/utils/append-work-dependencies.js +5 -2
- package/dist/planner/utils/append-work-environment.js +2 -0
- package/dist/planner/utils/append-work-service.js +5 -0
- package/dist/planner/utils/append-work-task.js +20 -1
- package/dist/planner/utils/assert-item-paths.js +50 -0
- package/dist/planner/utils/hosted-volumes.js +35 -0
- package/dist/planner/utils/task-arguments.js +3 -0
- package/dist/planner/work-network.js +193 -0
- package/dist/planner/work-runtime-docker.js +43 -1
- package/dist/planner/work-runtime-kubernetes.js +370 -111
- package/dist/planner/work-runtime-local.js +2 -1
- package/dist/program.js +33 -5
- package/dist/remote/annotations.js +115 -0
- package/dist/remote/bundle-text.js +24 -0
- package/dist/remote/bundle.js +9 -1
- package/dist/remote/remote-commands.js +15 -3
- package/dist/remote/remote-work-commands.js +272 -71
- package/dist/remote/server-client.js +18 -5
- package/dist/remote/source-manifest.js +15 -2
- package/dist/remote/token-source.js +67 -0
- package/dist/schema/build-file-base-task-schema.js +7 -0
- package/dist/schema/build-file-container-service-schema.js +8 -0
- package/dist/schema/build-file-container-task-schema.js +3 -0
- package/dist/schema/build-file-environment-schema.js +9 -0
- package/dist/schema/network-schema.js +78 -0
- package/dist/schema/reference-parser.js +2 -0
- package/dist/schema/schema-parser.js +16 -3
- package/dist/schema/work-scope-parser.js +5 -0
- package/dist/secrets/command-secret-provider.js +73 -10
- package/dist/secrets/github-app-token-command.js +26 -0
- package/dist/secrets/github-app-token.js +191 -0
- package/dist/server/accounts-api.js +9 -2
- package/dist/server/definitions-api.js +69 -47
- package/dist/server/definitions.js +76 -51
- package/dist/server/executor.js +156 -41
- package/dist/server/git-checkout.js +72 -8
- package/dist/server/kubernetes-backend.js +603 -0
- package/dist/server/kubernetes-sandbox-storage.js +997 -0
- package/dist/server/oauth.js +12 -0
- package/dist/server/plan.js +88 -2
- package/dist/server/policy.js +104 -15
- package/dist/server/proposals-api.js +24 -40
- package/dist/server/proposals.js +12 -25
- package/dist/server/repo-access.js +37 -6
- package/dist/server/run-logs.js +217 -0
- package/dist/server/run-plan.js +48 -2
- package/dist/server/run-request.js +29 -10
- package/dist/server/run-store.js +5 -0
- package/dist/server/run-worker-command.js +13 -1
- package/dist/server/run-worker.js +121 -24
- package/dist/server/runs.js +191 -10
- package/dist/server/sandbox-docker.js +62 -0
- package/dist/server/sandbox-files-api.js +269 -0
- package/dist/server/sandbox-files.js +1054 -0
- package/dist/server/sandbox-patch.js +481 -0
- package/dist/server/sandbox-pod-command.js +15 -0
- package/dist/server/sandbox-pod.js +146 -0
- package/dist/server/sandbox-storage.js +462 -0
- package/dist/server/sandboxes-api.js +216 -0
- package/dist/server/sandboxes.js +519 -0
- package/dist/server/server-command.js +39 -20
- package/dist/server/server-config.js +443 -22
- package/dist/server/server.js +219 -40
- package/dist/utils/abort-on-signals.js +46 -6
- package/dist/utils/run-id.js +12 -0
- package/dist/utils/tar.js +25 -0
- package/harness/opencode.ts +11 -0
- package/harness/pi.ts +7 -0
- package/package.json +8 -2
- package/dist/remote/text-diff.js +0 -89
package/build.schema.json
CHANGED
|
@@ -261,6 +261,37 @@
|
|
|
261
261
|
"additionalProperties": false,
|
|
262
262
|
"description": "cpu and memory requests and limits"
|
|
263
263
|
},
|
|
264
|
+
"network": {
|
|
265
|
+
"anyOf": [
|
|
266
|
+
{
|
|
267
|
+
"type": "string",
|
|
268
|
+
"const": "open"
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
"type": "string",
|
|
272
|
+
"const": "none"
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
"type": "object",
|
|
276
|
+
"properties": {
|
|
277
|
+
"allow": {
|
|
278
|
+
"type": "array",
|
|
279
|
+
"items": {
|
|
280
|
+
"type": "string"
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
"required": [
|
|
285
|
+
"allow"
|
|
286
|
+
],
|
|
287
|
+
"additionalProperties": false
|
|
288
|
+
}
|
|
289
|
+
],
|
|
290
|
+
"description": "network the task or service reaches besides its needs: open (default), none or { allow: [hosts or host:port] }"
|
|
291
|
+
},
|
|
292
|
+
"args": {
|
|
293
|
+
"type": "boolean"
|
|
294
|
+
},
|
|
264
295
|
"runner": {
|
|
265
296
|
"type": "string",
|
|
266
297
|
"minLength": 1
|
|
@@ -273,6 +304,10 @@
|
|
|
273
304
|
"items": {
|
|
274
305
|
"type": "string"
|
|
275
306
|
}
|
|
307
|
+
},
|
|
308
|
+
"volumeSize": {
|
|
309
|
+
"type": "string",
|
|
310
|
+
"description": "size of its claim on Kubernetes, e.g. 10Gi"
|
|
276
311
|
}
|
|
277
312
|
},
|
|
278
313
|
"required": [
|
|
@@ -335,6 +370,12 @@
|
|
|
335
370
|
"resources": {
|
|
336
371
|
"$ref": "#/definitions/hammerkit/properties/tasks/additionalProperties/anyOf/0/properties/resources"
|
|
337
372
|
},
|
|
373
|
+
"network": {
|
|
374
|
+
"$ref": "#/definitions/hammerkit/properties/tasks/additionalProperties/anyOf/0/properties/network"
|
|
375
|
+
},
|
|
376
|
+
"args": {
|
|
377
|
+
"$ref": "#/definitions/hammerkit/properties/tasks/additionalProperties/anyOf/0/properties/args"
|
|
378
|
+
},
|
|
338
379
|
"runner": {
|
|
339
380
|
"$ref": "#/definitions/hammerkit/properties/tasks/additionalProperties/anyOf/0/properties/runner"
|
|
340
381
|
},
|
|
@@ -468,6 +509,17 @@
|
|
|
468
509
|
"resources": {
|
|
469
510
|
"$ref": "#/definitions/hammerkit/properties/tasks/additionalProperties/anyOf/0/properties/resources",
|
|
470
511
|
"description": "cpu and memory requests and limits"
|
|
512
|
+
},
|
|
513
|
+
"volumeSize": {
|
|
514
|
+
"$ref": "#/definitions/hammerkit/properties/tasks/additionalProperties/anyOf/0/properties/volumeSize",
|
|
515
|
+
"description": "size of its claim on Kubernetes, e.g. 10Gi"
|
|
516
|
+
},
|
|
517
|
+
"network": {
|
|
518
|
+
"$ref": "#/definitions/hammerkit/properties/tasks/additionalProperties/anyOf/0/properties/network",
|
|
519
|
+
"description": "network the task or service reaches besides its needs: open (default), none or { allow: [hosts or host:port] }"
|
|
520
|
+
},
|
|
521
|
+
"args": {
|
|
522
|
+
"type": "boolean"
|
|
471
523
|
}
|
|
472
524
|
},
|
|
473
525
|
"required": [
|
|
@@ -630,6 +682,15 @@
|
|
|
630
682
|
"additionalProperties": false
|
|
631
683
|
}
|
|
632
684
|
},
|
|
685
|
+
"networkPolicy": {
|
|
686
|
+
"type": "string",
|
|
687
|
+
"const": "enforced",
|
|
688
|
+
"description": "the cluster enforces NetworkPolicy, which limited networks need"
|
|
689
|
+
},
|
|
690
|
+
"volumeSize": {
|
|
691
|
+
"$ref": "#/definitions/hammerkit/properties/tasks/additionalProperties/anyOf/0/properties/volumeSize",
|
|
692
|
+
"description": "size of the claim of each task and service, 1Gi by default"
|
|
693
|
+
},
|
|
633
694
|
"ingresses": {
|
|
634
695
|
"not": {}
|
|
635
696
|
}
|
|
@@ -750,7 +811,7 @@
|
|
|
750
811
|
"$ref": "#/definitions/hammerkit/properties/tasks/additionalProperties/anyOf/0/properties/timeout"
|
|
751
812
|
},
|
|
752
813
|
"maxSize": {
|
|
753
|
-
"
|
|
814
|
+
"$ref": "#/definitions/hammerkit/properties/tasks/additionalProperties/anyOf/0/properties/volumeSize"
|
|
754
815
|
},
|
|
755
816
|
"keepPerTask": {
|
|
756
817
|
"type": "integer",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createLocalCacheBackend = void 0;
|
|
3
|
+
exports.createLocalCacheBackend = exports.getDefaultLocalCachePath = void 0;
|
|
4
4
|
const path_1 = require("path");
|
|
5
5
|
const os_1 = require("os");
|
|
6
6
|
const promises_1 = require("fs/promises");
|
|
@@ -16,8 +16,16 @@ async function directories(path) {
|
|
|
16
16
|
return [];
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
+
// Below the home directory, or below `HAMMERKIT_DIR` when that is set: a server sets
|
|
20
|
+
// it per source trust, so the runs of one repository share their cache and nobody
|
|
21
|
+
// else's run finds it (a run's home directory is its own and goes with it).
|
|
22
|
+
function getDefaultLocalCachePath() {
|
|
23
|
+
const directory = process.env.HAMMERKIT_DIR;
|
|
24
|
+
return directory ? (0, path_1.join)(directory, 'remote-cache') : (0, path_1.join)((0, os_1.homedir)(), '.hammerkit', 'remote-cache');
|
|
25
|
+
}
|
|
26
|
+
exports.getDefaultLocalCachePath = getDefaultLocalCachePath;
|
|
19
27
|
function createLocalCacheBackend(spec) {
|
|
20
|
-
const root = spec.path ?? (
|
|
28
|
+
const root = spec.path ?? getDefaultLocalCachePath();
|
|
21
29
|
async function readEntry(taskId, stateKey) {
|
|
22
30
|
const dir = (0, path_1.join)(root, taskId, stateKey);
|
|
23
31
|
let created;
|
|
@@ -5,6 +5,7 @@ const crypto_1 = require("crypto");
|
|
|
5
5
|
const os_1 = require("os");
|
|
6
6
|
const path_1 = require("path");
|
|
7
7
|
const tar_1 = require("tar");
|
|
8
|
+
const tar_2 = require("../../utils/tar");
|
|
8
9
|
const registry_reference_1 = require("./registry/registry-reference");
|
|
9
10
|
const registry_client_1 = require("./registry/registry-client");
|
|
10
11
|
const MAX_TAG_LENGTH = 128;
|
|
@@ -74,8 +75,7 @@ function createRegistryCacheBackend(spec) {
|
|
|
74
75
|
const layerFile = (0, path_1.join)(dir, 'layer.tar');
|
|
75
76
|
const files = (await environment.file.listFiles(from)).sort();
|
|
76
77
|
// portable + mtime-free so identical entries produce identical digests
|
|
77
|
-
|
|
78
|
-
await (0, tar_1.create)({ file: layerFile, cwd: from, portable: true, noMtime: true }, files);
|
|
78
|
+
await (0, tar_2.packArchive)({ file: layerFile, cwd: from, portable: true, noMtime: true }, files);
|
|
79
79
|
const layer = await (0, registry_client_1.digestFile)(layerFile);
|
|
80
80
|
const config = Buffer.from(JSON.stringify({
|
|
81
81
|
architecture: 'amd64',
|
package/dist/cache/explain.js
CHANGED
|
@@ -121,6 +121,19 @@ async function explainTask(item, defaultCacheMethod, environment, memo = new Map
|
|
|
121
121
|
return { taskId: item.id(), taskName: item.name, status: 'miss', causes: [{ kind: 'never-cached' }] };
|
|
122
122
|
}
|
|
123
123
|
visiting.add(item.id());
|
|
124
|
+
// Like the scheduler, a task whose cache is off is never looked up, so its
|
|
125
|
+
// sources aren't hashed for it.
|
|
126
|
+
if ((0, state_key_1.resolveEffective)(item, defaultCacheMethod).method === 'none') {
|
|
127
|
+
const explanation = {
|
|
128
|
+
taskId: item.id(),
|
|
129
|
+
taskName: item.name,
|
|
130
|
+
status: 'uncacheable',
|
|
131
|
+
causes: [{ kind: 'caching-disabled' }],
|
|
132
|
+
};
|
|
133
|
+
memo.set(item.id(), explanation);
|
|
134
|
+
visiting.delete(item.id());
|
|
135
|
+
return explanation;
|
|
136
|
+
}
|
|
124
137
|
const { stateKey, stats, resolved, provable, unmatched } = await (0, state_key_1.computeStateKey)(item, defaultCacheMethod, environment);
|
|
125
138
|
// Mirrors the scheduler: a task that cannot be proven up to date always runs
|
|
126
139
|
// (see computeStateKey), whatever a cache holds for it.
|
|
@@ -144,17 +157,6 @@ async function explainTask(item, defaultCacheMethod, environment, memo = new Map
|
|
|
144
157
|
visiting.delete(item.id());
|
|
145
158
|
return explanation;
|
|
146
159
|
}
|
|
147
|
-
if (resolved.method === 'none') {
|
|
148
|
-
const explanation = {
|
|
149
|
-
taskId: item.id(),
|
|
150
|
-
taskName: item.name,
|
|
151
|
-
status: 'uncacheable',
|
|
152
|
-
causes: [{ kind: 'caching-disabled' }],
|
|
153
|
-
};
|
|
154
|
-
memo.set(item.id(), explanation);
|
|
155
|
-
visiting.delete(item.id());
|
|
156
|
-
return explanation;
|
|
157
|
-
}
|
|
158
160
|
const runtimeStateKey = await safeCurrentStateKey(item, environment);
|
|
159
161
|
const hasEntry = await safeHas(item, stateKey, environment);
|
|
160
162
|
const predictedHit = runtimeStateKey === stateKey || hasEntry;
|
package/dist/cli.js
CHANGED
|
@@ -23,6 +23,7 @@ const dry_run_1 = require("./executer/dry-run");
|
|
|
23
23
|
const cache_sync_1 = require("./cache/cache-sync");
|
|
24
24
|
const cache_inventory_1 = require("./cache/cache-inventory");
|
|
25
25
|
const prefetch_secrets_1 = require("./secrets/prefetch-secrets");
|
|
26
|
+
const work_network_1 = require("./planner/work-network");
|
|
26
27
|
const isCliTask = (val) => val.type === 'task';
|
|
27
28
|
exports.isCliTask = isCliTask;
|
|
28
29
|
const isCliService = (val) => val.type === 'service';
|
|
@@ -50,6 +51,7 @@ class Cli {
|
|
|
50
51
|
return {
|
|
51
52
|
state: processWorkTree,
|
|
52
53
|
start: async () => {
|
|
54
|
+
(0, work_network_1.applyNetworkCeiling)(workTree, type === 'down' ? null : options?.network ?? null);
|
|
53
55
|
if (type !== 'down') {
|
|
54
56
|
await this.prepareSecrets(true);
|
|
55
57
|
}
|
|
@@ -80,6 +82,7 @@ class Cli {
|
|
|
80
82
|
skipDeps: options?.skipDeps ?? true,
|
|
81
83
|
wait: options?.wait ?? 'ready',
|
|
82
84
|
resourceCheck: options?.resourceCheck ?? true,
|
|
85
|
+
network: options?.network ?? null,
|
|
83
86
|
});
|
|
84
87
|
}
|
|
85
88
|
const result = (0, get_scheduler_execute_result_1.getSchedulerExecuteResult)(workTree);
|