9090 run : pnpm lint
9191 - name : Check types
9292 run : pnpm check-types
93+ - name : Validate Code QA workflow
94+ run : pnpm test:code-qa-ci
9395 - name : Model-check task lifecycle protocols
9496 run : pnpm lifecycle:model-check
97+ - name : Validate MCP OAuth integration
98+ run : pnpm mcp:integration-check
9599
96100 build-vsix :
97101 name : Build test VSIX
@@ -123,17 +127,21 @@ jobs:
123127 unit-test :
124128 name : platform-unit-test (${{ matrix.name }})
125129 runs-on : ${{ matrix.os }}
130+ concurrency :
131+ # Duplicate runs for one commit must not race the OS-specific Turbo cache save.
132+ group : unit-test-${{ github.repository }}-${{ github.sha }}-${{ matrix.name }}
133+ cancel-in-progress : false
126134 strategy :
127135 matrix :
128136 include :
129137 - os : ubuntu-latest
130138 name : ubuntu-latest
131139 codecov-flag : ubuntu
132- upload -coverage : true
140+ collect -coverage : true
133141 - os : windows-latest
134142 name : windows-latest
135143 codecov-flag : windows
136- upload -coverage : false
144+ collect -coverage : false
137145 steps :
138146 - name : Checkout code
139147 uses : actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
@@ -148,12 +156,56 @@ jobs:
148156 restore-keys : |
149157 ${{ runner.os }}-turbo-${{ hashFiles('**/pnpm-lock.yaml') }}-
150158 ${{ runner.os }}-turbo-
151- - name : Run non-core coverage
152- run : pnpm turbo run test:coverage --filter="!@roo-code/core" --log-order grouped --output-logs new-only
159+ # Windows never uploads coverage, so Windows runs the same test
160+ # suites through the uninstrumented Turbo tasks. Ubuntu stays the
161+ # authoritative coverage lane.
162+ - name : Run non-extension package coverage
163+ if : matrix.collect-coverage
164+ run : pnpm turbo run test:coverage --filter="!@roo-code/core" --filter="!zoo-code" --log-order grouped --output-logs new-only
165+ - name : Run non-extension package tests
166+ if : ${{ !matrix.collect-coverage }}
167+ run : pnpm turbo run test --filter="!@roo-code/core" --filter="!zoo-code" --log-order grouped --output-logs new-only
168+ - name : Run extension coverage lanes
169+ if : matrix.collect-coverage
170+ run : pnpm turbo run test:coverage:api test:coverage:core test:coverage:services test:coverage:misc test:coverage:tree-sitter --filter="zoo-code" --concurrency=2 --log-order grouped --output-logs new-only
171+ - name : Run extension test lanes
172+ if : ${{ !matrix.collect-coverage }}
173+ run : pnpm turbo run test:api test:core test:services test:misc test:tree-sitter --filter="zoo-code" --concurrency=2 --log-order grouped --output-logs new-only
174+ - name : Verify extension coverage contract
175+ if : matrix.collect-coverage
176+ run : pnpm --dir src run verify:coverage-contract
177+ - name : Run extension dist smoke test
178+ run : pnpm turbo run test:dist --filter="zoo-code" --log-order grouped --output-logs new-only
153179 - name : Run core unit coverage
180+ if : matrix.collect-coverage
154181 run : pnpm turbo run test:coverage:unit --filter="@roo-code/core" --log-order grouped --output-logs new-only
182+ - name : Run core unit tests
183+ if : ${{ !matrix.collect-coverage }}
184+ run : pnpm turbo run test:unit --filter="@roo-code/core" --log-order grouped --output-logs new-only
155185 - name : Run core integration coverage
186+ if : matrix.collect-coverage
156187 run : pnpm turbo run test:coverage:integration --filter="@roo-code/core" --log-order grouped --output-logs new-only
188+ - name : Run core integration tests
189+ if : ${{ !matrix.collect-coverage }}
190+ run : pnpm turbo run test:integration --filter="@roo-code/core" --log-order grouped --output-logs new-only
191+ - name : Verify extension coverage reports
192+ if : matrix.collect-coverage
193+ run : |
194+ node src/scripts/verify-lcov.mjs src/coverage/api/lcov.info
195+ node src/scripts/verify-lcov.mjs src/coverage/core/lcov.info
196+ node src/scripts/verify-lcov.mjs src/coverage/services/lcov.info
197+ node src/scripts/verify-lcov.mjs src/coverage/misc/lcov.info
198+ node src/scripts/verify-lcov.mjs src/coverage/tree-sitter/lcov.info
199+ - name : Merge extension coverage reports
200+ if : matrix.collect-coverage
201+ run : |
202+ mkdir -p src/coverage/merged
203+ pnpm --dir src run merge:coverage
204+ node src/scripts/verify-lcov.mjs src/coverage/merged/lcov.info
205+ # Validate cache boundaries before publishing any new Turbo entries.
206+ - name : Verify coverage cache inputs
207+ if : matrix.collect-coverage
208+ run : pnpm --dir src run verify:coverage-cache-inputs
157209 - name : Save Turbo cache
158210 if : steps.turbo-cache.outputs.cache-hit != 'true'
159211 uses : actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
@@ -165,54 +217,58 @@ jobs:
165217 # there mostly adds Codecov overhead without changing pass/fail
166218 # behavior.
167219 # Coverage is uploaded in separate steps so each LCOV gets the
168- # correct flag set. Codecov double-counts overlapping lines when a
169- # single upload carries multiple flags whose paths overlap, so the
170- # core lanes and webview lane must be uploaded individually with
171- # their own flag.
220+ # correct flag set. Extension lanes instrument the same sources, so
221+ # union them before upload; a line is covered when any lane executes
222+ # it. Core and webview reports retain their independent flags.
172223 # See https://docs.codecov.com/docs/flags
173224 - name : Upload non-core coverage to Codecov
174- if : matrix.upload -coverage
225+ if : matrix.collect -coverage
175226 uses : codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
176227 with :
177228 files : >-
178- src/coverage/lcov.info,
229+ src/coverage/merged/ lcov.info,
179230 packages/cloud/coverage/lcov.info,
180231 packages/telemetry/coverage/lcov.info,
181232 apps/cli/coverage/lcov.info
182233 disable_search : true
183234 flags : ${{ matrix.codecov-flag }}
184235 token : ${{ secrets.CODECOV_TOKEN }}
185236 - name : Upload webview JSDOM coverage to Codecov
186- if : matrix.upload -coverage
237+ if : matrix.collect -coverage
187238 uses : codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
188239 with :
189240 files : webview-ui/coverage/lcov.info
190241 disable_search : true
191242 flags : webview-ui
192243 token : ${{ secrets.CODECOV_TOKEN }}
193244 - name : Upload core unit coverage to Codecov
194- if : matrix.upload -coverage
245+ if : matrix.collect -coverage
195246 uses : codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
196247 with :
197248 files : packages/core/coverage/unit/lcov.info
198249 disable_search : true
199250 flags : ${{ matrix.codecov-flag }},core-unit
200251 token : ${{ secrets.CODECOV_TOKEN }}
201252 - name : Upload core integration coverage to Codecov
202- if : matrix.upload -coverage
253+ if : matrix.collect -coverage
203254 uses : codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
204255 with :
205256 files : packages/core/coverage/integration/lcov.info
206257 disable_search : true
207258 flags : ${{ matrix.codecov-flag }},core-integration
208259 token : ${{ secrets.CODECOV_TOKEN }}
209260 - name : Upload coverage reports to GitHub
210- if : matrix.upload -coverage
261+ if : matrix.collect -coverage
211262 uses : actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
212263 with :
213264 name : coverage-reports-${{ matrix.name }}
214265 path : |
215- src/coverage/lcov.info
266+ src/coverage/api/lcov.info
267+ src/coverage/core/lcov.info
268+ src/coverage/services/lcov.info
269+ src/coverage/misc/lcov.info
270+ src/coverage/tree-sitter/lcov.info
271+ src/coverage/merged/lcov.info
216272 webview-ui/coverage/lcov.info
217273 packages/cloud/coverage/lcov.info
218274 packages/telemetry/coverage/lcov.info
0 commit comments