7
7
branches : [main]
8
8
9
9
jobs :
10
+ changes :
11
+ name : Determine suites to run
12
+ runs-on : ubuntu-latest
13
+ outputs :
14
+ matrix : ${{ steps.set-matrix.outputs.matrix }}
15
+ should_run : ${{ steps.set-matrix.outputs.should_run }}
16
+ steps :
17
+ - name : Checkout code
18
+ uses : actions/checkout@v4
19
+ with :
20
+ fetch-depth : 0
21
+
22
+ - name : Detect changed areas
23
+ id : filter
24
+ uses : dorny/paths-filter@v3
25
+ with :
26
+ filters : |
27
+ core_ts:
28
+ - 'typescript-sdk/packages/**'
29
+ - 'typescript-sdk/package.json'
30
+ - 'typescript-sdk/pnpm-lock.yaml'
31
+ - 'typescript-sdk/pnpm-workspace.yaml'
32
+ - 'typescript-sdk/tsconfig.json'
33
+ - 'typescript-sdk/turbo.json'
34
+ core_py:
35
+ - 'python-sdk/**'
36
+ e2e_tests:
37
+ - 'typescript-sdk/apps/dojo/e2e/**'
38
+ - 'typescript-sdk/apps/dojo/scripts/**'
39
+ workflow_self:
40
+ - '.github/workflows/dojo-e2e.yml'
41
+ agno:
42
+ - 'typescript-sdk/integrations/agno/**'
43
+ crew_ai:
44
+ - 'typescript-sdk/integrations/crewai/**'
45
+ langgraph:
46
+ - 'typescript-sdk/integrations/langgraph/**'
47
+ llama_index:
48
+ - 'typescript-sdk/integrations/llamaindex/**'
49
+ mastra:
50
+ - 'typescript-sdk/integrations/mastra/**'
51
+ middleware_starter:
52
+ - 'typescript-sdk/integrations/middleware-starter/**'
53
+ pydantic_ai:
54
+ - 'typescript-sdk/integrations/pydantic-ai/**'
55
+ server_starter:
56
+ - 'typescript-sdk/integrations/server-starter/**'
57
+ server_starter_all:
58
+ - 'typescript-sdk/integrations/server-starter-all-features/**'
59
+ vercel_ai_sdk:
60
+ - 'typescript-sdk/integrations/vercel-ai-sdk/**'
61
+
62
+ - name : Build dynamic matrix
63
+ id : set-matrix
64
+ env :
65
+ CORE_TS : ${{ steps.filter.outputs.core_ts }}
66
+ CORE_PY : ${{ steps.filter.outputs.core_py }}
67
+ E2E_TESTS : ${{ steps.filter.outputs.e2e_tests }}
68
+ WORKFLOW_SELF : ${{ steps.filter.outputs.workflow_self }}
69
+ AGNO : ${{ steps.filter.outputs.agno }}
70
+ CREW_AI : ${{ steps.filter.outputs.crew_ai }}
71
+ LANGGRAPH : ${{ steps.filter.outputs.langgraph }}
72
+ LLAMA_INDEX : ${{ steps.filter.outputs.llama_index }}
73
+ MASTRA : ${{ steps.filter.outputs.mastra }}
74
+ MIDDLEWARE_STARTER : ${{ steps.filter.outputs.middleware_starter }}
75
+ PYDANTIC_AI : ${{ steps.filter.outputs.pydantic_ai }}
76
+ SERVER_STARTER : ${{ steps.filter.outputs.server_starter }}
77
+ SERVER_STARTER_ALL : ${{ steps.filter.outputs.server_starter_all }}
78
+ VERCEL_AI_SDK : ${{ steps.filter.outputs.vercel_ai_sdk }}
79
+ run : |
80
+ python3 - << 'PY'
81
+ import os, json
82
+
83
+ all_entries = [
84
+ {"suite": "agno", "test_path": "tests/agnoTests", "services": ["dojo","agno"], "wait_on": "http://localhost:9999,tcp:localhost:8002"},
85
+ {"suite": "crew-ai", "test_path": "tests/crewAITests", "services": ["dojo","crew-ai"], "wait_on": "http://localhost:9999,tcp:localhost:8003"},
86
+ {"suite": "langgraph", "test_path": "tests/langgraphTests", "services": ["dojo","langgraph-platform-python","langgraph-platform-typescript"], "wait_on": "http://localhost:9999,tcp:localhost:8005,tcp:localhost:8006"},
87
+ {"suite": "langgraph-fastapi", "test_path": "tests/langgraphFastAPITests", "services": ["dojo","langgraph-fastapi"], "wait_on": "http://localhost:9999,tcp:localhost:8004"},
88
+ {"suite": "llama-index", "test_path": "tests/llamaIndexTests", "services": ["dojo","llama-index"], "wait_on": "http://localhost:9999,tcp:localhost:8007"},
89
+ {"suite": "mastra", "test_path": "tests/mastraTests", "services": ["dojo","mastra"], "wait_on": "http://localhost:9999,tcp:localhost:8008"},
90
+ {"suite": "mastra-agent-local", "test_path": "tests/mastraAgentLocalTests", "services": ["dojo"], "wait_on": "http://localhost:9999"},
91
+ {"suite": "middleware-starter", "test_path": "tests/middlewareStarterTests", "services": ["dojo"], "wait_on": "http://localhost:9999"},
92
+ {"suite": "pydantic-ai", "test_path": "tests/pydanticAITests", "services": ["dojo","pydantic-ai"], "wait_on": "http://localhost:9999,tcp:localhost:8009"},
93
+ {"suite": "server-starter", "test_path": "tests/serverStarterTests", "services": ["dojo","server-starter"], "wait_on": "http://localhost:9999,tcp:localhost:8000"},
94
+ {"suite": "server-starter-all", "test_path": "tests/serverStarterAllFeaturesTests", "services": ["dojo","server-starter-all"], "wait_on": "http://localhost:9999,tcp:localhost:8001"},
95
+ {"suite": "vercel-ai-sdk", "test_path": "tests/vercelAISdkTests", "services": ["dojo"], "wait_on": "http://localhost:9999"},
96
+ ]
97
+
98
+ entry_by_suite = {e["suite"]: e for e in all_entries}
99
+ core_changed = (
100
+ (os.environ.get('CORE_TS') == 'true') or
101
+ (os.environ.get('CORE_PY') == 'true') or
102
+ (os.environ.get('E2E_TESTS') == 'true') or
103
+ (os.environ.get('WORKFLOW_SELF') == 'true')
104
+ )
105
+
106
+ include = []
107
+ if core_changed:
108
+ include = all_entries
109
+ else:
110
+ if os.environ.get('AGNO') == 'true':
111
+ include.append(entry_by_suite['agno'])
112
+ if os.environ.get('CREW_AI') == 'true':
113
+ include.append(entry_by_suite['crew-ai'])
114
+ if os.environ.get('LANGGRAPH') == 'true':
115
+ include.append(entry_by_suite['langgraph'])
116
+ include.append(entry_by_suite['langgraph-fastapi'])
117
+ if os.environ.get('LLAMA_INDEX') == 'true':
118
+ include.append(entry_by_suite['llama-index'])
119
+ if os.environ.get('MASTRA') == 'true':
120
+ include.append(entry_by_suite['mastra'])
121
+ include.append(entry_by_suite['mastra-agent-local'])
122
+ if os.environ.get('MIDDLEWARE_STARTER') == 'true':
123
+ include.append(entry_by_suite['middleware-starter'])
124
+ if os.environ.get('PYDANTIC_AI') == 'true':
125
+ include.append(entry_by_suite['pydantic-ai'])
126
+ if os.environ.get('SERVER_STARTER') == 'true':
127
+ include.append(entry_by_suite['server-starter'])
128
+ if os.environ.get('SERVER_STARTER_ALL') == 'true':
129
+ include.append(entry_by_suite['server-starter-all'])
130
+ if os.environ.get('VERCEL_AI_SDK') == 'true':
131
+ include.append(entry_by_suite['vercel-ai-sdk'])
132
+
133
+ matrix = {"include": include}
134
+ with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
135
+ fh.write(f"matrix={json.dumps(matrix)}\n")
136
+ fh.write(f"should_run={'true' if include else 'false'}\n")
137
+ PY
10
138
e2e :
11
- name : E2E Tests
12
- runs-on : depot-ubuntu-latest-8
139
+ needs : changes
140
+ if : ${{ needs.changes.outputs.should_run == 'true' }}
141
+ name : ${{ matrix.suite }}
142
+ runs-on : depot-ubuntu-24.04
143
+ strategy :
144
+ fail-fast : false
145
+ matrix : ${{ fromJSON(needs.changes.outputs.matrix) }}
13
146
14
147
steps :
15
148
- name : Checkout code
@@ -25,6 +158,33 @@ jobs:
25
158
with :
26
159
version : 10.13.1
27
160
161
+ # Now that pnpm is available, cache its store to speed installs
162
+ - name : Resolve pnpm store path
163
+ id : pnpm-store
164
+ run : echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
165
+
166
+ - name : Cache pnpm store
167
+ uses : actions/cache@v4
168
+ with :
169
+ path : ${{ env.STORE_PATH }}
170
+ key : ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
171
+ restore-keys : |
172
+ ${{ runner.os }}-pnpm-store-
173
+
174
+ # Cache Python tool caches and virtualenvs; restore only to avoid long saves
175
+ - name : Cache Python dependencies (restore-only)
176
+ id : cache-python
177
+ uses : actions/cache/restore@v4
178
+ with :
179
+ path : |
180
+ ~/.cache/pip
181
+ ~/.cache/pypoetry
182
+ ~/.cache/uv
183
+ **/.venv
184
+ key : ${{ runner.os }}-pydeps-${{ hashFiles('**/poetry.lock', '**/pyproject.toml') }}
185
+ restore-keys : |
186
+ ${{ runner.os }}-pydeps-
187
+
28
188
- name : Install Poetry
29
189
uses : snok/install-poetry@v1
30
190
with :
@@ -35,21 +195,14 @@ jobs:
35
195
- name : Install uv
36
196
uses : astral-sh/setup-uv@v6
37
197
38
- - name : Setup pnpm cache
39
- uses : actions/cache@v4
40
- with :
41
- path : ~/.local/share/pnpm/store
42
- key : ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
43
- restore-keys : |
44
- ${{ runner.os }}-pnpm-store-
45
-
46
198
- name : Install dependencies
47
199
working-directory : typescript-sdk
48
200
run : pnpm install --frozen-lockfile
49
201
50
202
- name : Prepare dojo for e2e
51
203
working-directory : typescript-sdk/apps/dojo
52
- run : node ./scripts/prep-dojo-everything.js -e2e
204
+ if : ${{ join(matrix.services, ',') != '' }}
205
+ run : node ./scripts/prep-dojo-everything.js --only ${{ join(matrix.services, ',') }}
53
206
54
207
- name : Install e2e dependencies
55
208
working-directory : typescript-sdk/apps/dojo/e2e
61
214
env :
62
215
OPENAI_API_KEY : ${{ secrets.OPENAI_API_KEY }}
63
216
LANGSMITH_API_KEY : ${{ secrets.LANGSMITH_API_KEY }}
217
+ if : ${{ contains(join(matrix.services, ','), 'langgraph-fastapi') || contains(join(matrix.services, ','), 'langgraph-platform-python') || contains(join(matrix.services, ','), 'langgraph-platform-typescript') }}
64
218
run : |
65
219
echo "OPENAI_API_KEY=${OPENAI_API_KEY}" > examples/python/.env
66
220
echo "LANGSMITH_API_KEY=${LANGSMITH_API_KEY}" >> examples/python/.env
@@ -74,33 +228,28 @@ jobs:
74
228
env :
75
229
OPENAI_API_KEY : ${{ secrets.OPENAI_API_KEY }}
76
230
LANGSMITH_API_KEY : ${{ secrets.LANGSMITH_API_KEY }}
231
+ if : ${{ join(matrix.services, ',') != '' && contains(join(matrix.services, ','), 'dojo') }}
77
232
with :
78
233
run : |
79
- node ../scripts/run-dojo-everything.js
234
+ node ../scripts/run-dojo-everything.js --only ${{ join(matrix.services, ',') }}
80
235
working-directory : typescript-sdk/apps/dojo/e2e
81
- wait-on : |
82
- http://localhost:9999
83
- tcp:localhost:8000
84
- tcp:localhost:8001
85
- tcp:localhost:8002
86
- tcp:localhost:8003
87
- tcp:localhost:8004
88
- tcp:localhost:8005
89
- tcp:localhost:8006
90
- tcp:localhost:8007
91
- tcp:localhost:8008
92
- tcp:localhost:8009
93
-
94
- - name : Run tests
236
+ wait-on : ${{ matrix.wait_on }}
237
+ wait-for : 300000
238
+
239
+ - name : Run tests – ${{ matrix.suite }}
95
240
working-directory : typescript-sdk/apps/dojo/e2e
96
241
env :
97
242
BASE_URL : http://localhost:9999
98
- run : pnpm test
243
+ PLAYWRIGHT_SUITE : ${{ matrix.suite }}
244
+ run : |
245
+ pnpm test -- ${{ matrix.test_path }}
99
246
100
- - name : Upload traces
247
+ - name : Upload traces – ${{ matrix.suite }}
101
248
if : always() # Uploads artifacts even if tests fail
102
249
uses : actions/upload-artifact@v4
103
250
with :
104
- name : playwright-traces
105
- path : typescript-sdk/apps/dojo/e2e/test-results/
251
+ name : ${{ matrix.suite }}-playwright-traces
252
+ path : |
253
+ typescript-sdk/apps/dojo/e2e/test-results/${{ matrix.suite }}/**/*
254
+ typescript-sdk/apps/dojo/e2e/playwright-report/**/*
106
255
retention-days : 7
0 commit comments