@kody-ade/kody-engine 0.1.4 → 0.1.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/dist/bin/cli.mjs +90 -19
- package/dist/bin/cli.mjs.map +1 -1
- package/package.json +1 -1
package/dist/bin/cli.mjs
CHANGED
|
@@ -7965,10 +7965,16 @@ async function runPipeline(ctx, pipeline, hooks, rebuildPipeline) {
|
|
|
7965
7965
|
}
|
|
7966
7966
|
if (!ctx.input.dryRun && !ctx.input.local) {
|
|
7967
7967
|
try {
|
|
7968
|
-
const currentBranch = execFileSync13(
|
|
7969
|
-
|
|
7970
|
-
|
|
7971
|
-
|
|
7968
|
+
const currentBranch = execFileSync13(
|
|
7969
|
+
"git",
|
|
7970
|
+
["branch", "--show-current"],
|
|
7971
|
+
{
|
|
7972
|
+
encoding: "utf-8"
|
|
7973
|
+
}
|
|
7974
|
+
).trim();
|
|
7975
|
+
const isFeatureBranch = !["dev", "main", "master"].includes(
|
|
7976
|
+
currentBranch
|
|
7977
|
+
);
|
|
7972
7978
|
if (isFeatureBranch) {
|
|
7973
7979
|
commitPipelineFiles({
|
|
7974
7980
|
taskDir: ctx.taskDir,
|
|
@@ -7981,7 +7987,10 @@ async function runPipeline(ctx, pipeline, hooks, rebuildPipeline) {
|
|
|
7981
7987
|
logger.info(" \u2713 Pushed fresh running status.json to branch");
|
|
7982
7988
|
}
|
|
7983
7989
|
} catch (earlyPushErr) {
|
|
7984
|
-
logger.warn(
|
|
7990
|
+
logger.warn(
|
|
7991
|
+
{ err: earlyPushErr },
|
|
7992
|
+
"Early status push failed (non-fatal)"
|
|
7993
|
+
);
|
|
7985
7994
|
}
|
|
7986
7995
|
}
|
|
7987
7996
|
} else {
|
|
@@ -8002,7 +8011,9 @@ async function runPipeline(ctx, pipeline, hooks, rebuildPipeline) {
|
|
|
8002
8011
|
}
|
|
8003
8012
|
}
|
|
8004
8013
|
if (state.state === "paused") {
|
|
8005
|
-
const anyPausedStage = Object.values(state.stages).some(
|
|
8014
|
+
const anyPausedStage = Object.values(state.stages).some(
|
|
8015
|
+
(s) => s.state === "paused"
|
|
8016
|
+
);
|
|
8006
8017
|
if (!anyPausedStage) {
|
|
8007
8018
|
state = {
|
|
8008
8019
|
...state,
|
|
@@ -8035,7 +8046,11 @@ async function runPipeline(ctx, pipeline, hooks, rebuildPipeline) {
|
|
|
8035
8046
|
const recoveredState = recoverStaleStages(currentState);
|
|
8036
8047
|
if (recoveredState !== currentState) {
|
|
8037
8048
|
logger.info("\u26A0\uFE0F Periodic recovery: reset stale running stages");
|
|
8038
|
-
logRecovery(
|
|
8049
|
+
logRecovery(
|
|
8050
|
+
"stale-stage-recovery",
|
|
8051
|
+
ctx.taskId,
|
|
8052
|
+
"Reset stale running stages"
|
|
8053
|
+
);
|
|
8039
8054
|
state = recoveredState;
|
|
8040
8055
|
writeState(ctx.taskId, state);
|
|
8041
8056
|
}
|
|
@@ -8047,7 +8062,10 @@ async function runPipeline(ctx, pipeline, hooks, rebuildPipeline) {
|
|
|
8047
8062
|
const newOrder = flattenPipelineOrder(pipeline.order);
|
|
8048
8063
|
for (const stageName of newOrder) {
|
|
8049
8064
|
if (!state.stages[stageName]) {
|
|
8050
|
-
state = updateStage(state, stageName, {
|
|
8065
|
+
state = updateStage(state, stageName, {
|
|
8066
|
+
state: "pending",
|
|
8067
|
+
retries: 0
|
|
8068
|
+
});
|
|
8051
8069
|
}
|
|
8052
8070
|
}
|
|
8053
8071
|
writeState(ctx.taskId, state);
|
|
@@ -8088,7 +8106,9 @@ async function runPipeline(ctx, pipeline, hooks, rebuildPipeline) {
|
|
|
8088
8106
|
const stageState = failedStage?.[1];
|
|
8089
8107
|
const stageOutcome = stageState?.state || "unknown";
|
|
8090
8108
|
const stageError = stageState?.error ? `: ${stageState.error}` : "";
|
|
8091
|
-
throw new Error(
|
|
8109
|
+
throw new Error(
|
|
8110
|
+
`Pipeline failed at stage: ${stageName} (${stageOutcome})${stageError}`
|
|
8111
|
+
);
|
|
8092
8112
|
}
|
|
8093
8113
|
return state;
|
|
8094
8114
|
}
|
|
@@ -8134,7 +8154,10 @@ async function executeSingleStep(ctx, pipeline, state, stageName) {
|
|
|
8134
8154
|
logger.info(` ${stageName} already completed, skipping`);
|
|
8135
8155
|
return state;
|
|
8136
8156
|
}
|
|
8137
|
-
state = updateStage(state, stageName, {
|
|
8157
|
+
state = updateStage(state, stageName, {
|
|
8158
|
+
state: "running",
|
|
8159
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8160
|
+
});
|
|
8138
8161
|
writeState(ctx.taskId, state);
|
|
8139
8162
|
logStageStart(stageName, ctx.taskId);
|
|
8140
8163
|
if (ctx.input.dryRun) {
|
|
@@ -8156,7 +8179,30 @@ async function executeSingleStep(ctx, pipeline, state, stageName) {
|
|
|
8156
8179
|
const handler = getHandler(def.name, def.type);
|
|
8157
8180
|
const result = await handler.execute(ctx, def);
|
|
8158
8181
|
ciGroupEnd();
|
|
8159
|
-
|
|
8182
|
+
if (result.outcome === "failed" || result.outcome === "timed_out") {
|
|
8183
|
+
if (def.postActions && !ctx.input.dryRun) {
|
|
8184
|
+
try {
|
|
8185
|
+
for (const action of def.postActions) {
|
|
8186
|
+
await executePostAction(ctx, action, state);
|
|
8187
|
+
}
|
|
8188
|
+
} catch (postError) {
|
|
8189
|
+
logger.error(
|
|
8190
|
+
{ err: postError },
|
|
8191
|
+
` Post-action failed for ${stageName}:`
|
|
8192
|
+
);
|
|
8193
|
+
}
|
|
8194
|
+
}
|
|
8195
|
+
const errorMessage = `${stageName} ${result.outcome === "timed_out" ? "timed out" : "failed"}: ${result.reason || "unknown"}`;
|
|
8196
|
+
throw new Error(errorMessage);
|
|
8197
|
+
}
|
|
8198
|
+
return await handleStageResult(
|
|
8199
|
+
ctx,
|
|
8200
|
+
pipeline,
|
|
8201
|
+
state,
|
|
8202
|
+
stageName,
|
|
8203
|
+
result,
|
|
8204
|
+
def
|
|
8205
|
+
);
|
|
8160
8206
|
} catch (error) {
|
|
8161
8207
|
ciGroupEnd();
|
|
8162
8208
|
if (error instanceof PipelinePausedError) {
|
|
@@ -8214,7 +8260,10 @@ async function executeSingleStep(ctx, pipeline, state, stageName) {
|
|
|
8214
8260
|
return completeState(state, "failed");
|
|
8215
8261
|
}
|
|
8216
8262
|
} catch (observerError) {
|
|
8217
|
-
logger.error(
|
|
8263
|
+
logger.error(
|
|
8264
|
+
{ err: observerError },
|
|
8265
|
+
`[StateMachine] Observer error, falling back`
|
|
8266
|
+
);
|
|
8218
8267
|
state = updateStage(state, stageName, {
|
|
8219
8268
|
state: "failed",
|
|
8220
8269
|
error: errorMessage
|
|
@@ -8261,7 +8310,10 @@ async function executeParallelStep(ctx, pipeline, state, stageNames) {
|
|
|
8261
8310
|
stagesToRun.map(async (stageName) => {
|
|
8262
8311
|
const def = pipeline.stages.get(stageName);
|
|
8263
8312
|
if (!def) {
|
|
8264
|
-
throw new StageError(
|
|
8313
|
+
throw new StageError(
|
|
8314
|
+
`Stage '${stageName}' not found in pipeline definitions`,
|
|
8315
|
+
stageName
|
|
8316
|
+
);
|
|
8265
8317
|
}
|
|
8266
8318
|
if (def.shouldSkip) {
|
|
8267
8319
|
const skipResult = def.shouldSkip(ctx);
|
|
@@ -8360,7 +8412,10 @@ async function executeParallelStep(ctx, pipeline, state, stageNames) {
|
|
|
8360
8412
|
pausedStage = stageName;
|
|
8361
8413
|
continue;
|
|
8362
8414
|
}
|
|
8363
|
-
logger.error(
|
|
8415
|
+
logger.error(
|
|
8416
|
+
{ err: postError },
|
|
8417
|
+
` Post-action failed for parallel stage ${stageName}:`
|
|
8418
|
+
);
|
|
8364
8419
|
const postErrorMsg = postError instanceof Error ? postError.message : String(postError);
|
|
8365
8420
|
state = updateStage(state, stageName, {
|
|
8366
8421
|
state: "failed",
|
|
@@ -8386,7 +8441,10 @@ async function executeParallelStep(ctx, pipeline, state, stageNames) {
|
|
|
8386
8441
|
error: stageResult.reason || "timed out"
|
|
8387
8442
|
});
|
|
8388
8443
|
if (!isAdvisory) {
|
|
8389
|
-
criticalFailures.push({
|
|
8444
|
+
criticalFailures.push({
|
|
8445
|
+
name: stageName,
|
|
8446
|
+
reason: stageResult.reason || "timed out"
|
|
8447
|
+
});
|
|
8390
8448
|
}
|
|
8391
8449
|
} else if (stageResult.outcome === "failed") {
|
|
8392
8450
|
const isAdvisory = pipeline.stages.get(stageName)?.advisory === true;
|
|
@@ -8395,20 +8453,28 @@ async function executeParallelStep(ctx, pipeline, state, stageNames) {
|
|
|
8395
8453
|
state: "failed",
|
|
8396
8454
|
error: stageResult.reason || "failed"
|
|
8397
8455
|
});
|
|
8398
|
-
advisoryFailures.push({
|
|
8456
|
+
advisoryFailures.push({
|
|
8457
|
+
name: stageName,
|
|
8458
|
+
reason: stageResult.reason || "failed"
|
|
8459
|
+
});
|
|
8399
8460
|
} else {
|
|
8400
8461
|
state = updateStage(state, stageName, {
|
|
8401
8462
|
state: "failed",
|
|
8402
8463
|
error: stageResult.reason || "failed"
|
|
8403
8464
|
});
|
|
8404
|
-
criticalFailures.push({
|
|
8465
|
+
criticalFailures.push({
|
|
8466
|
+
name: stageName,
|
|
8467
|
+
reason: stageResult.reason || "failed"
|
|
8468
|
+
});
|
|
8405
8469
|
}
|
|
8406
8470
|
}
|
|
8407
8471
|
}
|
|
8408
8472
|
if (criticalFailures.length > 0) {
|
|
8409
8473
|
const errors = criticalFailures.map((f) => f.reason).join("; ");
|
|
8410
8474
|
const names = criticalFailures.map((f) => f.name);
|
|
8411
|
-
logger.error(
|
|
8475
|
+
logger.error(
|
|
8476
|
+
` \u274C Parallel stages [${names.join(", ")}] failed: ${errors}`
|
|
8477
|
+
);
|
|
8412
8478
|
if (ctx.input.issueNumber) {
|
|
8413
8479
|
setLifecycleLabel(ctx.input.issueNumber, "kody:failed");
|
|
8414
8480
|
}
|
|
@@ -8434,7 +8500,12 @@ async function handleStageResult(ctx, pipeline, state, stageName, result, def) {
|
|
|
8434
8500
|
cost: result.cost,
|
|
8435
8501
|
sessionId: result.sessionId
|
|
8436
8502
|
});
|
|
8437
|
-
logStageComplete(
|
|
8503
|
+
logStageComplete(
|
|
8504
|
+
stageName,
|
|
8505
|
+
ctx.taskId,
|
|
8506
|
+
"completed",
|
|
8507
|
+
elapsed ? elapsed * 1e3 : void 0
|
|
8508
|
+
);
|
|
8438
8509
|
if (result.sessionId) {
|
|
8439
8510
|
ctx.lastSessionId = result.sessionId;
|
|
8440
8511
|
}
|