Skip to content

Commit e509e3f

Browse files
committed
feat: dynamic integration test filtering based on changed paths
Instead of skipping the entire integration job, compute which test directories to run based on paths-filter outputs: - ipc filter: src/node/services, orpc, config, git, utils, common, cli, desktop, tests/ipc - runtime filter: src/node/runtime, tests/runtime - config changes: run all integration tests - manual override: workflow_dispatch test_filter still works The job always runs (unless docs-only), but tests are scoped to relevant changes.
1 parent 9fa5f70 commit e509e3f

File tree

2 files changed

+56
-19
lines changed

2 files changed

+56
-19
lines changed

.github/workflows/pr.yml

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@ concurrency:
1616
cancel-in-progress: true
1717

1818
jobs:
19-
# Detect what files changed to skip jobs for docs-only or browser-only PRs
19+
# Detect what files changed to determine which jobs/tests to run
2020
changes:
2121
name: Detect Changes
2222
runs-on: ubuntu-latest
2323
outputs:
2424
docs-only: ${{ steps.filter.outputs.docs == 'true' && steps.filter.outputs.src == 'false' && steps.filter.outputs.config == 'false' }}
25-
# Browser-only: only browser/renderer code changed, no backend/node changes
26-
browser-only: ${{ steps.filter.outputs.browser == 'true' && steps.filter.outputs.backend == 'false' && steps.filter.outputs.config == 'false' }}
25+
config: ${{ steps.filter.outputs.config }}
26+
ipc: ${{ steps.filter.outputs.ipc }}
27+
runtime: ${{ steps.filter.outputs.runtime }}
2728
steps:
2829
- uses: actions/checkout@v4
2930
- uses: dorny/paths-filter@v3
@@ -39,19 +40,20 @@ jobs:
3940
- 'src/**'
4041
- 'tests/**'
4142
- 'vscode/**'
42-
browser:
43-
- 'src/browser/**'
44-
- 'src/styles/**'
45-
- 'src/components/**'
46-
- 'src/hooks/**'
47-
- '**/*.stories.tsx'
48-
- '.storybook/**'
49-
backend:
50-
- 'src/node/**'
43+
# IPC tests: backend services, ORPC, config, common types
44+
ipc:
45+
- 'src/node/services/**'
46+
- 'src/node/orpc/**'
47+
- 'src/node/config/**'
48+
- 'src/node/git/**'
49+
- 'src/node/utils/**'
50+
- 'src/common/**'
5151
- 'src/cli/**'
5252
- 'src/desktop/**'
53-
- 'src/common/**'
5453
- 'tests/ipc/**'
54+
# Runtime tests: runtime implementations (SSH, worktree)
55+
runtime:
56+
- 'src/node/runtime/**'
5557
- 'tests/runtime/**'
5658
config:
5759
- '.github/**'
@@ -113,8 +115,7 @@ jobs:
113115
test-integration:
114116
name: Test / Integration
115117
needs: [changes]
116-
# Skip for docs-only or browser-only (integration tests are backend IPC tests)
117-
if: ${{ needs.changes.outputs.docs-only != 'true' && needs.changes.outputs.browser-only != 'true' }}
118+
if: ${{ needs.changes.outputs.docs-only != 'true' }}
118119
timeout-minutes: 10
119120
runs-on: ${{ github.repository_owner == 'coder' && 'depot-ubuntu-22.04-16' || 'ubuntu-latest' }}
120121
steps:
@@ -123,11 +124,49 @@ jobs:
123124
fetch-depth: 0
124125
- uses: ./.github/actions/setup-mux
125126
- run: make build-main
126-
- run: TEST_INTEGRATION=1 bun x jest --coverage --maxWorkers=100% --silent ${{ github.event.inputs.test_filter || 'tests/ipc tests/runtime' }}
127+
- name: Compute test filter
128+
id: test-filter
129+
run: |
130+
# Manual override takes precedence
131+
if [[ -n "${{ github.event.inputs.test_filter }}" ]]; then
132+
echo "filter=${{ github.event.inputs.test_filter }}" >> $GITHUB_OUTPUT
133+
exit 0
134+
fi
135+
136+
# Config changes = run everything
137+
if [[ "${{ needs.changes.outputs.config }}" == "true" ]]; then
138+
echo "filter=tests/ipc tests/runtime" >> $GITHUB_OUTPUT
139+
exit 0
140+
fi
141+
142+
# Build filter from changed paths
143+
paths=""
144+
if [[ "${{ needs.changes.outputs.ipc }}" == "true" ]]; then
145+
paths="$paths tests/ipc"
146+
fi
147+
if [[ "${{ needs.changes.outputs.runtime }}" == "true" ]]; then
148+
paths="$paths tests/runtime"
149+
fi
150+
paths=$(echo $paths | xargs) # trim whitespace
151+
152+
if [[ -z "$paths" ]]; then
153+
echo "No integration tests needed for changed paths"
154+
echo "filter=" >> $GITHUB_OUTPUT
155+
else
156+
echo "Running: $paths"
157+
echo "filter=$paths" >> $GITHUB_OUTPUT
158+
fi
159+
- name: Run integration tests
160+
if: ${{ steps.test-filter.outputs.filter != '' }}
161+
run: TEST_INTEGRATION=1 bun x jest --coverage --maxWorkers=100% --silent ${{ steps.test-filter.outputs.filter }}
127162
env:
128163
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
129164
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
165+
- name: Skip integration tests
166+
if: ${{ steps.test-filter.outputs.filter == '' }}
167+
run: echo "Skipping integration tests - no relevant paths changed"
130168
- uses: codecov/codecov-action@v5
169+
if: ${{ steps.test-filter.outputs.filter != '' }}
131170
with:
132171
token: ${{ secrets.CODECOV_TOKEN }}
133172
files: ./coverage/lcov.info

src/common/constants/knownModels.test.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@ describe("Known Models Integration", () => {
3939
const modelId = model.providerModelId;
4040
// xAI models are prefixed with "xai/" in models.json
4141
const lookupKey = model.provider === "xai" ? `xai/${modelId}` : modelId;
42-
const modelData =
43-
(modelsJson[lookupKey as keyof typeof modelsJson] as Record<string, unknown>) ??
44-
(modelsExtra[modelId] as Record<string, unknown>);
42+
const modelData = modelsJson[lookupKey as keyof typeof modelsJson] ?? modelsExtra[modelId];
4543

4644
expect(modelData).toBeDefined();
4745
// Check that basic metadata fields exist (not all models have all fields)

0 commit comments

Comments
 (0)