@oisincoveney/pipeline 1.18.0 → 1.18.1
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/dist/config.d.ts +3 -3
- package/dist/runner-job/run.js +11 -14
- package/dist/runner-job-contract.d.ts +23 -4
- package/dist/runner-job-contract.js +20 -19
- package/docs/operator-guide.md +9 -11
- package/docs/pipeline-console-runner-contract.md +18 -20
- package/package.json +1 -1
package/dist/config.d.ts
CHANGED
|
@@ -223,8 +223,8 @@ declare const configSchema: z.ZodObject<{
|
|
|
223
223
|
policy: z.ZodOptional<z.ZodObject<{
|
|
224
224
|
commands: z.ZodOptional<z.ZodEnum<{
|
|
225
225
|
allow: "allow";
|
|
226
|
-
deny: "deny";
|
|
227
226
|
"trusted-only": "trusted-only";
|
|
227
|
+
deny: "deny";
|
|
228
228
|
}>>;
|
|
229
229
|
modules: z.ZodOptional<z.ZodEnum<{
|
|
230
230
|
allow: "allow";
|
|
@@ -279,10 +279,10 @@ declare const configSchema: z.ZodObject<{
|
|
|
279
279
|
}, z.core.$strict>>;
|
|
280
280
|
output: z.ZodOptional<z.ZodObject<{
|
|
281
281
|
format: z.ZodEnum<{
|
|
282
|
-
json_schema: "json_schema";
|
|
283
282
|
text: "text";
|
|
284
283
|
json: "json";
|
|
285
284
|
jsonl: "jsonl";
|
|
285
|
+
json_schema: "json_schema";
|
|
286
286
|
}>;
|
|
287
287
|
repair: z.ZodOptional<z.ZodObject<{
|
|
288
288
|
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -340,10 +340,10 @@ declare const configSchema: z.ZodObject<{
|
|
|
340
340
|
disabled: "disabled";
|
|
341
341
|
}>>>;
|
|
342
342
|
output_formats: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
343
|
-
json_schema: "json_schema";
|
|
344
343
|
text: "text";
|
|
345
344
|
json: "json";
|
|
346
345
|
jsonl: "jsonl";
|
|
346
|
+
json_schema: "json_schema";
|
|
347
347
|
}>>>;
|
|
348
348
|
rules: z.ZodOptional<z.ZodBoolean>;
|
|
349
349
|
skills: z.ZodOptional<z.ZodBoolean>;
|
package/dist/runner-job/run.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PipelineConfigError } from "../config.js";
|
|
2
2
|
import { runPipelineFromConfig } from "../pipeline-runtime.js";
|
|
3
|
-
import { RUNNER_PAYLOAD_ENV, parseRunnerJobPayloadWithIssues
|
|
3
|
+
import { RUNNER_PAYLOAD_ENV, parseRunnerJobPayloadWithIssues } from "../runner-job-contract.js";
|
|
4
4
|
import { createRunnerEventSink } from "../runner-event-sink.js";
|
|
5
5
|
import { compileScheduleArtifact, generateScheduleArtifact } from "../schedule-planner.js";
|
|
6
6
|
import { createPullRequest } from "./delivery.js";
|
|
@@ -14,8 +14,6 @@ const EXIT_FAIL = 1;
|
|
|
14
14
|
const EXIT_CANCELLED = 130;
|
|
15
15
|
const EXIT_VALIDATION = 64;
|
|
16
16
|
const EXIT_STARTUP = 70;
|
|
17
|
-
const RUNNER_EVENT_SINK_URL_ENV = "OISIN_PIPELINE_EVENT_SINK_URL";
|
|
18
|
-
const RUNNER_EVENT_SINK_AUTH_HEADER_ENV = "OISIN_PIPELINE_EVENT_AUTH_HEADER";
|
|
19
17
|
const RUNNER_SCHEDULE_ENTRYPOINT = "pipe";
|
|
20
18
|
async function runRunnerJob(options = {}) {
|
|
21
19
|
const prepared = prepareRunnerJob(options);
|
|
@@ -30,6 +28,7 @@ async function runRunnerJob(options = {}) {
|
|
|
30
28
|
let signalFinalResultRecorded = false;
|
|
31
29
|
const sink = createRunnerSink({
|
|
32
30
|
env,
|
|
31
|
+
events: payload.events,
|
|
33
32
|
fetch: options.fetch,
|
|
34
33
|
runId: payload.run.id
|
|
35
34
|
});
|
|
@@ -209,6 +208,7 @@ async function reportPreparedValidationFailure(failure, options) {
|
|
|
209
208
|
if (failure.recoverable) {
|
|
210
209
|
const sink = createRunnerSink({
|
|
211
210
|
env: failure.env,
|
|
211
|
+
events: failure.recoverable.events,
|
|
212
212
|
fetch: options.fetch,
|
|
213
213
|
runId: failure.recoverable.run.id
|
|
214
214
|
});
|
|
@@ -217,26 +217,23 @@ async function reportPreparedValidationFailure(failure, options) {
|
|
|
217
217
|
}
|
|
218
218
|
return EXIT_VALIDATION;
|
|
219
219
|
}
|
|
220
|
-
function resolveAuthToken(env, stderr) {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
225
|
-
stderr.write(`${message}\n`);
|
|
220
|
+
function resolveAuthToken(authTokenEnv, env, stderr) {
|
|
221
|
+
const token = env[authTokenEnv]?.trim();
|
|
222
|
+
if (!token) {
|
|
223
|
+
stderr.write(`Runner event auth token is required. Set ${authTokenEnv}.\n`);
|
|
226
224
|
return null;
|
|
227
225
|
}
|
|
226
|
+
return token;
|
|
228
227
|
}
|
|
229
228
|
function createRunnerSink(options) {
|
|
230
|
-
const
|
|
231
|
-
if (!url) return createNoopRunnerEventSink();
|
|
232
|
-
const authToken = resolveAuthToken(options.env, { write: () => true });
|
|
229
|
+
const authToken = resolveAuthToken(options.events.authTokenEnv, options.env, { write: () => true });
|
|
233
230
|
if (!authToken) return createNoopRunnerEventSink();
|
|
234
231
|
return createRunnerEventSink({
|
|
235
|
-
authHeader: options.
|
|
232
|
+
authHeader: options.events.authHeader,
|
|
236
233
|
authToken,
|
|
237
234
|
fetch: options.fetch,
|
|
238
235
|
runId: options.runId,
|
|
239
|
-
url
|
|
236
|
+
url: options.events.url
|
|
240
237
|
});
|
|
241
238
|
}
|
|
242
239
|
function createNoopRunnerEventSink() {
|
|
@@ -38,6 +38,11 @@ declare const runnerRepositoryContextSchema: z.ZodObject<{
|
|
|
38
38
|
declare const runnerDeliverySchema: z.ZodObject<{
|
|
39
39
|
pullRequest: z.ZodDefault<z.ZodBoolean>;
|
|
40
40
|
}, z.core.$strict>;
|
|
41
|
+
declare const runnerEventsSchema: z.ZodObject<{
|
|
42
|
+
authHeader: z.ZodDefault<z.ZodString>;
|
|
43
|
+
authTokenEnv: z.ZodString;
|
|
44
|
+
url: z.ZodString;
|
|
45
|
+
}, z.core.$strict>;
|
|
41
46
|
declare const runnerMomokayaContextSchema: z.ZodObject<{
|
|
42
47
|
automationNamespace: z.ZodOptional<z.ZodString>;
|
|
43
48
|
previewEnabled: z.ZodBoolean;
|
|
@@ -48,6 +53,11 @@ declare const runnerJobPayloadSchema: z.ZodObject<{
|
|
|
48
53
|
delivery: z.ZodDefault<z.ZodObject<{
|
|
49
54
|
pullRequest: z.ZodDefault<z.ZodBoolean>;
|
|
50
55
|
}, z.core.$strict>>;
|
|
56
|
+
events: z.ZodObject<{
|
|
57
|
+
authHeader: z.ZodDefault<z.ZodString>;
|
|
58
|
+
authTokenEnv: z.ZodString;
|
|
59
|
+
url: z.ZodString;
|
|
60
|
+
}, z.core.$strict>;
|
|
51
61
|
momokaya: z.ZodOptional<z.ZodObject<{
|
|
52
62
|
automationNamespace: z.ZodOptional<z.ZodString>;
|
|
53
63
|
previewEnabled: z.ZodBoolean;
|
|
@@ -75,6 +85,7 @@ declare const runnerJobPayloadSchema: z.ZodObject<{
|
|
|
75
85
|
}, z.core.$strict>], "kind">;
|
|
76
86
|
}, z.core.$strict>;
|
|
77
87
|
type RunnerDelivery = z.infer<typeof runnerDeliverySchema>;
|
|
88
|
+
type RunnerEvents = z.infer<typeof runnerEventsSchema>;
|
|
78
89
|
type RunnerJobPayload = z.infer<typeof runnerJobPayloadSchema>;
|
|
79
90
|
type RunnerMomokayaContext = z.infer<typeof runnerMomokayaContextSchema>;
|
|
80
91
|
type RunnerRepositoryContext = z.infer<typeof runnerRepositoryContextSchema>;
|
|
@@ -87,6 +98,11 @@ declare const runnerJobPayloadJsonSchema: z.core.ZodStandardJSONSchemaPayload<z.
|
|
|
87
98
|
delivery: z.ZodDefault<z.ZodObject<{
|
|
88
99
|
pullRequest: z.ZodDefault<z.ZodBoolean>;
|
|
89
100
|
}, z.core.$strict>>;
|
|
101
|
+
events: z.ZodObject<{
|
|
102
|
+
authHeader: z.ZodDefault<z.ZodString>;
|
|
103
|
+
authTokenEnv: z.ZodString;
|
|
104
|
+
url: z.ZodString;
|
|
105
|
+
}, z.core.$strict>;
|
|
90
106
|
momokaya: z.ZodOptional<z.ZodObject<{
|
|
91
107
|
automationNamespace: z.ZodOptional<z.ZodString>;
|
|
92
108
|
previewEnabled: z.ZodBoolean;
|
|
@@ -119,6 +135,7 @@ interface RunnerJobPayloadValidationIssue {
|
|
|
119
135
|
path: string;
|
|
120
136
|
}
|
|
121
137
|
interface RecoverableRunnerJobPayloadEnvelope {
|
|
138
|
+
events: RunnerEvents;
|
|
122
139
|
run: RunnerRunIdentity;
|
|
123
140
|
}
|
|
124
141
|
declare class RunnerJobPayloadValidationError extends Error {
|
|
@@ -135,12 +152,14 @@ type RunnerJobPayloadParseResult = {
|
|
|
135
152
|
};
|
|
136
153
|
interface BuildRunnerJobPayloadOptions {
|
|
137
154
|
delivery?: RunnerDelivery;
|
|
155
|
+
events: RunnerEvents;
|
|
138
156
|
momokaya?: RunnerMomokayaContext;
|
|
139
157
|
repository: RunnerRepositoryContext;
|
|
140
158
|
run: RunnerRunIdentity;
|
|
141
159
|
task: RunnerTask;
|
|
142
160
|
}
|
|
143
161
|
interface CreateRunnerJobPayloadEnvOptions {
|
|
162
|
+
events: RunnerEvents;
|
|
144
163
|
project: string;
|
|
145
164
|
repository: RunnerRepositoryContext;
|
|
146
165
|
requestedBy?: string;
|
|
@@ -148,8 +167,8 @@ interface CreateRunnerJobPayloadEnvOptions {
|
|
|
148
167
|
taskPrompt: string;
|
|
149
168
|
}
|
|
150
169
|
interface ResolveRunnerEventSinkAuthTokenOptions {
|
|
170
|
+
authTokenEnv: string;
|
|
151
171
|
env?: Record<string, string | undefined>;
|
|
152
|
-
serviceAccountTokenPath?: string;
|
|
153
172
|
}
|
|
154
173
|
interface RunnerEventMappingContext {
|
|
155
174
|
runId: string;
|
|
@@ -276,8 +295,8 @@ type RunnerEventRecord = (RunnerEventEnvelope & {
|
|
|
276
295
|
finalResult: RunnerFinalResultDetails;
|
|
277
296
|
type: "workflow.finish";
|
|
278
297
|
});
|
|
279
|
-
declare function resolveRunnerEventSinkAuthToken(options
|
|
280
|
-
declare function resolveRunnerEventSinkAuthHeader(options
|
|
298
|
+
declare function resolveRunnerEventSinkAuthToken(options: ResolveRunnerEventSinkAuthTokenOptions): string;
|
|
299
|
+
declare function resolveRunnerEventSinkAuthHeader(options: ResolveRunnerEventSinkAuthTokenOptions): string;
|
|
281
300
|
declare function createRunnerJobPayloadEnv(options: CreateRunnerJobPayloadEnvOptions): {
|
|
282
301
|
name: typeof RUNNER_PAYLOAD_ENV;
|
|
283
302
|
value: string;
|
|
@@ -287,4 +306,4 @@ declare function parseRunnerJobPayload(rawPayload: string): RunnerJobPayload;
|
|
|
287
306
|
declare function parseRunnerJobPayloadWithIssues(rawPayload: string): RunnerJobPayloadParseResult;
|
|
288
307
|
declare function mapRuntimeEventToRunnerEventRecords(event: PipelineRuntimeEvent, context: RunnerEventMappingContext): RunnerEventRecord[];
|
|
289
308
|
//#endregion
|
|
290
|
-
export { BuildRunnerJobPayloadOptions, CreateRunnerJobPayloadEnvOptions, RUNNER_JOB_CONTRACT_VERSION, RUNNER_PAYLOAD_ENV, RecoverableRunnerJobPayloadEnvelope, ResolveRunnerEventSinkAuthTokenOptions, RunnerArtifactDetails, RunnerArtifactStatus, RunnerDelivery, RunnerEventMappingContext, RunnerEventRecord, RunnerFinalResultDetails, RunnerGateDetails, RunnerGateStatus, RunnerHookResultDetails, RunnerJobPayload, RunnerJobPayloadParseResult, RunnerJobPayloadValidationError, RunnerJobPayloadValidationIssue, RunnerLogDetails, RunnerLogLevel, RunnerMomokayaContext, RunnerNodeDetails, RunnerNodeStatus, RunnerRepositoryContext, RunnerRunIdentity, RunnerTask, RunnerTaskPrompt, RunnerTaskTicket, RunnerWorkflowEdgeDetails, RunnerWorkflowEdgeRecordDetails, RunnerWorkflowNodeDetails, RunnerWorkflowPlanDetails, buildRunnerJobPayload, createRunnerJobPayloadEnv, mapRuntimeEventToRunnerEventRecords, parseRunnerJobPayload, parseRunnerJobPayloadWithIssues, resolveRunnerEventSinkAuthHeader, resolveRunnerEventSinkAuthToken, runnerDeliverySchema, runnerJobPayloadJsonSchema, runnerJobPayloadSchema, runnerMomokayaContextSchema, runnerRepositoryContextSchema, runnerRunIdentitySchema, runnerTaskPromptSchema, runnerTaskSchema, runnerTaskTicketSchema };
|
|
309
|
+
export { BuildRunnerJobPayloadOptions, CreateRunnerJobPayloadEnvOptions, RUNNER_JOB_CONTRACT_VERSION, RUNNER_PAYLOAD_ENV, RecoverableRunnerJobPayloadEnvelope, ResolveRunnerEventSinkAuthTokenOptions, RunnerArtifactDetails, RunnerArtifactStatus, RunnerDelivery, RunnerEventMappingContext, RunnerEventRecord, RunnerEvents, RunnerFinalResultDetails, RunnerGateDetails, RunnerGateStatus, RunnerHookResultDetails, RunnerJobPayload, RunnerJobPayloadParseResult, RunnerJobPayloadValidationError, RunnerJobPayloadValidationIssue, RunnerLogDetails, RunnerLogLevel, RunnerMomokayaContext, RunnerNodeDetails, RunnerNodeStatus, RunnerRepositoryContext, RunnerRunIdentity, RunnerTask, RunnerTaskPrompt, RunnerTaskTicket, RunnerWorkflowEdgeDetails, RunnerWorkflowEdgeRecordDetails, RunnerWorkflowNodeDetails, RunnerWorkflowPlanDetails, buildRunnerJobPayload, createRunnerJobPayloadEnv, mapRuntimeEventToRunnerEventRecords, parseRunnerJobPayload, parseRunnerJobPayloadWithIssues, resolveRunnerEventSinkAuthHeader, resolveRunnerEventSinkAuthToken, runnerDeliverySchema, runnerEventsSchema, runnerJobPayloadJsonSchema, runnerJobPayloadSchema, runnerMomokayaContextSchema, runnerRepositoryContextSchema, runnerRunIdentitySchema, runnerTaskPromptSchema, runnerTaskSchema, runnerTaskTicketSchema };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { parseJson } from "./safe-json.js";
|
|
2
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
3
2
|
import { z } from "zod";
|
|
4
3
|
//#region src/runner-job-contract.ts
|
|
5
4
|
const RUNNER_PAYLOAD_ENV = "OISIN_PIPELINE_RUNNER_PAYLOAD_JSON";
|
|
@@ -27,6 +26,11 @@ const runnerRepositoryContextSchema = z.object({
|
|
|
27
26
|
url: z.string().url()
|
|
28
27
|
}).strict();
|
|
29
28
|
const runnerDeliverySchema = z.object({ pullRequest: z.boolean().default(false) }).strict();
|
|
29
|
+
const runnerEventsSchema = z.object({
|
|
30
|
+
authHeader: z.string().min(1).default("Authorization"),
|
|
31
|
+
authTokenEnv: z.string().min(1),
|
|
32
|
+
url: z.string().url()
|
|
33
|
+
}).strict();
|
|
30
34
|
const runnerMomokayaContextSchema = z.object({
|
|
31
35
|
automationNamespace: z.string().min(1).optional(),
|
|
32
36
|
previewEnabled: z.boolean(),
|
|
@@ -35,6 +39,7 @@ const runnerMomokayaContextSchema = z.object({
|
|
|
35
39
|
const runnerJobPayloadSchema = z.object({
|
|
36
40
|
contractVersion: z.literal("1", { error: "runner job payload contract version must be 1" }).default("1"),
|
|
37
41
|
delivery: runnerDeliverySchema.default({ pullRequest: false }),
|
|
42
|
+
events: runnerEventsSchema,
|
|
38
43
|
momokaya: runnerMomokayaContextSchema.optional(),
|
|
39
44
|
repository: runnerRepositoryContextSchema,
|
|
40
45
|
run: runnerRunIdentitySchema,
|
|
@@ -49,22 +54,12 @@ var RunnerJobPayloadValidationError = class extends Error {
|
|
|
49
54
|
this.issues = issues;
|
|
50
55
|
}
|
|
51
56
|
};
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
for (const key of EVENT_AUTH_TOKEN_ENV_KEYS) {
|
|
57
|
-
const token = env[key]?.trim();
|
|
58
|
-
if (token) return token;
|
|
59
|
-
}
|
|
60
|
-
const tokenPath = options.serviceAccountTokenPath ?? DEFAULT_SERVICE_ACCOUNT_TOKEN_PATH;
|
|
61
|
-
if (existsSync(tokenPath)) {
|
|
62
|
-
const token = readFileSync(tokenPath, "utf8").trim();
|
|
63
|
-
if (token) return token;
|
|
64
|
-
}
|
|
65
|
-
throw new Error(`Runner event auth token is required. Set ${EVENT_AUTH_TOKEN_ENV_KEYS.join(" or ")}, or mount a readable Kubernetes service account token at ${tokenPath}.`);
|
|
57
|
+
function resolveRunnerEventSinkAuthToken(options) {
|
|
58
|
+
const token = (options.env ?? process.env)[options.authTokenEnv]?.trim();
|
|
59
|
+
if (token) return token;
|
|
60
|
+
throw new Error(`Runner event auth token is required. Set ${options.authTokenEnv}.`);
|
|
66
61
|
}
|
|
67
|
-
function resolveRunnerEventSinkAuthHeader(options
|
|
62
|
+
function resolveRunnerEventSinkAuthHeader(options) {
|
|
68
63
|
return `Bearer ${resolveRunnerEventSinkAuthToken(options)}`;
|
|
69
64
|
}
|
|
70
65
|
function createRunnerJobPayloadEnv(options) {
|
|
@@ -74,6 +69,7 @@ function createRunnerJobPayloadEnv(options) {
|
|
|
74
69
|
project: options.project,
|
|
75
70
|
requestedBy: options.requestedBy
|
|
76
71
|
},
|
|
72
|
+
events: options.events,
|
|
77
73
|
repository: options.repository,
|
|
78
74
|
task: {
|
|
79
75
|
kind: "prompt",
|
|
@@ -89,6 +85,7 @@ function buildRunnerJobPayload(options) {
|
|
|
89
85
|
return runnerJobPayloadSchema.parse({
|
|
90
86
|
contractVersion: "1",
|
|
91
87
|
delivery: options.delivery,
|
|
88
|
+
events: options.events,
|
|
92
89
|
momokaya: options.momokaya,
|
|
93
90
|
repository: options.repository,
|
|
94
91
|
run: options.run,
|
|
@@ -393,8 +390,12 @@ function recoverablePayloadEnvelope(payload) {
|
|
|
393
390
|
const envelope = readRecord(payload);
|
|
394
391
|
if (!envelope) return {};
|
|
395
392
|
const run = runnerRunIdentitySchema.safeParse(envelope.run);
|
|
396
|
-
|
|
397
|
-
|
|
393
|
+
const events = runnerEventsSchema.safeParse(envelope.events);
|
|
394
|
+
if (!(run.success && events.success)) return {};
|
|
395
|
+
return { recoverable: {
|
|
396
|
+
events: events.data,
|
|
397
|
+
run: run.data
|
|
398
|
+
} };
|
|
398
399
|
}
|
|
399
400
|
function omitUndefined(value) {
|
|
400
401
|
return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== void 0));
|
|
@@ -406,4 +407,4 @@ function assertNever(value) {
|
|
|
406
407
|
throw new Error(`Unhandled runtime event: ${String(value)}`);
|
|
407
408
|
}
|
|
408
409
|
//#endregion
|
|
409
|
-
export { RUNNER_JOB_CONTRACT_VERSION, RUNNER_PAYLOAD_ENV, RunnerJobPayloadValidationError, buildRunnerJobPayload, createRunnerJobPayloadEnv, mapRuntimeEventToRunnerEventRecords, parseRunnerJobPayload, parseRunnerJobPayloadWithIssues, resolveRunnerEventSinkAuthHeader, resolveRunnerEventSinkAuthToken, runnerDeliverySchema, runnerJobPayloadJsonSchema, runnerJobPayloadSchema, runnerMomokayaContextSchema, runnerRepositoryContextSchema, runnerRunIdentitySchema, runnerTaskPromptSchema, runnerTaskSchema, runnerTaskTicketSchema };
|
|
410
|
+
export { RUNNER_JOB_CONTRACT_VERSION, RUNNER_PAYLOAD_ENV, RunnerJobPayloadValidationError, buildRunnerJobPayload, createRunnerJobPayloadEnv, mapRuntimeEventToRunnerEventRecords, parseRunnerJobPayload, parseRunnerJobPayloadWithIssues, resolveRunnerEventSinkAuthHeader, resolveRunnerEventSinkAuthToken, runnerDeliverySchema, runnerEventsSchema, runnerJobPayloadJsonSchema, runnerJobPayloadSchema, runnerMomokayaContextSchema, runnerRepositoryContextSchema, runnerRunIdentitySchema, runnerTaskPromptSchema, runnerTaskSchema, runnerTaskTicketSchema };
|
package/docs/operator-guide.md
CHANGED
|
@@ -122,7 +122,8 @@ Host choices are `all`, `opencode`, and `codex`.
|
|
|
122
122
|
Runs the in-pod backend worker entrypoint. The job reads
|
|
123
123
|
`OISIN_PIPELINE_RUNNER_PAYLOAD_JSON`, prepares `PIPELINE_TARGET_PATH` or clones
|
|
124
124
|
the requested repository into `/workspace`, generates a task-specific schedule,
|
|
125
|
-
and appends runtime events to
|
|
125
|
+
and appends runtime events to the Console endpoint configured by payload
|
|
126
|
+
`events.url`.
|
|
126
127
|
|
|
127
128
|
The runner job does not call the Kubernetes API. Validation errors exit `64`,
|
|
128
129
|
startup errors exit `70`, runtime failure exits `1`, cancellation exits `130`,
|
|
@@ -132,9 +133,8 @@ Local dry run:
|
|
|
132
133
|
|
|
133
134
|
```shell
|
|
134
135
|
export PIPELINE_TARGET_PATH=/path/to/target/repo
|
|
135
|
-
export
|
|
136
|
-
export
|
|
137
|
-
export OISIN_PIPELINE_RUNNER_PAYLOAD_JSON='{"contractVersion":"1","run":{"id":"run-uid-1","project":"alpha","requestedBy":"@agent"},"repository":{"url":"https://github.com/oisin-ee/pipeline-runner.git","baseBranch":"main"},"task":{"kind":"prompt","prompt":"PIPE-38"},"delivery":{"pullRequest":false}}'
|
|
136
|
+
export PIPELINE_EVENT_API_TOKEN=dev-token
|
|
137
|
+
export OISIN_PIPELINE_RUNNER_PAYLOAD_JSON='{"contractVersion":"1","run":{"id":"run-uid-1","project":"alpha","requestedBy":"@agent"},"repository":{"url":"https://github.com/oisin-ee/pipeline-runner.git","baseBranch":"main"},"task":{"kind":"prompt","prompt":"PIPE-38"},"delivery":{"pullRequest":false},"events":{"url":"http://127.0.0.1:3000/api/pipeline/runner-events","authHeader":"Authorization","authTokenEnv":"PIPELINE_EVENT_API_TOKEN"}}'
|
|
138
138
|
pipe runner-job
|
|
139
139
|
```
|
|
140
140
|
|
|
@@ -162,10 +162,8 @@ spec:
|
|
|
162
162
|
image: ghcr.io/oisin-ee/pipeline-runner:latest
|
|
163
163
|
env:
|
|
164
164
|
- name: OISIN_PIPELINE_RUNNER_PAYLOAD_JSON
|
|
165
|
-
value: '{"contractVersion":"1","run":{"id":"run-uid-1","project":"alpha"},"repository":{"url":"https://github.com/oisin-ee/pipeline-runner.git","baseBranch":"main","sha":"0123456789abcdef0123456789abcdef01234567"},"task":{"kind":"prompt","prompt":"PIPE-38"},"delivery":{"pullRequest":true}}'
|
|
166
|
-
- name:
|
|
167
|
-
value: https://console.example/api/pipeline/runs/run-uid-1/events
|
|
168
|
-
- name: OISIN_PIPELINE_EVENT_AUTH_TOKEN
|
|
165
|
+
value: '{"contractVersion":"1","run":{"id":"run-uid-1","project":"alpha"},"repository":{"url":"https://github.com/oisin-ee/pipeline-runner.git","baseBranch":"main","sha":"0123456789abcdef0123456789abcdef01234567"},"task":{"kind":"prompt","prompt":"PIPE-38"},"delivery":{"pullRequest":true},"events":{"url":"https://console.example/api/pipeline/runner-events","authHeader":"Authorization","authTokenEnv":"PIPELINE_EVENT_API_TOKEN"}}'
|
|
166
|
+
- name: PIPELINE_EVENT_API_TOKEN
|
|
169
167
|
valueFrom:
|
|
170
168
|
secretKeyRef:
|
|
171
169
|
name: pipeline-runner-event-auth
|
|
@@ -175,9 +173,9 @@ spec:
|
|
|
175
173
|
The runner image is configured in `pipeline-console` as
|
|
176
174
|
`pipeline.runner.image`. Console runner settings include queue name, service
|
|
177
175
|
account, CPU/memory requests and limits, active deadline, TTL, backoff limit,
|
|
178
|
-
event sink URL, and
|
|
179
|
-
|
|
180
|
-
|
|
176
|
+
event sink URL, auth header, and the token environment variable name. The
|
|
177
|
+
runner-side secret mounted at `events.authTokenEnv` must match the console API
|
|
178
|
+
`PIPELINE_EVENT_API_TOKEN`.
|
|
181
179
|
|
|
182
180
|
The runner payload contract lives at
|
|
183
181
|
`@oisincoveney/pipeline/runner-job-contract`. `pipeline-console` should create
|
|
@@ -37,6 +37,11 @@ subpath exports `parseRunnerJobPayload`, `RUNNER_JOB_CONTRACT_VERSION`, and
|
|
|
37
37
|
},
|
|
38
38
|
"delivery": {
|
|
39
39
|
"pullRequest": true
|
|
40
|
+
},
|
|
41
|
+
"events": {
|
|
42
|
+
"url": "https://console.example/api/pipeline/runner-events",
|
|
43
|
+
"authHeader": "Authorization",
|
|
44
|
+
"authTokenEnv": "PIPELINE_EVENT_API_TOKEN"
|
|
40
45
|
}
|
|
41
46
|
}
|
|
42
47
|
```
|
|
@@ -51,10 +56,12 @@ subpath exports `parseRunnerJobPayload`, `RUNNER_JOB_CONTRACT_VERSION`, and
|
|
|
51
56
|
{ "kind": "ticket", "id": "PC-27", "path": "tickets/PC-27.md" }
|
|
52
57
|
```
|
|
53
58
|
|
|
54
|
-
Payloads describe
|
|
55
|
-
|
|
56
|
-
modes, clone credential env names, repository owner/repo duplicates, or
|
|
57
|
-
|
|
59
|
+
Payloads describe run identity, repository/task intent, delivery intent, and the
|
|
60
|
+
Console event destination. They must not carry workflow selectors, entrypoints,
|
|
61
|
+
workspace modes, clone credential env names, repository owner/repo duplicates, or
|
|
62
|
+
secrets. `events.authTokenEnv` names the environment variable containing the
|
|
63
|
+
Console event API token; the token value itself stays in Kubernetes secrets. The
|
|
64
|
+
runner clones `repository.url` into `/workspace`, checks out a
|
|
58
65
|
`pipeline/<task-or-run>` branch from `repository.sha` when present or
|
|
59
66
|
`origin/<repository.baseBranch>` otherwise, sets `PIPELINE_TARGET_PATH`, loads the
|
|
60
67
|
repository `.pipeline` config, generates a task-specific `pipe` schedule, and
|
|
@@ -81,19 +88,9 @@ Console-created Jobs are labeled with `kueue.x-k8s.io/queue-name` and
|
|
|
81
88
|
|
|
82
89
|
## Event Batches
|
|
83
90
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
otherwise `Authorization`, and resolves the bearer token using this lookup order:
|
|
88
|
-
|
|
89
|
-
1. `OISIN_PIPELINE_EVENT_AUTH_TOKEN`
|
|
90
|
-
2. `PIPELINE_EVENT_API_TOKEN`
|
|
91
|
-
3. `/var/run/secrets/kubernetes.io/serviceaccount/token`
|
|
92
|
-
|
|
93
|
-
If the event sink URL or token is unavailable, the runner still executes with a
|
|
94
|
-
no-op sink. If a configured terminal sink flush fails, the Job exits `70`.
|
|
95
|
-
|
|
96
|
-
The runner posts authenticated JSON batches to `OISIN_PIPELINE_EVENT_SINK_URL`:
|
|
91
|
+
Console supplies `events.url`, `events.authHeader`, and `events.authTokenEnv` in
|
|
92
|
+
the runner payload. The runner reads the token from the named environment
|
|
93
|
+
variable and posts progressive authenticated JSON batches to `events.url`:
|
|
97
94
|
|
|
98
95
|
```json
|
|
99
96
|
{
|
|
@@ -113,9 +110,10 @@ Each event has a strictly increasing integer `sequence`, a string `type`, an
|
|
|
113
110
|
`node`, `gate`, `artifact`, `log`, and `finalResult`. The console stores
|
|
114
111
|
non-reserved top-level fields as event payload.
|
|
115
112
|
|
|
116
|
-
If
|
|
117
|
-
|
|
118
|
-
posts `
|
|
113
|
+
If a configured terminal sink flush fails, the Job exits `70`. If payload
|
|
114
|
+
validation fails but the runner can recover the run identity and event config, it
|
|
115
|
+
posts a `runner.schema.validation` warning event, then posts `workflow.finish`
|
|
116
|
+
with outcome `FAIL`, and exits `64`. If identity or event config is not
|
|
119
117
|
recoverable, it writes the validation error to stderr and exits `64` without
|
|
120
118
|
posting events.
|
|
121
119
|
|
package/package.json
CHANGED
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
"prepack": "bun run build:cli"
|
|
100
100
|
},
|
|
101
101
|
"type": "module",
|
|
102
|
-
"version": "1.18.
|
|
102
|
+
"version": "1.18.1",
|
|
103
103
|
"description": "Config-driven multi-agent pipeline runner for repository work",
|
|
104
104
|
"main": "./dist/index.js",
|
|
105
105
|
"types": "./dist/index.d.ts",
|