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
|
@@ -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,54 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ensureIngress = void 0;
|
|
4
|
-
const apply_1 = require("./apply");
|
|
5
|
-
const resources_1 = require("./resources");
|
|
6
|
-
async function ensureIngress(instance, env, ingress, service) {
|
|
7
|
-
const resource = {
|
|
8
|
-
kind: 'Ingress',
|
|
9
|
-
apiVersion: 'networking.k8s.io/v1',
|
|
10
|
-
metadata: {
|
|
11
|
-
name: ingress.host,
|
|
12
|
-
namespace: env.namespace,
|
|
13
|
-
annotations: {
|
|
14
|
-
'cert-manager.io/cluster-issuer': 'hammerkit-issuer',
|
|
15
|
-
},
|
|
16
|
-
labels: {
|
|
17
|
-
'hammerkit.dev/id': service.id(),
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
spec: {
|
|
21
|
-
ingressClassName: 'nginx',
|
|
22
|
-
rules: [
|
|
23
|
-
{
|
|
24
|
-
host: ingress.host,
|
|
25
|
-
http: {
|
|
26
|
-
paths: [
|
|
27
|
-
{
|
|
28
|
-
path: ingress.path ?? '/',
|
|
29
|
-
pathType: 'Prefix',
|
|
30
|
-
backend: {
|
|
31
|
-
service: {
|
|
32
|
-
name: (0, resources_1.getResourceName)(service),
|
|
33
|
-
port: {
|
|
34
|
-
number: ingress.servicePort ?? service.data.ports[0].containerPort,
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
],
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
|
-
],
|
|
43
|
-
tls: [
|
|
44
|
-
{
|
|
45
|
-
secretName: `${ingress.host}-tls`,
|
|
46
|
-
hosts: [ingress.host],
|
|
47
|
-
},
|
|
48
|
-
],
|
|
49
|
-
},
|
|
50
|
-
};
|
|
51
|
-
return await (0, apply_1.apply)(instance, resource);
|
|
52
|
-
}
|
|
53
|
-
exports.ensureIngress = ensureIngress;
|
|
54
|
-
//# sourceMappingURL=ensure-ingress.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
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const resolve_pod_name_1 = require("./resolve-pod-name");
|
|
4
|
-
function podBody(items) {
|
|
5
|
-
return {
|
|
6
|
-
body: {
|
|
7
|
-
items: items.map((p) => ({
|
|
8
|
-
metadata: { name: p.name },
|
|
9
|
-
status: {
|
|
10
|
-
conditions: [{ type: 'Ready', status: p.ready ? 'True' : 'False' }],
|
|
11
|
-
},
|
|
12
|
-
})),
|
|
13
|
-
},
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
function makeCoreApi(opts = {}) {
|
|
17
|
-
return {
|
|
18
|
-
readNamespacedService: vi.fn().mockResolvedValue({ body: { spec: { selector: opts.service?.selector } } }),
|
|
19
|
-
listNamespacedPod: vi.fn().mockResolvedValue(podBody(opts.pods ?? [])),
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
function makeAppsApi(opts = {}) {
|
|
23
|
-
return {
|
|
24
|
-
readNamespacedDeployment: vi
|
|
25
|
-
.fn()
|
|
26
|
-
.mockResolvedValue({ body: { spec: { selector: { matchLabels: opts.deployment?.matchLabels } } } }),
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
describe('resolvePodName', () => {
|
|
30
|
-
it('returns the name directly for selector type "pod"', async () => {
|
|
31
|
-
const core = makeCoreApi();
|
|
32
|
-
const apps = makeAppsApi();
|
|
33
|
-
await expect((0, resolve_pod_name_1.resolvePodName)(core, apps, 'ns', { type: 'pod', name: 'my-pod' })).resolves.toBe('my-pod');
|
|
34
|
-
expect(core.listNamespacedPod).not.toHaveBeenCalled();
|
|
35
|
-
});
|
|
36
|
-
it('resolves a service to a ready pod', async () => {
|
|
37
|
-
const core = makeCoreApi({
|
|
38
|
-
service: { selector: { app: 'api' } },
|
|
39
|
-
pods: [
|
|
40
|
-
{ name: 'api-old', ready: false },
|
|
41
|
-
{ name: 'api-new', ready: true },
|
|
42
|
-
],
|
|
43
|
-
});
|
|
44
|
-
const apps = makeAppsApi();
|
|
45
|
-
await expect((0, resolve_pod_name_1.resolvePodName)(core, apps, 'ns', { type: 'service', name: 'api' })).resolves.toBe('api-new');
|
|
46
|
-
expect(core.listNamespacedPod).toHaveBeenCalledWith('ns', undefined, undefined, undefined, undefined, 'app=api');
|
|
47
|
-
});
|
|
48
|
-
it('falls back to the first pod if none are ready', async () => {
|
|
49
|
-
const core = makeCoreApi({
|
|
50
|
-
service: { selector: { app: 'api' } },
|
|
51
|
-
pods: [
|
|
52
|
-
{ name: 'api-1', ready: false },
|
|
53
|
-
{ name: 'api-2', ready: false },
|
|
54
|
-
],
|
|
55
|
-
});
|
|
56
|
-
const apps = makeAppsApi();
|
|
57
|
-
await expect((0, resolve_pod_name_1.resolvePodName)(core, apps, 'ns', { type: 'service', name: 'api' })).resolves.toBe('api-1');
|
|
58
|
-
});
|
|
59
|
-
it('resolves a deployment via matchLabels', async () => {
|
|
60
|
-
const core = makeCoreApi({ pods: [{ name: 'p', ready: true }] });
|
|
61
|
-
const apps = makeAppsApi({ deployment: { matchLabels: { 'hammerkit.dev/id': 'x' } } });
|
|
62
|
-
await expect((0, resolve_pod_name_1.resolvePodName)(core, apps, 'ns', { type: 'deployment', name: 'api' })).resolves.toBe('p');
|
|
63
|
-
expect(core.listNamespacedPod).toHaveBeenCalledWith('ns', undefined, undefined, undefined, undefined, 'hammerkit.dev/id=x');
|
|
64
|
-
});
|
|
65
|
-
it('throws when a service has no selector', async () => {
|
|
66
|
-
const core = makeCoreApi({ service: { selector: undefined } });
|
|
67
|
-
const apps = makeAppsApi();
|
|
68
|
-
await expect((0, resolve_pod_name_1.resolvePodName)(core, apps, 'ns', { type: 'service', name: 'api' })).rejects.toThrow(/no selector/);
|
|
69
|
-
});
|
|
70
|
-
it('throws when no pods match', async () => {
|
|
71
|
-
const core = makeCoreApi({ service: { selector: { app: 'api' } }, pods: [] });
|
|
72
|
-
const apps = makeAppsApi();
|
|
73
|
-
await expect((0, resolve_pod_name_1.resolvePodName)(core, apps, 'ns', { type: 'service', name: 'api' })).rejects.toThrow(/no pod found/);
|
|
74
|
-
});
|
|
75
|
-
it('rejects unsupported selector types', async () => {
|
|
76
|
-
const core = makeCoreApi();
|
|
77
|
-
const apps = makeAppsApi();
|
|
78
|
-
await expect((0, resolve_pod_name_1.resolvePodName)(core, apps, 'ns', { type: 'statefulset', name: 'x' })).rejects.toThrow(/unsupported selector type/);
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
//# sourceMappingURL=resolve-pod-name.spec.js.map
|
package/dist/log.spec.js
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const stream_1 = require("stream");
|
|
4
|
-
const log_1 = require("./log");
|
|
5
|
-
const environment_mock_1 = require("./executer/environment-mock");
|
|
6
|
-
function capture() {
|
|
7
|
-
const chunks = [];
|
|
8
|
-
const stream = new stream_1.Writable({
|
|
9
|
-
write(chunk, _enc, cb) {
|
|
10
|
-
chunks.push(chunk.toString());
|
|
11
|
-
cb();
|
|
12
|
-
},
|
|
13
|
-
});
|
|
14
|
-
return { stream, read: () => chunks.join('') };
|
|
15
|
-
}
|
|
16
|
-
describe('log helpers', () => {
|
|
17
|
-
describe('getLogs', () => {
|
|
18
|
-
it('splits on \\r?\\n and drops empty lines', () => {
|
|
19
|
-
expect((0, log_1.getLogs)('a\r\nb\nc\n\n')).toEqual(['a', 'b', 'c']);
|
|
20
|
-
});
|
|
21
|
-
it('accepts a Buffer', () => {
|
|
22
|
-
expect((0, log_1.getLogs)(Buffer.from('x\ny'))).toEqual(['x', 'y']);
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
describe('getLogLevel', () => {
|
|
26
|
-
it.each(['debug', 'info', 'warn', 'error'])('returns a string containing %s', (level) => {
|
|
27
|
-
expect((0, log_1.getLogLevel)(level)).toContain(level);
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
describe('getErrorMessage', () => {
|
|
31
|
-
it('uses Error.message for Error instances', () => {
|
|
32
|
-
expect((0, log_1.getErrorMessage)(new Error('boom'))).toBe('boom');
|
|
33
|
-
});
|
|
34
|
-
it('returns a string value unchanged', () => {
|
|
35
|
-
expect((0, log_1.getErrorMessage)('plain')).toBe('plain');
|
|
36
|
-
});
|
|
37
|
-
it('falls back to "unknown error <value>" for other values', () => {
|
|
38
|
-
expect((0, log_1.getErrorMessage)({ x: 1 })).toMatch(/^unknown error/);
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
describe('consoleContext', () => {
|
|
42
|
-
it('writes formatted lines for each level', () => {
|
|
43
|
-
const cap = capture();
|
|
44
|
-
const ctx = (0, log_1.consoleContext)(cap.stream);
|
|
45
|
-
ctx.debug('d-msg');
|
|
46
|
-
ctx.info('i-msg');
|
|
47
|
-
ctx.warn('w-msg');
|
|
48
|
-
ctx.error('e-msg');
|
|
49
|
-
const out = cap.read();
|
|
50
|
-
expect(out).toContain('d-msg');
|
|
51
|
-
expect(out).toContain('i-msg');
|
|
52
|
-
expect(out).toContain('w-msg');
|
|
53
|
-
expect(out).toContain('e-msg');
|
|
54
|
-
// 4 newlines, one per call
|
|
55
|
-
expect(out.split('\n').filter((l) => l.length > 0)).toHaveLength(4);
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
describe('getType / getNodeName / getMaxNameLength', () => {
|
|
59
|
-
it('formats the type with the configured padding', () => {
|
|
60
|
-
expect((0, log_1.getType)('cli')).toContain('cli');
|
|
61
|
-
});
|
|
62
|
-
it('pads name to a given length', () => {
|
|
63
|
-
expect((0, log_1.getNodeName)('a', 4)).toContain('a');
|
|
64
|
-
// pads with spaces to reach the requested length, then color codes
|
|
65
|
-
// surround it — assert by inspecting the visible characters
|
|
66
|
-
// ANSI color wrappers can only add chars, so the rendered string is at
|
|
67
|
-
// least the requested width even when colors are enabled.
|
|
68
|
-
expect((0, log_1.getNodeName)('a', 4).length).toBeGreaterThanOrEqual(4);
|
|
69
|
-
});
|
|
70
|
-
it('getMaxNameLength returns the longest name yielded', () => {
|
|
71
|
-
const names = function* () {
|
|
72
|
-
yield 'aa';
|
|
73
|
-
yield 'aaaaa';
|
|
74
|
-
yield 'a';
|
|
75
|
-
};
|
|
76
|
-
expect((0, log_1.getMaxNameLength)(names)).toBe(5);
|
|
77
|
-
});
|
|
78
|
-
it('getMaxNameLength returns 0 for an empty source', () => {
|
|
79
|
-
expect((0, log_1.getMaxNameLength)(() => [])).toBe(0);
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
describe('print helpers', () => {
|
|
83
|
-
it('printItem with and without description', () => {
|
|
84
|
-
const env = (0, environment_mock_1.environmentMock)('/tmp');
|
|
85
|
-
const cap = capture();
|
|
86
|
-
env.stdout = cap.stream;
|
|
87
|
-
(0, log_1.printItem)(env, { name: 'a', description: null });
|
|
88
|
-
(0, log_1.printItem)(env, { name: 'b', description: 'desc' });
|
|
89
|
-
const out = cap.read();
|
|
90
|
-
expect(out).toContain('• a\n');
|
|
91
|
-
expect(out).toContain('• b');
|
|
92
|
-
expect(out).toContain('desc');
|
|
93
|
-
});
|
|
94
|
-
it('printProperty writes "<name>: <value>"', () => {
|
|
95
|
-
const env = (0, environment_mock_1.environmentMock)('/tmp');
|
|
96
|
-
const cap = capture();
|
|
97
|
-
env.stdout = cap.stream;
|
|
98
|
-
(0, log_1.printProperty)(env, 'image', 'alpine');
|
|
99
|
-
expect(cap.read()).toContain('image:');
|
|
100
|
-
expect(cap.read()).toContain('alpine');
|
|
101
|
-
});
|
|
102
|
-
it('printTitle writes the title with a colon', () => {
|
|
103
|
-
const env = (0, environment_mock_1.environmentMock)('/tmp');
|
|
104
|
-
const cap = capture();
|
|
105
|
-
env.stdout = cap.stream;
|
|
106
|
-
(0, log_1.printTitle)(env, 'Tasks');
|
|
107
|
-
expect(cap.read()).toContain('Tasks:');
|
|
108
|
-
});
|
|
109
|
-
});
|
|
110
|
-
describe('formatDate', () => {
|
|
111
|
-
it('produces a [yyyy-MM-DD HH:mm:ss.SSS] formatted timestamp', () => {
|
|
112
|
-
// Use a fixed Date in UTC; the function uses local-time getters, so only
|
|
113
|
-
// pattern-check the output rather than the literal value.
|
|
114
|
-
const out = (0, log_1.formatDate)(new Date(2024, 0, 2, 3, 4, 5, 6));
|
|
115
|
-
expect(out).toMatch(/\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}\]/);
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
describe('cursor', () => {
|
|
119
|
-
it('hideCursor / showCursor write escape sequences', () => {
|
|
120
|
-
const env = (0, environment_mock_1.environmentMock)('/tmp');
|
|
121
|
-
const cap = capture();
|
|
122
|
-
env.stdout = cap.stream;
|
|
123
|
-
(0, log_1.hideCursor)(env);
|
|
124
|
-
(0, log_1.showCursor)(env);
|
|
125
|
-
const out = cap.read();
|
|
126
|
-
expect(out).toContain('\x1B[?25l');
|
|
127
|
-
expect(out).toContain('\x1B[?25h');
|
|
128
|
-
});
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
//# sourceMappingURL=log.spec.js.map
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// Verifies that the grouped logger only flushes a task/service once it reaches
|
|
3
|
-
// a terminal state, by mocking the underlying log helpers and iterators.
|
|
4
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
vi.mock('../log', () => ({
|
|
6
|
-
writeWorkItemLogToConsole: vi.fn(),
|
|
7
|
-
printWorkTreeResult: vi.fn().mockResolvedValue(undefined),
|
|
8
|
-
getWorkItemMaxLength: vi.fn(() => 10),
|
|
9
|
-
}));
|
|
10
|
-
vi.mock('../planner/utils/plan-work-tasks', () => ({
|
|
11
|
-
iterateWorkTasks: vi.fn(),
|
|
12
|
-
iterateWorkServices: vi.fn(),
|
|
13
|
-
}));
|
|
14
|
-
const grouped_logger_1 = require("./grouped-logger");
|
|
15
|
-
const state_1 = require("../executer/state");
|
|
16
|
-
const plan_work_tasks_1 = require("../planner/utils/plan-work-tasks");
|
|
17
|
-
const log_1 = require("../log");
|
|
18
|
-
const mockedIterTasks = plan_work_tasks_1.iterateWorkTasks;
|
|
19
|
-
const mockedIterServices = plan_work_tasks_1.iterateWorkServices;
|
|
20
|
-
const mockedWrite = log_1.writeWorkItemLogToConsole;
|
|
21
|
-
const mockedPrint = log_1.printWorkTreeResult;
|
|
22
|
-
function fakeTask(name, type, logs = []) {
|
|
23
|
-
return { name, state: { current: { type } }, status: { read: () => logs } };
|
|
24
|
-
}
|
|
25
|
-
describe('groupedLogger', () => {
|
|
26
|
-
beforeEach(() => {
|
|
27
|
-
mockedWrite.mockClear();
|
|
28
|
-
mockedPrint.mockClear();
|
|
29
|
-
mockedIterTasks.mockReset();
|
|
30
|
-
mockedIterServices.mockReset();
|
|
31
|
-
});
|
|
32
|
-
it('flushes a task only once it reaches a terminal state and not again on re-emit', () => {
|
|
33
|
-
const t = fakeTask('t1', 'pending', [{ id: 1 }]);
|
|
34
|
-
mockedIterTasks.mockImplementation(function* () {
|
|
35
|
-
yield t;
|
|
36
|
-
});
|
|
37
|
-
mockedIterServices.mockImplementation(function* () { });
|
|
38
|
-
const state = new state_1.State({ services: {}, tasks: { t1: t } });
|
|
39
|
-
(0, grouped_logger_1.groupedLogger)(state, {});
|
|
40
|
-
state.set(state.current); // pending — should NOT flush
|
|
41
|
-
expect(mockedWrite).not.toHaveBeenCalled();
|
|
42
|
-
t.state.current.type = 'completed';
|
|
43
|
-
state.set(state.current); // completed — flush once
|
|
44
|
-
expect(mockedWrite).toHaveBeenCalledTimes(1);
|
|
45
|
-
state.set(state.current); // already-flushed task — must not flush again
|
|
46
|
-
expect(mockedWrite).toHaveBeenCalledTimes(1);
|
|
47
|
-
});
|
|
48
|
-
it.each(['crash', 'error', 'completed'])('flushes on terminal state %s', (terminal) => {
|
|
49
|
-
const t = fakeTask('t1', terminal, [{ id: 1 }]);
|
|
50
|
-
mockedIterTasks.mockImplementation(function* () {
|
|
51
|
-
yield t;
|
|
52
|
-
});
|
|
53
|
-
mockedIterServices.mockImplementation(function* () { });
|
|
54
|
-
const state = new state_1.State({ services: {}, tasks: { t1: t } });
|
|
55
|
-
(0, grouped_logger_1.groupedLogger)(state, {});
|
|
56
|
-
state.set(state.current);
|
|
57
|
-
expect(mockedWrite).toHaveBeenCalledTimes(1);
|
|
58
|
-
});
|
|
59
|
-
it('flushes a service on type "end" and not again', () => {
|
|
60
|
-
const s = fakeTask('svc1', 'starting', [{ id: 1 }]);
|
|
61
|
-
mockedIterTasks.mockImplementation(function* () { });
|
|
62
|
-
mockedIterServices.mockImplementation(function* () {
|
|
63
|
-
yield s;
|
|
64
|
-
});
|
|
65
|
-
const state = new state_1.State({ services: { svc1: s }, tasks: {} });
|
|
66
|
-
(0, grouped_logger_1.groupedLogger)(state, {});
|
|
67
|
-
state.set(state.current); // not yet ended
|
|
68
|
-
expect(mockedWrite).not.toHaveBeenCalled();
|
|
69
|
-
s.state.current.type = 'end';
|
|
70
|
-
state.set(state.current); // ended — flush
|
|
71
|
-
expect(mockedWrite).toHaveBeenCalledTimes(1);
|
|
72
|
-
state.set(state.current); // already flushed — no second call
|
|
73
|
-
expect(mockedWrite).toHaveBeenCalledTimes(1);
|
|
74
|
-
});
|
|
75
|
-
it('complete() delegates to printWorkTreeResult', async () => {
|
|
76
|
-
mockedIterTasks.mockImplementation(function* () { });
|
|
77
|
-
mockedIterServices.mockImplementation(function* () { });
|
|
78
|
-
const state = new state_1.State({ services: {}, tasks: {} });
|
|
79
|
-
const logger = (0, grouped_logger_1.groupedLogger)(state, {});
|
|
80
|
-
await logger.complete({ state: state.current, success: true }, {});
|
|
81
|
-
expect(mockedPrint).toHaveBeenCalledTimes(1);
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
//# sourceMappingURL=grouped-logger.spec.js.map
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// interactiveLogger hides the cursor, polls writeWorkTreeStatus on a 100ms
|
|
3
|
-
// ticker, and writes on every state change until complete() stops it.
|
|
4
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
vi.mock('../log', () => ({
|
|
6
|
-
writeWorkTreeStatus: vi.fn(),
|
|
7
|
-
printWorkTreeResult: vi.fn().mockResolvedValue(undefined),
|
|
8
|
-
hideCursor: vi.fn(),
|
|
9
|
-
showCursor: vi.fn(),
|
|
10
|
-
}));
|
|
11
|
-
vi.mock('readline', () => ({ clearScreenDown: vi.fn() }));
|
|
12
|
-
const interactive_logger_1 = require("./interactive-logger");
|
|
13
|
-
const state_1 = require("../executer/state");
|
|
14
|
-
const log_1 = require("../log");
|
|
15
|
-
const readline_1 = require("readline");
|
|
16
|
-
const mockedWriteStatus = log_1.writeWorkTreeStatus;
|
|
17
|
-
const mockedHide = log_1.hideCursor;
|
|
18
|
-
const mockedShow = log_1.showCursor;
|
|
19
|
-
const mockedClear = readline_1.clearScreenDown;
|
|
20
|
-
const mockedPrint = log_1.printWorkTreeResult;
|
|
21
|
-
describe('interactiveLogger', () => {
|
|
22
|
-
beforeEach(() => {
|
|
23
|
-
vi.useFakeTimers();
|
|
24
|
-
mockedWriteStatus.mockClear();
|
|
25
|
-
mockedHide.mockClear();
|
|
26
|
-
mockedShow.mockClear();
|
|
27
|
-
mockedClear.mockClear();
|
|
28
|
-
mockedPrint.mockClear();
|
|
29
|
-
});
|
|
30
|
-
afterEach(() => {
|
|
31
|
-
vi.useRealTimers();
|
|
32
|
-
});
|
|
33
|
-
it('hides the cursor, ticks every 100ms, and writes on state changes', async () => {
|
|
34
|
-
const state = new state_1.State({ services: {}, tasks: {} });
|
|
35
|
-
const env = { stdout: { write: vi.fn() } };
|
|
36
|
-
const logger = (0, interactive_logger_1.interactiveLogger)(state, env);
|
|
37
|
-
// hideCursor on construction; initial tick fired immediately
|
|
38
|
-
expect(mockedHide).toHaveBeenCalledTimes(1);
|
|
39
|
-
expect(mockedWriteStatus).toHaveBeenCalledTimes(1);
|
|
40
|
-
// advance one tick window → one additional writeWorkTreeStatus
|
|
41
|
-
vi.advanceTimersByTime(100);
|
|
42
|
-
expect(mockedWriteStatus).toHaveBeenCalledTimes(2);
|
|
43
|
-
// a state change writes status synchronously
|
|
44
|
-
state.set({ services: {}, tasks: {} });
|
|
45
|
-
expect(mockedWriteStatus).toHaveBeenCalledTimes(3);
|
|
46
|
-
// complete() stops the ticker and restores the cursor
|
|
47
|
-
await logger.complete({ state: state.current, success: true }, env);
|
|
48
|
-
expect(mockedClear).toHaveBeenCalledWith(env.stdout);
|
|
49
|
-
expect(mockedPrint).toHaveBeenCalledTimes(1);
|
|
50
|
-
expect(mockedShow).toHaveBeenCalledTimes(1);
|
|
51
|
-
// after complete, advancing time must NOT schedule further writes
|
|
52
|
-
const after = mockedWriteStatus.mock.calls.length;
|
|
53
|
-
vi.advanceTimersByTime(1000);
|
|
54
|
-
expect(mockedWriteStatus.mock.calls.length).toBe(after);
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
//# sourceMappingURL=interactive-logger.spec.js.map
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// liveLogger forwards every status message verbatim to writeWorkItemLogToConsole.
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
vi.mock('../log', () => ({
|
|
5
|
-
writeWorkItemLogToConsole: vi.fn(),
|
|
6
|
-
printWorkTreeResult: vi.fn().mockResolvedValue(undefined),
|
|
7
|
-
getWorkItemMaxLength: vi.fn(() => 10),
|
|
8
|
-
}));
|
|
9
|
-
const live_logger_1 = require("./live-logger");
|
|
10
|
-
const state_1 = require("../executer/state");
|
|
11
|
-
const log_1 = require("../log");
|
|
12
|
-
const emitter_1 = require("../utils/emitter");
|
|
13
|
-
const mockedWrite = log_1.writeWorkItemLogToConsole;
|
|
14
|
-
const mockedPrint = log_1.printWorkTreeResult;
|
|
15
|
-
describe('liveLogger', () => {
|
|
16
|
-
beforeEach(() => {
|
|
17
|
-
mockedWrite.mockClear();
|
|
18
|
-
mockedPrint.mockClear();
|
|
19
|
-
});
|
|
20
|
-
it('forwards each status message to writeWorkItemLogToConsole', () => {
|
|
21
|
-
const status = (0, emitter_1.emitter)();
|
|
22
|
-
const env = { status };
|
|
23
|
-
const state = new state_1.State({ services: {}, tasks: {} });
|
|
24
|
-
(0, live_logger_1.liveLogger)(state, env);
|
|
25
|
-
const msg = { type: 'status', message: 'hi' };
|
|
26
|
-
status.emit(msg);
|
|
27
|
-
expect(mockedWrite).toHaveBeenCalledWith(env, msg, 10);
|
|
28
|
-
});
|
|
29
|
-
it('complete() delegates to printWorkTreeResult', async () => {
|
|
30
|
-
const status = (0, emitter_1.emitter)();
|
|
31
|
-
const state = new state_1.State({ services: {}, tasks: {} });
|
|
32
|
-
const logger = (0, live_logger_1.liveLogger)(state, { status });
|
|
33
|
-
await logger.complete({ state: state.current, success: true }, {});
|
|
34
|
-
expect(mockedPrint).toHaveBeenCalledTimes(1);
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
//# sourceMappingURL=live-logger.spec.js.map
|