hammerkit 1.4.0 → 1.5.0-alpha.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/.devcontainer/Dockerfile +5 -0
- package/.devcontainer/devcontainer.json +40 -0
- package/README.md +13 -86
- package/SUMMARY.md +43 -0
- package/build.schema.json +56 -2
- package/dist/cli.js +97 -0
- package/dist/cli.spec.js +5 -0
- package/dist/console/console-context-mock.js +11 -0
- package/dist/console/get-logger.js +23 -0
- package/dist/docker/pull.js +5 -5
- package/dist/docker/remove-container.js +21 -0
- package/dist/docker/stream.js +14 -10
- package/dist/docker/using-container.js +28 -0
- package/dist/environment/get-process-env.js +4 -4
- package/dist/environment/replace-env-variables.js +2 -3
- package/dist/executer/abort.js +13 -0
- package/dist/executer/check-readiness.js +25 -0
- package/dist/executer/create-scheduler-state.js +32 -0
- package/dist/executer/docker-node.js +123 -0
- package/dist/executer/docker-service.js +113 -0
- package/dist/executer/environment-mock.js +17 -0
- package/dist/executer/event-cache.js +165 -0
- package/dist/executer/execute-command.js +42 -0
- package/dist/executer/execute-docker.js +58 -194
- package/dist/executer/execute.spec.js +37 -37
- package/dist/executer/execution-steps.js +57 -0
- package/dist/executer/get-docker-executor.js +6 -100
- package/dist/executer/hierarchy-scheduler.js +94 -0
- package/dist/executer/kubernetes-service.js +64 -0
- package/dist/executer/label-values.js +65 -0
- package/dist/executer/local-node.js +57 -0
- package/dist/executer/print-container-options.js +17 -0
- package/dist/{logging/log-strategy.js → executer/process-item.js} +1 -1
- package/dist/executer/process-listener.js +3 -0
- package/dist/executer/process-manager.js +111 -0
- package/dist/executer/process-manager.spec.js +91 -0
- package/dist/executer/{executor.js → process.js} +1 -1
- package/dist/executer/{execute-result.js → readonly-state.js} +1 -1
- package/dist/executer/schedule.js +139 -0
- package/dist/executer/scheduler/check-for-loop.js +21 -0
- package/dist/executer/scheduler/enqueue-next.js +27 -0
- package/dist/{testing/test-context.js → executer/scheduler/node-state.js} +1 -1
- package/dist/executer/scheduler/scheduler-result.js +3 -0
- package/dist/executer/scheduler/scheduler-state.js +3 -0
- package/dist/executer/scheduler/service-state.js +3 -0
- package/dist/executer/service-dns.js +6 -0
- package/dist/executer/set-user-permission.js +16 -0
- package/dist/executer/start-node.js +59 -0
- package/dist/executer/state-listener.js +3 -0
- package/dist/executer/state.js +49 -0
- package/dist/executer/states.js +4 -159
- package/dist/executer/watch-node.js +57 -0
- package/dist/executer/watch-service.js +54 -0
- package/dist/executer/work-scope.js +10 -0
- package/dist/file/get-file-context-mock.spec.js +5 -5
- package/dist/file/get-file-context.js +41 -18
- package/dist/file/move-files.js +1 -1
- package/dist/get-work-context.js +29 -0
- package/dist/index.js +8 -4
- package/dist/log.js +192 -50
- package/dist/logging/grouped-logger.js +31 -19
- package/dist/logging/interactive-logger.js +20 -23
- package/dist/logging/live-logger.js +7 -17
- package/dist/optimizer/calculate-checksum.js +1 -1
- package/dist/optimizer/get-cache-directory.js +8 -13
- package/dist/optimizer/get-work-node-cache-stats.js +68 -21
- package/dist/optimizer/read-work-node-cache.js +2 -2
- package/dist/optimizer/work-node-cache-description.js +12 -11
- package/dist/optimizer/write-work-node-cache.js +9 -8
- package/dist/{executer/execution-context.js → parser/build-file-service.js} +1 -1
- package/dist/{optimizer → parser}/cache-method.js +0 -0
- package/dist/parser/get-build-file.js +1 -1
- package/dist/parser/parse-boolean.js +29 -0
- package/dist/parser/parse-boolean.spec.js +48 -0
- package/dist/parser/parse-build-file-references.js +2 -2
- package/dist/parser/parse-build-file-services.js +58 -0
- package/dist/parser/parse-build-file-task-command.js +6 -5
- package/dist/parser/parse-build-file-task-source.js +5 -5
- package/dist/parser/parse-build-file.js +27 -15
- package/dist/parser/parse-context.js +13 -0
- package/dist/parser/parse-envs.js +4 -3
- package/dist/parser/parse-healthcheck.js +28 -0
- package/dist/parser/parse-label-arguments.js +23 -0
- package/dist/parser/parse-service-selector.js +39 -0
- package/dist/parser/parse-string-array.js +6 -5
- package/dist/parser/parse-string-map.js +30 -0
- package/dist/parser/parse-string.js +20 -0
- package/dist/parser/read-build-file.js +16 -5
- package/dist/parser/read-env-file.js +3 -3
- package/dist/planner/utils/get-container-mounts.js +24 -0
- package/dist/planner/utils/normalize-path.js +17 -0
- package/dist/planner/utils/parse-work-node-mount.js +3 -14
- package/dist/planner/utils/parse-work-node-mount.spec.js +10 -10
- package/dist/planner/utils/parse-work-service-volume.js +21 -0
- package/dist/planner/utils/plan-work-command.js +1 -1
- package/dist/planner/utils/plan-work-dependency.js +17 -5
- package/dist/planner/utils/plan-work-node.js +203 -128
- package/dist/planner/utils/plan-work-nodes.js +59 -14
- package/dist/planner/utils/plan-work-tree.js +8 -4
- package/dist/planner/utils/plan-work-volume.js +25 -0
- package/dist/planner/validate.js +56 -8
- package/dist/planner/work-context.js +20 -0
- package/dist/planner/work-mount.js +3 -0
- package/dist/planner/work-node-id.js +4 -4
- package/dist/planner/work-node-id.spec.js +11 -8
- package/dist/planner/work-node-path.js +0 -1
- package/dist/planner/work-node-status.js +121 -18
- package/dist/planner/work-node.js +3 -3
- package/dist/planner/work-service-id.js +13 -0
- package/dist/planner/work-service-volume.js +3 -0
- package/dist/planner/work-service.js +6 -0
- package/dist/planner/work-services.js +3 -0
- package/dist/planner/work-volume.js +3 -0
- package/dist/program.js +155 -90
- package/dist/program.spec.js +20 -0
- package/dist/start-watch-processes.js +28 -0
- package/dist/testing/cli.js +73 -0
- package/dist/testing/create-build-file.js +1 -1
- package/dist/testing/example-test-suite.js +54 -0
- package/dist/testing/expect.js +30 -18
- package/dist/testing/get-logger.js +23 -0
- package/dist/testing/get-node.js +2 -2
- package/dist/testing/get-test-context.js +5 -3
- package/dist/testing/get-test-suite.js +2 -50
- package/dist/testing/integration/cache.spec.js +25 -28
- package/dist/testing/integration/cancellation.spec.js +19 -21
- package/dist/testing/integration/clean.spec.js +25 -28
- package/dist/testing/integration/cmd.spec.js +5 -8
- package/dist/testing/integration/concurrency.spec.js +8 -17
- package/dist/testing/integration/docker.spec.js +6 -9
- package/dist/testing/integration/env.spec.js +27 -34
- package/dist/testing/integration/error.spec.js +5 -9
- package/dist/testing/integration/extend.spec.js +32 -0
- package/dist/testing/integration/glob.spec.js +35 -28
- package/dist/testing/integration/include.spec.js +17 -16
- package/dist/testing/integration/invalid.spec.js +3 -2
- package/dist/testing/integration/invalid_loop.spec.js +13 -0
- package/dist/testing/integration/kubernetes.spec.js +15 -0
- package/dist/testing/integration/labels.spec.js +47 -0
- package/dist/testing/integration/local.spec.js +4 -7
- package/dist/testing/integration/monorepo.spec.js +5 -9
- package/dist/testing/integration/multi-line.spec.js +4 -4
- package/dist/testing/integration/program.spec.js +3 -10
- package/dist/testing/integration/reference.spec.js +10 -13
- package/dist/testing/integration/services.spec.js +14 -0
- package/dist/testing/integration/store.spec.js +42 -38
- package/dist/testing/integration/unknown.spec.js +4 -4
- package/dist/testing/integration/validate.spec.js +4 -4
- package/dist/testing/integration/watch.spec.js +34 -33
- package/dist/testing/lazy.js +17 -0
- package/dist/testing/start-watch-processes.js +29 -0
- package/dist/testing/test-suite-setup.js +3 -0
- package/dist/utils/abort-event.js +14 -1
- package/dist/utils/abortable-function.js +71 -0
- package/dist/utils/debouncer.spec.js +8 -8
- package/dist/utils/environment-config.js +13 -0
- package/dist/utils/fail-never.js +1 -1
- package/dist/utils/sleep.spec.js +3 -3
- package/package.json +24 -21
- package/dist/console/get-console-context-mock.js +0 -33
- package/dist/executer/clean.js +0 -17
- package/dist/executer/execute-local.js +0 -59
- package/dist/executer/execute.js +0 -139
- package/dist/executer/execution-context-event.js +0 -3
- package/dist/executer/execution-context-mock.js +0 -3
- package/dist/executer/executor-mock.js +0 -61
- package/dist/executer/get-environment-mock.js +0 -16
- package/dist/executer/get-execution-context-mock.js +0 -18
- package/dist/executer/get-local-executor.js +0 -56
- package/dist/executer/restore.js +0 -19
- package/dist/executer/store.js +0 -19
- package/dist/logging/get-logger.js +0 -23
- package/dist/logging/message-to-console.js +0 -16
- package/dist/optimizer/optimize.js +0 -32
- package/dist/optimizer/work-node-description.js +0 -12
- package/dist/planner/utils/find-build-task.js +0 -18
- package/dist/testing/create-work-tree.js +0 -11
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getCli = exports.isCliService = exports.isCliTask = void 0;
|
|
4
|
+
const plan_work_nodes_1 = require("../planner/utils/plan-work-nodes");
|
|
5
|
+
const create_scheduler_state_1 = require("../executer/create-scheduler-state");
|
|
6
|
+
const ci_1 = require("../utils/ci");
|
|
7
|
+
const get_logger_1 = require("./get-logger");
|
|
8
|
+
const hierarchy_scheduler_1 = require("../executer/hierarchy-scheduler");
|
|
9
|
+
const event_cache_1 = require("../executer/event-cache");
|
|
10
|
+
const validate_1 = require("../planner/validate");
|
|
11
|
+
const start_watch_processes_1 = require("./start-watch-processes");
|
|
12
|
+
const process_manager_1 = require("../executer/process-manager");
|
|
13
|
+
const isCliTask = (val) => val.type === 'task';
|
|
14
|
+
exports.isCliTask = isCliTask;
|
|
15
|
+
const isCliService = (val) => val.type === 'service';
|
|
16
|
+
exports.isCliService = isCliService;
|
|
17
|
+
function getCli(workTree, environment) {
|
|
18
|
+
return {
|
|
19
|
+
execWatch(options) {
|
|
20
|
+
const processManager = new process_manager_1.ProcessManager(environment, options?.workers ?? 0);
|
|
21
|
+
const state = (0, create_scheduler_state_1.createSchedulerState)({
|
|
22
|
+
services: workTree.services,
|
|
23
|
+
nodes: workTree.nodes,
|
|
24
|
+
watch: options?.watch ?? false,
|
|
25
|
+
logMode: options?.logMode ?? ci_1.isCI ? 'live' : 'interactive',
|
|
26
|
+
cacheMethod: options?.cacheDefault ?? 'checksum',
|
|
27
|
+
});
|
|
28
|
+
const logMode = options?.logMode ?? (ci_1.isCI ? 'live' : 'interactive');
|
|
29
|
+
const logger = (0, get_logger_1.getLogger)(logMode, state, environment);
|
|
30
|
+
if (options?.watch) {
|
|
31
|
+
(0, start_watch_processes_1.startWatchProcesses)(state, processManager, environment);
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
state,
|
|
35
|
+
start: async () => {
|
|
36
|
+
const result = await (0, hierarchy_scheduler_1.schedule)(processManager, state, environment);
|
|
37
|
+
await logger.complete(result, environment);
|
|
38
|
+
return result;
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
async exec(options) {
|
|
43
|
+
return this.execWatch(options).start();
|
|
44
|
+
},
|
|
45
|
+
async clean() {
|
|
46
|
+
await (0, event_cache_1.cleanCache)(workTree, environment);
|
|
47
|
+
},
|
|
48
|
+
async restore(path) {
|
|
49
|
+
await (0, event_cache_1.restoreCache)(path, workTree, environment);
|
|
50
|
+
},
|
|
51
|
+
async store(path) {
|
|
52
|
+
await (0, event_cache_1.storeCache)(path, workTree, environment);
|
|
53
|
+
},
|
|
54
|
+
ls() {
|
|
55
|
+
return [
|
|
56
|
+
...Array.from((0, plan_work_nodes_1.iterateWorkServices)(workTree.services)).map((item) => ({ item, type: 'service' })),
|
|
57
|
+
...Array.from((0, plan_work_nodes_1.iterateWorkNodes)(workTree.nodes)).map((item) => ({ item, type: 'task' })),
|
|
58
|
+
];
|
|
59
|
+
},
|
|
60
|
+
validate() {
|
|
61
|
+
return (0, validate_1.validate)(workTree, environment);
|
|
62
|
+
},
|
|
63
|
+
node(name) {
|
|
64
|
+
const node = Object.values(workTree.nodes).find((n) => n.name == name);
|
|
65
|
+
if (!node) {
|
|
66
|
+
throw new Error(`unable to find node ${name}`);
|
|
67
|
+
}
|
|
68
|
+
return node;
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
exports.getCli = getCli;
|
|
73
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.createBuildFile = void 0;
|
|
4
4
|
const parse_build_file_1 = require("../parser/parse-build-file");
|
|
5
5
|
function createBuildFile(env, buildFile) {
|
|
6
|
-
return parse_build_file_1.parseBuildFile(`${env.cwd}/build.yaml`, {}, buildFile, env);
|
|
6
|
+
return (0, parse_build_file_1.parseBuildFile)(`${env.cwd}/build.yaml`, {}, buildFile, env);
|
|
7
7
|
}
|
|
8
8
|
exports.createBuildFile = createBuildFile;
|
|
9
9
|
//# sourceMappingURL=create-build-file.js.map
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ExampleTestSuite = void 0;
|
|
4
|
+
const path_1 = require("path");
|
|
5
|
+
const get_file_context_1 = require("../file/get-file-context");
|
|
6
|
+
const console_context_mock_1 = require("../console/console-context-mock");
|
|
7
|
+
const work_node_status_1 = require("../planner/work-node-status");
|
|
8
|
+
const program_1 = require("../program");
|
|
9
|
+
const execute_docker_1 = require("../executer/execute-docker");
|
|
10
|
+
class ExampleTestSuite {
|
|
11
|
+
constructor(exampleName, files) {
|
|
12
|
+
this.files = files;
|
|
13
|
+
this.tests = [];
|
|
14
|
+
this.exampleDirectory = (0, path_1.join)(__dirname, '../../examples/', exampleName);
|
|
15
|
+
this.path = (0, path_1.join)(process.cwd(), 'temp', exampleName);
|
|
16
|
+
this.file = (0, get_file_context_1.getFileContext)(this.path);
|
|
17
|
+
}
|
|
18
|
+
async close() {
|
|
19
|
+
for (const test of this.tests) {
|
|
20
|
+
await this.file.remove(test.cwd);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async setup(scope) {
|
|
24
|
+
await this.file.remove(this.path);
|
|
25
|
+
await this.file.createDirectory(this.path);
|
|
26
|
+
const environment = {
|
|
27
|
+
processEnvs: { ...process.env, ...(scope.envs ?? {}) },
|
|
28
|
+
abortCtrl: new AbortController(),
|
|
29
|
+
cwd: this.path,
|
|
30
|
+
file: this.file,
|
|
31
|
+
console: (0, console_context_mock_1.consoleContextMock)(),
|
|
32
|
+
status: (0, work_node_status_1.statusConsole)(),
|
|
33
|
+
docker: (0, execute_docker_1.getContainerCli)(),
|
|
34
|
+
};
|
|
35
|
+
for (const file of this.files) {
|
|
36
|
+
await this.file.copy((0, path_1.join)(this.exampleDirectory, file), (0, path_1.join)(this.path, file));
|
|
37
|
+
}
|
|
38
|
+
const fileName = (0, path_1.join)(this.path, 'build.yaml');
|
|
39
|
+
this.tests.push({
|
|
40
|
+
cwd: this.path,
|
|
41
|
+
});
|
|
42
|
+
const cli = await (0, program_1.createCli)(fileName, environment, scope);
|
|
43
|
+
await cli.clean({ service: true });
|
|
44
|
+
// reset cli clean stats
|
|
45
|
+
environment.console = (0, console_context_mock_1.consoleContextMock)();
|
|
46
|
+
environment.status = (0, work_node_status_1.statusConsole)();
|
|
47
|
+
return {
|
|
48
|
+
cli,
|
|
49
|
+
environment,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
exports.ExampleTestSuite = ExampleTestSuite;
|
|
54
|
+
//# sourceMappingURL=example-test-suite.js.map
|
package/dist/testing/expect.js
CHANGED
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.expectContainsLog = exports.expectLog = exports.expectSuccessfulResult = void 0;
|
|
4
|
-
|
|
4
|
+
const plan_work_nodes_1 = require("../planner/utils/plan-work-nodes");
|
|
5
|
+
async function expectSuccessfulResult(result, env) {
|
|
5
6
|
if (!result.success) {
|
|
6
|
-
for (const
|
|
7
|
-
|
|
8
|
-
if (node.state.type === 'failed') {
|
|
7
|
+
for (const state of (0, plan_work_nodes_1.iterateWorkNodes)(result.state.node)) {
|
|
8
|
+
if (state.type !== 'completed') {
|
|
9
9
|
expect({
|
|
10
|
-
nodeId,
|
|
11
|
-
status:
|
|
12
|
-
|
|
10
|
+
nodeId: state.node.id,
|
|
11
|
+
status: state.type,
|
|
12
|
+
updates: Array.from(env.status.task(state.node).read()).map((s) => `${s.level}: ${s.message}`),
|
|
13
|
+
logs: Array.from(env.status.task(state.node).logs()).map((l) => `${l.console}: ${l.message}`),
|
|
14
|
+
errorMessage: state.type === 'error' ? state.errorMessage : undefined,
|
|
15
|
+
needs: state.node.needs.map((need) => ({
|
|
16
|
+
name: need.name,
|
|
17
|
+
updates: Array.from(env.status.service(need).read()).map((s) => `${s.level}: ${s.message}`),
|
|
18
|
+
logs: Array.from(env.status.service(need).logs()).map((l) => `${l.console}: ${l.message}`),
|
|
19
|
+
})),
|
|
13
20
|
}).toEqual({
|
|
14
|
-
nodeId,
|
|
21
|
+
nodeId: state.node.id,
|
|
15
22
|
status: 'completed',
|
|
16
23
|
});
|
|
17
24
|
}
|
|
@@ -19,23 +26,28 @@ async function expectSuccessfulResult(result) {
|
|
|
19
26
|
}
|
|
20
27
|
}
|
|
21
28
|
exports.expectSuccessfulResult = expectSuccessfulResult;
|
|
22
|
-
function
|
|
23
|
-
const node = Object.values(
|
|
29
|
+
function getNodeState(state, name) {
|
|
30
|
+
const node = Object.values(state.node).find((n) => n.node.name === name);
|
|
24
31
|
if (!node) {
|
|
25
32
|
throw new Error(`could not find node ${name}`);
|
|
26
33
|
}
|
|
27
34
|
return node;
|
|
28
35
|
}
|
|
29
|
-
async function expectLog(result, name, message) {
|
|
30
|
-
const
|
|
31
|
-
const logs =
|
|
32
|
-
expect(logs
|
|
36
|
+
async function expectLog(result, env, name, message) {
|
|
37
|
+
const state = getNodeState(result.state, name);
|
|
38
|
+
const logs = Array.from(env.status.task(state.node).logs()).map((n) => n.message);
|
|
39
|
+
expect(logs).toContain(message);
|
|
33
40
|
}
|
|
34
41
|
exports.expectLog = expectLog;
|
|
35
|
-
async function expectContainsLog(result, name, message) {
|
|
36
|
-
const
|
|
37
|
-
const logs =
|
|
38
|
-
|
|
42
|
+
async function expectContainsLog(result, env, name, message) {
|
|
43
|
+
const state = getNodeState(result.state, name);
|
|
44
|
+
const logs = env.status.task(state.node).logs();
|
|
45
|
+
for (const log of logs) {
|
|
46
|
+
if (log.message.indexOf(message) >= 0) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
expect(Array.from(logs)).toContain(message);
|
|
39
51
|
}
|
|
40
52
|
exports.expectContainsLog = expectContainsLog;
|
|
41
53
|
//# sourceMappingURL=expect.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getLogger = void 0;
|
|
4
|
+
const grouped_logger_1 = require("../logging/grouped-logger");
|
|
5
|
+
const live_logger_1 = require("../logging/live-logger");
|
|
6
|
+
const interactive_logger_1 = require("../logging/interactive-logger");
|
|
7
|
+
const fail_never_1 = require("../utils/fail-never");
|
|
8
|
+
function getLogger(mode, state, env) {
|
|
9
|
+
if (mode === 'grouped') {
|
|
10
|
+
return (0, grouped_logger_1.groupedLogger)(state, env);
|
|
11
|
+
}
|
|
12
|
+
else if (mode === 'live') {
|
|
13
|
+
return (0, live_logger_1.liveLogger)(state, env);
|
|
14
|
+
}
|
|
15
|
+
else if (mode === 'interactive') {
|
|
16
|
+
return (0, interactive_logger_1.interactiveLogger)(state, env);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
(0, fail_never_1.failNever)(mode, 'unknown log mode');
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.getLogger = getLogger;
|
|
23
|
+
//# sourceMappingURL=get-logger.js.map
|
package/dist/testing/get-node.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getNode = void 0;
|
|
4
|
-
function getNode(buildFile,
|
|
5
|
-
const node = Object.values(
|
|
4
|
+
function getNode(buildFile, nodes, taskName) {
|
|
5
|
+
const node = Object.values(nodes).find((n) => n.name === taskName);
|
|
6
6
|
if (!node) {
|
|
7
7
|
throw new Error(`could not find node ${taskName}`);
|
|
8
8
|
}
|
|
@@ -2,14 +2,16 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getTestContext = void 0;
|
|
4
4
|
const get_file_context_1 = require("../file/get-file-context");
|
|
5
|
-
const
|
|
5
|
+
const work_node_status_1 = require("../planner/work-node-status");
|
|
6
|
+
const log_1 = require("../log");
|
|
6
7
|
function getTestContext(cwd) {
|
|
7
8
|
const context = {
|
|
8
9
|
processEnvs: { ...process.env },
|
|
9
10
|
abortCtrl: new AbortController(),
|
|
10
11
|
cwd,
|
|
11
|
-
file: get_file_context_1.getFileContext(),
|
|
12
|
-
console:
|
|
12
|
+
file: (0, get_file_context_1.getFileContext)(cwd),
|
|
13
|
+
console: (0, log_1.consoleContext)(),
|
|
14
|
+
status: (0, work_node_status_1.statusConsole)(),
|
|
13
15
|
};
|
|
14
16
|
return context;
|
|
15
17
|
}
|
|
@@ -1,57 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getTestSuite = void 0;
|
|
4
|
-
const
|
|
5
|
-
const get_build_file_1 = require("../parser/get-build-file");
|
|
6
|
-
const get_docker_executor_1 = require("../executer/get-docker-executor");
|
|
7
|
-
const get_console_context_mock_1 = require("../console/get-console-context-mock");
|
|
8
|
-
const get_file_context_1 = require("../file/get-file-context");
|
|
9
|
-
const emitter_1 = require("../utils/emitter");
|
|
10
|
-
const clean_1 = require("../executer/clean");
|
|
11
|
-
const plan_work_nodes_1 = require("../planner/utils/plan-work-nodes");
|
|
4
|
+
const example_test_suite_1 = require("./example-test-suite");
|
|
12
5
|
function getTestSuite(exampleName, files) {
|
|
13
|
-
|
|
14
|
-
const testDirectory = path_1.join(process.cwd(), 'temp', exampleName);
|
|
15
|
-
const file = get_file_context_1.getFileContext();
|
|
16
|
-
const tests = [];
|
|
17
|
-
return {
|
|
18
|
-
async close() {
|
|
19
|
-
for (const test of tests) {
|
|
20
|
-
await file.remove(test.cwd);
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
async setup(executionOptions) {
|
|
24
|
-
const context = {
|
|
25
|
-
processEnvs: { ...process.env },
|
|
26
|
-
abortCtrl: new AbortController(),
|
|
27
|
-
cwd: testDirectory,
|
|
28
|
-
file,
|
|
29
|
-
console: get_console_context_mock_1.getConsoleContextMock(),
|
|
30
|
-
};
|
|
31
|
-
await file.remove(testDirectory);
|
|
32
|
-
await file.createDirectory(testDirectory);
|
|
33
|
-
for (const file of files) {
|
|
34
|
-
await context.file.copy(path_1.join(exampleDirectory, file), path_1.join(testDirectory, file));
|
|
35
|
-
}
|
|
36
|
-
const fileName = path_1.join(testDirectory, 'build.yaml');
|
|
37
|
-
const buildFile = await get_build_file_1.getBuildFile(fileName, context);
|
|
38
|
-
const workNodes = plan_work_nodes_1.planWorkNodes(buildFile);
|
|
39
|
-
const executor = get_docker_executor_1.getDockerExecutor();
|
|
40
|
-
await clean_1.clean(workNodes, context, executor);
|
|
41
|
-
const executionContext = {
|
|
42
|
-
environment: context,
|
|
43
|
-
watch: executionOptions?.watch ?? false,
|
|
44
|
-
cacheMethod: executionOptions?.cacheMethod ?? 'checksum',
|
|
45
|
-
workers: executionOptions?.workers ?? 0,
|
|
46
|
-
events: emitter_1.emitter(),
|
|
47
|
-
executor,
|
|
48
|
-
};
|
|
49
|
-
tests.push({
|
|
50
|
-
cwd: testDirectory,
|
|
51
|
-
});
|
|
52
|
-
return { buildFile, context, executionContext };
|
|
53
|
-
},
|
|
54
|
-
};
|
|
6
|
+
return new example_test_suite_1.ExampleTestSuite(exampleName, files);
|
|
55
7
|
}
|
|
56
8
|
exports.getTestSuite = getTestSuite;
|
|
57
9
|
//# sourceMappingURL=get-test-suite.js.map
|
|
@@ -3,50 +3,47 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
require("jest-extended");
|
|
4
4
|
const write_work_node_cache_1 = require("../../optimizer/write-work-node-cache");
|
|
5
5
|
const expect_1 = require("../expect");
|
|
6
|
-
const plan_work_tree_1 = require("../../planner/utils/plan-work-tree");
|
|
7
|
-
const execute_1 = require("../../executer/execute");
|
|
8
|
-
const optimize_1 = require("../../optimizer/optimize");
|
|
9
6
|
const get_test_suite_1 = require("../get-test-suite");
|
|
10
7
|
const path_1 = require("path");
|
|
11
|
-
const
|
|
12
|
-
const
|
|
8
|
+
const enqueue_next_1 = require("../../executer/scheduler/enqueue-next");
|
|
9
|
+
const read_build_file_1 = require("../../parser/read-build-file");
|
|
13
10
|
describe('cache', () => {
|
|
14
|
-
const suite = get_test_suite_1.getTestSuite('cache', ['build.yaml', 'package.json', 'package-lock.json']);
|
|
11
|
+
const suite = (0, get_test_suite_1.getTestSuite)('cache', ['build.yaml', 'package.json', 'package-lock.json']);
|
|
15
12
|
afterAll(() => suite.close());
|
|
16
13
|
async function testCache(action, expectInvalidate) {
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
await
|
|
21
|
-
await
|
|
22
|
-
|
|
14
|
+
const setupBefore = await suite.setup({ taskName: 'example' });
|
|
15
|
+
const nodeBefore = setupBefore.cli.node('example');
|
|
16
|
+
await (0, write_work_node_cache_1.writeWorkNodeCache)(nodeBefore, setupBefore.environment);
|
|
17
|
+
await action(setupBefore.environment);
|
|
18
|
+
const setupAfter = await suite.setup({ taskName: 'example' });
|
|
19
|
+
const node = setupAfter.cli.node('example');
|
|
20
|
+
const checksumUpToDate = await (0, enqueue_next_1.checkCacheState)(node, 'checksum', setupAfter.environment);
|
|
21
|
+
const modifyDateUpToDate = await (0, enqueue_next_1.checkCacheState)(node, 'modify-date', setupAfter.environment);
|
|
23
22
|
if (expectInvalidate) {
|
|
24
|
-
expect(
|
|
23
|
+
expect(checksumUpToDate.cached).toBeFalsy();
|
|
24
|
+
expect(modifyDateUpToDate.cached).toBeFalsy();
|
|
25
25
|
}
|
|
26
26
|
else {
|
|
27
|
-
expect(
|
|
27
|
+
expect(checksumUpToDate.cached).toBeTruthy();
|
|
28
|
+
expect(modifyDateUpToDate.cached).toBeTruthy();
|
|
28
29
|
}
|
|
29
30
|
}
|
|
30
31
|
it('should run invalid cache on src file change', async () => {
|
|
31
|
-
await testCache(async (
|
|
32
|
-
await
|
|
32
|
+
await testCache(async (environment) => {
|
|
33
|
+
await environment.file.appendFile((0, path_1.join)(environment.cwd, 'package.json'), '\n');
|
|
33
34
|
}, true);
|
|
34
35
|
});
|
|
35
36
|
it('should mount generations of dependant tasks', async () => {
|
|
36
|
-
const {
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
await expect_1.
|
|
40
|
-
await expect_1.expectLog(result, `dependant`, 'node_modules');
|
|
37
|
+
const { cli, environment } = await suite.setup({ taskName: 'dependant' });
|
|
38
|
+
const result = await cli.exec();
|
|
39
|
+
await (0, expect_1.expectSuccessfulResult)(result, environment);
|
|
40
|
+
await (0, expect_1.expectLog)(result, environment, `dependant`, 'node_modules');
|
|
41
41
|
});
|
|
42
42
|
it('should invalid cache on image change', async () => {
|
|
43
|
-
await testCache(async (
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
delete workTree.nodes[node.id];
|
|
48
|
-
node.id = work_node_id_1.getWorkNodeId(node.cwd, node.mergedTask, node.mergedDeps);
|
|
49
|
-
workTree.nodes[node.id] = node;
|
|
43
|
+
await testCache(async (environment) => {
|
|
44
|
+
const buildFile = await (0, read_build_file_1.read)('build.yaml', environment);
|
|
45
|
+
buildFile.tasks['example'].image = '15.0.0';
|
|
46
|
+
await (0, read_build_file_1.write)('build.yaml', buildFile, environment);
|
|
50
47
|
}, true);
|
|
51
48
|
});
|
|
52
49
|
});
|
|
@@ -1,42 +1,40 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const path_1 = require("path");
|
|
4
|
-
const plan_work_tree_1 = require("../../planner/utils/plan-work-tree");
|
|
5
4
|
const get_test_suite_1 = require("../get-test-suite");
|
|
6
|
-
const execute_1 = require("../../executer/execute");
|
|
7
5
|
describe('cancellation', () => {
|
|
8
|
-
const suite = get_test_suite_1.getTestSuite('cancellation', ['build.yaml']);
|
|
6
|
+
const suite = (0, get_test_suite_1.getTestSuite)('cancellation', ['build.yaml']);
|
|
9
7
|
afterAll(() => suite.close());
|
|
10
8
|
async function testAbort(taskName, expectedState) {
|
|
11
|
-
const {
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
setTimeout(() => {
|
|
18
|
-
executionContext.environment.abortCtrl.abort();
|
|
19
|
-
}, 2000);
|
|
20
|
-
}
|
|
21
|
-
});
|
|
9
|
+
const { cli, environment } = await suite.setup({ taskName });
|
|
10
|
+
const exec = await cli.execWatch({ logMode: 'live' });
|
|
11
|
+
const abortNode = Object.values(exec.state.current.node).find((n) => n.node.name.startsWith('long_'));
|
|
12
|
+
exec.processManager.on((evt) => {
|
|
13
|
+
if (evt.type === 'started' && evt.context.id === abortNode?.node.id) {
|
|
14
|
+
environment.abortCtrl.abort();
|
|
22
15
|
}
|
|
23
16
|
});
|
|
24
|
-
const result = await
|
|
17
|
+
const result = await exec.start();
|
|
25
18
|
expect(result.success).toBeFalsy();
|
|
26
|
-
|
|
27
|
-
|
|
19
|
+
if (abortNode) {
|
|
20
|
+
expect(result.state.node[abortNode.node.id].type).toEqual(expectedState);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
expect(abortNode).toBeDefined();
|
|
24
|
+
}
|
|
25
|
+
expect(await environment.file.exists((0, path_1.join)(suite.path, 'test'))).toBeFalsy();
|
|
28
26
|
}
|
|
29
27
|
it('should cancel local task with dependencies', async () => {
|
|
30
|
-
await testAbort('local_cancel', '
|
|
28
|
+
await testAbort('local_cancel', 'canceled');
|
|
31
29
|
});
|
|
32
30
|
it('should cancel local task', async () => {
|
|
33
|
-
await testAbort('long_running_local', '
|
|
31
|
+
await testAbort('long_running_local', 'canceled');
|
|
34
32
|
});
|
|
35
33
|
it('should cancel docker task', async () => {
|
|
36
|
-
await testAbort('long_running_docker', '
|
|
34
|
+
await testAbort('long_running_docker', 'canceled');
|
|
37
35
|
});
|
|
38
36
|
it('should cancel docker task with dependencies', async () => {
|
|
39
|
-
await testAbort('
|
|
37
|
+
await testAbort('docker_cancel', 'canceled');
|
|
40
38
|
});
|
|
41
39
|
});
|
|
42
40
|
//# sourceMappingURL=cancellation.spec.js.map
|
|
@@ -3,41 +3,38 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const path_1 = require("path");
|
|
4
4
|
const fs_1 = require("fs");
|
|
5
5
|
const expect_1 = require("../expect");
|
|
6
|
-
const plan_work_tree_1 = require("../../planner/utils/plan-work-tree");
|
|
7
|
-
const clean_1 = require("../../executer/clean");
|
|
8
6
|
const get_test_suite_1 = require("../get-test-suite");
|
|
9
|
-
const execute_1 = require("../../executer/execute");
|
|
10
|
-
const get_local_executor_1 = require("../../executer/get-local-executor");
|
|
11
|
-
const execute_docker_1 = require("../../executer/execute-docker");
|
|
12
7
|
const get_docker_executor_1 = require("../../executer/get-docker-executor");
|
|
8
|
+
const plan_work_volume_1 = require("../../planner/utils/plan-work-volume");
|
|
13
9
|
describe('clean', () => {
|
|
14
|
-
const suite = get_test_suite_1.getTestSuite('clean', ['build.yaml', 'package.json']);
|
|
10
|
+
const suite = (0, get_test_suite_1.getTestSuite)('clean', ['build.yaml', 'package.json']);
|
|
15
11
|
afterAll(() => suite.close());
|
|
16
12
|
it('should clean generated outputs locally', async () => {
|
|
17
|
-
const {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
await
|
|
23
|
-
|
|
24
|
-
expect(fs_1.existsSync(outputPath)).toBeTruthy();
|
|
25
|
-
await clean_1.clean(workTree.nodes, context, executionContext.executor);
|
|
26
|
-
expect(fs_1.existsSync(outputPath)).toBeFalsy();
|
|
13
|
+
const { cli, environment } = await suite.setup({ taskName: 'example' });
|
|
14
|
+
const result = await cli.exec({ cacheDefault: 'none' });
|
|
15
|
+
await (0, expect_1.expectSuccessfulResult)(result, environment);
|
|
16
|
+
const outputPath = (0, path_1.join)(suite.path, 'node_modules');
|
|
17
|
+
expect((0, fs_1.existsSync)(outputPath)).toBeTruthy();
|
|
18
|
+
await cli.clean();
|
|
19
|
+
expect((0, fs_1.existsSync)(outputPath)).toBeFalsy();
|
|
27
20
|
});
|
|
28
21
|
it('should clean generated outputs in containers', async () => {
|
|
29
|
-
const {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
await
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
await
|
|
40
|
-
|
|
22
|
+
const { cli, environment } = await suite.setup({ taskName: 'docker:example' });
|
|
23
|
+
const result = await cli.exec({ cacheDefault: 'none' });
|
|
24
|
+
await (0, expect_1.expectSuccessfulResult)(result, environment);
|
|
25
|
+
const outputPath = (0, path_1.join)(suite.path, 'node_modules');
|
|
26
|
+
const volumeName = (0, plan_work_volume_1.getVolumeName)(outputPath);
|
|
27
|
+
expect(await (0, get_docker_executor_1.existsVolume)(environment, volumeName)).toBeTruthy();
|
|
28
|
+
await cli.clean();
|
|
29
|
+
expect(await (0, get_docker_executor_1.existsVolume)(environment, volumeName)).toBeFalsy();
|
|
30
|
+
});
|
|
31
|
+
it('should clean and restore created data in volumes', async () => {
|
|
32
|
+
const { cli, environment } = await suite.setup({ taskName: 'example:service' });
|
|
33
|
+
const result = await cli.exec();
|
|
34
|
+
await (0, expect_1.expectSuccessfulResult)(result, environment);
|
|
35
|
+
await cli.clean({ service: true });
|
|
36
|
+
const resultAfterClean = await cli.exec();
|
|
37
|
+
await (0, expect_1.expectSuccessfulResult)(resultAfterClean, environment);
|
|
41
38
|
});
|
|
42
39
|
});
|
|
43
40
|
//# sourceMappingURL=clean.spec.js.map
|
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const expect_1 = require("../expect");
|
|
4
|
-
const plan_work_tree_1 = require("../../planner/utils/plan-work-tree");
|
|
5
4
|
const get_test_suite_1 = require("../get-test-suite");
|
|
6
|
-
const execute_1 = require("../../executer/execute");
|
|
7
5
|
describe('cmd', () => {
|
|
8
|
-
const suite = get_test_suite_1.getTestSuite('cmd', ['build.yaml', 'sub/README.md']);
|
|
6
|
+
const suite = (0, get_test_suite_1.getTestSuite)('cmd', ['build.yaml', 'sub/README.md']);
|
|
9
7
|
afterAll(() => suite.close());
|
|
10
8
|
it('should run with path arg', async () => {
|
|
11
|
-
const {
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
await expect_1.
|
|
15
|
-
await expect_1.expectContainsLog(result, `example`, 'README.md');
|
|
9
|
+
const { cli, environment } = await suite.setup({ taskName: 'example' });
|
|
10
|
+
const result = await cli.exec();
|
|
11
|
+
await (0, expect_1.expectSuccessfulResult)(result, environment);
|
|
12
|
+
await (0, expect_1.expectContainsLog)(result, environment, `example`, 'README.md');
|
|
16
13
|
});
|
|
17
14
|
});
|
|
18
15
|
//# sourceMappingURL=cmd.spec.js.map
|
|
@@ -1,28 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const expect_1 = require("../expect");
|
|
4
|
-
const plan_work_tree_1 = require("../../planner/utils/plan-work-tree");
|
|
5
4
|
const get_test_suite_1 = require("../get-test-suite");
|
|
6
|
-
const execute_1 = require("../../executer/execute");
|
|
7
5
|
describe('concurrency', () => {
|
|
8
|
-
const suite = get_test_suite_1.getTestSuite('concurrency', ['build.yaml']);
|
|
6
|
+
const suite = (0, get_test_suite_1.getTestSuite)('concurrency', ['build.yaml']);
|
|
9
7
|
afterAll(() => suite.close());
|
|
10
8
|
it('should run with concurrency lower than total tasks', async () => {
|
|
11
|
-
const {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
concurrentRunners++;
|
|
17
|
-
}
|
|
18
|
-
else if (evt.newState.type === 'failed' || evt.newState.type === 'completed') {
|
|
19
|
-
concurrentRunners--;
|
|
20
|
-
}
|
|
21
|
-
expect(concurrentRunners).toBeLessThanOrEqual(1);
|
|
9
|
+
const { cli, environment } = await suite.setup({ taskName: 'example' });
|
|
10
|
+
const exec = cli.execWatch({ workers: 1 });
|
|
11
|
+
exec.state.on((state) => {
|
|
12
|
+
const runningNodes = Object.values(state.node).filter((n) => n.type === 'running');
|
|
13
|
+
expect(runningNodes.length).toBeLessThanOrEqual(1);
|
|
22
14
|
});
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
await expect_1.expectSuccessfulResult(result);
|
|
15
|
+
const result = await exec.start();
|
|
16
|
+
await (0, expect_1.expectSuccessfulResult)(result, environment);
|
|
26
17
|
});
|
|
27
18
|
});
|
|
28
19
|
//# sourceMappingURL=concurrency.spec.js.map
|
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const expect_1 = require("../expect");
|
|
4
|
-
const plan_work_tree_1 = require("../../planner/utils/plan-work-tree");
|
|
5
4
|
const get_test_suite_1 = require("../get-test-suite");
|
|
6
|
-
const execute_1 = require("../../executer/execute");
|
|
7
5
|
describe('docker', () => {
|
|
8
|
-
const suite = get_test_suite_1.getTestSuite('docker', ['build.yaml']);
|
|
6
|
+
const suite = (0, get_test_suite_1.getTestSuite)('docker', ['build.yaml']);
|
|
9
7
|
afterAll(() => suite.close());
|
|
10
8
|
it('should pull docker image', async () => {
|
|
11
|
-
const {
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
await expect_1.
|
|
15
|
-
await expect_1.expectLog(result, `example`, '
|
|
16
|
-
await expect_1.expectLog(result, `example`, 'v16.6.0');
|
|
9
|
+
const { cli, environment } = await suite.setup({ taskName: 'example' });
|
|
10
|
+
const result = await cli.exec();
|
|
11
|
+
await (0, expect_1.expectSuccessfulResult)(result, environment);
|
|
12
|
+
await (0, expect_1.expectLog)(result, environment, `example`, '7.19.1');
|
|
13
|
+
await (0, expect_1.expectLog)(result, environment, `example`, 'v16.6.0');
|
|
17
14
|
});
|
|
18
15
|
});
|
|
19
16
|
//# sourceMappingURL=docker.spec.js.map
|