Skip to content

Commit 3fdc9f1

Browse files
ci: dispatch per-driver integration tests based on changed paths (#245)
## Summary - Rename `adbc-pr-test` → `adbc-csharp-pr-test` to match the test repo's workflow trigger - Add `adbc-rust-pr-test` dispatch for Rust integration tests - PR label flow: detect changed paths via GitHub API, only dispatch tests for the driver that changed - Merge queue flow: output separate `csharp-changed` / `rust-changed` flags, dispatch conditionally ## Test plan - [ ] PR touching only `csharp/` → only C# tests triggered - [ ] PR touching only `rust/` → only Rust tests triggered - [ ] PR touching both → both triggered - [ ] PR touching neither → no dispatch; merge queue's `auto-approve-no-relevant-changes` handles it 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 4780d28 commit 3fdc9f1

File tree

1 file changed

+193
-75
lines changed

1 file changed

+193
-75
lines changed

.github/workflows/trigger-integration-tests.yml

Lines changed: 193 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -106,20 +106,53 @@ jobs:
106106
issues: write
107107
pull-requests: write
108108
steps:
109-
- name: Generate GitHub App Token
109+
- name: Detect changed driver paths
110+
id: changed
111+
uses: actions/github-script@v7
112+
with:
113+
script: |
114+
const { data: files } = await github.rest.pulls.listFiles({
115+
owner: context.repo.owner,
116+
repo: context.repo.repo,
117+
pull_number: context.payload.pull_request.number,
118+
per_page: 100
119+
});
120+
const names = files.map(f => f.filename);
121+
const csharpChanged = names.some(f => f.startsWith('csharp/'));
122+
const rustChanged = names.some(f => f.startsWith('rust/'));
123+
const workflowChanged = names.some(f => f.startsWith('.github/workflows/'));
124+
// Workflow change triggers all targets; otherwise only changed driver folders
125+
const runCsharp = csharpChanged || workflowChanged;
126+
const runRust = rustChanged || workflowChanged;
127+
if (workflowChanged) console.log('✅ Workflow files changed - triggering all targets');
128+
core.setOutput('csharp', runCsharp.toString());
129+
core.setOutput('rust', runRust.toString());
130+
131+
- name: Generate GitHub App Token (internal repo)
110132
id: app-token
111133
uses: actions/create-github-app-token@v1
112134
with:
113135
app-id: ${{ secrets.INTEGRATION_TEST_APP_ID }}
114136
private-key: ${{ secrets.INTEGRATION_TEST_PRIVATE_KEY }}
115137
owner: databricks
116138
repositories: databricks-driver-test
117-
- name: Dispatch tests to internal repo
139+
140+
- name: Generate GitHub App Token (public repo)
141+
id: adbc-token
142+
uses: actions/create-github-app-token@v1
143+
with:
144+
app-id: ${{ secrets.INTEGRATION_TEST_APP_ID }}
145+
private-key: ${{ secrets.INTEGRATION_TEST_PRIVATE_KEY }}
146+
owner: adbc-drivers
147+
repositories: databricks
148+
149+
- name: Dispatch C# tests to internal repo
150+
if: steps.changed.outputs.csharp == 'true'
118151
uses: peter-evans/repository-dispatch@v3
119152
with:
120153
token: ${{ steps.app-token.outputs.token }}
121154
repository: databricks/databricks-driver-test
122-
event-type: adbc-pr-test
155+
event-type: adbc-csharp-pr-test
123156
client-payload: |
124157
{
125158
"pr_number": "${{ github.event.pull_request.number }}",
@@ -129,6 +162,64 @@ jobs:
129162
"pr_title": "${{ github.event.pull_request.title }}",
130163
"pr_author": "${{ github.event.pull_request.user.login }}"
131164
}
165+
166+
- name: Dispatch Rust tests to internal repo
167+
if: steps.changed.outputs.rust == 'true'
168+
uses: peter-evans/repository-dispatch@v3
169+
with:
170+
token: ${{ steps.app-token.outputs.token }}
171+
repository: databricks/databricks-driver-test
172+
event-type: adbc-rust-pr-test
173+
client-payload: |
174+
{
175+
"pr_number": "${{ github.event.pull_request.number }}",
176+
"commit_sha": "${{ github.event.pull_request.head.sha }}",
177+
"pr_repo": "${{ github.repository }}",
178+
"pr_url": "${{ github.event.pull_request.html_url }}",
179+
"pr_title": "${{ github.event.pull_request.title }}",
180+
"pr_author": "${{ github.event.pull_request.user.login }}"
181+
}
182+
183+
- name: Pass Integration Tests check (C# not needed)
184+
if: steps.changed.outputs.csharp != 'true'
185+
uses: actions/github-script@v7
186+
with:
187+
github-token: ${{ steps.adbc-token.outputs.token }}
188+
script: |
189+
await github.rest.checks.create({
190+
owner: 'adbc-drivers',
191+
repo: 'databricks',
192+
name: 'C# Integration Tests',
193+
head_sha: context.payload.pull_request.head.sha,
194+
status: 'completed',
195+
conclusion: 'success',
196+
completed_at: new Date().toISOString(),
197+
output: {
198+
title: 'Skipped - no C# changes',
199+
summary: '✅ No C# driver files changed.'
200+
}
201+
});
202+
203+
- name: Pass Rust Integration Tests check (Rust not needed)
204+
if: steps.changed.outputs.rust != 'true'
205+
uses: actions/github-script@v7
206+
with:
207+
github-token: ${{ steps.adbc-token.outputs.token }}
208+
script: |
209+
await github.rest.checks.create({
210+
owner: 'adbc-drivers',
211+
repo: 'databricks',
212+
name: 'Rust Integration Tests',
213+
head_sha: context.payload.pull_request.head.sha,
214+
status: 'completed',
215+
conclusion: 'success',
216+
completed_at: new Date().toISOString(),
217+
output: {
218+
title: 'Skipped - no Rust changes',
219+
summary: '✅ No Rust driver files changed.'
220+
}
221+
});
222+
132223
- name: Comment on PR
133224
uses: actions/github-script@v7
134225
with:
@@ -146,6 +237,8 @@ jobs:
146237
if: github.event_name == 'merge_group'
147238
runs-on: [self-hosted, Linux, X64, peco-driver]
148239
outputs:
240+
csharp-changed: ${{ steps.check-paths.outputs.csharp_changed }}
241+
rust-changed: ${{ steps.check-paths.outputs.rust_changed }}
149242
should-test: ${{ steps.check-paths.outputs.should_test }}
150243
steps:
151244
- name: Checkout code
@@ -155,32 +248,37 @@ jobs:
155248
- name: Check if relevant files changed
156249
id: check-paths
157250
run: |
158-
# Get the base and head commits for the merge queue
159251
BASE_SHA="${{ github.event.merge_group.base_sha }}"
160252
HEAD_SHA="${{ github.event.merge_group.head_sha }}"
161253
echo "Checking files changed between $BASE_SHA and $HEAD_SHA"
162-
# Define paths to check
163-
PATHS=(
164-
".github/workflows/trigger-integration-tests.yml"
165-
"ci/scripts/"
166-
"csharp/src/"
167-
"csharp/test/"
168-
)
169-
# Check if any relevant files changed
170-
CHANGED=false
171-
for path in "${PATHS[@]}"; do
172-
if git diff --name-only "$BASE_SHA" "$HEAD_SHA" | grep -q "^${path}"; then
173-
echo "✅ Found changes in: $path"
174-
CHANGED=true
175-
break
176-
fi
177-
done
178-
if [ "$CHANGED" = true ]; then
254+
CHANGED_FILES=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA")
255+
256+
CSHARP_CHANGED=false
257+
RUST_CHANGED=false
258+
259+
if echo "$CHANGED_FILES" | grep -q "^csharp/"; then
260+
echo "✅ C# files changed"
261+
CSHARP_CHANGED=true
262+
fi
263+
if echo "$CHANGED_FILES" | grep -q "^rust/"; then
264+
echo "✅ Rust files changed"
265+
RUST_CHANGED=true
266+
fi
267+
if echo "$CHANGED_FILES" | grep -q "^\.github/workflows/"; then
268+
echo "✅ Workflow files changed - triggering all targets"
269+
CSHARP_CHANGED=true
270+
RUST_CHANGED=true
271+
fi
272+
273+
echo "csharp_changed=$CSHARP_CHANGED" >> $GITHUB_OUTPUT
274+
echo "rust_changed=$RUST_CHANGED" >> $GITHUB_OUTPUT
275+
276+
if [ "$CSHARP_CHANGED" = true ] || [ "$RUST_CHANGED" = true ]; then
179277
echo "should_test=true" >> $GITHUB_OUTPUT
180278
echo "✅ Relevant files changed - will run tests"
181279
else
182280
echo "should_test=false" >> $GITHUB_OUTPUT
183-
echo "⏭️ No relevant files changed - skipping tests"
281+
echo "⏭️ No driver/workflow files changed - will auto-approve"
184282
fi
185283
# =============================================================================
186284
# For Merge Queue: Check if tests already passed on PR
@@ -236,32 +334,29 @@ jobs:
236334
pull_number: prNumber
237335
});
238336
console.log(`PR #${prNumber} head SHA: ${pr.head.sha}`);
239-
// Get checks for current PR head SHA
240-
const { data: checks } = await github.rest.checks.listForRef({
241-
owner: context.repo.owner,
242-
repo: context.repo.repo,
243-
ref: pr.head.sha,
244-
check_name: 'Integration Tests'
245-
});
246-
console.log(`Found ${checks.total_count} check runs for "Integration Tests"`);
247-
// Find the most recent passing check
248-
const passingChecks = checks.check_runs
249-
.filter(run => run.conclusion === 'success')
250-
.sort((a, b) => new Date(b.completed_at) - new Date(a.completed_at));
251-
if (passingChecks.length === 0) {
252-
console.log('❌ No passing checks found');
253-
return false;
254-
}
255-
const latestPassing = passingChecks[0];
256-
// CRITICAL: Check if the passing test ran on the CURRENT head SHA
257-
if (latestPassing.head_sha !== pr.head.sha) {
258-
console.log(`⚠️ Tests passed on ${latestPassing.head_sha}, but PR head is now ${pr.head.sha}`);
259-
return false;
337+
// Check both required checks passed on current PR head SHA
338+
const checkNames = ['C# Integration Tests', 'Rust Integration Tests'];
339+
const results = await Promise.all(checkNames.map(name =>
340+
github.rest.checks.listForRef({
341+
owner: context.repo.owner,
342+
repo: context.repo.repo,
343+
ref: pr.head.sha,
344+
check_name: name
345+
})
346+
));
347+
for (let i = 0; i < checkNames.length; i++) {
348+
const name = checkNames[i];
349+
const runs = results[i].data.check_runs;
350+
const passing = runs.filter(r => r.conclusion === 'success' && r.head_sha === pr.head.sha);
351+
if (passing.length === 0) {
352+
console.log(`❌ No passing check found for "${name}"`);
353+
return false;
354+
}
355+
console.log(`✅ "${name}" passed on current head`);
260356
}
261-
console.log(`✅ Tests passed on current head ${pr.head.sha}`);
262357
return true;
263358
trigger-tests-merge:
264-
needs: check-previous-run
359+
needs: [check-merge-queue-paths, check-previous-run]
265360
if: needs.check-previous-run.outputs.already-passed != 'true'
266361
runs-on: [self-hosted, Linux, X64, peco-driver]
267362
steps:
@@ -273,12 +368,29 @@ jobs:
273368
private-key: ${{ secrets.INTEGRATION_TEST_PRIVATE_KEY }}
274369
owner: databricks
275370
repositories: databricks-driver-test
276-
- name: Dispatch tests to internal repo
371+
- name: Dispatch C# tests to internal repo
372+
if: needs.check-merge-queue-paths.outputs.csharp-changed == 'true'
373+
uses: peter-evans/repository-dispatch@v3
374+
with:
375+
token: ${{ steps.app-token.outputs.token }}
376+
repository: databricks/databricks-driver-test
377+
event-type: adbc-csharp-pr-test
378+
client-payload: |
379+
{
380+
"pr_number": "${{ needs.check-previous-run.outputs.pr-number }}",
381+
"commit_sha": "${{ github.event.merge_group.head_sha }}",
382+
"pr_repo": "${{ github.repository }}",
383+
"pr_url": "https://github.com/${{ github.repository }}/pull/${{ needs.check-previous-run.outputs.pr-number }}",
384+
"pr_title": "Merge queue validation",
385+
"pr_author": "merge-queue"
386+
}
387+
- name: Dispatch Rust tests to internal repo
388+
if: needs.check-merge-queue-paths.outputs.rust-changed == 'true'
277389
uses: peter-evans/repository-dispatch@v3
278390
with:
279391
token: ${{ steps.app-token.outputs.token }}
280392
repository: databricks/databricks-driver-test
281-
event-type: adbc-pr-test
393+
event-type: adbc-rust-pr-test
282394
client-payload: |
283395
{
284396
"pr_number": "${{ needs.check-previous-run.outputs.pr-number }}",
@@ -301,24 +413,27 @@ jobs:
301413
private-key: ${{ secrets.INTEGRATION_TEST_PRIVATE_KEY }}
302414
owner: adbc-drivers
303415
repositories: databricks
304-
- name: Create passing check (no relevant changes)
416+
- name: Create passing checks (no relevant changes)
305417
uses: actions/github-script@v7
306418
with:
307419
github-token: ${{ steps.app-token.outputs.token }}
308420
script: |
309-
await github.rest.checks.create({
310-
owner: context.repo.owner,
311-
repo: context.repo.repo,
312-
name: 'Integration Tests',
313-
head_sha: '${{ github.event.merge_group.head_sha }}',
314-
status: 'completed',
315-
conclusion: 'success',
316-
completed_at: new Date().toISOString(),
317-
output: {
318-
title: 'Auto-approved - no relevant changes',
319-
summary: '✅ No integration test files changed. Skipping tests.'
320-
}
321-
});
421+
const headSha = '${{ github.event.merge_group.head_sha }}';
422+
for (const name of ['C# Integration Tests', 'Rust Integration Tests']) {
423+
await github.rest.checks.create({
424+
owner: context.repo.owner,
425+
repo: context.repo.repo,
426+
name,
427+
head_sha: headSha,
428+
status: 'completed',
429+
conclusion: 'success',
430+
completed_at: new Date().toISOString(),
431+
output: {
432+
title: 'Auto-approved - no relevant changes',
433+
summary: '✅ No driver or workflow files changed. Skipping tests.'
434+
}
435+
});
436+
}
322437
auto-approve-already-passed:
323438
needs: check-previous-run
324439
if: needs.check-previous-run.outputs.already-passed == 'true'
@@ -332,21 +447,24 @@ jobs:
332447
private-key: ${{ secrets.INTEGRATION_TEST_PRIVATE_KEY }}
333448
owner: adbc-drivers
334449
repositories: databricks
335-
- name: Create passing check (auto-approve)
450+
- name: Create passing checks (auto-approve)
336451
uses: actions/github-script@v7
337452
with:
338453
github-token: ${{ steps.app-token.outputs.token }}
339454
script: |
340-
await github.rest.checks.create({
341-
owner: context.repo.owner,
342-
repo: context.repo.repo,
343-
name: 'Integration Tests',
344-
head_sha: '${{ github.event.merge_group.head_sha }}',
345-
status: 'completed',
346-
conclusion: 'success',
347-
completed_at: new Date().toISOString(),
348-
output: {
349-
title: 'Auto-approved for merge queue',
350-
summary: '✅ Tests already passed on PR head commit. Skipping duplicate test run.'
351-
}
352-
});
455+
const headSha = '${{ github.event.merge_group.head_sha }}';
456+
for (const name of ['C# Integration Tests', 'Rust Integration Tests']) {
457+
await github.rest.checks.create({
458+
owner: context.repo.owner,
459+
repo: context.repo.repo,
460+
name,
461+
head_sha: headSha,
462+
status: 'completed',
463+
conclusion: 'success',
464+
completed_at: new Date().toISOString(),
465+
output: {
466+
title: 'Auto-approved for merge queue',
467+
summary: '✅ Tests already passed on PR head commit. Skipping duplicate test run.'
468+
}
469+
});
470+
}

0 commit comments

Comments
 (0)