Skip to content

Commit 3b91a81

Browse files
committed
migrate to Checks API for integration tests
Use GitHub Checks API instead of Statuses API to report integration test results. This enables the use of GitHub App authentication and eliminates the need for monthly PAT rotation. Changes: - Generate a second GitHub App token for check creation - Create check run before triggering tests in eng-dev-ecosystem - Pass check_run_id to the workflow for status updates - Update get_status() to query Checks API instead of Statuses API
1 parent 819274c commit 3b91a81

2 files changed

Lines changed: 78 additions & 25 deletions

File tree

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
if: "${{ !github.event.pull_request.head.repo.fork }}"
2323

2424
steps:
25-
- name: Generate GitHub App Token
25+
- name: Generate GitHub App Token for Workflow Trigger
2626
id: generate-token
2727
uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
2828
with:
@@ -31,11 +31,20 @@ jobs:
3131
owner: ${{ secrets.ORG_NAME }}
3232
repositories: ${{secrets.REPO_NAME}}
3333

34+
- name: Generate GitHub App Token for Check Updates
35+
id: generate-check-token
36+
uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
37+
with:
38+
app-id: ${{ secrets.DECO_TEST_APPROVAL_APP_ID }}
39+
private-key: ${{ secrets.DECO_TEST_APPROVAL_PRIVATE_KEY }}
40+
owner: databricks
41+
3442
- name: Fetch start_integration_tests.py
3543
run: wget https://raw.githubusercontent.com/databricks/cli/refs/heads/main/tools/start_integration_tests.py
3644

3745
- name: Run start_integration_tests.py
3846
env:
3947
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
48+
GH_CHECK_TOKEN: ${{ steps.generate-check-token.outputs.token }}
4049
run: |-
4150
python3 ./start_integration_tests.py -R ${{ secrets.ORG_NAME }}/${{secrets.REPO_NAME}} --yes

tools/start_integration_tests.py

Lines changed: 68 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@
88

99
import argparse
1010
import json
11+
import os
1112
import subprocess
1213
import sys
13-
from pathlib import Path
14-
import re
1514

1615

1716
CLI_REPO = "databricks/cli"
@@ -20,14 +19,17 @@
2019
ALLOWED_HEAD_OWNER = {"id": "MDEyOk9yZ2FuaXphdGlvbjQ5OTgwNTI=", "login": "databricks"}
2120

2221

23-
def run(cmd):
22+
def run(cmd, env=None):
2423
sys.stderr.write("+ " + " ".join(cmd) + "\n")
25-
return subprocess.run(cmd, check=True)
24+
return subprocess.run(cmd, check=True, env=env)
2625

2726

28-
def run_json(cmd):
27+
def run_json(cmd, env=None):
2928
sys.stderr.write("+ " + " ".join(cmd) + "\n")
30-
result = subprocess.run(cmd, stdout=subprocess.PIPE, encoding="utf-8", check=True)
29+
run_env = os.environ.copy()
30+
if env:
31+
run_env.update(env)
32+
result = subprocess.run(cmd, stdout=subprocess.PIPE, encoding="utf-8", check=True, env=run_env)
3133

3234
try:
3335
return json.loads(result.stdout)
@@ -36,6 +38,38 @@ def run_json(cmd):
3638
raise
3739

3840

41+
def create_check(commit_sha):
42+
"""Create a check run for the given commit and return the check_run_id."""
43+
check_token = os.environ.get("GH_CHECK_TOKEN")
44+
if not check_token:
45+
print("Warning: GH_CHECK_TOKEN not set, skipping check creation")
46+
return None
47+
48+
response = run_json(
49+
[
50+
"gh",
51+
"api",
52+
"-X",
53+
"POST",
54+
f"/repos/{CLI_REPO}/check-runs",
55+
"-f",
56+
"name=Integration Tests",
57+
"-f",
58+
f"head_sha={commit_sha}",
59+
"-f",
60+
"status=queued",
61+
"-f",
62+
"output[title]=Integration Tests",
63+
"-f",
64+
"output[summary]=Tests queued and will be triggered shortly...",
65+
],
66+
env={"GH_TOKEN": check_token},
67+
)
68+
check_run_id = response.get("id")
69+
print(f"Created check run: {check_run_id}")
70+
return check_run_id
71+
72+
3973
def get_approved_prs_by_non_team():
4074
prs = run_json(
4175
[
@@ -108,30 +142,40 @@ def start_job(pr_number, commit_sha, author, approved_by, workflow, repo, force=
108142
response = input("Start integration tests? (y/n): ")
109143

110144
if response.lower() == "y":
111-
result = run(
112-
[
113-
"gh",
114-
"workflow",
115-
"run",
116-
workflow,
117-
"-R",
118-
repo,
119-
"-F",
120-
f"pull_request_number={pr_number}",
121-
"-F",
122-
f"commit_sha={commit_sha}",
123-
],
124-
)
145+
check_run_id = create_check(commit_sha)
146+
147+
cmd = [
148+
"gh",
149+
"workflow",
150+
"run",
151+
workflow,
152+
"-R",
153+
repo,
154+
"-F",
155+
f"pull_request_number={pr_number}",
156+
"-F",
157+
f"commit_sha={commit_sha}",
158+
]
159+
if check_run_id:
160+
cmd.extend(["-F", f"check_run_id={check_run_id}"])
161+
162+
run(cmd)
125163
print(f"Started integration tests for PR #{pr_number}")
126164

127165

128166
def get_status(commit_sha):
129-
statuses = run_json(["gh", "api", f"repos/{CLI_REPO}/commits/{commit_sha}/statuses"])
167+
response = run_json(["gh", "api", f"repos/{CLI_REPO}/commits/{commit_sha}/check-runs"])
130168
result = []
131-
for st in statuses:
132-
if st["context"] != "Integration Tests Check":
169+
for check in response.get("check_runs", []):
170+
if check["name"] != "Integration Tests":
133171
continue
134-
result.append(f"{st['state']} {st['target_url']}")
172+
status = check["status"]
173+
conclusion = check.get("conclusion", "")
174+
details_url = check.get("details_url", "")
175+
if conclusion:
176+
result.append(f"{conclusion} {details_url}")
177+
else:
178+
result.append(f"{status} {details_url}")
135179
return result
136180

137181

0 commit comments

Comments
 (0)