@oisincoveney/pipeline 2.8.3 → 2.9.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/.agents/skills/orchestrate/SKILL.md +45 -32
- package/README.md +51 -41
- package/defaults/pipeline.yaml +13 -12
- package/defaults/profiles.yaml +1 -1
- package/dist/argo-submit.js +1 -1
- package/dist/cli/doctor.d.ts +21 -0
- package/dist/cli/doctor.js +268 -0
- package/dist/cli/format.js +6 -3
- package/dist/cli/program.d.ts +14 -16
- package/dist/cli/program.js +291 -104
- package/dist/cli/run-resolver.js +58 -0
- package/dist/commands/bench-command.js +12 -4
- package/dist/commands/pipeline-command.js +22 -5
- package/dist/commands/runner-command-command.js +32 -9
- package/dist/config/lint.js +44 -26
- package/dist/config/load.js +0 -1
- package/dist/config/schemas.d.ts +0 -6
- package/dist/config/schemas.js +0 -8
- package/dist/context/repo-map.js +72 -56
- package/dist/gates.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +20 -14
- package/dist/install-commands/claude-code.js +4 -33
- package/dist/install-commands/opencode.js +119 -171
- package/dist/mcp/repo-local-backends.js +51 -39
- package/dist/moka-submit.js +3 -3
- package/dist/pipeline-runtime.js +15 -5
- package/dist/planning/generate.js +5 -11
- package/dist/run-control/commands.js +340 -0
- package/dist/run-control/contracts.d.ts +21 -0
- package/dist/run-control/contracts.js +129 -0
- package/dist/run-control/detach.js +79 -0
- package/dist/run-control/runtime-reporter.js +187 -0
- package/dist/run-control/store.js +304 -0
- package/dist/run-control/supervisor.js +192 -0
- package/dist/runner-command/finalize.js +28 -37
- package/dist/runner-command/lifecycle-context.js +130 -63
- package/dist/runner-command/lifecycle.js +22 -31
- package/dist/runner-command/run.js +120 -72
- package/dist/runner-command/task-descriptor.js +11 -4
- package/dist/runner.js +1 -1
- package/dist/runtime/agent-node/agent-node.js +3 -3
- package/dist/runtime/builtins/builtins.js +1 -3
- package/dist/runtime/changed-files/changed-files.js +1 -1
- package/dist/runtime/context/context.js +1 -1
- package/dist/runtime/contracts/contracts.d.ts +4 -0
- package/dist/runtime/hooks/hooks.js +1 -1
- package/dist/runtime/json-validation/json-validation.js +49 -23
- package/dist/runtime/local-scheduler.js +49 -26
- package/dist/runtime/opencode-adapter.js +14 -10
- package/dist/runtime/opencode-runtime.js +22 -20
- package/dist/runtime/opencode-session-executor.js +1 -1
- package/dist/runtime/parallel-node/parallel-node.js +10 -0
- package/dist/runtime/parallel-worktrees/parallel-worktrees.js +2 -35
- package/dist/runtime/run-journal.js +17 -10
- package/dist/runtime/services/file-system-service.js +29 -0
- package/dist/runtime/services/opencode-runtime-server-service.js +27 -0
- package/dist/runtime/services/repo-io-service.js +48 -0
- package/dist/runtime/services/run-journal-file-service.js +20 -0
- package/dist/runtime/services/runner-command-io-service.js +88 -0
- package/dist/runtime/workflow-lifecycle.js +76 -39
- package/dist/schedule/backlog-context.js +55 -29
- package/dist/schedule/passes/index.js +0 -1
- package/docs/config-architecture.md +4 -26
- package/docs/operator-guide.md +73 -32
- package/package.json +2 -1
- package/dist/runtime/select-candidate/select-candidate.js +0 -144
- package/dist/runtime/services/select-candidate-service.js +0 -13
- package/dist/schedule/passes/candidates.js +0 -51
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { compileArgoExecutionGraph } from "../argo-graph.js";
|
|
2
|
-
import { RunnerCommandPayloadValidationError } from "../runner-command-contract.js";
|
|
3
|
-
import { promoteFinalRef } from "../run-state/git-refs.js";
|
|
4
2
|
import { dispatchHooks } from "../runtime/hooks/hooks.js";
|
|
5
3
|
import "../runtime/hooks/index.js";
|
|
6
4
|
import { finalizeWorkflowLifecycle } from "../runtime/workflow-lifecycle.js";
|
|
7
|
-
import {
|
|
5
|
+
import { RunnerCommandPayloadValidationError } from "../runner-command-contract.js";
|
|
6
|
+
import { RunnerCommandIoService, flushAndReport, isOutputStream, runValidatedRunnerCommand } from "../runtime/services/runner-command-io-service.js";
|
|
7
|
+
import { createRunnerLifecycleContextEffect } from "./lifecycle-context.js";
|
|
8
8
|
import { z } from "zod";
|
|
9
|
+
import { Effect } from "effect";
|
|
9
10
|
//#region src/runner-command/finalize.ts
|
|
10
11
|
const runnerFinalizeOptionsSchema = z.object({
|
|
11
12
|
argoStatus: z.string().min(1),
|
|
@@ -20,26 +21,26 @@ const EXIT_PASS = 0;
|
|
|
20
21
|
const EXIT_FAIL = 1;
|
|
21
22
|
const EXIT_VALIDATION = 64;
|
|
22
23
|
const EXIT_STARTUP = 70;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
24
|
+
function runRunnerFinalize(rawOptions = {}) {
|
|
25
|
+
return runValidatedRunnerCommand(runnerFinalizeOptionsSchema, rawOptions, runRunnerFinalizeEffect);
|
|
26
|
+
}
|
|
27
|
+
function runRunnerFinalizeEffect(options, stderr) {
|
|
28
|
+
return Effect.gen(function* () {
|
|
29
|
+
const io = yield* RunnerCommandIoService;
|
|
30
|
+
const { compiled, context, payload, sink, worktreePath } = yield* createRunnerLifecycleContextEffect(options);
|
|
31
|
+
const lifecycle = yield* Effect.tryPromise({
|
|
32
|
+
try: () => finalizeWorkflowLifecycle({
|
|
33
|
+
buildResult: (outcome, nodes, failure) => runnerFinalizeRuntimeResult(context, outcome, nodes, failure),
|
|
34
|
+
runWorkflowHook: (event, failure) => dispatchHooks(context, event, failure)
|
|
35
|
+
}, {
|
|
36
|
+
completed: [],
|
|
37
|
+
outcome: options.argoStatus === "Succeeded" ? "PASS" : "FAIL"
|
|
38
|
+
}),
|
|
39
|
+
catch: (error) => error
|
|
39
40
|
});
|
|
40
41
|
if (lifecycle.result.outcome === "PASS") {
|
|
41
42
|
const graph = compileArgoExecutionGraph(compiled.plan);
|
|
42
|
-
|
|
43
|
+
yield* io.promoteFinalRef({
|
|
43
44
|
committer: compiled.config.runner_command.git.committer,
|
|
44
45
|
payload,
|
|
45
46
|
sourceNodeIds: graph.terminalNodeIds,
|
|
@@ -47,13 +48,14 @@ async function runRunnerFinalize(rawOptions = {}) {
|
|
|
47
48
|
});
|
|
48
49
|
}
|
|
49
50
|
sink.recordFinalResult(lifecycle.result.outcome, payload.workflow.id);
|
|
50
|
-
|
|
51
|
+
yield* flushAndReport(sink, stderr);
|
|
51
52
|
return lifecycle.result.outcome === "PASS" ? EXIT_PASS : EXIT_FAIL;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
53
|
+
}).pipe(Effect.catchAll((error) => Effect.sync(() => finalizeErrorExitCode(error, stderr))));
|
|
54
|
+
}
|
|
55
|
+
function finalizeErrorExitCode(error, stderr) {
|
|
56
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
57
|
+
stderr.write(`${message}\n`);
|
|
58
|
+
return error instanceof RunnerCommandPayloadValidationError || error instanceof z.ZodError ? EXIT_VALIDATION : EXIT_STARTUP;
|
|
57
59
|
}
|
|
58
60
|
function runnerFinalizeRuntimeResult(context, outcome, nodes, failure) {
|
|
59
61
|
return {
|
|
@@ -68,16 +70,5 @@ function runnerFinalizeRuntimeResult(context, outcome, nodes, failure) {
|
|
|
68
70
|
structuredOutputs: context.nodeStateStore.structuredOutputList()
|
|
69
71
|
};
|
|
70
72
|
}
|
|
71
|
-
function isOutputStream(value) {
|
|
72
|
-
return typeof value === "object" && value !== null && "write" in value && typeof value.write === "function";
|
|
73
|
-
}
|
|
74
|
-
async function flushAndReport(sink, stderr) {
|
|
75
|
-
try {
|
|
76
|
-
await sink.flush();
|
|
77
|
-
} catch (error) {
|
|
78
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
79
|
-
stderr.write(`runner event flush failed: ${message}\n`);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
73
|
//#endregion
|
|
83
74
|
export { runRunnerFinalize };
|
|
@@ -1,75 +1,142 @@
|
|
|
1
1
|
import { PIPELINE_CONFIG_PATH, PROFILES_CONFIG_PATH, RUNNERS_CONFIG_PATH } from "../config/defaults.js";
|
|
2
2
|
import { loadPipelineConfig, parsePipelineConfigParts } from "../config/load.js";
|
|
3
3
|
import "../config.js";
|
|
4
|
-
import { compileScheduleArtifact, parseScheduleArtifact } from "../planning/generate.js";
|
|
5
|
-
import { parseRunnerCommandPayload, resolveRunnerEventSinkAuthToken } from "../runner-command-contract.js";
|
|
6
|
-
import { prepareRunnerGitWorkspace } from "../run-state/git-refs.js";
|
|
7
|
-
import { createRunnerEventSink } from "../runner-event-sink.js";
|
|
8
4
|
import { initialNodeStateStore } from "../runtime/node-state-store.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
5
|
+
import { parseRunnerCommandPayload } from "../runner-command-contract.js";
|
|
6
|
+
import { RunnerCommandIoService, createRunnerCommandEventSink } from "../runtime/services/runner-command-io-service.js";
|
|
7
|
+
import { compileScheduleArtifact, parseScheduleArtifact } from "../planning/generate.js";
|
|
8
|
+
import { runnerTaskTextEffect } from "./run.js";
|
|
9
|
+
import { Effect } from "effect";
|
|
11
10
|
import { join } from "node:path";
|
|
12
11
|
//#region src/runner-command/lifecycle-context.ts
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
executor: () => ({
|
|
32
|
-
exitCode: 0,
|
|
33
|
-
stdout: ""
|
|
12
|
+
function createRunnerLifecycleContextEffect(options) {
|
|
13
|
+
return Effect.gen(function* () {
|
|
14
|
+
const payload = yield* readRunnerPayloadEffect(options.payloadFile);
|
|
15
|
+
const sink = createRunnerCommandEventSink({
|
|
16
|
+
fetch: options.fetch,
|
|
17
|
+
payload
|
|
18
|
+
});
|
|
19
|
+
const worktreePath = yield* prepareRunnerWorktreeEffect(payload, options.cwd);
|
|
20
|
+
const compiled = yield* compileRunnerScheduleEffect(yield* loadRunnerLifecycleConfigEffect(worktreePath), options.scheduleFile, worktreePath);
|
|
21
|
+
yield* assertWorkflowIdsMatch(payload.workflow.id, compiled.workflowId);
|
|
22
|
+
return {
|
|
23
|
+
compiled,
|
|
24
|
+
context: buildRunnerRuntimeContext({
|
|
25
|
+
compiled,
|
|
26
|
+
payload,
|
|
27
|
+
sink,
|
|
28
|
+
task: yield* runnerTaskTextEffect(payload.task, worktreePath),
|
|
29
|
+
worktreePath
|
|
34
30
|
}),
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
hookPolicy: {
|
|
38
|
-
allowCommandHooks: payload.hookPolicy?.allowCommandHooks ?? true,
|
|
39
|
-
allowUntrustedCommandHooks: payload.hookPolicy?.allowUntrustedCommandHooks ?? true,
|
|
40
|
-
env: payload.hookPolicy?.env ?? {},
|
|
41
|
-
envPassthrough: payload.hookPolicy?.envPassthrough ?? ["PATH"],
|
|
42
|
-
outputLimitBytes: payload.hookPolicy?.outputLimitBytes ?? 64 * 1024,
|
|
43
|
-
timeoutMs: payload.hookPolicy?.timeoutMs ?? 3e4
|
|
44
|
-
},
|
|
45
|
-
hookResults: /* @__PURE__ */ new Map(),
|
|
46
|
-
nodeStateStore: initialNodeStateStore(compiled.plan),
|
|
47
|
-
plan: compiled.plan,
|
|
48
|
-
reporter: (event) => sink.recordRuntimeEvent(event),
|
|
49
|
-
runId: payload.run.id,
|
|
50
|
-
task: runnerTaskText(payload.task, worktreePath),
|
|
51
|
-
workflowId: compiled.workflowId,
|
|
31
|
+
payload,
|
|
32
|
+
sink,
|
|
52
33
|
worktreePath
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
34
|
+
};
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function readRunnerPayloadEffect(payloadFile) {
|
|
38
|
+
return Effect.gen(function* () {
|
|
39
|
+
const payloadRaw = yield* (yield* RunnerCommandIoService).readText(payloadFile);
|
|
40
|
+
return yield* attemptSync(() => parseRunnerCommandPayload(payloadRaw));
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function prepareRunnerWorktreeEffect(payload, cwd) {
|
|
44
|
+
return Effect.gen(function* () {
|
|
45
|
+
return yield* (yield* RunnerCommandIoService).prepareRunnerGitWorkspace(payload, { cwd });
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function compileRunnerScheduleEffect(config, scheduleFile, worktreePath) {
|
|
49
|
+
return Effect.gen(function* () {
|
|
50
|
+
const scheduleRaw = yield* (yield* RunnerCommandIoService).readText(scheduleFile);
|
|
51
|
+
return yield* attemptSync(() => compileScheduleArtifact(config, parseScheduleArtifact(scheduleRaw, scheduleFile), worktreePath));
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function assertWorkflowIdsMatch(payloadWorkflowId, scheduleWorkflowId) {
|
|
55
|
+
if (payloadWorkflowId === scheduleWorkflowId) return Effect.void;
|
|
56
|
+
return Effect.fail(/* @__PURE__ */ new Error(`Runner payload workflow '${payloadWorkflowId}' does not match schedule workflow '${scheduleWorkflowId}'`));
|
|
57
|
+
}
|
|
58
|
+
function buildRunnerRuntimeContext(options) {
|
|
59
|
+
return {
|
|
60
|
+
agentInvocations: [],
|
|
61
|
+
config: options.compiled.config,
|
|
62
|
+
executor: () => ({
|
|
63
|
+
exitCode: 0,
|
|
64
|
+
stdout: ""
|
|
65
|
+
}),
|
|
66
|
+
gates: [],
|
|
67
|
+
hookFailures: [],
|
|
68
|
+
hookPolicy: runnerHookPolicy(options.payload),
|
|
69
|
+
hookResults: /* @__PURE__ */ new Map(),
|
|
70
|
+
nodeStateStore: initialNodeStateStore(options.compiled.plan),
|
|
71
|
+
plan: options.compiled.plan,
|
|
72
|
+
reporter: (event) => options.sink.recordRuntimeEvent(event),
|
|
73
|
+
runId: options.payload.run.id,
|
|
74
|
+
task: options.task,
|
|
75
|
+
workflowId: options.compiled.workflowId,
|
|
76
|
+
worktreePath: options.worktreePath
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function runnerHookPolicy(payload) {
|
|
80
|
+
const { allowCommandHooks = true, allowUntrustedCommandHooks = true, env = {}, envPassthrough = ["PATH"], outputLimitBytes = 64 * 1024, timeoutMs = 3e4 } = payload.hookPolicy ?? {};
|
|
81
|
+
return {
|
|
82
|
+
allowCommandHooks,
|
|
83
|
+
allowUntrustedCommandHooks,
|
|
84
|
+
env,
|
|
85
|
+
envPassthrough,
|
|
86
|
+
outputLimitBytes,
|
|
87
|
+
timeoutMs
|
|
57
88
|
};
|
|
58
89
|
}
|
|
59
|
-
function
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
90
|
+
function loadRunnerLifecycleConfigEffect(worktreePath) {
|
|
91
|
+
return Effect.gen(function* () {
|
|
92
|
+
const pipelinePath = join(worktreePath, PIPELINE_CONFIG_PATH);
|
|
93
|
+
const profilesPath = join(worktreePath, PROFILES_CONFIG_PATH);
|
|
94
|
+
const runnersPath = join(worktreePath, RUNNERS_CONFIG_PATH);
|
|
95
|
+
if (yield* hasRunnerLifecycleConfigParts([
|
|
96
|
+
pipelinePath,
|
|
97
|
+
profilesPath,
|
|
98
|
+
runnersPath
|
|
99
|
+
])) {
|
|
100
|
+
const parts = yield* readRunnerLifecycleConfigParts({
|
|
101
|
+
pipelinePath,
|
|
102
|
+
profilesPath,
|
|
103
|
+
runnersPath
|
|
104
|
+
});
|
|
105
|
+
return yield* attemptSync(() => parsePipelineConfigParts({
|
|
106
|
+
pipeline: parts.pipeline,
|
|
107
|
+
profiles: parts.profiles,
|
|
108
|
+
runners: parts.runners
|
|
109
|
+
}, worktreePath, {
|
|
110
|
+
pipeline: PIPELINE_CONFIG_PATH,
|
|
111
|
+
profiles: PROFILES_CONFIG_PATH,
|
|
112
|
+
runners: RUNNERS_CONFIG_PATH
|
|
113
|
+
}, { allowMissingLintFileReferences: true }));
|
|
114
|
+
}
|
|
115
|
+
return yield* attemptSync(() => loadPipelineConfig(worktreePath, { allowMissingLintFileReferences: true }));
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
function hasRunnerLifecycleConfigParts(paths) {
|
|
119
|
+
return Effect.gen(function* () {
|
|
120
|
+
const io = yield* RunnerCommandIoService;
|
|
121
|
+
for (const path of paths) if (!(yield* io.exists(path))) return false;
|
|
122
|
+
return true;
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
function readRunnerLifecycleConfigParts(paths) {
|
|
126
|
+
return Effect.gen(function* () {
|
|
127
|
+
const io = yield* RunnerCommandIoService;
|
|
128
|
+
return {
|
|
129
|
+
pipeline: yield* io.readText(paths.pipelinePath),
|
|
130
|
+
profiles: yield* io.readText(paths.profilesPath),
|
|
131
|
+
runners: yield* io.readText(paths.runnersPath)
|
|
132
|
+
};
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
function attemptSync(try_) {
|
|
136
|
+
return Effect.try({
|
|
137
|
+
try: try_,
|
|
138
|
+
catch: (error) => error
|
|
139
|
+
});
|
|
73
140
|
}
|
|
74
141
|
//#endregion
|
|
75
|
-
export {
|
|
142
|
+
export { createRunnerLifecycleContextEffect };
|
|
@@ -2,8 +2,10 @@ import { emitWorkflowPlanned, emitWorkflowStarted } from "../runtime/events/even
|
|
|
2
2
|
import { dispatchHooks } from "../runtime/hooks/hooks.js";
|
|
3
3
|
import "../runtime/hooks/index.js";
|
|
4
4
|
import { runWorkflowStartLifecycle } from "../runtime/workflow-lifecycle.js";
|
|
5
|
-
import {
|
|
5
|
+
import { flushAndReport, isOutputStream, runValidatedRunnerCommand } from "../runtime/services/runner-command-io-service.js";
|
|
6
|
+
import { createRunnerLifecycleContextEffect } from "./lifecycle-context.js";
|
|
6
7
|
import { z } from "zod";
|
|
8
|
+
import { Effect } from "effect";
|
|
7
9
|
//#region src/runner-command/lifecycle.ts
|
|
8
10
|
const runnerLifecycleOptionsSchema = z.object({
|
|
9
11
|
cwd: z.string().min(1).optional(),
|
|
@@ -17,39 +19,28 @@ const EXIT_PASS = 0;
|
|
|
17
19
|
const EXIT_FAIL = 1;
|
|
18
20
|
const EXIT_VALIDATION = 64;
|
|
19
21
|
const EXIT_STARTUP = 70;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
runWorkflowHook: (event) => dispatchHooks(context, event)
|
|
22
|
+
function runRunnerLifecycle(rawOptions = {}) {
|
|
23
|
+
return runValidatedRunnerCommand(runnerLifecycleOptionsSchema, rawOptions, runRunnerLifecycleEffect);
|
|
24
|
+
}
|
|
25
|
+
function runRunnerLifecycleEffect(options, stderr) {
|
|
26
|
+
return Effect.gen(function* () {
|
|
27
|
+
const { context, sink } = yield* createRunnerLifecycleContextEffect(options);
|
|
28
|
+
const failure = yield* Effect.tryPromise({
|
|
29
|
+
try: () => runWorkflowStartLifecycle({
|
|
30
|
+
emitWorkflowPlanned: () => emitWorkflowPlanned(context),
|
|
31
|
+
emitWorkflowStarted: () => emitWorkflowStarted(context),
|
|
32
|
+
runWorkflowHook: (event) => dispatchHooks(context, event)
|
|
33
|
+
}),
|
|
34
|
+
catch: (error) => error
|
|
34
35
|
});
|
|
35
|
-
|
|
36
|
+
yield* flushAndReport(sink, stderr);
|
|
36
37
|
return failure ? EXIT_FAIL : EXIT_PASS;
|
|
37
|
-
}
|
|
38
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
39
|
-
stderr.write(`${message}\n`);
|
|
40
|
-
return error instanceof z.ZodError ? EXIT_VALIDATION : EXIT_STARTUP;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
function isOutputStream(value) {
|
|
44
|
-
return typeof value === "object" && value !== null && "write" in value && typeof value.write === "function";
|
|
38
|
+
}).pipe(Effect.catchAll((error) => Effect.sync(() => lifecycleErrorExitCode(error, stderr))));
|
|
45
39
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
51
|
-
stderr.write(`runner event flush failed: ${message}\n`);
|
|
52
|
-
}
|
|
40
|
+
function lifecycleErrorExitCode(error, stderr) {
|
|
41
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
42
|
+
stderr.write(`${message}\n`);
|
|
43
|
+
return error instanceof z.ZodError ? EXIT_VALIDATION : EXIT_STARTUP;
|
|
53
44
|
}
|
|
54
45
|
//#endregion
|
|
55
46
|
export { runRunnerLifecycle };
|