Refactor pipeline task handling and UI flows

This commit is contained in:
2026-06-13 21:09:49 +02:00
parent 21c7e4c9a4
commit ff4c572157
24 changed files with 1346 additions and 236 deletions

View File

@@ -0,0 +1,92 @@
import assert from "node:assert/strict";
import { existsSync, readFileSync } from "node:fs";
import path from "node:path";
import test from "node:test";
const source = (relativePath: string) => {
return readFileSync(path.join(process.cwd(), ...relativePath.split("/")), "utf8");
};
const fileExists = (relativePath: string) => {
return existsSync(path.join(process.cwd(), ...relativePath.split("/")));
};
test("Convex Workflow and Workpool dependencies and components are registered", () => {
const packageSource = source("package.json");
const configSource = source("convex/convex.config.ts");
assert.match(packageSource, /"@convex-dev\/workflow"/);
assert.match(packageSource, /"@convex-dev\/workpool"/);
assert.match(configSource, /from\s+["@']@convex-dev\/workflow\/convex\.config["@']/);
assert.match(configSource, /from\s+["@']@convex-dev\/workpool\/convex\.config["@']/);
assert.match(configSource, /app\.use\(workflow/);
assert.match(configSource, /app\.use\(auditWorkpool/);
});
test("audit workflow defines durable workflow manager with retrying workpool options", () => {
assert.equal(fileExists("convex/auditWorkflow.ts"), true);
const workflowSource = source("convex/auditWorkflow.ts");
assert.match(workflowSource, /WorkflowManager/);
assert.match(workflowSource, /components\.workflow/);
assert.match(workflowSource, /workpoolOptions/);
assert.match(workflowSource, /maxParallelism:\s*3/);
assert.match(workflowSource, /retryActionsByDefault:\s*true/);
assert.match(workflowSource, /maxAttempts:\s*3/);
assert.match(workflowSource, /initialBackoffMs:\s*1000/);
assert.match(workflowSource, /base:\s*2/);
assert.match(workflowSource, /step\.runAction/);
assert.match(workflowSource, /step\.runMutation/);
assert.match(workflowSource, /Promise\.all/);
});
test("requestLeadAudit creates a visible agentRun and starts the workflow", () => {
const pageSpeedSource = source("convex/pageSpeed.ts");
assert.match(pageSpeedSource, /internal\.auditWorkflow\.startLeadAuditWorkflow/);
assert.match(pageSpeedSource, /type:\s*"audit"/);
assert.match(pageSpeedSource, /progressLabel:\s*"Audit vorbereitet"/);
assert.match(pageSpeedSource, /workflowId/);
});
test("workflow PageSpeed start accepts root runs already marked running", () => {
const pageSpeedSource = source("convex/pageSpeed.ts");
assert.match(
pageSpeedSource,
/run\.status\s*!==\s*"pending"[\s\S]*run\.status\s*!==\s*"failed"[\s\S]*run\.status\s*!==\s*"running"/,
);
});
test("workflow failure progress stays on the failing step instead of jumping to quality review", () => {
const workflowSource = source("convex/auditWorkflow.ts");
const catchIndex = workflowSource.indexOf("} catch (error)");
assert.notEqual(catchIndex, -1, "Expected workflow catch block.");
const nextExportIndex = workflowSource.indexOf("export const startLeadAuditWorkflow", catchIndex);
assert.notEqual(nextExportIndex, -1, "Expected workflow catch block end.");
const catchSource = workflowSource.slice(catchIndex, nextExportIndex);
assert.doesNotMatch(catchSource, /progressPatch\(args\.runId,\s*"qualityReview"\)/);
assert.doesNotMatch(catchSource, /progressStep|progressTotal|progressLabel|progressPercent/);
assert.match(catchSource, /status:\s*"failed"/);
});
test("audit dashboard query includes root audit runs and exposes progress and retry fields", () => {
const auditsSource = source("convex/audits.ts");
assert.match(auditsSource, /\.eq\("type",\s*"audit"\)/);
assert.match(auditsSource, /kind:\s*"generation"/);
assert.match(auditsSource, /runType/);
assert.match(auditsSource, /progress:/);
assert.match(auditsSource, /retry:/);
assert.match(auditsSource, /canRetry/);
});
test("audit retry mutation restarts final failed or canceled runs through workflow", () => {
const auditsSource = source("convex/audits.ts");
assert.match(auditsSource, /export const retryAuditRun = mutation/);
assert.match(auditsSource, /requireOperator\(ctx\)/);
assert.match(auditsSource, /status !== "failed"[\s\S]*status !== "canceled"/);
assert.match(auditsSource, /internal\.auditWorkflow\.restartAuditWorkflow/);
});