feat(cli): add bulk cancel, --status filter, fix step JSON hydration#1467
feat(cli): add bulk cancel, --status filter, fix step JSON hydration#1467VaguelySerious merged 2 commits intomainfrom
Conversation
- Bulk cancel: `workflow cancel --status=running` cancels all matching runs with confirmation prompt (bypass with -y). Supports --workflowName and --limit. - Status filter: `workflow inspect runs --status=completed` filters by status. - Fix: `inspect steps --withData --json` now shows hydrated values, not raw bytes. Signed-off-by: Lucas Ralph <lucas@vercel.com> Signed-off-by: Lucas Ralph <lucas.ralph@vercel.com>
🦋 Changeset detectedLatest commit: d004676 The changes in this PR will be included in the next version bump. This PR includes changesets to release 16 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
cc @vercel/workflow — ready for review when you get a chance |
📊 Benchmark Results
workflow with no steps💻 Local Development
▲ Production (Vercel)
workflow with 1 step💻 Local Development
▲ Production (Vercel)
workflow with 10 sequential steps💻 Local Development
▲ Production (Vercel)
workflow with 25 sequential steps💻 Local Development
▲ Production (Vercel)
workflow with 50 sequential steps💻 Local Development
▲ Production (Vercel)
Promise.all with 10 concurrent steps💻 Local Development
▲ Production (Vercel)
Promise.all with 25 concurrent steps💻 Local Development
▲ Production (Vercel)
Promise.all with 50 concurrent steps💻 Local Development
▲ Production (Vercel)
Promise.race with 10 concurrent steps💻 Local Development
▲ Production (Vercel)
Promise.race with 25 concurrent steps💻 Local Development
▲ Production (Vercel)
Promise.race with 50 concurrent steps💻 Local Development
▲ Production (Vercel)
workflow with 10 sequential data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
workflow with 25 sequential data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
workflow with 50 sequential data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
workflow with 10 concurrent data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
workflow with 25 concurrent data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
workflow with 50 concurrent data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
Stream Benchmarks (includes TTFB metrics)workflow with stream💻 Local Development
▲ Production (Vercel)
stream pipeline with 5 transform steps (1MB)💻 Local Development
▲ Production (Vercel)
10 parallel streams (1MB each)💻 Local Development
▲ Production (Vercel)
fan-out fan-in 10 streams (1MB each)💻 Local Development
▲ Production (Vercel)
SummaryFastest Framework by WorldWinner determined by most benchmark wins
Fastest World by FrameworkWinner determined by most benchmark wins
Column Definitions
Worlds:
❌ Some benchmark jobs failed:
Check the workflow run for details. |
🧪 E2E Test Results❌ Some tests failed Summary
❌ Failed Tests▲ Vercel Production (1 failed)nuxt (1 failed):
🌍 Community Worlds (56 failed)mongodb (3 failed):
redis (2 failed):
turso (51 failed):
Details by Category❌ ▲ Vercel Production
✅ 💻 Local Development
✅ 📦 Local Production
✅ 🐘 Local Postgres
✅ 🪟 Windows
❌ 🌍 Community Worlds
✅ 📋 Other
❌ Some E2E test jobs failed:
Check the workflow run for details. |
karthikscale3
left a comment
There was a problem hiding this comment.
One minor nit, otherwise looks good to me:
Non-TTY prompt behavior — promptConfirm() returns true when !process.stdin.isTTY, meaning non-interactive environments will auto-confirm. This is arguably a dangerous default — a CI script calling workflow cancel --status=running without -y would silently cancel all matching runs. Should we flip this?
…ts (CI, pipes, cron) without requiring the `-y` flag, risking accidental mass cancellation of workflow runs. This commit fixes the issue reported at packages/cli/src/commands/cancel.ts:175 ## Bug Analysis The `promptConfirm` function in `packages/cli/src/commands/cancel.ts` (line 172-189) is designed to ask the user for interactive confirmation before bulk-cancelling workflow runs. However, when `process.stdin.isTTY` is `false` (as in CI pipelines, cron jobs, piped commands, etc.), the function returns `true` — meaning it auto-confirms the destructive bulk cancel operation without any user interaction. The control flow is: 1. If `--confirm`/`-y` flag is passed → skip prompt entirely, proceed with cancel (line 138) 2. If `-y` is NOT passed → call `promptConfirm()` (line 140) 3. Inside `promptConfirm()`: if stdin is not a TTY → return `true` (auto-confirm) ← **BUG** This means running `workflow cancel --status=running` in a CI script (where stdin is not a TTY) would silently cancel ALL matching runs without any confirmation, even though the user did NOT pass the `-y` flag. The `-y`/`--confirm` flag exists precisely to explicitly opt into non-interactive confirmation, but the non-TTY code path bypasses this safety mechanism entirely. **Impact**: A user running a bulk cancel command in a CI pipeline or piped script without `-y` would expect the command to either prompt (and fail/abort since there's no TTY) or refuse to proceed. Instead, it silently proceeds with the destructive operation. ## Fix Changed the return value in the non-TTY branch of `promptConfirm` from `true` to `false`. Now when stdin is not a TTY and `-y` was not passed: * `promptConfirm` returns `false` * The caller logs "Aborted." and returns without cancelling anything * Users must explicitly pass `-y`/`--confirm` to perform bulk cancels in non-interactive environments This is the standard safe pattern: default-deny for destructive operations when interactive confirmation cannot be obtained. The prompt's default is already `[y/N]` (default No), so aborting in non-TTY is consistent with that default. Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com> Co-authored-by: VaguelySerious <mittgfu@gmail.com>
|
Since there was no update in this PR for 3 days, I am applying the Vade suggestion and merging this |
* origin/main: [ai] Add experimental_context to DurableAgentOptions (#1489) [ai] Expose configured tools on DurableAgent instances (#1488) fix(builders): catch node builtin usage when entry fields diverge (#1455) [web-shared] Fix timeline duration format and precision (#1482) [cli] Add bulk cancel, --status filter, fix step JSON hydration (#1467) [utils] Re-export parseName utilities and add workflow/observability module (#1453) [o11y] Polish display when run data has expired (#1438) Add CommonJS `require()` support for class serialization detection in SWC plugin (#1144) fix(next): stabilize deferred canary e2e in nextjs workbenches (#1468) [web] Support legacy newline-delimited stream format in `useStreamReader` (#1473) Revert "Add support for calling start() inside workflow functions (#1133)" (#1475)
…naygp-db9e68c1 * 'main' of https://github.com/vercel/workflow: (32 commits) chore: bump @nestjs/* to ^11.1.17 (#1497) chore: bump hono to ^4.12.8 (#1495) Revert "Inline class serialization registration to fix 3rd-party package supp…" (#1493) [world] Add stream pagination and metadata endpoints (#1470) [cli] [world-local] Ensure update checks don't suggest upgrading from stable release to pre-releases (#1490) Remove NestJS Vercel integration while in experimental phase (#1485) feat: export semantic error types and add API reference docs (#1447) feat: enforce max queue deliveries in handlers with graceful failure (#1344) [world-postgres] Migrate client from `postgres.js` to `pg` (#1484) Inline class serialization registration to fix 3rd-party package support (#1480) [ai] Add experimental_context to DurableAgentOptions (#1489) [ai] Expose configured tools on DurableAgent instances (#1488) fix(builders): catch node builtin usage when entry fields diverge (#1455) [web-shared] Fix timeline duration format and precision (#1482) [cli] Add bulk cancel, --status filter, fix step JSON hydration (#1467) [utils] Re-export parseName utilities and add workflow/observability module (#1453) [o11y] Polish display when run data has expired (#1438) Add CommonJS `require()` support for class serialization detection in SWC plugin (#1144) fix(next): stabilize deferred canary e2e in nextjs workbenches (#1468) [web] Support legacy newline-delimited stream format in `useStreamReader` (#1473) ...
…naygp-6fadd605 * 'main' of https://github.com/vercel/workflow: (73 commits) chore: bump next to 16.2.1 and fix deferred build (#1496) chore: bump nitropack to ^2.13.1 (#1501) chore: bump nuxt ecosystem dependencies (#1500) chore: bump sveltekit ecosystem (#1498) chore: bump express and fastify in workbenches (#1499) chore: bump @nestjs/* to ^11.1.17 (#1497) chore: bump hono to ^4.12.8 (#1495) Revert "Inline class serialization registration to fix 3rd-party package supp…" (#1493) [world] Add stream pagination and metadata endpoints (#1470) [cli] [world-local] Ensure update checks don't suggest upgrading from stable release to pre-releases (#1490) Remove NestJS Vercel integration while in experimental phase (#1485) feat: export semantic error types and add API reference docs (#1447) feat: enforce max queue deliveries in handlers with graceful failure (#1344) [world-postgres] Migrate client from `postgres.js` to `pg` (#1484) Inline class serialization registration to fix 3rd-party package support (#1480) [ai] Add experimental_context to DurableAgentOptions (#1489) [ai] Expose configured tools on DurableAgent instances (#1488) fix(builders): catch node builtin usage when entry fields diverge (#1455) [web-shared] Fix timeline duration format and precision (#1482) [cli] Add bulk cancel, --status filter, fix step JSON hydration (#1467) ... # Conflicts: # packages/core/src/runtime/start.ts
Description
Three changes to the CLI:
1. Bulk cancel (
workflow cancel --status=<status>)--statusand/or--workflowNamefilters-y/--confirmfor CI)--limitcontrols max runs per batch (default 50), warns if more match2. Status filter for inspect runs (
--status)--statusflag onworkflow inspect runsListWorkflowRunsParams.statusin World API3. Fix: step I/O hydration in JSON output
workflow inspect steps --withData --jsonnow shows hydrated JS values{"0":100,...})inspect runs --jsonWhy: Needed to manually cancel 40+ stuck runs one at a time. The World API already supports status filtering — the CLI just didn't expose it.
CLI Output Examples
Bulk cancel 3 running workflows:
hasMore warning (more runs than --limit):
No matching runs:
Error — no filters provided:
--status filter on inspect runs:
Step hydration fix (--json shows actual values, not byte arrays):
{ "stepName": "step//./workflows/98_duplicate_case//add", "status": "completed", "input": { "args": [205, 5] }, "output": 210 }Previously
"output"would show{"0": 210}(raw devalue bytes).How did you test your changes?
Reusable E2E test script (
packages/cli/test-bulk-cancel.sh) against local world backend — 8/8 passing:--statusfilter on inspect runs--status=running(3 workflows)--workflowNamefilterhasMorewarning with--limit=1Run with:
cd packages/cli && pnpm build && bash test-bulk-cancel.sh(requires workbench on :3000)Known limitations / follow-ups
--workflowNamerequires full WDK path —sleepingWorkflowwon't matchworkflow//./workflows/99_e2e//sleepingWorkflow. The World API does exact match. Could add substring/suffix matching in a follow-up.-yauto-confirm. ThepromptConfirm()function is standard readline, but no automated TTY test exists.--backend local— Vercel backend uses different workflow name formats. Status filter should work identically since it passes through to the same World API.cancel --status=completedlists runs and attempts cancel, but each cancel fails with "Cannot transition from terminal state". Could filter these out upfront or add a pre-check.PR Checklist - Required to merge
pnpm changesetwas run to create a changelog for this PR@vercel/workflowin a comment once the PR is ready🤖 Generated with Claude Code