feat: add wmill job rerun subcommand (#9275)

* feat: add wmill job rerun subcommand

* feat: add wmill job restart subcommand for flow restart-at-step
This commit is contained in:
hugocasa
2026-05-25 12:10:02 +02:00
committed by Diego Imbert
parent 767eed9983
commit 45ac955799
6 changed files with 90 additions and 1 deletions
+72 -1
View File
@@ -376,6 +376,63 @@ async function cancel(
log.info(colors.green(`Job ${id} canceled.`));
}
async function rerun(
opts: GlobalOptions,
id: string
) {
log.setSilent(true);
opts = await mergeConfigWithConfigFile(opts);
const workspace = await resolveWorkspace(opts);
await requireLogin(opts);
const response = await wmill.batchReRunJobs({
workspace: workspace.workspaceId,
requestBody: {
job_ids: [id],
script_options_by_path: {},
flow_options_by_path: {},
},
});
const newIds: string[] = [];
const errorLines: string[] = [];
for (const line of String(response).split("\n")) {
const trimmed = line.trim();
if (!trimmed) continue;
if (trimmed.startsWith("Error:")) errorLines.push(trimmed);
else newIds.push(trimmed);
}
for (const err of errorLines) log.error(err);
if (newIds.length === 0) {
throw new Error(`Failed to re-run job ${id}.`);
}
console.log(newIds[0]);
}
async function restart(
opts: GlobalOptions & { step: string; iteration?: number },
id: string
) {
log.setSilent(true);
opts = await mergeConfigWithConfigFile(opts);
const workspace = await resolveWorkspace(opts);
await requireLogin(opts);
const newId = await wmill.restartFlowAtStep({
workspace: workspace.workspaceId,
id,
requestBody: {
step_id: opts.step,
branch_or_iteration_n: opts.iteration,
},
});
console.log(newId);
}
// Shared list options to avoid repetition between default action and list subcommand
const listOptions = (cmd: Command) =>
cmd
@@ -410,6 +467,20 @@ const command = listOptions(new Command()
.command("cancel", "Cancel a running or queued job")
.arguments("<id:string>")
.option("--reason <reason:string>", "Reason for cancellation")
.action(cancel as any);
.action(cancel as any)
.command(
"rerun",
"Re-run a completed job with the same args. Prints the new job UUID on stdout."
)
.arguments("<id:string>")
.action(rerun as any)
.command(
"restart",
"Restart a completed flow at a given top-level step. Prints the new flow job UUID on stdout."
)
.arguments("<id:string>")
.option("--step <stepId:string>", "Top-level step id to restart the flow from", { required: true })
.option("--iteration <n:number>", "For a top-level branchall or for-loop step, the iteration to restart at")
.action(restart as any);
export default command;
+2
View File
@@ -147,6 +147,8 @@ When the user reports a script or flow failure, is investigating unexpected outp
- \`wmill job logs <id>\` — stdout/stderr; for flows, aggregates every step's logs
- \`wmill job result <id>\` — JSON result of a completed job
- \`wmill job cancel <id>\` — stop a running or queued job
- \`wmill job rerun <id>\` — re-run a completed job with the same args (single-job equivalent of the frontend "rerun" button)
- \`wmill job restart <id> --step <step-id> [--iteration <n>]\` — restart a completed flow at a top-level step (for nested-container restart, use the UI)
For flow failures, start with \`wmill job get <id>\` to identify the failing step and its sub-job ID, then \`wmill job logs <sub-job-id>\` to drill in.
+4
View File
@@ -6948,6 +6948,10 @@ Manage jobs (list, inspect, cancel)
- \`job logs <id:string>\` - Get job logs. For flows: aggregates all step logs
- \`job cancel <id:string>\` - Cancel a running or queued job
- \`--reason <reason:string>\` - Reason for cancellation
- \`job rerun <id:string>\` - Re-run a completed job with the same args. Prints the new job UUID on stdout.
- \`job restart <id:string>\` - Restart a completed flow at a given top-level step. Prints the new flow job UUID on stdout.
- \`--step <stepId:string>\` - Top-level step id to restart the flow from
- \`--iteration <n:number>\` - For a top-level branchall or for-loop step, the iteration to restart at
### jobs
@@ -334,6 +334,10 @@ Manage jobs (list, inspect, cancel)
- `job logs <id:string>` - Get job logs. For flows: aggregates all step logs
- `job cancel <id:string>` - Cancel a running or queued job
- `--reason <reason:string>` - Reason for cancellation
- `job rerun <id:string>` - Re-run a completed job with the same args. Prints the new job UUID on stdout.
- `job restart <id:string>` - Restart a completed flow at a given top-level step. Prints the new flow job UUID on stdout.
- `--step <stepId:string>` - Top-level step id to restart the flow from
- `--iteration <n:number>` - For a top-level branchall or for-loop step, the iteration to restart at
### jobs
+4
View File
@@ -2865,6 +2865,10 @@ Manage jobs (list, inspect, cancel)
- \`job logs <id:string>\` - Get job logs. For flows: aggregates all step logs
- \`job cancel <id:string>\` - Cancel a running or queued job
- \`--reason <reason:string>\` - Reason for cancellation
- \`job rerun <id:string>\` - Re-run a completed job with the same args. Prints the new job UUID on stdout.
- \`job restart <id:string>\` - Restart a completed flow at a given top-level step. Prints the new flow job UUID on stdout.
- \`--step <stepId:string>\` - Top-level step id to restart the flow from
- \`--iteration <n:number>\` - For a top-level branchall or for-loop step, the iteration to restart at
### jobs
@@ -339,6 +339,10 @@ Manage jobs (list, inspect, cancel)
- `job logs <id:string>` - Get job logs. For flows: aggregates all step logs
- `job cancel <id:string>` - Cancel a running or queued job
- `--reason <reason:string>` - Reason for cancellation
- `job rerun <id:string>` - Re-run a completed job with the same args. Prints the new job UUID on stdout.
- `job restart <id:string>` - Restart a completed flow at a given top-level step. Prints the new flow job UUID on stdout.
- `--step <stepId:string>` - Top-level step id to restart the flow from
- `--iteration <n:number>` - For a top-level branchall or for-loop step, the iteration to restart at
### jobs