Skip to content

Commit 0873631

Browse files
committed
Add driver-test integration workflow trigger
Dispatch Node.js PR and merge-queue validations to databricks-driver-test so proxy-based integration tests can run with internal credentials. Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
1 parent a3bf320 commit 0873631

1 file changed

Lines changed: 350 additions & 0 deletions

File tree

Lines changed: 350 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,350 @@
1+
name: Trigger Integration Tests
2+
3+
# Dispatches the proxy-based Node.js integration suite in
4+
# databricks/databricks-driver-test to run against this PR's commit.
5+
#
6+
# Matches the label-gated / merge-queue pattern used by the Python connector:
7+
# normal PR events get an immediate green check, maintainers can preview with
8+
# the `integration-test` label, and merge queue runs the real required gate.
9+
10+
on:
11+
pull_request:
12+
types: [opened, synchronize, reopened, labeled]
13+
merge_group:
14+
15+
jobs:
16+
remove-label-on-new-commit:
17+
if: github.event_name == 'pull_request' && github.event.action == 'synchronize'
18+
runs-on:
19+
group: databricks-protected-runner-group
20+
labels: linux-ubuntu-latest
21+
permissions:
22+
pull-requests: write
23+
issues: write
24+
steps:
25+
- name: Check if integration-test label exists
26+
id: check-label
27+
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
28+
with:
29+
script: |
30+
const labels = context.payload.pull_request.labels.map((label) => label.name);
31+
const hasLabel = labels.includes('integration-test');
32+
console.log(`integration-test label exists: ${hasLabel}`);
33+
return hasLabel;
34+
35+
- name: Remove integration-test label
36+
if: steps.check-label.outputs.result == 'true'
37+
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
38+
with:
39+
script: |
40+
try {
41+
await github.rest.issues.removeLabel({
42+
owner: context.repo.owner,
43+
repo: context.repo.repo,
44+
issue_number: context.issue.number,
45+
name: 'integration-test'
46+
});
47+
console.log('Removed integration-test label');
48+
} catch (error) {
49+
if (error.status === 404) {
50+
console.log('Label already removed or does not exist');
51+
} else {
52+
throw error;
53+
}
54+
}
55+
56+
- name: Comment on PR about label removal
57+
if: steps.check-label.outputs.result == 'true'
58+
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
59+
with:
60+
script: |
61+
const pr = context.payload.pull_request;
62+
const isFromFork = pr.head.repo.full_name !== pr.base.repo.full_name;
63+
const repoType = isFromFork ? '**fork PR**' : 'PR';
64+
65+
const body = [
66+
'Integration test approval reset.',
67+
'',
68+
`New commits were pushed to this ${repoType}. The \`integration-test\` label has been automatically removed for security.`,
69+
'',
70+
'**A maintainer must re-review the changes and re-add the label to trigger tests again.**',
71+
'',
72+
`Latest commit: ${pr.head.sha.substring(0, 7)}`
73+
].join('\n');
74+
75+
await github.rest.issues.createComment({
76+
owner: context.repo.owner,
77+
repo: context.repo.repo,
78+
issue_number: context.issue.number,
79+
body
80+
});
81+
82+
skip-integration-tests-pr:
83+
if: github.event_name == 'pull_request' && github.event.action != 'labeled'
84+
runs-on:
85+
group: databricks-protected-runner-group
86+
labels: linux-ubuntu-latest
87+
permissions:
88+
checks: write
89+
steps:
90+
- name: Skip Node.js Integration Tests
91+
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
92+
with:
93+
github-token: ${{ github.token }}
94+
script: |
95+
await github.rest.checks.create({
96+
owner: context.repo.owner,
97+
repo: context.repo.repo,
98+
name: 'Node.js Integration Tests',
99+
head_sha: context.payload.pull_request.head.sha,
100+
status: 'completed',
101+
conclusion: 'success',
102+
completed_at: new Date().toISOString(),
103+
output: {
104+
title: 'Skipped on PR - runs in merge queue',
105+
summary: 'Node.js integration tests are skipped on ordinary PR events and run as a required gate in the merge queue. Add the `integration-test` label to preview them on this PR.'
106+
}
107+
});
108+
109+
trigger-tests-pr:
110+
if: |
111+
github.event_name == 'pull_request' &&
112+
github.event.action == 'labeled' &&
113+
contains(github.event.pull_request.labels.*.name, 'integration-test')
114+
runs-on:
115+
group: databricks-protected-runner-group
116+
labels: linux-ubuntu-latest
117+
permissions:
118+
issues: write
119+
pull-requests: write
120+
checks: write
121+
steps:
122+
- name: Detect changed driver paths
123+
id: changed
124+
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
125+
with:
126+
script: |
127+
const { data: files } = await github.rest.pulls.listFiles({
128+
owner: context.repo.owner,
129+
repo: context.repo.repo,
130+
pull_number: context.payload.pull_request.number,
131+
per_page: 100
132+
});
133+
134+
const names = files.map((file) => file.filename);
135+
const sourceChanged = names.some((file) =>
136+
file.startsWith('bin/') ||
137+
file.startsWith('lib/') ||
138+
file.startsWith('spec/') ||
139+
file.startsWith('thrift/') ||
140+
file.startsWith('tests/e2e/') ||
141+
file.startsWith('tests/integration/') ||
142+
file === 'package.json' ||
143+
file === 'package-lock.json' ||
144+
file === 'tsconfig.json' ||
145+
file === 'tsconfig.build.json'
146+
);
147+
const workflowChanged = names.some((file) => file.startsWith('.github/workflows/'));
148+
const runNode = sourceChanged || workflowChanged;
149+
150+
if (workflowChanged) console.log('Workflow files changed - triggering Node.js integration tests');
151+
if (sourceChanged) console.log('Driver source files changed - triggering Node.js integration tests');
152+
core.setOutput('nodejs', runNode.toString());
153+
154+
- name: Generate GitHub App Token (driver-test repo)
155+
id: app-token
156+
if: steps.changed.outputs.nodejs == 'true'
157+
uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3.0.0
158+
with:
159+
app-id: ${{ secrets.INTEGRATION_TEST_APP_ID }}
160+
private-key: ${{ secrets.INTEGRATION_TEST_PRIVATE_KEY }}
161+
owner: databricks
162+
repositories: databricks-driver-test
163+
164+
- name: Sanitize PR title
165+
id: sanitize
166+
if: steps.changed.outputs.nodejs == 'true'
167+
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
168+
with:
169+
result-encoding: string
170+
script: |
171+
const title = context.payload.pull_request.title || '';
172+
return title.replace(/[\\"\n\r\t]/g, ' ').substring(0, 200);
173+
174+
- name: Dispatch Node.js tests to driver-test
175+
if: steps.changed.outputs.nodejs == 'true'
176+
uses: peter-evans/repository-dispatch@ff45666b9427631e3450c54a1bcbee4d9ff4d7c0 # v3.0.0
177+
with:
178+
token: ${{ steps.app-token.outputs.token }}
179+
repository: databricks/databricks-driver-test
180+
event-type: nodejs-pr-test
181+
client-payload: |
182+
{
183+
"pr_number": "${{ github.event.pull_request.number }}",
184+
"commit_sha": "${{ github.event.pull_request.head.sha }}",
185+
"pr_repo": "${{ github.repository }}",
186+
"pr_url": "${{ github.event.pull_request.html_url }}",
187+
"pr_title": "${{ steps.sanitize.outputs.result }}",
188+
"pr_author": "${{ github.event.pull_request.user.login }}"
189+
}
190+
191+
- name: Pass Node.js Integration Tests check (no driver changes)
192+
if: steps.changed.outputs.nodejs != 'true'
193+
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
194+
with:
195+
github-token: ${{ github.token }}
196+
script: |
197+
await github.rest.checks.create({
198+
owner: context.repo.owner,
199+
repo: context.repo.repo,
200+
name: 'Node.js Integration Tests',
201+
head_sha: context.payload.pull_request.head.sha,
202+
status: 'completed',
203+
conclusion: 'success',
204+
completed_at: new Date().toISOString(),
205+
output: {
206+
title: 'Skipped - no driver changes',
207+
summary: 'No Node.js driver source files changed; skipping integration tests.'
208+
}
209+
});
210+
211+
- name: Fail check on dispatch error
212+
if: failure() && steps.changed.outputs.nodejs == 'true'
213+
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
214+
with:
215+
github-token: ${{ github.token }}
216+
script: |
217+
await github.rest.checks.create({
218+
owner: context.repo.owner,
219+
repo: context.repo.repo,
220+
name: 'Node.js Integration Tests',
221+
head_sha: context.payload.pull_request.head.sha,
222+
status: 'completed',
223+
conclusion: 'failure',
224+
completed_at: new Date().toISOString(),
225+
output: {
226+
title: 'Failed - error dispatching tests',
227+
summary: 'An error occurred while dispatching Node.js integration tests. Check this workflow run for details.'
228+
}
229+
});
230+
231+
- name: Comment on PR
232+
if: steps.changed.outputs.nodejs == 'true'
233+
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
234+
with:
235+
script: |
236+
await github.rest.issues.createComment({
237+
owner: context.repo.owner,
238+
repo: context.repo.repo,
239+
issue_number: context.issue.number,
240+
body: 'Node.js integration tests triggered. [View workflow run](https://github.com/databricks/databricks-driver-test/actions/workflows/databricks-nodejs-integration-tests.yml).'
241+
});
242+
243+
merge-queue-nodejs:
244+
if: github.event_name == 'merge_group'
245+
runs-on:
246+
group: databricks-protected-runner-group
247+
labels: linux-ubuntu-latest
248+
permissions:
249+
contents: read
250+
checks: write
251+
steps:
252+
- name: Checkout code
253+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
254+
with:
255+
fetch-depth: 0
256+
257+
- name: Check if driver files changed
258+
id: changed
259+
env:
260+
BASE_SHA: ${{ github.event.merge_group.base_sha }}
261+
HEAD_SHA: ${{ github.event.merge_group.head_sha }}
262+
run: |
263+
CHANGED=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA")
264+
if echo "$CHANGED" | grep -qE "^(bin/|lib/|spec/|thrift/|tests/e2e/|tests/integration/|package\.json|package-lock\.json|tsconfig(\.build)?\.json|\.github/workflows/)"; then
265+
echo "changed=true" >> "$GITHUB_OUTPUT"
266+
echo "Driver files changed - will dispatch Node.js integration tests"
267+
else
268+
echo "changed=false" >> "$GITHUB_OUTPUT"
269+
echo "No driver files changed - will auto-pass"
270+
fi
271+
272+
- name: Auto-pass (no driver changes)
273+
if: steps.changed.outputs.changed != 'true'
274+
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
275+
with:
276+
github-token: ${{ github.token }}
277+
script: |
278+
await github.rest.checks.create({
279+
owner: context.repo.owner,
280+
repo: context.repo.repo,
281+
name: 'Node.js Integration Tests',
282+
head_sha: '${{ github.event.merge_group.head_sha }}',
283+
status: 'completed',
284+
conclusion: 'success',
285+
completed_at: new Date().toISOString(),
286+
output: {
287+
title: 'Skipped - no driver changes',
288+
summary: 'No Node.js driver source files changed.'
289+
}
290+
});
291+
292+
- name: Extract PR number from merge queue ref
293+
if: steps.changed.outputs.changed == 'true'
294+
id: extract-pr
295+
env:
296+
MERGE_QUEUE_REF: ${{ github.event.merge_group.head_ref }}
297+
run: |
298+
if [[ "$MERGE_QUEUE_REF" =~ pr-([0-9]+) ]]; then
299+
echo "pr_number=${BASH_REMATCH[1]}" >> "$GITHUB_OUTPUT"
300+
else
301+
echo "Error: failed to extract PR number from merge group ref: '$MERGE_QUEUE_REF'" >&2
302+
exit 1
303+
fi
304+
305+
- name: Generate GitHub App Token (driver-test repo)
306+
if: steps.changed.outputs.changed == 'true'
307+
id: app-token
308+
uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3.0.0
309+
with:
310+
app-id: ${{ secrets.INTEGRATION_TEST_APP_ID }}
311+
private-key: ${{ secrets.INTEGRATION_TEST_PRIVATE_KEY }}
312+
owner: databricks
313+
repositories: databricks-driver-test
314+
315+
- name: Dispatch Node.js tests
316+
if: steps.changed.outputs.changed == 'true'
317+
uses: peter-evans/repository-dispatch@ff45666b9427631e3450c54a1bcbee4d9ff4d7c0 # v3.0.0
318+
with:
319+
token: ${{ steps.app-token.outputs.token }}
320+
repository: databricks/databricks-driver-test
321+
event-type: nodejs-pr-test
322+
client-payload: |
323+
{
324+
"pr_number": "${{ steps.extract-pr.outputs.pr_number }}",
325+
"commit_sha": "${{ github.event.merge_group.head_sha }}",
326+
"pr_repo": "${{ github.repository }}",
327+
"pr_url": "${{ github.server_url }}/${{ github.repository }}/pull/${{ steps.extract-pr.outputs.pr_number }}",
328+
"pr_title": "Merge queue validation",
329+
"pr_author": "merge-queue"
330+
}
331+
332+
- name: Fail check on dispatch error
333+
if: failure() && steps.changed.outputs.changed == 'true'
334+
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
335+
with:
336+
github-token: ${{ github.token }}
337+
script: |
338+
await github.rest.checks.create({
339+
owner: context.repo.owner,
340+
repo: context.repo.repo,
341+
name: 'Node.js Integration Tests',
342+
head_sha: '${{ github.event.merge_group.head_sha }}',
343+
status: 'completed',
344+
conclusion: 'failure',
345+
completed_at: new Date().toISOString(),
346+
output: {
347+
title: 'Failed - error dispatching tests',
348+
summary: 'An error occurred while dispatching Node.js integration tests. Check this workflow run for details.'
349+
}
350+
});

0 commit comments

Comments
 (0)