@oisincoveney/pipeline 3.15.3 → 3.15.5
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/defaults/profiles.yaml +2 -2
- package/dist/argo-graph.js +1 -1
- package/dist/argo-submit.js +1 -1
- package/dist/argo-workflow.d.ts +2 -40
- package/dist/argo-workflow.js +53 -434
- package/dist/config/defaults.js +1 -1
- package/dist/config/schemas.d.ts +5 -5
- package/dist/config/schemas.js +1 -1
- package/dist/hooks.d.ts +1 -1
- package/dist/install-commands/host-selection.js +13 -0
- package/dist/install-commands/planner.js +299 -0
- package/dist/install-commands/result-format.js +6 -0
- package/dist/install-commands/writer.js +45 -0
- package/dist/install-commands.js +22 -268
- package/dist/loop/gh-checks.js +1 -1
- package/dist/moka-global-config.js +1 -1
- package/dist/moka-submit.d.ts +404 -38
- package/dist/moka-submit.js +14 -327
- package/dist/planning/generate.js +1 -1
- package/dist/remote/argo/model.d.ts +44 -0
- package/dist/remote/argo/model.js +160 -0
- package/dist/remote/argo/policy.js +77 -0
- package/dist/remote/argo/storage.js +110 -0
- package/dist/remote/argo/templates.js +82 -0
- package/dist/remote/submit/argo-submission.d.ts +26 -0
- package/dist/remote/submit/argo-submission.js +62 -0
- package/dist/remote/submit/compilation.d.ts +8 -0
- package/dist/remote/submit/compilation.js +106 -0
- package/dist/remote/submit/event-boundary.js +118 -0
- package/dist/remote/submit/hook-events.js +14 -0
- package/dist/remote/submit/io.d.ts +13 -0
- package/dist/remote/submit/io.js +66 -0
- package/dist/remote/submit/service.d.ts +10 -0
- package/dist/remote/submit/service.js +26 -0
- package/dist/runner-command/finalize.js +1 -1
- package/dist/runner-command/lifecycle.js +1 -1
- package/dist/runner-command/run.js +1 -1
- package/dist/runner-command/task-descriptor.js +1 -1
- package/dist/runner-command-contract.d.ts +2 -2
- package/dist/runner-command-contract.js +1 -1
- package/dist/runner-event-schema.d.ts +2 -2
- package/dist/runtime/agent-node/prompt-rendering.js +36 -3
- package/dist/runtime/events/events.js +244 -89
- package/dist/runtime/hooks/command-hook.js +87 -0
- package/dist/runtime/hooks/context.js +38 -0
- package/dist/runtime/hooks/events.js +131 -0
- package/dist/runtime/hooks/execution.js +29 -0
- package/dist/runtime/hooks/hooks.js +33 -365
- package/dist/runtime/hooks/invocation.js +49 -0
- package/dist/runtime/hooks/module-hook.js +52 -0
- package/dist/runtime/hooks/policy.js +36 -0
- package/dist/runtime/hooks/results.js +81 -0
- package/dist/runtime/services/backlog-service.js +2 -3
- package/dist/tickets/backlog-task-store.d.ts +2 -2
- package/dist/tickets/backlog-task-store.js +1 -1
- package/dist/tickets/ticket-graph-dto.js +1 -1
- package/dist/tickets/ticket-plan.js +1 -1
- package/package.json +1 -2
package/defaults/profiles.yaml
CHANGED
|
@@ -155,7 +155,7 @@ profiles:
|
|
|
155
155
|
scheduling_roles: [implementation]
|
|
156
156
|
description: Add focused failing tests for the requested behavior.
|
|
157
157
|
timeout_ms: 900000
|
|
158
|
-
instructions: { inline: "Add focused failing tests for the requested behavior only. Do not change production code. Only edit files matching test paths such as **/*.test.*, **/*.spec.*, **/*_test.*, **/__tests__/**, test/**, or tests/**.
|
|
158
|
+
instructions: { inline: "This scheduled node is already dispatched by Moka; do direct repository work inside the current workspace. Do not invoke `moka run`, `moka submit`, `$dispatch`, `$scope`, `$execute`, or any nested Moka/workflow supervisor from this node. Add focused failing tests for the requested behavior only. Do not change production code. Only edit files matching test paths such as **/*.test.*, **/*.spec.*, **/*_test.*, **/__tests__/**, test/**, or tests/**. Tool findings about lint, types, complexity, or dead code must be resolved at source; comments must not hide them. If a gate flags your test, restructure the test (e.g. move restricted imports into shared support/fixture helpers). Return only valid JSON with top-level changes and verification. Every changes entry must include summary, why, and files. Include risks, followups, and lessons when present. Do not use Markdown fences or prose outside the JSON object." }
|
|
159
159
|
skills: [test]
|
|
160
160
|
mcp_servers: [pipeline-gateway]
|
|
161
161
|
tools: [read, list, grep, glob, bash, edit, write]
|
|
@@ -170,7 +170,7 @@ profiles:
|
|
|
170
170
|
scheduling_roles: [implementation]
|
|
171
171
|
description: Implement production code until the failing tests pass.
|
|
172
172
|
timeout_ms: 900000
|
|
173
|
-
instructions: { inline: "Implement the smallest production change that
|
|
173
|
+
instructions: { inline: "This scheduled node is already dispatched by Moka; do direct repository work inside the current workspace. Do not invoke `moka run`, `moka submit`, `$dispatch`, `$scope`, `$execute`, or any nested Moka/workflow supervisor from this node. Implement the smallest production change that makes the failing tests pass. Tool findings about lint, types, complexity, or dead code must be resolved at source; comments must not hide them. Reduce complexity by extracting helpers, remove genuinely dead code, and migrate off deprecated APIs rather than hiding the warning. Return only valid JSON with top-level changes and verification. Every changes entry must include summary, why, and files. Include risks, followups, and lessons when present. Do not use Markdown fences or prose outside the JSON object." }
|
|
174
174
|
skills: [trace, test, fix, library-first-development]
|
|
175
175
|
mcp_servers: [pipeline-gateway]
|
|
176
176
|
tools: [read, list, grep, glob, bash, edit, write]
|
package/dist/argo-graph.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { uniqueStrings } from "./strings.js";
|
|
2
2
|
import { resolveExecutableDependencyIds } from "./planning/dependency-refs.js";
|
|
3
3
|
import { terminalDependencyItems } from "./planning/graph.js";
|
|
4
|
-
import { z } from "zod";
|
|
5
4
|
import { Data } from "effect";
|
|
5
|
+
import { z } from "zod";
|
|
6
6
|
//#region src/argo-graph.ts
|
|
7
7
|
const argoExecutableTaskSchema = z.object({
|
|
8
8
|
dependencies: z.array(z.string().min(1)),
|
package/dist/argo-submit.js
CHANGED
|
@@ -8,8 +8,8 @@ import { normalizeRunnerRepositoryForSubmit } from "./git-remote-url.js";
|
|
|
8
8
|
import { KubernetesArgoService, KubernetesArgoServiceLive } from "./runtime/services/kubernetes-argo-service.js";
|
|
9
9
|
import { workflowSubmitResultSchema } from "./workflow-submit-contract.js";
|
|
10
10
|
import { stringify } from "yaml";
|
|
11
|
-
import { z } from "zod";
|
|
12
11
|
import { Effect } from "effect";
|
|
12
|
+
import { z } from "zod";
|
|
13
13
|
import { randomBytes } from "node:crypto";
|
|
14
14
|
//#region src/argo-submit.ts
|
|
15
15
|
const scheduleIdSchema = z.string().regex(/^[a-z][a-z0-9-]*$/);
|
package/dist/argo-workflow.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { WorkflowExecutionPlan } from "./planning/compile.js";
|
|
2
|
+
import { buildRunnerArgoWorkflowOptionsSchema } from "./remote/argo/model.js";
|
|
2
3
|
import { z } from "zod";
|
|
3
4
|
|
|
4
5
|
//#region src/argo-workflow.d.ts
|
|
@@ -59,7 +60,6 @@ declare const runnerArgoWorkflowManifestSchema: z.ZodObject<{
|
|
|
59
60
|
}, z.core.$strict>>;
|
|
60
61
|
dag: z.ZodOptional<z.ZodObject<{
|
|
61
62
|
tasks: z.ZodArray<z.ZodObject<{
|
|
62
|
-
dependencies: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
63
63
|
arguments: z.ZodOptional<z.ZodObject<{
|
|
64
64
|
artifacts: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
65
65
|
from: z.ZodOptional<z.ZodString>;
|
|
@@ -67,6 +67,7 @@ declare const runnerArgoWorkflowManifestSchema: z.ZodObject<{
|
|
|
67
67
|
path: z.ZodOptional<z.ZodString>;
|
|
68
68
|
}, z.core.$strict>>>;
|
|
69
69
|
}, z.core.$strict>>;
|
|
70
|
+
dependencies: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
70
71
|
name: z.ZodString;
|
|
71
72
|
template: z.ZodString;
|
|
72
73
|
}, z.core.$strict>>;
|
|
@@ -127,45 +128,6 @@ declare const runnerArgoWorkflowManifestSchema: z.ZodObject<{
|
|
|
127
128
|
}, z.core.$strict>>;
|
|
128
129
|
}, z.core.$strict>;
|
|
129
130
|
}, z.core.$strict>;
|
|
130
|
-
declare const buildRunnerArgoWorkflowOptionsSchema: z.ZodObject<{
|
|
131
|
-
activeDeadlineSeconds: z.ZodOptional<z.ZodNumber>;
|
|
132
|
-
eventAuthSecretKey: z.ZodOptional<z.ZodString>;
|
|
133
|
-
eventAuthSecretName: z.ZodOptional<z.ZodString>;
|
|
134
|
-
generateName: z.ZodOptional<z.ZodString>;
|
|
135
|
-
gitCredentialsSecretName: z.ZodOptional<z.ZodString>;
|
|
136
|
-
githubAuthSecretName: z.ZodOptional<z.ZodString>;
|
|
137
|
-
annotations: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodOptional<z.ZodString>>>;
|
|
138
|
-
image: z.ZodDefault<z.ZodString>;
|
|
139
|
-
imagePullPolicy: z.ZodDefault<z.ZodEnum<{
|
|
140
|
-
Always: "Always";
|
|
141
|
-
IfNotPresent: "IfNotPresent";
|
|
142
|
-
Never: "Never";
|
|
143
|
-
}>>;
|
|
144
|
-
imagePullSecretName: z.ZodOptional<z.ZodString>;
|
|
145
|
-
labels: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodOptional<z.ZodString>>>;
|
|
146
|
-
name: z.ZodOptional<z.ZodString>;
|
|
147
|
-
namespace: z.ZodString;
|
|
148
|
-
brokerAuth: z.ZodObject<{
|
|
149
|
-
secretKey: z.ZodDefault<z.ZodString>;
|
|
150
|
-
secretName: z.ZodString;
|
|
151
|
-
url: z.ZodDefault<z.ZodString>;
|
|
152
|
-
}, z.core.$strict>;
|
|
153
|
-
payloadConfigMapKey: z.ZodDefault<z.ZodString>;
|
|
154
|
-
payloadConfigMapName: z.ZodString;
|
|
155
|
-
resources: z.ZodOptional<z.ZodObject<{
|
|
156
|
-
limits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
157
|
-
requests: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
158
|
-
}, z.core.$strict>>;
|
|
159
|
-
scheduleConfigMapKey: z.ZodDefault<z.ZodString>;
|
|
160
|
-
scheduleConfigMapName: z.ZodString;
|
|
161
|
-
serviceAccountName: z.ZodDefault<z.ZodString>;
|
|
162
|
-
taskDescriptorConfigMapName: z.ZodString;
|
|
163
|
-
ttlStrategy: z.ZodOptional<z.ZodObject<{
|
|
164
|
-
secondsAfterCompletion: z.ZodOptional<z.ZodNumber>;
|
|
165
|
-
secondsAfterFailure: z.ZodOptional<z.ZodNumber>;
|
|
166
|
-
secondsAfterSuccess: z.ZodOptional<z.ZodNumber>;
|
|
167
|
-
}, z.core.$strict>>;
|
|
168
|
-
}, z.core.$strict>;
|
|
169
131
|
type ArgoWorkflowManifest = z.infer<typeof runnerArgoWorkflowManifestSchema>;
|
|
170
132
|
type BuildRunnerArgoWorkflowOptions = z.input<typeof buildRunnerArgoWorkflowOptionsSchema> & {
|
|
171
133
|
plan: WorkflowExecutionPlan;
|
package/dist/argo-workflow.js
CHANGED
|
@@ -1,457 +1,76 @@
|
|
|
1
1
|
import { compileArgoExecutionGraph } from "./argo-graph.js";
|
|
2
|
-
import {
|
|
2
|
+
import { RUNNER_WORKFLOW_ENTRYPOINT, RUNNER_WORKFLOW_START_TASK } from "./remote/argo/policy.js";
|
|
3
|
+
import { buildRunnerArgoWorkflowOptionsSchema, createRunnerArgoWorkflowManifestSchema } from "./remote/argo/model.js";
|
|
4
|
+
import { runnerWorkflowStorage } from "./remote/argo/storage.js";
|
|
5
|
+
import { runnerCommandTemplate, runnerFinalizerTemplate, runnerLifecycleTemplate } from "./remote/argo/templates.js";
|
|
3
6
|
import { stringify } from "yaml";
|
|
4
|
-
import { z } from "zod";
|
|
5
7
|
//#region src/argo-workflow.ts
|
|
6
|
-
const
|
|
7
|
-
const ARGO_WORKFLOW_KIND = "Workflow";
|
|
8
|
-
const RUNNER_WORKFLOW_IMAGE = "ghcr.io/oisin-ee/pipeline-runner:latest";
|
|
9
|
-
const RUNNER_WORKFLOW_SERVICE_ACCOUNT = "pipeline-runner";
|
|
10
|
-
const RUNNER_WORKFLOW_ENTRYPOINT = "pipeline";
|
|
11
|
-
const RUNNER_WORKFLOW_START_TASK = "workflow-start";
|
|
12
|
-
const RUNNER_WORKFLOW_PAYLOAD_PATH = "/etc/pipeline/payload.json";
|
|
13
|
-
const RUNNER_WORKFLOW_SCHEDULE_PATH = "/etc/pipeline/schedule.yaml";
|
|
14
|
-
const RUNNER_GIT_CREDENTIALS_PATH = "/etc/pipeline/git-credentials";
|
|
15
|
-
const RUNNER_RETRY_STRATEGY = {
|
|
16
|
-
expression: "lastRetry.status == 'Error' || (lastRetry.exitCode != '0' && lastRetry.exitCode != '1')",
|
|
17
|
-
limit: "3",
|
|
18
|
-
retryPolicy: "Always"
|
|
19
|
-
};
|
|
20
|
-
const RUNNER_OPENCODE_ENV = [
|
|
21
|
-
{
|
|
22
|
-
name: "CODEX_AUTH_PER_PROJECT_ACCOUNTS",
|
|
23
|
-
value: "0"
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
name: "PIPELINE_AGENT_TIMEOUT_MS",
|
|
27
|
-
value: "600000"
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
name: "PIPELINE_AGENT_IDLE_TIMEOUT_MS",
|
|
31
|
-
value: "180000"
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
name: "PIPELINE_DISABLED_MODELS",
|
|
35
|
-
value: "opencode-go/qwen3.7-max"
|
|
36
|
-
}
|
|
37
|
-
];
|
|
38
|
-
const DEFAULT_RUNNER_RESOURCES = {
|
|
39
|
-
limits: {
|
|
40
|
-
cpu: "4",
|
|
41
|
-
memory: "12Gi"
|
|
42
|
-
},
|
|
43
|
-
requests: {
|
|
44
|
-
cpu: "1",
|
|
45
|
-
memory: "5Gi"
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
const DEFAULT_RUNNER_DEADLINE_SECONDS = 5400;
|
|
49
|
-
const kubernetesNameSchema = z.string().min(1);
|
|
50
|
-
const labelValueSchema = z.string().min(1);
|
|
51
|
-
const stringMapSchema = z.record(z.string().min(1), z.string().min(1));
|
|
52
|
-
const configMapVolumeSchema = z.object({
|
|
53
|
-
items: z.array(z.object({
|
|
54
|
-
key: z.string().min(1),
|
|
55
|
-
path: z.string().min(1)
|
|
56
|
-
}).strict()),
|
|
57
|
-
name: kubernetesNameSchema
|
|
58
|
-
}).strict();
|
|
59
|
-
const secretVolumeSchema = z.object({
|
|
60
|
-
defaultMode: z.number().int().positive().optional(),
|
|
61
|
-
items: z.array(z.object({
|
|
62
|
-
key: z.string().min(1),
|
|
63
|
-
path: z.string().min(1)
|
|
64
|
-
}).strict()).optional(),
|
|
65
|
-
optional: z.boolean().optional(),
|
|
66
|
-
secretName: kubernetesNameSchema
|
|
67
|
-
}).strict();
|
|
68
|
-
const argoWorkflowVolumeSchema = z.object({
|
|
69
|
-
configMap: configMapVolumeSchema.optional(),
|
|
70
|
-
name: kubernetesNameSchema,
|
|
71
|
-
secret: secretVolumeSchema.optional()
|
|
72
|
-
}).strict().refine((volume) => volume.configMap !== void 0 || volume.secret !== void 0, { message: "Workflow volumes must declare configMap or secret" });
|
|
73
|
-
const argoWorkflowVolumeMountSchema = z.object({
|
|
74
|
-
mountPath: z.string().min(1),
|
|
75
|
-
name: kubernetesNameSchema,
|
|
76
|
-
readOnly: z.boolean().optional(),
|
|
77
|
-
subPath: z.string().min(1).optional()
|
|
78
|
-
}).strict();
|
|
79
|
-
const argoWorkflowResourceRequirementsSchema = z.object({
|
|
80
|
-
limits: stringMapSchema.optional(),
|
|
81
|
-
requests: stringMapSchema.optional()
|
|
82
|
-
}).strict();
|
|
83
|
-
const argoWorkflowArtifactSchema = z.object({
|
|
84
|
-
from: z.string().min(1).optional(),
|
|
85
|
-
name: z.string().min(1),
|
|
86
|
-
path: z.string().min(1).optional()
|
|
87
|
-
}).strict();
|
|
88
|
-
const argoWorkflowRetryStrategySchema = z.object({
|
|
89
|
-
expression: z.string().min(1).optional(),
|
|
90
|
-
limit: z.string().min(1).optional(),
|
|
91
|
-
retryPolicy: z.enum([
|
|
92
|
-
"Always",
|
|
93
|
-
"OnError",
|
|
94
|
-
"OnFailure",
|
|
95
|
-
"OnTransientError"
|
|
96
|
-
])
|
|
97
|
-
}).strict();
|
|
98
|
-
const argoWorkflowEnvVarSchema = z.union([z.object({
|
|
99
|
-
name: z.string().min(1),
|
|
100
|
-
value: z.string()
|
|
101
|
-
}).strict(), z.object({
|
|
102
|
-
name: z.string().min(1),
|
|
103
|
-
valueFrom: z.object({ secretKeyRef: z.object({
|
|
104
|
-
key: z.string().min(1),
|
|
105
|
-
name: kubernetesNameSchema
|
|
106
|
-
}).strict() }).strict()
|
|
107
|
-
}).strict()]);
|
|
108
|
-
const argoWorkflowTemplateSchema = z.object({
|
|
109
|
-
container: z.object({
|
|
110
|
-
args: z.array(z.string().min(1)).min(1),
|
|
111
|
-
command: z.array(z.string().min(1)).min(1).optional(),
|
|
112
|
-
env: z.array(argoWorkflowEnvVarSchema).optional(),
|
|
113
|
-
image: z.string().min(1),
|
|
114
|
-
imagePullPolicy: z.enum([
|
|
115
|
-
"Always",
|
|
116
|
-
"IfNotPresent",
|
|
117
|
-
"Never"
|
|
118
|
-
]),
|
|
119
|
-
name: z.string().min(1).optional(),
|
|
120
|
-
resources: argoWorkflowResourceRequirementsSchema.optional(),
|
|
121
|
-
volumeMounts: z.array(argoWorkflowVolumeMountSchema)
|
|
122
|
-
}).strict().optional(),
|
|
123
|
-
dag: z.object({ tasks: z.array(z.object({
|
|
124
|
-
dependencies: z.array(z.string().min(1)).optional(),
|
|
125
|
-
arguments: z.object({ artifacts: z.array(argoWorkflowArtifactSchema).optional() }).strict().optional(),
|
|
126
|
-
name: z.string().min(1),
|
|
127
|
-
template: z.string().min(1)
|
|
128
|
-
}).strict()).min(1) }).strict().optional(),
|
|
129
|
-
inputs: z.object({
|
|
130
|
-
artifacts: z.array(argoWorkflowArtifactSchema).optional(),
|
|
131
|
-
parameters: z.array(z.object({ name: z.string().min(1) }).strict()).optional()
|
|
132
|
-
}).strict().optional(),
|
|
133
|
-
outputs: z.object({ artifacts: z.array(argoWorkflowArtifactSchema) }).strict().optional(),
|
|
134
|
-
activeDeadlineSeconds: z.number().int().positive().optional(),
|
|
135
|
-
name: z.string().min(1),
|
|
136
|
-
retryStrategy: argoWorkflowRetryStrategySchema.optional()
|
|
137
|
-
}).strict().refine((template) => template.container !== void 0 || template.dag !== void 0, { message: "Workflow templates must declare container or dag" });
|
|
138
|
-
const runnerArgoWorkflowManifestSchema = z.object({
|
|
139
|
-
apiVersion: z.literal(ARGO_WORKFLOW_API_VERSION),
|
|
140
|
-
kind: z.literal(ARGO_WORKFLOW_KIND),
|
|
141
|
-
metadata: z.object({
|
|
142
|
-
annotations: z.record(z.string().min(1), z.string().min(1)).optional(),
|
|
143
|
-
generateName: z.string().min(1).optional(),
|
|
144
|
-
labels: z.record(z.string().min(1), labelValueSchema).optional(),
|
|
145
|
-
name: z.string().min(1).optional(),
|
|
146
|
-
namespace: kubernetesNameSchema
|
|
147
|
-
}).strict().refine((metadata) => metadata.name !== void 0 || metadata.generateName !== void 0, { message: "Workflow metadata must declare name or generateName" }),
|
|
148
|
-
spec: z.object({
|
|
149
|
-
activeDeadlineSeconds: z.number().int().positive().optional(),
|
|
150
|
-
entrypoint: z.literal(RUNNER_WORKFLOW_ENTRYPOINT),
|
|
151
|
-
imagePullSecrets: z.array(z.object({ name: kubernetesNameSchema }).strict()).optional(),
|
|
152
|
-
podMetadata: z.object({ labels: z.record(z.string().min(1), labelValueSchema).optional() }).strict().optional(),
|
|
153
|
-
serviceAccountName: kubernetesNameSchema,
|
|
154
|
-
onExit: z.string().min(1).optional(),
|
|
155
|
-
templates: z.array(argoWorkflowTemplateSchema).min(2),
|
|
156
|
-
ttlStrategy: z.object({
|
|
157
|
-
secondsAfterCompletion: z.number().int().positive().optional(),
|
|
158
|
-
secondsAfterFailure: z.number().int().positive().optional(),
|
|
159
|
-
secondsAfterSuccess: z.number().int().positive().optional()
|
|
160
|
-
}).strict().optional(),
|
|
161
|
-
volumes: z.array(argoWorkflowVolumeSchema).min(1)
|
|
162
|
-
}).strict()
|
|
163
|
-
}).strict();
|
|
164
|
-
const buildRunnerArgoWorkflowOptionsSchema = z.object({
|
|
165
|
-
activeDeadlineSeconds: z.number().int().positive().optional(),
|
|
166
|
-
eventAuthSecretKey: z.string().min(1).optional(),
|
|
167
|
-
eventAuthSecretName: kubernetesNameSchema.optional(),
|
|
168
|
-
generateName: z.string().min(1).optional(),
|
|
169
|
-
gitCredentialsSecretName: kubernetesNameSchema.optional(),
|
|
170
|
-
githubAuthSecretName: kubernetesNameSchema.optional(),
|
|
171
|
-
annotations: z.record(z.string().min(1), z.string().min(1).optional()).default({}),
|
|
172
|
-
image: z.string().min(1).default(RUNNER_WORKFLOW_IMAGE),
|
|
173
|
-
imagePullPolicy: z.enum([
|
|
174
|
-
"Always",
|
|
175
|
-
"IfNotPresent",
|
|
176
|
-
"Never"
|
|
177
|
-
]).default("Always"),
|
|
178
|
-
imagePullSecretName: kubernetesNameSchema.optional(),
|
|
179
|
-
labels: z.record(z.string().min(1), z.string().min(1).optional()).default({}),
|
|
180
|
-
name: z.string().min(1).optional(),
|
|
181
|
-
namespace: kubernetesNameSchema,
|
|
182
|
-
brokerAuth: z.object({
|
|
183
|
-
secretKey: z.string().min(1).default("api-key"),
|
|
184
|
-
secretName: kubernetesNameSchema,
|
|
185
|
-
url: z.string().min(1).default("https://cliproxy.momokaya.ee")
|
|
186
|
-
}).strict(),
|
|
187
|
-
payloadConfigMapKey: z.string().min(1).default("payload.json"),
|
|
188
|
-
payloadConfigMapName: kubernetesNameSchema,
|
|
189
|
-
resources: argoWorkflowResourceRequirementsSchema.optional(),
|
|
190
|
-
scheduleConfigMapKey: z.string().min(1).default("schedule.yaml"),
|
|
191
|
-
scheduleConfigMapName: kubernetesNameSchema,
|
|
192
|
-
serviceAccountName: kubernetesNameSchema.default(RUNNER_WORKFLOW_SERVICE_ACCOUNT),
|
|
193
|
-
taskDescriptorConfigMapName: kubernetesNameSchema,
|
|
194
|
-
ttlStrategy: z.object({
|
|
195
|
-
secondsAfterCompletion: z.number().int().positive().optional(),
|
|
196
|
-
secondsAfterFailure: z.number().int().positive().optional(),
|
|
197
|
-
secondsAfterSuccess: z.number().int().positive().optional()
|
|
198
|
-
}).strict().optional()
|
|
199
|
-
}).strict().refine((options) => options.name !== void 0 || options.generateName !== void 0, { message: "Runner Workflow options must declare name or generateName" });
|
|
8
|
+
const runnerArgoWorkflowManifestSchema = createRunnerArgoWorkflowManifestSchema();
|
|
200
9
|
function buildRunnerArgoWorkflowManifest(rawOptions) {
|
|
201
|
-
const
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
plan
|
|
205
|
-
};
|
|
206
|
-
const graph = compileArgoExecutionGraph(plan);
|
|
207
|
-
const { volumeMounts, volumes } = runnerWorkflowStorage(options, graph.tasks);
|
|
10
|
+
const options = parsedBuildOptions(rawOptions);
|
|
11
|
+
const graph = compileArgoExecutionGraph(options.plan);
|
|
12
|
+
const storage = runnerWorkflowStorage(options, graph.tasks);
|
|
208
13
|
return runnerArgoWorkflowManifestSchema.parse({
|
|
209
|
-
apiVersion:
|
|
210
|
-
kind:
|
|
211
|
-
metadata:
|
|
212
|
-
|
|
213
|
-
...options.name ? { name: options.name } : {},
|
|
214
|
-
...options.generateName ? { generateName: options.generateName } : {},
|
|
215
|
-
labels: compactRecord({
|
|
216
|
-
"pipeline.oisin.dev/source": "argo-workflow",
|
|
217
|
-
"pipeline.oisin.dev/workflow": plan.workflowId,
|
|
218
|
-
...options.labels
|
|
219
|
-
}),
|
|
220
|
-
namespace: options.namespace
|
|
221
|
-
},
|
|
222
|
-
spec: {
|
|
223
|
-
...options.activeDeadlineSeconds ? { activeDeadlineSeconds: options.activeDeadlineSeconds } : {},
|
|
224
|
-
entrypoint: RUNNER_WORKFLOW_ENTRYPOINT,
|
|
225
|
-
...options.imagePullSecretName ? { imagePullSecrets: [{ name: options.imagePullSecretName }] } : {},
|
|
226
|
-
onExit: "pipeline-finalizer",
|
|
227
|
-
serviceAccountName: options.serviceAccountName,
|
|
228
|
-
templates: [
|
|
229
|
-
{
|
|
230
|
-
dag: { tasks: [{
|
|
231
|
-
name: RUNNER_WORKFLOW_START_TASK,
|
|
232
|
-
template: RUNNER_WORKFLOW_START_TASK
|
|
233
|
-
}, ...graph.tasks.map((task) => ({
|
|
234
|
-
dependencies: [RUNNER_WORKFLOW_START_TASK, ...task.dependencies],
|
|
235
|
-
name: task.taskName,
|
|
236
|
-
template: task.templateName
|
|
237
|
-
}))] },
|
|
238
|
-
name: RUNNER_WORKFLOW_ENTRYPOINT
|
|
239
|
-
},
|
|
240
|
-
runnerLifecycleTemplate(options, volumeMounts),
|
|
241
|
-
...graph.tasks.map((task) => runnerCommandTemplate(task, options, volumeMounts)),
|
|
242
|
-
runnerFinalizerTemplate(options, volumeMounts)
|
|
243
|
-
],
|
|
244
|
-
...options.ttlStrategy ? { ttlStrategy: options.ttlStrategy } : {},
|
|
245
|
-
volumes
|
|
246
|
-
}
|
|
14
|
+
apiVersion: "argoproj.io/v1alpha1",
|
|
15
|
+
kind: "Workflow",
|
|
16
|
+
metadata: workflowMetadata(options),
|
|
17
|
+
spec: workflowSpec(options, graph.tasks, storage)
|
|
247
18
|
});
|
|
248
19
|
}
|
|
249
20
|
function stringifyRunnerArgoWorkflow(workflow) {
|
|
250
21
|
return stringify(runnerArgoWorkflowManifestSchema.parse(workflow));
|
|
251
22
|
}
|
|
252
|
-
function
|
|
253
|
-
const
|
|
254
|
-
{
|
|
255
|
-
configMap: {
|
|
256
|
-
items: [{
|
|
257
|
-
key: options.payloadConfigMapKey,
|
|
258
|
-
path: "payload.json"
|
|
259
|
-
}],
|
|
260
|
-
name: options.payloadConfigMapName
|
|
261
|
-
},
|
|
262
|
-
name: "runner-payload"
|
|
263
|
-
},
|
|
264
|
-
{
|
|
265
|
-
configMap: {
|
|
266
|
-
items: [{
|
|
267
|
-
key: options.scheduleConfigMapKey,
|
|
268
|
-
path: "schedule.yaml"
|
|
269
|
-
}],
|
|
270
|
-
name: options.scheduleConfigMapName
|
|
271
|
-
},
|
|
272
|
-
name: "runner-schedule"
|
|
273
|
-
},
|
|
274
|
-
{
|
|
275
|
-
configMap: {
|
|
276
|
-
items: tasks.map((task) => ({
|
|
277
|
-
key: `${task.taskName}.json`,
|
|
278
|
-
path: `${task.taskName}.json`
|
|
279
|
-
})),
|
|
280
|
-
name: options.taskDescriptorConfigMapName
|
|
281
|
-
},
|
|
282
|
-
name: "runner-task-descriptor"
|
|
283
|
-
}
|
|
284
|
-
];
|
|
285
|
-
const volumeMounts = [{
|
|
286
|
-
mountPath: RUNNER_WORKFLOW_PAYLOAD_PATH,
|
|
287
|
-
name: "runner-payload",
|
|
288
|
-
readOnly: true,
|
|
289
|
-
subPath: "payload.json"
|
|
290
|
-
}, {
|
|
291
|
-
mountPath: RUNNER_WORKFLOW_SCHEDULE_PATH,
|
|
292
|
-
name: "runner-schedule",
|
|
293
|
-
readOnly: true,
|
|
294
|
-
subPath: "schedule.yaml"
|
|
295
|
-
}];
|
|
296
|
-
if (options.eventAuthSecretName) {
|
|
297
|
-
volumes.push({
|
|
298
|
-
name: "runner-event-auth",
|
|
299
|
-
secret: {
|
|
300
|
-
...options.eventAuthSecretKey ? { items: [{
|
|
301
|
-
key: options.eventAuthSecretKey,
|
|
302
|
-
path: options.eventAuthSecretKey
|
|
303
|
-
}] } : {},
|
|
304
|
-
secretName: options.eventAuthSecretName
|
|
305
|
-
}
|
|
306
|
-
});
|
|
307
|
-
volumeMounts.push({
|
|
308
|
-
mountPath: "/etc/pipeline/event-auth",
|
|
309
|
-
name: "runner-event-auth",
|
|
310
|
-
readOnly: true
|
|
311
|
-
});
|
|
312
|
-
}
|
|
313
|
-
if (options.gitCredentialsSecretName) {
|
|
314
|
-
volumes.push({
|
|
315
|
-
name: "runner-git-credentials",
|
|
316
|
-
secret: {
|
|
317
|
-
defaultMode: 256,
|
|
318
|
-
secretName: options.gitCredentialsSecretName
|
|
319
|
-
}
|
|
320
|
-
});
|
|
321
|
-
volumeMounts.push({
|
|
322
|
-
mountPath: RUNNER_GIT_CREDENTIALS_PATH,
|
|
323
|
-
name: "runner-git-credentials",
|
|
324
|
-
readOnly: true
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
if (options.githubAuthSecretName) {
|
|
328
|
-
volumes.push({
|
|
329
|
-
name: "github-auth",
|
|
330
|
-
secret: {
|
|
331
|
-
items: [{
|
|
332
|
-
key: "hosts.yml",
|
|
333
|
-
path: "hosts.yml"
|
|
334
|
-
}],
|
|
335
|
-
secretName: options.githubAuthSecretName
|
|
336
|
-
}
|
|
337
|
-
});
|
|
338
|
-
volumeMounts.push({
|
|
339
|
-
mountPath: "/root/.config/gh/hosts.yml",
|
|
340
|
-
name: "github-auth",
|
|
341
|
-
readOnly: true,
|
|
342
|
-
subPath: "hosts.yml"
|
|
343
|
-
});
|
|
344
|
-
}
|
|
23
|
+
function parsedBuildOptions(rawOptions) {
|
|
24
|
+
const { plan, ...schemaOptions } = rawOptions;
|
|
345
25
|
return {
|
|
346
|
-
|
|
347
|
-
|
|
26
|
+
...buildRunnerArgoWorkflowOptionsSchema.parse(schemaOptions),
|
|
27
|
+
plan
|
|
348
28
|
};
|
|
349
29
|
}
|
|
350
|
-
|
|
351
|
-
* The runner container env: static opencode/agent tuning plus BROKER_URL
|
|
352
|
-
* (literal) and BROKER_API_KEY (sourced from the broker secret key, never
|
|
353
|
-
* inlined into the manifest).
|
|
354
|
-
*/
|
|
355
|
-
function runnerContainerEnv(options) {
|
|
356
|
-
return [
|
|
357
|
-
...RUNNER_OPENCODE_ENV,
|
|
358
|
-
{
|
|
359
|
-
name: "BROKER_URL",
|
|
360
|
-
value: options.brokerAuth.url
|
|
361
|
-
},
|
|
362
|
-
{
|
|
363
|
-
name: "PIPELINE_BROKER_SECRET_NAME",
|
|
364
|
-
value: options.brokerAuth.secretName
|
|
365
|
-
},
|
|
366
|
-
{
|
|
367
|
-
name: "PIPELINE_BROKER_SECRET_KEY",
|
|
368
|
-
value: options.brokerAuth.secretKey
|
|
369
|
-
},
|
|
370
|
-
{
|
|
371
|
-
name: "BROKER_API_KEY",
|
|
372
|
-
valueFrom: { secretKeyRef: {
|
|
373
|
-
key: options.brokerAuth.secretKey,
|
|
374
|
-
name: options.brokerAuth.secretName
|
|
375
|
-
} }
|
|
376
|
-
}
|
|
377
|
-
];
|
|
378
|
-
}
|
|
379
|
-
function runnerLifecycleTemplate(options, volumeMounts) {
|
|
30
|
+
function workflowMetadata(options) {
|
|
380
31
|
return {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
],
|
|
391
|
-
command: ["moka"],
|
|
392
|
-
env: runnerContainerEnv(options),
|
|
393
|
-
image: options.image,
|
|
394
|
-
imagePullPolicy: options.imagePullPolicy,
|
|
395
|
-
name: "runner",
|
|
396
|
-
resources: options.resources ?? DEFAULT_RUNNER_RESOURCES,
|
|
397
|
-
volumeMounts
|
|
398
|
-
},
|
|
399
|
-
name: RUNNER_WORKFLOW_START_TASK,
|
|
400
|
-
retryStrategy: { ...RUNNER_RETRY_STRATEGY },
|
|
401
|
-
activeDeadlineSeconds: DEFAULT_RUNNER_DEADLINE_SECONDS
|
|
32
|
+
annotations: compactRecord(options.annotations),
|
|
33
|
+
...options.name ? { name: options.name } : {},
|
|
34
|
+
...options.generateName ? { generateName: options.generateName } : {},
|
|
35
|
+
labels: compactRecord({
|
|
36
|
+
"pipeline.oisin.dev/source": "argo-workflow",
|
|
37
|
+
"pipeline.oisin.dev/workflow": options.plan.workflowId,
|
|
38
|
+
...options.labels
|
|
39
|
+
}),
|
|
40
|
+
namespace: options.namespace
|
|
402
41
|
};
|
|
403
42
|
}
|
|
404
|
-
function
|
|
405
|
-
const taskVolumeMount = {
|
|
406
|
-
mountPath: DEFAULT_RUNNER_TASK_DESCRIPTOR_PATH,
|
|
407
|
-
name: "runner-task-descriptor",
|
|
408
|
-
readOnly: true,
|
|
409
|
-
subPath: `${task.taskName}.json`
|
|
410
|
-
};
|
|
43
|
+
function workflowSpec(options, tasks, storage) {
|
|
411
44
|
return {
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
command: ["moka"],
|
|
421
|
-
env: runnerContainerEnv(options),
|
|
422
|
-
image: options.image,
|
|
423
|
-
imagePullPolicy: options.imagePullPolicy,
|
|
424
|
-
name: "runner",
|
|
425
|
-
resources: options.resources ?? DEFAULT_RUNNER_RESOURCES,
|
|
426
|
-
volumeMounts: [...volumeMounts, taskVolumeMount]
|
|
427
|
-
},
|
|
428
|
-
name: task.templateName,
|
|
429
|
-
retryStrategy: { ...RUNNER_RETRY_STRATEGY },
|
|
430
|
-
activeDeadlineSeconds: DEFAULT_RUNNER_DEADLINE_SECONDS
|
|
45
|
+
...options.activeDeadlineSeconds ? { activeDeadlineSeconds: options.activeDeadlineSeconds } : {},
|
|
46
|
+
entrypoint: RUNNER_WORKFLOW_ENTRYPOINT,
|
|
47
|
+
...options.imagePullSecretName ? { imagePullSecrets: [{ name: options.imagePullSecretName }] } : {},
|
|
48
|
+
serviceAccountName: options.serviceAccountName,
|
|
49
|
+
onExit: "pipeline-finalizer",
|
|
50
|
+
templates: workflowTemplates(options, tasks, storage.volumeMounts),
|
|
51
|
+
...options.ttlStrategy ? { ttlStrategy: options.ttlStrategy } : {},
|
|
52
|
+
volumes: storage.volumes
|
|
431
53
|
};
|
|
432
54
|
}
|
|
433
|
-
function
|
|
55
|
+
function workflowTemplates(options, tasks, volumeMounts) {
|
|
56
|
+
return [
|
|
57
|
+
workflowDagTemplate(tasks),
|
|
58
|
+
runnerLifecycleTemplate(options, volumeMounts),
|
|
59
|
+
...tasks.map((task) => runnerCommandTemplate(task, options, volumeMounts)),
|
|
60
|
+
runnerFinalizerTemplate(options, volumeMounts)
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
function workflowDagTemplate(tasks) {
|
|
434
64
|
return {
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
],
|
|
445
|
-
command: ["moka"],
|
|
446
|
-
env: runnerContainerEnv(options),
|
|
447
|
-
image: options.image,
|
|
448
|
-
imagePullPolicy: options.imagePullPolicy,
|
|
449
|
-
name: "runner",
|
|
450
|
-
resources: options.resources ?? DEFAULT_RUNNER_RESOURCES,
|
|
451
|
-
volumeMounts
|
|
452
|
-
},
|
|
453
|
-
name: "pipeline-finalizer",
|
|
454
|
-
activeDeadlineSeconds: DEFAULT_RUNNER_DEADLINE_SECONDS
|
|
65
|
+
dag: { tasks: [{
|
|
66
|
+
name: RUNNER_WORKFLOW_START_TASK,
|
|
67
|
+
template: RUNNER_WORKFLOW_START_TASK
|
|
68
|
+
}, ...tasks.map((task) => ({
|
|
69
|
+
dependencies: [RUNNER_WORKFLOW_START_TASK, ...task.dependencies],
|
|
70
|
+
name: task.taskName,
|
|
71
|
+
template: task.templateName
|
|
72
|
+
}))] },
|
|
73
|
+
name: RUNNER_WORKFLOW_ENTRYPOINT
|
|
455
74
|
};
|
|
456
75
|
}
|
|
457
76
|
function compactRecord(input) {
|
package/dist/config/defaults.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ConfigIoService, parseConfigYamlAs, runConfigIoSync } from "../runtime/services/config-io-service.js";
|
|
2
|
-
import { z } from "zod";
|
|
3
2
|
import { Effect } from "effect";
|
|
3
|
+
import { z } from "zod";
|
|
4
4
|
//#region src/config/defaults.ts
|
|
5
5
|
const PIPELINE_CONFIG_PATH = ".pipeline/pipeline.yaml";
|
|
6
6
|
const RUNNERS_CONFIG_PATH = ".pipeline/runners.yaml";
|
package/dist/config/schemas.d.ts
CHANGED
|
@@ -226,8 +226,8 @@ declare const configSchema: z.ZodObject<{
|
|
|
226
226
|
policy: z.ZodOptional<z.ZodObject<{
|
|
227
227
|
commands: z.ZodOptional<z.ZodEnum<{
|
|
228
228
|
allow: "allow";
|
|
229
|
-
"trusted-only": "trusted-only";
|
|
230
229
|
deny: "deny";
|
|
230
|
+
"trusted-only": "trusted-only";
|
|
231
231
|
}>>;
|
|
232
232
|
modules: z.ZodOptional<z.ZodEnum<{
|
|
233
233
|
allow: "allow";
|
|
@@ -255,8 +255,8 @@ declare const configSchema: z.ZodObject<{
|
|
|
255
255
|
global: "global";
|
|
256
256
|
}>>;
|
|
257
257
|
mode: z.ZodEnum<{
|
|
258
|
-
hosted: "hosted";
|
|
259
258
|
local: "local";
|
|
259
|
+
hosted: "hosted";
|
|
260
260
|
}>;
|
|
261
261
|
provider: z.ZodLiteral<"toolhive">;
|
|
262
262
|
authorization_env: z.ZodDefault<z.ZodString>;
|
|
@@ -300,10 +300,10 @@ declare const configSchema: z.ZodObject<{
|
|
|
300
300
|
}, z.core.$strict>>;
|
|
301
301
|
output: z.ZodOptional<z.ZodObject<{
|
|
302
302
|
format: z.ZodEnum<{
|
|
303
|
+
json_schema: "json_schema";
|
|
303
304
|
text: "text";
|
|
304
305
|
json: "json";
|
|
305
306
|
jsonl: "jsonl";
|
|
306
|
-
json_schema: "json_schema";
|
|
307
307
|
}>;
|
|
308
308
|
repair: z.ZodOptional<z.ZodObject<{
|
|
309
309
|
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -379,10 +379,10 @@ declare const configSchema: z.ZodObject<{
|
|
|
379
379
|
disabled: "disabled";
|
|
380
380
|
}>>>;
|
|
381
381
|
output_formats: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
382
|
+
json_schema: "json_schema";
|
|
382
383
|
text: "text";
|
|
383
384
|
json: "json";
|
|
384
385
|
jsonl: "jsonl";
|
|
385
|
-
json_schema: "json_schema";
|
|
386
386
|
}>>>;
|
|
387
387
|
rules: z.ZodOptional<z.ZodBoolean>;
|
|
388
388
|
skills: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -503,8 +503,8 @@ declare const configSchema: z.ZodObject<{
|
|
|
503
503
|
schedules: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
504
504
|
description: z.ZodOptional<z.ZodString>;
|
|
505
505
|
baseline: z.ZodEnum<{
|
|
506
|
-
quick: "quick";
|
|
507
506
|
execute: "execute";
|
|
507
|
+
quick: "quick";
|
|
508
508
|
}>;
|
|
509
509
|
max_parallel_nodes: z.ZodOptional<z.ZodNumber>;
|
|
510
510
|
node_catalog: z.ZodOptional<z.ZodString>;
|