hammerkit 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/build.schema.json +49 -2
- 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 +5 -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 +2 -1
- 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-work-service.js +10 -1
- package/dist/executer/execute-work-task.js +95 -25
- package/dist/executer/execute-work-tree.js +26 -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/kubernetes/await-running-state.js +73 -19
- 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-service.js +2 -1
- package/dist/planner/utils/append-work-task.js +7 -1
- 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 +53 -15
- package/dist/planner/work-runtime-kubernetes.js +35 -3
- package/dist/planner/work-runtime-local.js +9 -3
- 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/cache-schema.js +21 -2
- package/dist/schema/duration-schema.js +18 -0
- 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 +12 -1
- 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-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-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
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const process_manager_1 = require("./process-manager");
|
|
4
|
-
const work_item_status_1 = require("../planner/work-item-status");
|
|
5
|
-
const empty_writable_1 = require("../utils/empty-writable");
|
|
6
|
-
describe('process-manager', () => {
|
|
7
|
-
function fakeWorkItem(id) {
|
|
8
|
-
return {
|
|
9
|
-
id: () => '',
|
|
10
|
-
status: (0, work_item_status_1.statusConsole)((0, empty_writable_1.emptyWritable)()).context((0, work_item_status_1.logContext)('task', { name: id })),
|
|
11
|
-
deps: [],
|
|
12
|
-
aliases: [id],
|
|
13
|
-
needs: [],
|
|
14
|
-
requiredBy: [],
|
|
15
|
-
name: id,
|
|
16
|
-
data: null,
|
|
17
|
-
state: null,
|
|
18
|
-
runtime: null,
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
it('should complete on success', async () => {
|
|
22
|
-
const manager = new process_manager_1.ProcessManager(0);
|
|
23
|
-
let called = false;
|
|
24
|
-
await manager.task(fakeWorkItem('a'), () => new Promise((resolve) => setTimeout(() => {
|
|
25
|
-
called = true;
|
|
26
|
-
resolve();
|
|
27
|
-
}, 100)));
|
|
28
|
-
expect(called).toBeTruthy();
|
|
29
|
-
});
|
|
30
|
-
it('should throw error', async () => {
|
|
31
|
-
const manager = new process_manager_1.ProcessManager(0);
|
|
32
|
-
await expect(manager.task(fakeWorkItem('a'), () => new Promise((resolve, reject) => setTimeout(() => reject(new Error('3')), 100)))).rejects.toThrow('3');
|
|
33
|
-
});
|
|
34
|
-
it('should not start more than worker count', async () => {
|
|
35
|
-
const manager = new process_manager_1.ProcessManager(1);
|
|
36
|
-
let concurrencyCount = 0;
|
|
37
|
-
const fakeAction = () => new Promise((resolve) => {
|
|
38
|
-
expect(concurrencyCount).toBe(0);
|
|
39
|
-
concurrencyCount++;
|
|
40
|
-
setTimeout(() => {
|
|
41
|
-
expect(concurrencyCount).toBe(1);
|
|
42
|
-
concurrencyCount--;
|
|
43
|
-
resolve();
|
|
44
|
-
}, 100);
|
|
45
|
-
});
|
|
46
|
-
await Promise.all([
|
|
47
|
-
manager.task(fakeWorkItem('a'), fakeAction),
|
|
48
|
-
manager.task(fakeWorkItem('b'), fakeAction),
|
|
49
|
-
manager.task(fakeWorkItem('c'), fakeAction),
|
|
50
|
-
]);
|
|
51
|
-
expect(concurrencyCount).toBe(0);
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
//# sourceMappingURL=process-manager.spec.js.map
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const path_1 = require("path");
|
|
4
|
-
const os_1 = require("os");
|
|
5
|
-
const fs_1 = require("fs");
|
|
6
|
-
const environment_mock_1 = require("../environment-mock");
|
|
7
|
-
const enqueue_next_1 = require("./enqueue-next");
|
|
8
|
-
const local_cache_backend_1 = require("../../cache/backends/local-cache-backend");
|
|
9
|
-
const state_1 = require("../state");
|
|
10
|
-
describe('checkCacheState', () => {
|
|
11
|
-
let scratch;
|
|
12
|
-
let remoteDir;
|
|
13
|
-
let machineHome;
|
|
14
|
-
let originalHome;
|
|
15
|
-
beforeEach(() => {
|
|
16
|
-
scratch = (0, fs_1.mkdtempSync)((0, path_1.join)((0, os_1.tmpdir)(), 'hammerkit-enqueue-'));
|
|
17
|
-
remoteDir = (0, fs_1.mkdtempSync)((0, path_1.join)((0, os_1.tmpdir)(), 'hammerkit-remote-'));
|
|
18
|
-
machineHome = (0, fs_1.mkdtempSync)((0, path_1.join)((0, os_1.tmpdir)(), 'hammerkit-home-'));
|
|
19
|
-
originalHome = process.env.HOME;
|
|
20
|
-
if (process.platform === 'win32') {
|
|
21
|
-
process.env.APPDATA = machineHome;
|
|
22
|
-
}
|
|
23
|
-
else {
|
|
24
|
-
process.env.HOME = machineHome;
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
afterEach(() => {
|
|
28
|
-
(0, fs_1.rmSync)(scratch, { recursive: true, force: true });
|
|
29
|
-
(0, fs_1.rmSync)(remoteDir, { recursive: true, force: true });
|
|
30
|
-
(0, fs_1.rmSync)(machineHome, { recursive: true, force: true });
|
|
31
|
-
if (originalHome !== undefined) {
|
|
32
|
-
process.env.HOME = originalHome;
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
delete process.env.HOME;
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
// empty remote → backend.pull always misses, so a key mismatch yields cached:false
|
|
39
|
-
function makeResolved(method) {
|
|
40
|
-
return {
|
|
41
|
-
name: 'remote',
|
|
42
|
-
method,
|
|
43
|
-
backend: (0, local_cache_backend_1.createLocalCacheBackend)({ type: 'local', path: remoteDir }),
|
|
44
|
-
implicit: false,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
function makeTask(id, options) {
|
|
48
|
-
const storedStateKey = options.storedStateKey ?? null;
|
|
49
|
-
return {
|
|
50
|
-
id: () => id,
|
|
51
|
-
name: id,
|
|
52
|
-
status: { write: vi.fn() },
|
|
53
|
-
data: {
|
|
54
|
-
type: 'local-task',
|
|
55
|
-
name: id,
|
|
56
|
-
cwd: scratch,
|
|
57
|
-
cmds: [],
|
|
58
|
-
generates: [],
|
|
59
|
-
src: (options.srcFiles ?? []).map((absolutePath) => ({
|
|
60
|
-
absolutePath,
|
|
61
|
-
source: absolutePath,
|
|
62
|
-
matcher: () => true,
|
|
63
|
-
inherited: null,
|
|
64
|
-
isFile: true,
|
|
65
|
-
})),
|
|
66
|
-
envs: { variables: {}, replacements: [] },
|
|
67
|
-
labels: {},
|
|
68
|
-
shell: '/bin/sh',
|
|
69
|
-
caching: options.resolved,
|
|
70
|
-
description: null,
|
|
71
|
-
scope: {},
|
|
72
|
-
},
|
|
73
|
-
needs: [],
|
|
74
|
-
deps: options.deps ?? [],
|
|
75
|
-
requiredBy: [],
|
|
76
|
-
state: new state_1.State({ type: 'pending', stateKey: null }),
|
|
77
|
-
runtime: {
|
|
78
|
-
async initialize() { },
|
|
79
|
-
async remove() { },
|
|
80
|
-
async execute() { },
|
|
81
|
-
async stop() { },
|
|
82
|
-
async archive() { },
|
|
83
|
-
async restore() { },
|
|
84
|
-
async currentStateKey() {
|
|
85
|
-
return storedStateKey;
|
|
86
|
-
},
|
|
87
|
-
},
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
it('reports cached:false when caching method is none', async () => {
|
|
91
|
-
const env = (0, environment_mock_1.environmentMock)(scratch);
|
|
92
|
-
const task = makeTask('none-task', { resolved: makeResolved('none') });
|
|
93
|
-
const result = await (0, enqueue_next_1.checkCacheState)(task, 'checksum', env);
|
|
94
|
-
expect(result.cached).toBe(false);
|
|
95
|
-
});
|
|
96
|
-
it('reports cached:true when the stored key matches the effective key', async () => {
|
|
97
|
-
const env = (0, environment_mock_1.environmentMock)(scratch);
|
|
98
|
-
const probe = makeTask('hit-task', { resolved: makeResolved('checksum') });
|
|
99
|
-
const { stateKey } = await (0, enqueue_next_1.checkCacheState)(probe, 'checksum', env);
|
|
100
|
-
const task = makeTask('hit-task', { resolved: makeResolved('checksum'), storedStateKey: stateKey });
|
|
101
|
-
const result = await (0, enqueue_next_1.checkCacheState)(task, 'checksum', env);
|
|
102
|
-
expect(result.cached).toBe(true);
|
|
103
|
-
expect(result.stateKey).toBe(stateKey);
|
|
104
|
-
});
|
|
105
|
-
it('invalidates a downstream task when an upstream dependency source changes', async () => {
|
|
106
|
-
const env = (0, environment_mock_1.environmentMock)(scratch);
|
|
107
|
-
const upstreamSrc = (0, path_1.join)(scratch, 'upstream.txt');
|
|
108
|
-
(0, fs_1.writeFileSync)(upstreamSrc, 'v1');
|
|
109
|
-
const makeUpstream = () => makeTask('upstream', { resolved: makeResolved('checksum'), srcFiles: [upstreamSrc] });
|
|
110
|
-
const makeDownstream = (storedStateKey) => makeTask('downstream', { resolved: makeResolved('checksum'), deps: [makeUpstream()], storedStateKey });
|
|
111
|
-
// First pass: capture the downstream effective key and pretend it was stored.
|
|
112
|
-
const keyBefore = (await (0, enqueue_next_1.checkCacheState)(makeDownstream(null), 'checksum', env)).stateKey;
|
|
113
|
-
const cachedHit = await (0, enqueue_next_1.checkCacheState)(makeDownstream(keyBefore), 'checksum', env);
|
|
114
|
-
expect(cachedHit.cached).toBe(true);
|
|
115
|
-
// Change ONLY the upstream source — downstream's own sources are untouched.
|
|
116
|
-
(0, fs_1.writeFileSync)(upstreamSrc, 'v2-changed');
|
|
117
|
-
const afterChange = await (0, enqueue_next_1.checkCacheState)(makeDownstream(keyBefore), 'checksum', env);
|
|
118
|
-
expect(afterChange.stateKey).not.toBe(keyBefore);
|
|
119
|
-
expect(afterChange.cached).toBe(false);
|
|
120
|
-
});
|
|
121
|
-
it('produces a stable key regardless of dependency declaration order', async () => {
|
|
122
|
-
const env = (0, environment_mock_1.environmentMock)(scratch);
|
|
123
|
-
const aSrc = (0, path_1.join)(scratch, 'a.txt');
|
|
124
|
-
const bSrc = (0, path_1.join)(scratch, 'b.txt');
|
|
125
|
-
(0, fs_1.writeFileSync)(aSrc, 'a');
|
|
126
|
-
(0, fs_1.writeFileSync)(bSrc, 'b');
|
|
127
|
-
const depA = () => makeTask('dep-a', { resolved: makeResolved('checksum'), srcFiles: [aSrc] });
|
|
128
|
-
const depB = () => makeTask('dep-b', { resolved: makeResolved('checksum'), srcFiles: [bSrc] });
|
|
129
|
-
const forward = makeTask('root', { resolved: makeResolved('checksum'), deps: [depA(), depB()] });
|
|
130
|
-
const reversed = makeTask('root', { resolved: makeResolved('checksum'), deps: [depB(), depA()] });
|
|
131
|
-
const keyForward = (await (0, enqueue_next_1.checkCacheState)(forward, 'checksum', env)).stateKey;
|
|
132
|
-
const keyReversed = (await (0, enqueue_next_1.checkCacheState)(reversed, 'checksum', env)).stateKey;
|
|
133
|
-
expect(keyForward).toBe(keyReversed);
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
//# sourceMappingURL=enqueue-next.spec.js.map
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const state_resolver_1 = require("./state-resolver");
|
|
4
|
-
const state_1 = require("./state");
|
|
5
|
-
const abort_1 = require("./abort");
|
|
6
|
-
describe('state-resolver', () => {
|
|
7
|
-
it('should resolve state', async () => {
|
|
8
|
-
const state = new state_1.State('a');
|
|
9
|
-
const isB = (val) => val === 'b';
|
|
10
|
-
const result = (0, state_resolver_1.isState)('test-state', state, isB, new AbortController().signal);
|
|
11
|
-
state.set('c');
|
|
12
|
-
state.set('a');
|
|
13
|
-
state.set('b');
|
|
14
|
-
await result;
|
|
15
|
-
});
|
|
16
|
-
it('should resolve state if already in', async () => {
|
|
17
|
-
const state = new state_1.State('b');
|
|
18
|
-
const isB = (val) => val === 'b';
|
|
19
|
-
await (0, state_resolver_1.isState)('test-state', state, isB, new AbortController().signal);
|
|
20
|
-
});
|
|
21
|
-
it('isState rejects with AbortError when aborted before the condition is met', async () => {
|
|
22
|
-
const state = new state_1.State('a');
|
|
23
|
-
const isB = (val) => val === 'b';
|
|
24
|
-
const abort = new AbortController();
|
|
25
|
-
const result = (0, state_resolver_1.isState)('test-state', state, isB, abort.signal);
|
|
26
|
-
abort.abort();
|
|
27
|
-
await expect(result).rejects.toBeInstanceOf(abort_1.AbortError);
|
|
28
|
-
});
|
|
29
|
-
it('awaitState rejects with AbortError when aborted before the condition is met', async () => {
|
|
30
|
-
const state = new state_1.State('a');
|
|
31
|
-
const abort = new AbortController();
|
|
32
|
-
const result = (0, state_resolver_1.awaitState)('test-state', state, (val) => val === 'b', abort.signal);
|
|
33
|
-
abort.abort();
|
|
34
|
-
await expect(result).rejects.toBeInstanceOf(abort_1.AbortError);
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
//# sourceMappingURL=state-resolver.spec.js.map
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const state_1 = require("./state");
|
|
4
|
-
describe('State', () => {
|
|
5
|
-
it('exposes the initial value via `current`', () => {
|
|
6
|
-
const s = new state_1.State(7);
|
|
7
|
-
expect(s.current).toBe(7);
|
|
8
|
-
});
|
|
9
|
-
it('set() updates current and returns the new value', () => {
|
|
10
|
-
const s = new state_1.State(0);
|
|
11
|
-
expect(s.set(3)).toBe(3);
|
|
12
|
-
expect(s.current).toBe(3);
|
|
13
|
-
});
|
|
14
|
-
it('notifies every registered listener on set()', () => {
|
|
15
|
-
const s = new state_1.State(0);
|
|
16
|
-
const a = vi.fn();
|
|
17
|
-
const b = vi.fn();
|
|
18
|
-
s.on('a', a);
|
|
19
|
-
s.on('b', b);
|
|
20
|
-
s.set(1);
|
|
21
|
-
expect(a).toHaveBeenCalledWith(1);
|
|
22
|
-
expect(b).toHaveBeenCalledWith(1);
|
|
23
|
-
});
|
|
24
|
-
it('close() on a listener handle stops further notifications', () => {
|
|
25
|
-
const s = new state_1.State(0);
|
|
26
|
-
const cb = vi.fn();
|
|
27
|
-
const handle = s.on('k', cb);
|
|
28
|
-
handle.close();
|
|
29
|
-
s.set(1);
|
|
30
|
-
expect(cb).not.toHaveBeenCalled();
|
|
31
|
-
});
|
|
32
|
-
it('close() on an already-removed listener is a no-op', () => {
|
|
33
|
-
const s = new state_1.State(0);
|
|
34
|
-
const handle = s.on('k', vi.fn());
|
|
35
|
-
handle.close();
|
|
36
|
-
expect(() => handle.close()).not.toThrow();
|
|
37
|
-
});
|
|
38
|
-
it('forwards sub-state changes to its own listeners', () => {
|
|
39
|
-
const sub = new state_1.State(0);
|
|
40
|
-
const parent = new state_1.State('p', { subStates: [sub] });
|
|
41
|
-
const cb = vi.fn();
|
|
42
|
-
parent.on('any', cb);
|
|
43
|
-
// emit a 'sub-state-forward' on the sub-state to trigger parent notification
|
|
44
|
-
sub.set(1); // sub.set notifies its listeners under whatever keys are registered
|
|
45
|
-
// The parent registered for 'sub-state-forward' on the sub; sub.set calls
|
|
46
|
-
// notifyListeners which dispatches to all listeners regardless of key, so
|
|
47
|
-
// the parent's forwarding listener fires and notifies parent listeners.
|
|
48
|
-
expect(cb).toHaveBeenCalledWith('p');
|
|
49
|
-
});
|
|
50
|
-
it('close() runs the onDestroy callback', () => {
|
|
51
|
-
const onDestroy = vi.fn();
|
|
52
|
-
const s = new state_1.State(0, { onDestroy });
|
|
53
|
-
s.close();
|
|
54
|
-
expect(onDestroy).toHaveBeenCalledTimes(1);
|
|
55
|
-
});
|
|
56
|
-
it('close() detaches sub-state forwarders', () => {
|
|
57
|
-
const sub = new state_1.State(0);
|
|
58
|
-
const parent = new state_1.State('p', { subStates: [sub] });
|
|
59
|
-
const cb = vi.fn();
|
|
60
|
-
parent.on('any', cb);
|
|
61
|
-
parent.close();
|
|
62
|
-
sub.set(1);
|
|
63
|
-
expect(cb).not.toHaveBeenCalled();
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
//# sourceMappingURL=state.spec.js.map
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const states_1 = require("./states");
|
|
4
|
-
describe('getDuration', () => {
|
|
5
|
-
it('returns the milliseconds elapsed since the given start date', () => {
|
|
6
|
-
const started = new Date(Date.now() - 250);
|
|
7
|
-
const d = (0, states_1.getDuration)(started);
|
|
8
|
-
expect(d).toBeGreaterThanOrEqual(250);
|
|
9
|
-
});
|
|
10
|
-
it('returns 0 (or very small) for a start date that is essentially now', () => {
|
|
11
|
-
expect((0, states_1.getDuration)(new Date())).toBeGreaterThanOrEqual(0);
|
|
12
|
-
});
|
|
13
|
-
});
|
|
14
|
-
//# sourceMappingURL=states.spec.js.map
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const path_1 = require("path");
|
|
4
|
-
const os_1 = require("os");
|
|
5
|
-
const fs_1 = require("fs");
|
|
6
|
-
const stream_1 = require("stream");
|
|
7
|
-
const get_file_context_1 = require("./get-file-context");
|
|
8
|
-
describe('getFileContext', () => {
|
|
9
|
-
let cwd;
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
cwd = (0, fs_1.mkdtempSync)((0, path_1.join)((0, os_1.tmpdir)(), 'hammerkit-fc-'));
|
|
12
|
-
});
|
|
13
|
-
afterEach(() => {
|
|
14
|
-
// maxRetries handles Windows' transient ENOTEMPTY/EBUSY when a handle is
|
|
15
|
-
// released a beat after the test ends (mirrors getFileContext.remove). The
|
|
16
|
-
// stream tests below also await 'close' so this is only a safety net.
|
|
17
|
-
(0, fs_1.rmSync)(cwd, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 });
|
|
18
|
-
});
|
|
19
|
-
describe('stats', () => {
|
|
20
|
-
it('reports type "directory" for a directory', async () => {
|
|
21
|
-
const fc = (0, get_file_context_1.getFileContext)(cwd);
|
|
22
|
-
expect((await fc.stats('.')).type).toBe('directory');
|
|
23
|
-
});
|
|
24
|
-
it('reports type "file" with lastModified for a regular file', async () => {
|
|
25
|
-
(0, fs_1.writeFileSync)((0, path_1.join)(cwd, 'a.txt'), 'x');
|
|
26
|
-
const fc = (0, get_file_context_1.getFileContext)(cwd);
|
|
27
|
-
const s = await fc.stats('a.txt');
|
|
28
|
-
expect(s.type).toBe('file');
|
|
29
|
-
if (s.type === 'file') {
|
|
30
|
-
expect(s.lastModified).toBeGreaterThan(0);
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
it('rejects when the path does not exist', async () => {
|
|
34
|
-
const fc = (0, get_file_context_1.getFileContext)(cwd);
|
|
35
|
-
await expect(fc.stats('missing')).rejects.toThrow();
|
|
36
|
-
});
|
|
37
|
-
it('reports type "other" for non-file non-directory entries (symlink to missing)', async () => {
|
|
38
|
-
const link = (0, path_1.join)(cwd, 'link');
|
|
39
|
-
try {
|
|
40
|
-
(0, fs_1.symlinkSync)('/no/such/target', link);
|
|
41
|
-
}
|
|
42
|
-
catch {
|
|
43
|
-
// symlink may not be permitted on this platform — accept either outcome
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
// statSync (used by stats()) follows symlinks; if the target is missing it errors.
|
|
47
|
-
// That is the existing behavior; we cover the rejection path here.
|
|
48
|
-
const fc = (0, get_file_context_1.getFileContext)(cwd);
|
|
49
|
-
await expect(fc.stats('link')).rejects.toThrow();
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
describe('exists', () => {
|
|
53
|
-
it('resolves true for an existing path and false otherwise', async () => {
|
|
54
|
-
const fc = (0, get_file_context_1.getFileContext)(cwd);
|
|
55
|
-
expect(await fc.exists('.')).toBe(true);
|
|
56
|
-
expect(await fc.exists('nope')).toBe(false);
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
describe('writeFile / read / appendFile', () => {
|
|
60
|
-
it('writes, reads, and appends file content', async () => {
|
|
61
|
-
const fc = (0, get_file_context_1.getFileContext)(cwd);
|
|
62
|
-
await fc.writeFile('f.txt', 'hello');
|
|
63
|
-
expect(await fc.read('f.txt')).toBe('hello');
|
|
64
|
-
await fc.appendFile('f.txt', ' world');
|
|
65
|
-
expect(await fc.read('f.txt')).toBe('hello world');
|
|
66
|
-
});
|
|
67
|
-
it('read rejects on missing file', async () => {
|
|
68
|
-
const fc = (0, get_file_context_1.getFileContext)(cwd);
|
|
69
|
-
await expect(fc.read('missing.txt')).rejects.toThrow();
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
describe('listFiles', () => {
|
|
73
|
-
it('returns the entries in a directory', async () => {
|
|
74
|
-
(0, fs_1.writeFileSync)((0, path_1.join)(cwd, 'a'), '');
|
|
75
|
-
(0, fs_1.writeFileSync)((0, path_1.join)(cwd, 'b'), '');
|
|
76
|
-
const fc = (0, get_file_context_1.getFileContext)(cwd);
|
|
77
|
-
expect((await fc.listFiles('.')).sort()).toEqual(['a', 'b']);
|
|
78
|
-
});
|
|
79
|
-
});
|
|
80
|
-
describe('createDirectory / remove', () => {
|
|
81
|
-
it('creates a directory recursively and removes it', async () => {
|
|
82
|
-
const fc = (0, get_file_context_1.getFileContext)(cwd);
|
|
83
|
-
await fc.createDirectory((0, path_1.join)('deep', 'inner'));
|
|
84
|
-
expect(await fc.exists((0, path_1.join)('deep', 'inner'))).toBe(true);
|
|
85
|
-
await fc.remove('deep');
|
|
86
|
-
expect(await fc.exists('deep')).toBe(false);
|
|
87
|
-
});
|
|
88
|
-
it('remove on a missing path is a no-op', async () => {
|
|
89
|
-
const fc = (0, get_file_context_1.getFileContext)(cwd);
|
|
90
|
-
await expect(fc.remove('nope')).resolves.toBeUndefined();
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
describe('copy', () => {
|
|
94
|
-
it('copies a file, creating the destination directory if needed', async () => {
|
|
95
|
-
const fc = (0, get_file_context_1.getFileContext)(cwd);
|
|
96
|
-
await fc.writeFile('src.txt', 'data');
|
|
97
|
-
await fc.copy('src.txt', (0, path_1.join)('dest', 'src.txt'));
|
|
98
|
-
expect((0, fs_1.readFileSync)((0, path_1.join)(cwd, 'dest', 'src.txt'), 'utf8')).toBe('data');
|
|
99
|
-
});
|
|
100
|
-
it('copies a directory recursively', async () => {
|
|
101
|
-
const fc = (0, get_file_context_1.getFileContext)(cwd);
|
|
102
|
-
(0, fs_1.mkdirSync)((0, path_1.join)(cwd, 'src', 'sub'), { recursive: true });
|
|
103
|
-
(0, fs_1.writeFileSync)((0, path_1.join)(cwd, 'src', 'a.txt'), 'a');
|
|
104
|
-
(0, fs_1.writeFileSync)((0, path_1.join)(cwd, 'src', 'sub', 'b.txt'), 'b');
|
|
105
|
-
await fc.copy('src', 'dest');
|
|
106
|
-
expect((0, fs_1.readFileSync)((0, path_1.join)(cwd, 'dest', 'a.txt'), 'utf8')).toBe('a');
|
|
107
|
-
expect((0, fs_1.readFileSync)((0, path_1.join)(cwd, 'dest', 'sub', 'b.txt'), 'utf8')).toBe('b');
|
|
108
|
-
});
|
|
109
|
-
it('copy of a missing source is a no-op', async () => {
|
|
110
|
-
const fc = (0, get_file_context_1.getFileContext)(cwd);
|
|
111
|
-
await expect(fc.copy('nope', 'dest')).resolves.toBeUndefined();
|
|
112
|
-
expect((0, fs_1.statSync)((0, path_1.join)(cwd))).toBeDefined(); // cwd still exists
|
|
113
|
-
});
|
|
114
|
-
it('copy preserves the destination directory when it already exists', async () => {
|
|
115
|
-
const fc = (0, get_file_context_1.getFileContext)(cwd);
|
|
116
|
-
await fc.writeFile('src.txt', 'x');
|
|
117
|
-
(0, fs_1.mkdirSync)((0, path_1.join)(cwd, 'dest'));
|
|
118
|
-
await fc.copy('src.txt', (0, path_1.join)('dest', 'src.txt'));
|
|
119
|
-
expect((0, fs_1.readFileSync)((0, path_1.join)(cwd, 'dest', 'src.txt'), 'utf8')).toBe('x');
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
describe('streams', () => {
|
|
123
|
-
it('writeStream pipes a Readable into a file', async () => {
|
|
124
|
-
const fc = (0, get_file_context_1.getFileContext)(cwd);
|
|
125
|
-
const target = (0, path_1.join)(cwd, 'out.bin');
|
|
126
|
-
await fc.writeStream(target, stream_1.Readable.from(['part-a', 'part-b']));
|
|
127
|
-
expect((0, fs_1.readFileSync)(target, 'utf8')).toBe('part-apart-b');
|
|
128
|
-
});
|
|
129
|
-
it('createWriteStream returns a writable stream', async () => {
|
|
130
|
-
const fc = (0, get_file_context_1.getFileContext)(cwd);
|
|
131
|
-
const target = (0, path_1.join)(cwd, 'wstream.txt');
|
|
132
|
-
const ws = fc.createWriteStream(target);
|
|
133
|
-
// Wait for 'close' (fd released), not just the end/'finish' callback (data
|
|
134
|
-
// flushed): on Windows an open write handle locks the file, so the afterEach
|
|
135
|
-
// rmSync would race it and fail with ENOTEMPTY.
|
|
136
|
-
await new Promise((resolve, reject) => {
|
|
137
|
-
ws.on('error', reject);
|
|
138
|
-
ws.on('close', () => resolve());
|
|
139
|
-
ws.end('payload');
|
|
140
|
-
});
|
|
141
|
-
expect((0, fs_1.readFileSync)(target, 'utf8')).toBe('payload');
|
|
142
|
-
});
|
|
143
|
-
it('readStream reads back what writeStream wrote', async () => {
|
|
144
|
-
const fc = (0, get_file_context_1.getFileContext)(cwd);
|
|
145
|
-
const target = (0, path_1.join)(cwd, 'r.txt');
|
|
146
|
-
(0, fs_1.writeFileSync)(target, 'abc');
|
|
147
|
-
const chunks = [];
|
|
148
|
-
await new Promise((resolve, reject) => {
|
|
149
|
-
const rs = fc.readStream(target);
|
|
150
|
-
rs.on('data', (c) => chunks.push(c));
|
|
151
|
-
rs.on('error', reject);
|
|
152
|
-
// 'close' (fd released) fires after 'end'; wait for it so an open read
|
|
153
|
-
// handle can't block the afterEach cleanup on Windows.
|
|
154
|
-
rs.on('close', resolve);
|
|
155
|
-
});
|
|
156
|
-
expect(Buffer.concat(chunks).toString()).toBe('abc');
|
|
157
|
-
});
|
|
158
|
-
});
|
|
159
|
-
describe('watch', () => {
|
|
160
|
-
it('returns a handle whose close() is callable; the polling override is honored', async () => {
|
|
161
|
-
const previous = process.env.HAMMERKIT_WATCH_POLLING;
|
|
162
|
-
process.env.HAMMERKIT_WATCH_POLLING = 'false';
|
|
163
|
-
try {
|
|
164
|
-
const fc = (0, get_file_context_1.getFileContext)(cwd);
|
|
165
|
-
const handle = fc.watch('.', () => undefined);
|
|
166
|
-
// close() returns a Promise on chokidar; await it
|
|
167
|
-
await Promise.resolve(handle.close());
|
|
168
|
-
}
|
|
169
|
-
finally {
|
|
170
|
-
if (previous === undefined)
|
|
171
|
-
delete process.env.HAMMERKIT_WATCH_POLLING;
|
|
172
|
-
else
|
|
173
|
-
process.env.HAMMERKIT_WATCH_POLLING = previous;
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
|
-
});
|
|
177
|
-
});
|
|
178
|
-
//# sourceMappingURL=get-file-context.spec.js.map
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const move_files_1 = require("./move-files");
|
|
4
|
-
function context(existing) {
|
|
5
|
-
const remove = vi.fn(async () => undefined);
|
|
6
|
-
const copy = vi.fn(async () => undefined);
|
|
7
|
-
const env = {
|
|
8
|
-
file: {
|
|
9
|
-
exists: vi.fn(async (p) => existing.includes(p)),
|
|
10
|
-
remove,
|
|
11
|
-
copy,
|
|
12
|
-
},
|
|
13
|
-
};
|
|
14
|
-
return { env, remove, copy };
|
|
15
|
-
}
|
|
16
|
-
const item = { status: { write: vi.fn() } };
|
|
17
|
-
function* once(from, to) {
|
|
18
|
-
yield { from, to };
|
|
19
|
-
}
|
|
20
|
-
describe('move-files', () => {
|
|
21
|
-
it('copies an existing folder and removes a pre-existing target first', async () => {
|
|
22
|
-
const { env, remove, copy } = context(['/a', '/out/a']);
|
|
23
|
-
await (0, move_files_1.moveFiles)(item, env, () => once('/a', '/out/a'));
|
|
24
|
-
expect(remove).toHaveBeenCalledWith('/out/a');
|
|
25
|
-
expect(copy).toHaveBeenCalledWith('/a', '/out/a');
|
|
26
|
-
});
|
|
27
|
-
it('does not remove the target when it does not exist yet', async () => {
|
|
28
|
-
const { env, remove, copy } = context(['/a']);
|
|
29
|
-
await (0, move_files_1.moveFiles)(item, env, () => once('/a', '/out/a'));
|
|
30
|
-
expect(remove).not.toHaveBeenCalled();
|
|
31
|
-
expect(copy).toHaveBeenCalledWith('/a', '/out/a');
|
|
32
|
-
});
|
|
33
|
-
it('skips folders whose source does not exist', async () => {
|
|
34
|
-
const { env, copy } = context([]);
|
|
35
|
-
await (0, move_files_1.moveFiles)(item, env, () => once('/missing', '/out/m'));
|
|
36
|
-
expect(copy).not.toHaveBeenCalled();
|
|
37
|
-
});
|
|
38
|
-
it('dedupes identical from/to pairs', async () => {
|
|
39
|
-
const { env, copy } = context(['/a']);
|
|
40
|
-
function* twice() {
|
|
41
|
-
yield { from: '/a', to: '/out/a' };
|
|
42
|
-
yield { from: '/a', to: '/out/a' };
|
|
43
|
-
}
|
|
44
|
-
await (0, move_files_1.moveFiles)(item, env, twice);
|
|
45
|
-
expect(copy).toHaveBeenCalledTimes(1);
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
//# sourceMappingURL=move-files.spec.js.map
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const ensure_http_route_1 = require("./ensure-http-route");
|
|
4
|
-
function httpError(statusCode) {
|
|
5
|
-
return Object.assign(new Error(`http ${statusCode}`), { statusCode });
|
|
6
|
-
}
|
|
7
|
-
function makeInstance(objectApi) {
|
|
8
|
-
return { objectApi };
|
|
9
|
-
}
|
|
10
|
-
const env = { type: 'kubernetes', namespace: 'demo', context: 'ctx', ingresses: [] };
|
|
11
|
-
const service = {
|
|
12
|
-
name: 'api',
|
|
13
|
-
id: () => 'abc123',
|
|
14
|
-
data: { ports: [{ containerPort: 3000, hostPort: null }] },
|
|
15
|
-
};
|
|
16
|
-
function ingress(overrides = {}) {
|
|
17
|
-
return {
|
|
18
|
-
kind: 'httproute',
|
|
19
|
-
host: 'api.example.com',
|
|
20
|
-
service: 'api',
|
|
21
|
-
gateway: 'web',
|
|
22
|
-
...overrides,
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
describe('ensureHttpRoute', () => {
|
|
26
|
-
it('creates an HTTPRoute with the expected shape', async () => {
|
|
27
|
-
const read = vi.fn().mockRejectedValue(httpError(404));
|
|
28
|
-
const create = vi.fn().mockResolvedValue({ body: {} });
|
|
29
|
-
await (0, ensure_http_route_1.ensureHttpRoute)(makeInstance({ read, create }), env, ingress(), service);
|
|
30
|
-
expect(create).toHaveBeenCalledTimes(1);
|
|
31
|
-
expect(create.mock.calls[0][0]).toMatchObject({
|
|
32
|
-
apiVersion: 'gateway.networking.k8s.io/v1',
|
|
33
|
-
kind: 'HTTPRoute',
|
|
34
|
-
metadata: { name: 'api.example.com', namespace: 'demo', labels: { 'hammerkit.dev/id': 'abc123' } },
|
|
35
|
-
spec: {
|
|
36
|
-
parentRefs: [{ name: 'web' }],
|
|
37
|
-
hostnames: ['api.example.com'],
|
|
38
|
-
rules: [
|
|
39
|
-
{
|
|
40
|
-
matches: [{ path: { type: 'PathPrefix', value: '/' } }],
|
|
41
|
-
backendRefs: [{ name: 'api-abc123', port: 3000 }],
|
|
42
|
-
},
|
|
43
|
-
],
|
|
44
|
-
},
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
it('uses servicePort, path and gatewayNamespace when provided', async () => {
|
|
48
|
-
const read = vi.fn().mockRejectedValue(httpError(404));
|
|
49
|
-
const create = vi.fn().mockResolvedValue({ body: {} });
|
|
50
|
-
await (0, ensure_http_route_1.ensureHttpRoute)(makeInstance({ read, create }), env, ingress({ servicePort: 8080, path: '/api', gatewayNamespace: 'gateways' }), service);
|
|
51
|
-
expect(create.mock.calls[0][0]).toMatchObject({
|
|
52
|
-
spec: {
|
|
53
|
-
parentRefs: [{ name: 'web', namespace: 'gateways' }],
|
|
54
|
-
rules: [
|
|
55
|
-
{
|
|
56
|
-
matches: [{ path: { type: 'PathPrefix', value: '/api' } }],
|
|
57
|
-
backendRefs: [{ name: 'api-abc123', port: 8080 }],
|
|
58
|
-
},
|
|
59
|
-
],
|
|
60
|
-
},
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
it('throws when no gateway is set', async () => {
|
|
64
|
-
const read = vi.fn();
|
|
65
|
-
const create = vi.fn();
|
|
66
|
-
await expect((0, ensure_http_route_1.ensureHttpRoute)(makeInstance({ read, create }), env, ingress({ gateway: undefined }), service)).rejects.toThrow(/requires a "gateway"/);
|
|
67
|
-
expect(create).not.toHaveBeenCalled();
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
//# sourceMappingURL=ensure-http-route.spec.js.map
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const ensure_namespace_1 = require("./ensure-namespace");
|
|
4
|
-
function httpError(statusCode) {
|
|
5
|
-
return Object.assign(new Error(`http ${statusCode}`), { statusCode });
|
|
6
|
-
}
|
|
7
|
-
function makeInstance(coreApi) {
|
|
8
|
-
return { coreApi };
|
|
9
|
-
}
|
|
10
|
-
describe('ensureNamespace', () => {
|
|
11
|
-
it('does nothing when the namespace already exists', async () => {
|
|
12
|
-
const readNamespace = vi.fn().mockResolvedValue({ body: {} });
|
|
13
|
-
const createNamespace = vi.fn();
|
|
14
|
-
await (0, ensure_namespace_1.ensureNamespace)(makeInstance({ readNamespace, createNamespace }), 'demo');
|
|
15
|
-
expect(readNamespace).toHaveBeenCalledWith('demo');
|
|
16
|
-
expect(createNamespace).not.toHaveBeenCalled();
|
|
17
|
-
});
|
|
18
|
-
it('creates the namespace (labeled managed) when missing', async () => {
|
|
19
|
-
const readNamespace = vi.fn().mockRejectedValue(httpError(404));
|
|
20
|
-
const createNamespace = vi.fn().mockResolvedValue({ body: {} });
|
|
21
|
-
await (0, ensure_namespace_1.ensureNamespace)(makeInstance({ readNamespace, createNamespace }), 'demo');
|
|
22
|
-
expect(createNamespace).toHaveBeenCalledTimes(1);
|
|
23
|
-
expect(createNamespace.mock.calls[0][0]).toMatchObject({
|
|
24
|
-
metadata: { name: 'demo', labels: { 'hammerkit.dev/managed': 'true' } },
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
it('swallows a 409 from a racing create', async () => {
|
|
28
|
-
const readNamespace = vi.fn().mockRejectedValue(httpError(404));
|
|
29
|
-
const createNamespace = vi.fn().mockRejectedValue(httpError(409));
|
|
30
|
-
await expect((0, ensure_namespace_1.ensureNamespace)(makeInstance({ readNamespace, createNamespace }), 'demo')).resolves.toBeUndefined();
|
|
31
|
-
});
|
|
32
|
-
it('rethrows unexpected read errors', async () => {
|
|
33
|
-
const readNamespace = vi.fn().mockRejectedValue(httpError(500));
|
|
34
|
-
const createNamespace = vi.fn();
|
|
35
|
-
await expect((0, ensure_namespace_1.ensureNamespace)(makeInstance({ readNamespace, createNamespace }), 'demo')).rejects.toThrow();
|
|
36
|
-
expect(createNamespace).not.toHaveBeenCalled();
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
//# sourceMappingURL=ensure-namespace.spec.js.map
|