Per-deployment SDK tarballs are now built by the tarballs/ app, not by
docs/. Remove the outdated reference to docs/scripts/pack.ts (which no
longer exists) and point readers at tarballs/README.md.
* ci: upgrade pnpm/action-setup to v5 and read version from package.json (#1785)
* ci: upgrade pnpm/action-setup to v6 and read version from package.json
Removes hardcoded pnpm version (10.14.0) from all workflows and instead
reads the version from the packageManager field in package.json, so CI
stays in sync with the version used locally.
* ci: update setup-workflow-dev composite action to use pnpm/action-setup@v6
Also removes the pnpm-version input since the action now reads the
version from package.json#packageManager.
* ci: downgrade pnpm/action-setup to v5
v6 installs pnpm 11 RC/beta, which has a regression
(pnpm/pnpm#11264, pnpm/action-setup#225/#227/#228) that causes
'ERR_PNPM_BROKEN_LOCKFILE: expected a single document in the stream'
when the project's packageManager pins a 10.x pnpm version. v5 is the
latest stable release before v6 and supports reading the version from
package.json#packageManager.
* ci: stop using Release App token in release workflows (#1866)
The Release App has been temporarily removed. Switch the Release and
Backport workflows to use the default GITHUB_TOKEN, and disable the
cross-repo Front dispatch workflow until the App is restored.
Also add a workflow_dispatch trigger to release.yml so the Version
Packages PR can be created/updated manually (since pushes made by
GITHUB_TOKEN do not trigger downstream workflow runs).
* ci: use GitHub API commit mode for changesets action (#1867)
The repo enforces "Commits must have verified signatures" via an
org/enterprise-level ruleset, which blocks unsigned commits pushed via
the Git CLI by GITHUB_TOKEN. Switching the changesets action to
commitMode: github-api makes commits GPG-signed by GitHub.
* Add changeset for backport
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Nathan Rajlich <n@n8.io>
---------
Signed-off-by: Nathan Rajlich <n@n8.io>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
The docs Next.js app is deployed only from main. Remove the app code
(components, layouts, configs, styles) from stable to eliminate
cherry-pick conflicts during backports. Keep docs/content/ which
contains the markdown files that are bundled into npm packages via
prepack scripts for AI agent consumption.
Changesets already handles dist-tags correctly:
- On main: pre-release mode publishes with the 'beta' tag
- On stable: GA publishes default to the 'latest' tag
* test: improve e2e test failure diagnostics with run context and GitHub annotations
When e2e tests fail, automatically dump workflow run diagnostics (status,
input/output, error details, event timeline, dashboard link) to the CI
logs. Emit GitHub Actions annotations that surface on PR file diffs.
Fix collectedRunIds which was declared but never populated, enabling
observability links in the PR comment. Enrich the aggregation script
to include run IDs and dashboard URLs for failed tests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: increase diagnostics hook timeout and fix flaky Vercel Prod tests
- Increase onTestFailed hook timeout to 30s (default was 10s) so
diagnostics can fetch run data even after slow test timeouts
- parallelSleepWorkflow: increase elapsed threshold from 10s to 25s to
accommodate Vercel cold start latency
- webhookWorkflow: increase hook polling deadline from 30s to 60s and
test timeout from 60s to 120s for slow Vercel webhook registration
- readableStreamWorkflow: stop reading once expected content is received
instead of waiting for stream close (which can hang on Vercel), and
increase test timeout to 120s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: emit ::error annotations via process.stdout.write to bypass vitest ANSI prefix
Vitest's console interceptor prepends ANSI escape codes to console.log
output, which prevents GitHub Actions from parsing ::error workflow
commands. Use process.stdout.write() directly to ensure clean output.
Also enhance the custom reporter to emit annotations in onFinished
(which runs after vitest output is complete) as a reliable fallback,
and enrich failure data from the diagnostics sidecar.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: only show observability links for vercel-prod test failures
Community world and local tests don't run on Vercel's backend, so
dashboard links are meaningless for those categories. Previously,
test name collisions across sidecar files could cause community
test failures to show Vercel dashboard URLs from vercel-prod runs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: link annotations to test files instead of symlinked workflow sources
The workflow source files in workbench/ are symlinks that GitHub can't
resolve, causing annotations to show raw paths like #L0 instead of
linking to code. Now:
- utils.ts: omit file= from onTestFailed annotations (just show title)
- github-reporter.ts: use the actual test file path (e.g.
packages/core/e2e/e2e.test.ts) which GitHub can resolve
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Set setupGitUser: false on changesets/action to prevent it from
overwriting our git config with the hardcoded github-actions[bot]
identity. The git identity is now configured in a prior step using
the app-slug output from actions/create-github-app-token.
Set git user.name and user.email so that the 'Version Packages' commit
created by changesets/action is attributed to the app's bot account
instead of the default github-actions[bot].
Replace GH_TOKEN_PULL_REQUESTS (shared org PAT) with a dedicated GitHub
App token to avoid rate limiting from noisy neighbors. The app token is
generated per-run via actions/create-github-app-token, providing its own
rate limit bucket and short-lived credentials.
* fix(ci): fix npm 'latest' dist-tag not being set during release
The OIDC trusted publishing change (a78af46f) removed NPM_TOKEN from the
changesets/action step and added registry-url to actions/setup-node. This
caused the 'Add latest dist-tag' step to break for the unscoped 'workflow'
package:
- actions/setup-node writes an .npmrc at a temp path that references
${NODE_AUTH_TOKEN}, and sets NPM_CONFIG_USERCONFIG to point at it
- The dist-tag step was writing its own ~/.npmrc using NPM_TOKEN, but npm
ignored it because NPM_CONFIG_USERCONFIG overrides the default path
- The OIDC token left over in NODE_AUTH_TOKEN worked for @workflow/* scoped
packages (which already had 'latest' set) but returned E401 for the
unscoped 'workflow' package
Fix: set NODE_AUTH_TOKEN to NPM_TOKEN_ELEVATED secret so npm picks up the
correct token from the .npmrc that actions/setup-node already configured.
Also fix silent failures: replace the piped while-read loop (which runs in
a subshell and swallows exit codes) with a for loop that tracks failures
and exits non-zero if any dist-tag operation fails.
* use process substitution instead of word-splitting for loop
* Fix og route handling in i18n middleware
* Add docs CI smoke test for OG and sitemap
* Run docs OG checks against Vercel preview
* Refactor docs CI checks and rename smoke test
* Use docs Vercel token for preview checks
* Expand docs OG smoke coverage
* Check docs HTML OG metadata
* fix: use types.isNativeError() for cross-VM Error serialization
FatalError was not properly serialized when passed from workflow code into a step function because the Error reducer checked `value instanceof global.Error` where `global` is the VM's globalThis. Errors created in the host context (like FatalError from @workflow/errors) have a different Error prototype than the VM context, so the instanceof check returned false and the error was silently dropped.
Replaced with `types.isNativeError()` from `node:util` which uses V8's internal type tag and works across VM context boundaries.
* ci: don't cancel in-progress CI runs on main branch
Add missing WORKFLOW_PUBLIC_MANIFEST env var to e2e-community-world.yml.
The e2e tests fetch the workflow manifest from
/.well-known/workflow/v1/manifest.json, but this endpoint is only
exposed when WORKFLOW_PUBLIC_MANIFEST=1 is set. Every other CI workflow
(tests.yml, benchmarks.yml, benchmark-community-world.yml) already sets
this variable, but it was missing from the community world e2e workflow.
https://claude.ai/code/session_01GezavpthQcEpyYVisScncM
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
Refactors the E2E tests to call `start()` from `workflow/api` directly instead of going through the `/api/trigger` HTTP endpoint in each workbench app. This removes a layer of indirection — the tests now use the same API that users would use to start workflows programmatically.
### Before
```ts
const run = await triggerWorkflow('addTenWorkflow', [123]);
const returnValue = await getWorkflowReturnValue(run.runId);
```
- `triggerWorkflow()` sent an HTTP POST to `/api/trigger` on the workbench app
- The workbench app looked up the workflow function, called `start()`, and returned the run ID
- `getWorkflowReturnValue()` polled `GET /api/trigger?runId=...` until the workflow completed
### After
```ts
const run = await start(await e2e('addTenWorkflow'), [123]);
const returnValue = await run.returnValue;
```
- `e2e()` / `getWorkflowMetadata()` fetches the manifest from `/.well-known/workflow/v1/manifest.json` to look up the correct `workflowId`
- `start()` is called directly from the test process via the configured World
- `run.returnValue` polls for completion via the World (no HTTP polling endpoint needed)
### Changes
**`packages/core/e2e/e2e.test.ts`**
- Removed `triggerWorkflow()` and `getWorkflowReturnValue()` helpers
- Added `fetchManifest()` to fetch and cache the workflow manifest from the deployment
- Added `getWorkflowMetadata(file, fn)` to look up `{ workflowId }` from the manifest
- Added `e2e(fn)` shorthand for the common case of `workflows/99_e2e.ts`
- All tests call `start()` and `run.returnValue` directly
- Error tests use `.catch()` to inspect `WorkflowRunFailedError`
- Output stream tests use `run.getReadable()` directly (skipped on local world where cross-process streaming isn't supported)
- `beforeAll` configures the local World with the correct data directory and base URL
- Pages Router tests use `startWorkflowViaHttp()` to specifically validate the HTTP trigger path
**Workbench apps (hono, express, fastify, nest)**
- Removed `/api/trigger` route handlers
- Kept `/api/hook`, `/api/test-direct-step-call`, `/api/test-health-check` endpoints
- Re-added `_workflows.js` side-effect import for hono/express/fastify to maintain Nitro's HMR dependency graph
**Deleted trigger-only route files** from: nextjs-turbopack, nextjs-webpack, vite, sveltekit, astro, nuxt, nitro-v2, nitro-v3, example
**`.github/workflows/tests.yml`**
- Added `WORKFLOW_PUBLIC_MANIFEST: '1'` to all E2E test jobs
### Dependencies
Stacked on #963 which adds `WORKFLOW_PUBLIC_MANIFEST` support to all framework builders.
* Add 50, 100, 500 concurrent step benchmarks
Enable Promise.all and Promise.race benchmarks for 50, 100, and 500
concurrent steps (previously 100+ were skipped).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add 50, 100, 500 sequential step benchmarks
Extends the sequential step benchmarks to test workflows with 50, 100,
and 500 sequential steps in addition to the existing 10 step test.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add full/quick benchmark suite toggle for CI
- Add BENCHMARK_FULL_SUITE env var to control which benchmarks run
- Quick suite (default for PRs): 10, 25, 50 step benchmarks
- Full suite (main branch, manual dispatch): adds 100, 500 step benchmarks
- Add workflow_dispatch input to manually trigger full suite from GitHub UI
- Skip 100+ sequential and concurrent step benchmarks by default
This keeps PR benchmarks fast while allowing full stress testing on demand.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add 25 sequential steps benchmark
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix benchmark API calls to use binary format
PR #853 changed the workflow trigger API to expect binary data
(application/octet-stream) instead of JSON. The e2e tests were updated
but the benchmark file was missed, causing all benchmarks to fail
silently since Jan 28.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Only run full benchmark suite on manual dispatch
Remove automatic full suite on main branch pushes - only run full suite
when manually triggered with full_suite=true.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Added `WORKFLOW_SERVER_URL_OVERRIDE` configuration to the Vercel world adapter and removed the deprecated `WORKFLOW_VERCEL_SKIP_PROXY` and `WORKFLOW_VERCEL_BACKEND_URL` environment variables.
### What changed?
- Added a changeset for a patch release across multiple packages
- Removed `WORKFLOW_VERCEL_SKIP_PROXY` environment variable from GitHub workflow tests
- Removed `WORKFLOW_VERCEL_BACKEND_URL` from environment variables in CLI and core packages
- Simplified the URL resolution logic in the Vercel world adapter
- Added support for a `WORKFLOW_SERVER_URL_OVERRIDE` constant for testing against different workflow-server versions
- Added the `x-vercel-workflow-api-url` header when the URL override is set
### How to test?
1. Verify that Vercel deployments continue to work without the removed environment variables
2. Test with a custom workflow server URL by setting the `WORKFLOW_SERVER_URL_OVERRIDE` constant in the world-vercel package
### Why make this change?
This change simplifies the configuration for the Vercel world adapter by removing deprecated environment variables and standardizing on a cleaner approach for specifying the workflow API URL. The new implementation automatically determines whether to use the proxy based on project configuration, making it more intuitive and reducing the need for explicit configuration.
* Refactor e2e tests for errors
* Improve step error tests to check workflow return value
Step error workflows now catch the error and return message/stack,
making assertions cleaner. Tests verify both:
- Workflow return value (caught error message)
- CLI step result (original stack with function names)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add assertion for stack trace in caught step error
With the fix in step.ts that propagates original stack traces,
we can now verify that caught step errors include function names
directly in the workflow return value (not just via CLI).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* logging
* Fix: When a step handler is re-invoked after max retries are exhausted, the step_failed event doesn't include a stack trace, breaking stack trace propagation for this edge case.
This commit fixes the issue reported at packages/core/src/runtime/step-handler.ts:127-146
## Stack trace loss in step_failed event when max retries are exceeded
**What fails:** Step handler does not include stack property in step_failed event when step is re-invoked after max retries exhausted, causing FatalError in workflow to lose original stack trace
**How to reproduce:**
1. Create a step that always fails with an error that includes a stack trace
2. Exhaust all retry attempts (e.g., maxRetries = 3, so 4 total attempts)
3. The step handler is re-invoked (attempt > maxRetries + 1)
4. This triggers the edge case at lines 127-146 in step-handler.ts
5. A step_failed event is created with fatal: true but without stack property
6. When step.ts processes this event (lines 103-104), the stack remains unset since event.eventData.stack is undefined
**Result:** FatalError created in workflow has default stack (from step.ts) instead of original error stack from step execution
**Expected:** Stack trace should be propagated consistently across all error paths. All other step_failed events with fatal: true include stack property (lines 311-313 and 351-353), but edge case was missing it.
**Root cause:** When step handler is re-invoked after max retries exhausted (attempt > maxRetries + 1), the code creates a step_failed event without including step.error?.stack, which contains the previous error information from the last failed attempt. Other code paths capture this correctly.
Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>
* add withData
* Enable source maps for step bundles and validate in e2e tests
- Move sourcemap generation from intermediate workflow bundle to steps bundle
- Enhance step error tests to validate function names and source files in stack traces
- Remove isLocalDeployment() checks since source maps now work in dev mode
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add changeset for step bundle source maps
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add changeset for core package e2e test improvements
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Enable source maps in CI e2e tests
Add NODE_OPTIONS="--enable-source-maps" to all e2e test jobs to ensure
stack traces show original source file paths.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix step error source map checks for local prod builds
Add hasStepSourceMaps() helper that correctly identifies when source maps
are expected to work:
- Vercel prod: works (production builds have proper source maps)
- Local dev: works (DEV_TEST_CONFIG is set, uses step bundle with inline source maps)
- Local prod: doesn't work (nitro/bundler output doesn't preserve source maps)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add hasWorkflowSourceMaps() utility for vite-based framework exception
- Add isViteBasedFramework() helper to detect vite, sveltekit, astro apps
- Add hasWorkflowSourceMaps() to check if workflow errors have source maps
(known issue: vite-based frameworks in local deployments don't preserve them)
- Refactor e2e.test.ts to use the new utility instead of inline check
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* prevent sourcemap checks in nextjs and sveltekit (known offenders)
* improve source maps matrix check
* fix matrix again
* ugh more matrix ignoring
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>