@oisincoveney/pipeline 3.15.2 → 3.15.4
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 +2 -2
- package/dist/argo-workflow.d.ts +2 -40
- package/dist/argo-workflow.js +53 -434
- package/dist/cli/bootstrap-commands.js +34 -0
- package/dist/cli/loop-commands.js +49 -0
- package/dist/cli/mcp-gateway-commands.js +60 -0
- package/dist/cli/plan-commands.js +156 -0
- package/dist/cli/program.d.ts +1 -26
- package/dist/cli/program.js +39 -595
- package/dist/cli/run-commands.js +58 -0
- package/dist/cli/run-service.d.ts +29 -0
- package/dist/cli/run-service.js +349 -0
- package/dist/commands/ticket/create.js +1 -1
- package/dist/config/defaults.js +1 -1
- package/dist/config/schemas.d.ts +1 -1
- package/dist/config/schemas.js +1 -1
- package/dist/{broker-auth.d.ts → credentials/broker.d.ts} +2 -3
- package/dist/credentials/broker.js +34 -0
- package/dist/credentials/codex-config.js +32 -0
- package/dist/credentials/file-targets.js +26 -0
- package/dist/{codex-auth-sync.js → credentials/local-codex-auth-sync.js} +21 -9
- package/dist/credentials/opencode-config.js +65 -0
- package/dist/credentials/runner.js +31 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/install-commands/claude-code.js +1 -1
- package/dist/install-commands/host-selection.js +13 -0
- package/dist/install-commands/opencode.js +2 -2
- 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/install-hooks.js +1 -1
- package/dist/loop/gh-checks.js +1 -1
- package/dist/moka-global-config.js +2 -2
- package/dist/moka-submit.d.ts +410 -44
- package/dist/moka-submit.js +15 -328
- package/dist/pipeline-runtime.d.ts +7 -27
- package/dist/pipeline-runtime.js +11 -869
- package/dist/planning/generate.js +3 -3
- 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/run-control/next-node.js +2 -21
- package/dist/run-control/runtime-reporter.js +1 -1
- package/dist/run-control/submit-result.js +1 -1
- package/dist/run-state/git-refs.js +28 -10
- package/dist/runner/subprocess.js +1 -1
- package/dist/runner-command/finalize.js +1 -1
- package/dist/runner-command/lifecycle-context.js +1 -1
- package/dist/runner-command/lifecycle.js +1 -1
- package/dist/runner-command/run.js +2 -2
- 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 +6 -6
- package/dist/runtime/agent-node/agent-node.js +83 -545
- package/dist/runtime/agent-node/handoff-finalization.js +55 -0
- package/dist/runtime/agent-node/model-selection.js +38 -0
- package/dist/runtime/agent-node/output-finalization.js +263 -0
- package/dist/runtime/agent-node/prompt-rendering.js +302 -0
- package/dist/runtime/agent-node/session-execution.js +48 -0
- package/dist/runtime/builtins/builtins.js +1 -1
- package/dist/runtime/config-error.js +6 -0
- package/dist/runtime/context/context.js +1 -1
- package/dist/runtime/durable-store/acquisition.js +10 -0
- 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/journal-acquisition.d.ts +9 -0
- package/dist/runtime/journal-acquisition.js +28 -0
- package/dist/runtime/node-execution.js +560 -0
- package/dist/runtime/opencode-runtime.js +47 -1
- package/dist/runtime/runtime-results.js +75 -0
- package/dist/runtime/scheduled-dependencies.d.ts +4 -0
- package/dist/runtime/scheduled-dependencies.js +98 -0
- package/dist/runtime/services/backlog-service.js +2 -3
- package/dist/runtime/services/runner-command-io-service.js +1 -1
- package/dist/runtime/workflow-execution.js +84 -0
- 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/dist/broker-auth.js +0 -173
- package/dist/run-state/opencode-accounts.js +0 -47
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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ArgoGraphCompilerError, compileArgoExecutionGraph } from "./argo-graph.js";
|
|
2
|
-
import { brokerAuthOptionSchema } from "./broker
|
|
2
|
+
import { brokerAuthOptionSchema } from "./credentials/broker.js";
|
|
3
3
|
import { compileScheduleArtifact, parseScheduleArtifact } from "./planning/generate.js";
|
|
4
4
|
import { parseRunnerCommandPayload, runnerCommandPayloadSchema } from "./runner-command-contract.js";
|
|
5
5
|
import { buildRunnerTaskDescriptor } from "./runner-command/task-descriptor.js";
|
|
@@ -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) {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { formatCodexAuthSyncResult, syncLocalCodexAuth } from "../credentials/local-codex-auth-sync.js";
|
|
2
|
+
import { formatPipelineInitResult, initPipelineProject } from "../pipeline-init.js";
|
|
3
|
+
import { runDoctor } from "./doctor.js";
|
|
4
|
+
import { formatDoctorResult } from "./format.js";
|
|
5
|
+
import { resolve } from "node:path";
|
|
6
|
+
//#region src/cli/bootstrap-commands.ts
|
|
7
|
+
function registerBootstrapCommands(program) {
|
|
8
|
+
program.command("doctor").description("Check local prerequisites for pipeline init and execution").option("--cluster [namespace]", "also check runner-job Kubernetes prerequisites").option("--json", "print machine-readable readiness results").option("--kube-context <context>", "kubectl context for cluster checks").option("--kubeconfig <path>", "kubeconfig path for cluster checks").action(async (flags) => {
|
|
9
|
+
const result = await runDoctor(process.env.PIPELINE_TARGET_PATH ?? process.cwd(), flags);
|
|
10
|
+
console.log(flags.json ? JSON.stringify(result) : formatDoctorResult(result));
|
|
11
|
+
if (!result.passed) throw new Error("Doctor checks failed.");
|
|
12
|
+
});
|
|
13
|
+
program.command("init").description("Install or refresh package-owned pipeline support: per-machine harness (skills + slash-command adapters + agent hooks + global instruction files) installed globally to ~/.claude, ~/.config/opencode, ~/.codex with no repo-local config").option("--check", "verify the generated harness is current; fail if stale").option("--dry-run", "show planned changes without writing files").option("--force", "overwrite manually edited harness files").action(async (flags) => {
|
|
14
|
+
const result = await initPipelineProject({
|
|
15
|
+
...flags,
|
|
16
|
+
cwd: process.env.PIPELINE_TARGET_PATH ?? process.cwd()
|
|
17
|
+
});
|
|
18
|
+
console.log(formatPipelineInitResult(result, {
|
|
19
|
+
check: flags.check,
|
|
20
|
+
dryRun: flags.dryRun
|
|
21
|
+
}));
|
|
22
|
+
});
|
|
23
|
+
program.command("codex-auth").description("Manage local Codex broker auth integration").command("sync-local").description("Point local dev repos' opencode openai provider at the central CLIProxyAPI broker").option("--root <path>", "directory containing repositories to sync").option("--dry-run", "show planned changes without writing files").option("--check", "fail if local Codex auth config is not synced").action((flags) => {
|
|
24
|
+
const result = syncLocalCodexAuth({
|
|
25
|
+
check: flags.check,
|
|
26
|
+
dryRun: flags.dryRun,
|
|
27
|
+
root: resolve(flags.root ?? process.env.PIPELINE_TARGET_PATH ?? process.cwd())
|
|
28
|
+
});
|
|
29
|
+
console.log(formatCodexAuthSyncResult(result));
|
|
30
|
+
if (!result.ok) process.exitCode = 1;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
export { registerBootstrapCommands };
|