Repository navigation
[core] Single-orchestrator runtime (spec 9) #4661
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
71e79bc
3a3a193
42971f5
142dc76
3a199c9
55e9a1a
260909f
6684099
89c587c
f085b14
cacdf29
89920ef
4f83dbf
c0d750d
534306e
ec6ebd0
1535692
41bb00e
68cb3de
58d7dde
0c1d755
7254fd5
504b28c
ee28454
8c6b923
a29ce9b
1e6ac7f
b19584c
f14aca1
12894c5
16f7001
5d513ea
7e8ad1d
0fa41f1
789e103
27cfda6
e0c54bb
94c7c14
dfbb6df
ecf4ec4
ad998a2
bc75d58
dfff41b
b97ad32
5ed5339
c00fcd5
945ee60
6d9bfb4
f5caa5f
6a3d1d2
97bd73d
2b80f92
a74038a
1bf0acd
365fab0
af94e2c
3cda0ec
7c8a90b
ff26315
75ddd45
f496b33
6cbe1fc
3c7440e
2cd65d5
d617404
83ee220
e277334
5b53481
072fff9
c9446d4
76643fe
0f58c8d
f1d403f
670ea7b
560e89d
9f96925
ff5ef5c
ad9f92f
48c5865
589ad95
d5d8977
e6c4252
8a79811
5724bf8
cea1893
d0437df
c3cfbcd
eec0d6d
c215273
28018f6
86eb382
baeef30
722fe2a
d0fe48e
8820365
594cc5f
9cd2281
aea0fd2
8e6e547
b075bd0
90dde6e
a26b9a4
5cd8631
d239120
6d1c305
0d54ad6
cf8a20d
8156506
7f1bb96
b489e75
d08a880
bfb970a
2b02860
ddc7189
5fe3e38
b154d33
dd5037f
d36a017
c349183
1f7b912
87c4c9f
e17bd0c
4ed4f07
80972c8
53cd1e3
6292be4
72954bb
261dd84
26a8d61
5c0dbf3
ea01262
a09d313
2cfc12f
8b6ef71
62be2c9
931539b
6d7e0f4
2270ab0
3ba56bb
66b355d
aa928b7
51a21f6
ea2aa05
427ded4
0528815
1ddbe74
6b4c0ce
1a808df
4b94003
bb70daf
4b7610f
a45cfb0
1a02e52
ab37131
dcddeb7
030f774
502f40d
76f33f7
281f150
b48f83d
dbb4d8a
c88100f
157d8ce
339c9a9
0af8145
6a5d1f0
f4f8149
c9c1c27
9856839
6c6955d
700c39d
e36eb29
dfe9702
e3018c0
af8f076
008530f
7fc8954
f0849c9
3e3cd8c
15b1f0a
838cc29
8c50d00
a2ddc02
f089295
6a1353e
f2fd403
0bf649f
70e4b37
4754c9c
cd71167
cc518ab
0f21b75
38f7e29
4de3495
ed5d0f1
8d999e4
53fc8cc
0915559
0239c72
e6b64a7
fc0aa31
6f79f60
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@workflow/core": patch | ||
| --- | ||
|
|
||
| With `WORKFLOW_VM=quickjs`, replay ignores events for a step, wait or hook after its terminal event, as the default engine does. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| --- | ||
| "@workflow/core": minor | ||
| "@workflow/world": minor | ||
| "@workflow/errors": patch | ||
| "@workflow/world-vercel": minor | ||
| "@workflow/world-local": minor | ||
| "@workflow/world-postgres": minor | ||
| "@workflow/world-testing": patch | ||
| "@workflow/vitest": patch | ||
| --- | ||
|
|
||
| Add opt-in spec 9 runs, driven by a single orchestrator per run: set `WORKFLOW_SPEC_VERSION=9`. New runs stay on spec 8 by default. | ||
|
|
||
| - Without the setting, new runs are spec 8 and behave as before. | ||
| - To opt in, first upgrade every deployment and process that calls `start()` or shares the World to this release, then set `WORKFLOW_SPEC_VERSION=9` on all of them. An older release fails writes to spec 9 runs (reads still work, nothing is corrupted), so do not roll back below this release while spec 9 runs are in flight. | ||
| - Custom Worlds: `mintedSpecVersion()` keeps creating spec 8 runs. A World that implements the in-band writer fence declares `capabilities.inBandFence` and passes `{ inBandFence: true }` to create spec 9 runs. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@workflow/world-local": patch | ||
| --- | ||
|
|
||
| Hold a queue concurrency slot for each delivery, not across the sleeps and backoffs between deliveries. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@workflow/world-local": patch | ||
| --- | ||
|
|
||
| Back off retries of a queue message whose deliveries keep failing after 32 attempts, as Vercel Queues does. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,6 +30,7 @@ jobs: | |
| vercel-prod-matrix: ${{ steps.vercel-matrix.outputs.vercel-prod-matrix }} | ||
| vercel-ws-transport-matrix: ${{ steps.vercel-matrix.outputs.vercel-ws-transport-matrix }} | ||
| vercel-http-transport-matrix: ${{ steps.vercel-matrix.outputs.vercel-http-transport-matrix }} | ||
| vercel-spec9-matrix: ${{ steps.vercel-matrix.outputs.vercel-spec9-matrix }} | ||
| steps: | ||
| - name: Checkout Repo | ||
| uses: actions/checkout@v4 | ||
|
|
@@ -649,6 +650,97 @@ jobs: | |
| token: ${{ secrets.VERCEL_LABS_TOKEN }} | ||
| e2e-start-ms: ${{ steps.e2eStart.outputs.ms }} | ||
|
|
||
| e2e-vercel-spec9: | ||
| # Spec 9 runs (the single orchestrator) are opt-in with | ||
| # WORKFLOW_SPEC_VERSION=9, so every other Vercel lane runs the default, | ||
| # spec 8. This lane deploys its own preview with the variable set and runs | ||
| # the full suite against it on both VMs. | ||
| # | ||
| # The variable is set on the deployment AND on the test runner: a | ||
| # cross-deployment start() stamps the lower of the target's and the | ||
| # caller's version, so with only the deployment env set this lane would | ||
| # silently test spec 8. The e2e test "stamps the spec version the lane | ||
| # opts in to" fails if either side stops seeing it. | ||
| # | ||
| # Same dedicated-deployment pattern as e2e-vercel-ws-transport above. | ||
| name: E2E Vercel Spec 9 Test (${{ matrix.app.name }}, ${{ matrix.vm }}) | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 30 | ||
| needs: ci-scope | ||
| if: ${{ needs.ci-scope.outputs.fast-path != 'true' }} | ||
| concurrency: | ||
| group: e2e-vercel-spec9-${{ matrix.app.name }}-${{ matrix.vm }}-${{ needs.ci-scope.outputs.e2e-vercel-slot }} | ||
| queue: max | ||
| permissions: | ||
| id-token: write | ||
| contents: read | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: ${{ fromJSON(needs.ci-scope.outputs.vercel-spec9-matrix) }} | ||
| env: | ||
| TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} | ||
| TURBO_TEAM: ${{ vars.TURBO_TEAM }} | ||
| WORKFLOW_PUBLIC_MANIFEST: '1' | ||
| VERCEL_TEAM_ID: ${{ needs.ci-scope.outputs.vercel-team-id }} | ||
| steps: | ||
| - name: Checkout Repo | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| ref: ${{ github.event.pull_request.head.sha || github.sha }} | ||
|
|
||
| - name: Setup environment | ||
| uses: ./.github/actions/setup-workflow-dev | ||
| with: | ||
| build-packages: 'false' | ||
|
|
||
| - name: Build CLI | ||
| run: pnpm turbo run build --filter='@workflow/cli' | ||
|
|
||
| - name: Deploy a dedicated spec 9 preview | ||
| id: deployment | ||
| uses: ./.github/actions/deploy-vercel-preview | ||
| with: | ||
| project-id: ${{ matrix.app.project-id }} | ||
| team-id: ${{ env.VERCEL_TEAM_ID }} | ||
| token: ${{ secrets.VERCEL_LABS_TOKEN }} | ||
| env: | | ||
| WORKFLOW_SPEC_VERSION=9 | ||
|
|
||
| - name: Record E2E start time | ||
| id: e2eStart | ||
| run: echo "ms=$(($(date +%s) * 1000))" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Run E2E Tests | ||
| run: pnpm run test:e2e --reporter=verbose --reporter=json --reporter=./packages/core/e2e/github-reporter.ts "--outputFile=e2e-vercel-spec9-$APP_NAME-$WORKFLOW_VM.json" | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Keep explicit spec-9 storm coverage after the opt-in flip. This lane correctly tests spec 9, but Please run the storm harness with both deployment and runner opted into 9, and assert the created run's spec, while retaining default/spec-8 coverage. Source/CI inspection only; no local tests run. Local agent review (`openai/gpt-6-astra`)
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nah |
||
| env: | ||
| NODE_OPTIONS: "--enable-source-maps" | ||
| DEPLOYMENT_URL: ${{ steps.deployment.outputs.deployment-url }} | ||
| VERCEL_DEPLOYMENT_ID: ${{ steps.deployment.outputs.deployment-id }} | ||
| APP_NAME: ${{ matrix.app.name }} | ||
| WORKFLOW_VM: ${{ matrix.vm }} | ||
| WORKFLOW_SPEC_VERSION: '9' | ||
| WORKFLOW_VERCEL_ENV: "preview" | ||
| WORKFLOW_VERCEL_AUTH_TOKEN: ${{ secrets.VERCEL_LABS_TOKEN }} | ||
| WORKFLOW_VERCEL_TEAM: ${{ env.VERCEL_TEAM_ID }} | ||
| WORKFLOW_VERCEL_PROJECT: ${{ matrix.app.project-id }} | ||
| WORKFLOW_VERCEL_PROJECT_SLUG: ${{ matrix.app.project-slug }} | ||
| VERCEL_WORKFLOW_SERVER_URL: ${{ github.ref != 'refs/heads/main' && secrets.VERCEL_WORKFLOW_SERVER_URL || '' }} | ||
|
|
||
| - name: Report E2E results | ||
| if: always() | ||
| uses: ./.github/actions/report-vercel-e2e | ||
| with: | ||
| results-name: vercel-spec9-${{ matrix.app.name }}-${{ matrix.vm }} | ||
| app: ${{ matrix.app.name }} | ||
| summary-title: E2E Vercel Spec 9 (${{ matrix.app.name }}, ${{ matrix.vm }}) | ||
| capture-runtime-logs: ${{ job.status == 'failure' }} | ||
| deployment-id: ${{ steps.deployment.outputs.deployment-id }} | ||
| environment: preview | ||
| project-id: ${{ matrix.app.project-id }} | ||
| team-id: ${{ env.VERCEL_TEAM_ID }} | ||
| token: ${{ secrets.VERCEL_LABS_TOKEN }} | ||
| e2e-start-ms: ${{ steps.e2eStart.outputs.ms }} | ||
|
|
||
| e2e-vercel-http-transport: | ||
| # The counterpart to e2e-vercel-ws-transport. With | ||
| # WORKFLOW_EVENTS_TRANSPORT defaulting to `ws`, e2e-vercel-prod — which | ||
|
|
@@ -1461,7 +1553,7 @@ jobs: | |
| summary: | ||
| name: E2E Summary | ||
| runs-on: ubuntu-latest | ||
| needs: [ci-scope, e2e-vercel-prod, e2e-vercel-multi-region, e2e-vercel-ws-transport, e2e-vercel-http-transport, e2e-local-dev, e2e-local-prod, e2e-local-postgres, e2e-python, e2e-windows] | ||
| needs: [ci-scope, e2e-vercel-prod, e2e-vercel-multi-region, e2e-vercel-ws-transport, e2e-vercel-http-transport, e2e-vercel-spec9, e2e-local-dev, e2e-local-prod, e2e-local-postgres, e2e-python, e2e-windows] | ||
| if: always() && !cancelled() && needs.ci-scope.outputs.fast-path != 'true' | ||
| timeout-minutes: 10 | ||
|
|
||
|
|
@@ -1497,7 +1589,7 @@ jobs: | |
| e2e-required-check: | ||
| name: E2E Required Check | ||
| runs-on: ubuntu-latest | ||
| needs: [ci-scope, unit, e2e-package-build, e2e-vercel-prod, e2e-vercel-ws-transport, e2e-vercel-http-transport, e2e-local-dev, e2e-local-prod, e2e-local-postgres, e2e-windows] | ||
| needs: [ci-scope, unit, e2e-package-build, e2e-vercel-prod, e2e-vercel-ws-transport, e2e-vercel-http-transport, e2e-vercel-spec9, e2e-local-dev, e2e-local-prod, e2e-local-postgres, e2e-windows] | ||
| if: always() | ||
| timeout-minutes: 5 | ||
|
|
||
|
|
@@ -1509,6 +1601,7 @@ jobs: | |
| VERCEL_STATUS: ${{ needs.e2e-vercel-prod.result }} | ||
| VERCEL_WS_STATUS: ${{ needs.e2e-vercel-ws-transport.result }} | ||
| VERCEL_HTTP_STATUS: ${{ needs.e2e-vercel-http-transport.result }} | ||
| VERCEL_SPEC9_STATUS: ${{ needs.e2e-vercel-spec9.result }} | ||
| LOCAL_DEV_STATUS: ${{ needs.e2e-local-dev.result }} | ||
| LOCAL_PROD_STATUS: ${{ needs.e2e-local-prod.result }} | ||
| POSTGRES_STATUS: ${{ needs.e2e-local-postgres.result }} | ||
|
|
@@ -1554,6 +1647,7 @@ jobs: | |
| [[ "$VERCEL_STATUS" == "success" ]] || FAILED_JOBS+=("e2e-vercel-prod ($VERCEL_STATUS)") | ||
| [[ "$VERCEL_WS_STATUS" == "success" ]] || FAILED_JOBS+=("e2e-vercel-ws-transport ($VERCEL_WS_STATUS)") | ||
| [[ "$VERCEL_HTTP_STATUS" == "success" ]] || FAILED_JOBS+=("e2e-vercel-http-transport ($VERCEL_HTTP_STATUS)") | ||
| [[ "$VERCEL_SPEC9_STATUS" == "success" ]] || FAILED_JOBS+=("e2e-vercel-spec9 ($VERCEL_SPEC9_STATUS)") | ||
| [[ "$LOCAL_DEV_STATUS" == "success" ]] || FAILED_JOBS+=("e2e-local-dev ($LOCAL_DEV_STATUS)") | ||
| [[ "$LOCAL_PROD_STATUS" == "success" ]] || FAILED_JOBS+=("e2e-local-prod ($LOCAL_PROD_STATUS)") | ||
| [[ "$POSTGRES_STATUS" == "success" ]] || FAILED_JOBS+=("e2e-local-postgres ($POSTGRES_STATUS)") | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[minor, coverage] With spec 8 now the minted default, this lane is the only e2e coverage of spec 9. The Event Log Race Repro (
event-log-race-repro.yml) resolves the standard preview and sets noWORKFLOW_SPEC_VERSIONon the deployment or the runner, so from this head on it races spec 8 runs only. That's the harness that caught the spec 9 run-aheadCORRUPTED_EVENT_LOGfixed in dfe9702; its last spec 9 passes were at dfe9702 and 838cc29, two clean runs of an intermittent failure. The local-World e2e lanes (e2e-local-dev/prod/postgres) also no longer run spec 9 on world-local or world-postgres.Suggestion: give the race repro a spec 9 variant (a preview with
WORKFLOW_SPEC_VERSION=9, with the variable also in the runner env as in this lane), and run at least one local-World lane withWORKFLOW_SPEC_VERSION=9. Otherwise a regression in the spec 9 race paths only shows up in unit tests.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(AI) Added in 8d999e4. The Vercel lane of the Event Log Race Repro is now a matrix with a
spec9cell, which deploys a dedicated preview withWORKFLOW_SPEC_VERSION=9and sets the variable on the runner too. The harness records each run's spec version and fails if a run comes back at another one; the cell gates like the default one and has its own row in the PR comment. First run, at 53fc8cc: 32 of 32 runs completed, all 32 spec 9, 0 corrupted. The local-World lanes still run spec 8 only.