Skip to content

Commit c7a3f17

Browse files
authored
[ci] start tracking retried tests (#15326)
## Change Description Start capturing retried failed tests as a proxy for flaky tests. This will allow us to follow up with additional tracking of the most common failures, make lists of links to similar test failures for bulk analysis, etc. Potentially, we could even add a "YOLO merge anyway" button as an alternative to Retry, but let's start with a simple tracking change and see how far we can get with just improving the tests. Example row recorded by a test Retry: ``` mysql> select * from retried_tests; +----+----------+--------+--------------+--------+-----------+-----------+-------------------+------------------------+------------------------------------------+------------+---------------------+ | id | batch_id | job_id | job_name | state | exit_code | pr_number | target_branch | source_branch | source_sha | retried_by | retried_at | +----+----------+--------+--------------+--------+-----------+-----------+-------------------+------------------------+------------------------------------------+------------+---------------------+ | 1 | 8370753 | 186 | test_batch_4 | Failed | 1 | 15320 | hail-is/hail:main | refresh-cert-on-deploy | 1518edb | chrisl | 2026-03-10 19:03:09 | +----+----------+--------+--------------+--------+-----------+-----------+-------------------+------------------------+------------------------------------------+------------+---------------------+ 1 row in set (0.01 sec) ``` ## Security Assessment - This change potentially impacts the Hail Batch instance as deployed by Broad Institute in GCP ### Impact Rating - This change has a low security impact ### Impact Description Store well defined data types (that are already being stored elsewhere in the db) in a new table, as part of an existing development workflow. ### Appsec Review - [x] Required: The impact has been assessed and approved by appsec
1 parent 3e042de commit c7a3f17

4 files changed

Lines changed: 64 additions & 3 deletions

File tree

build.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2093,6 +2093,9 @@ steps:
20932093
- name: add-service-rate-limits
20942094
script: /io/sql/006-add-service-rate-limits.sql
20952095
online: true
2096+
- name: retried-tests
2097+
script: /io/sql/007-retried-tests.sql
2098+
online: true
20962099
inputs:
20972100
- from: /repo/ci/sql
20982101
to: /io/sql

ci/ci/ci.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ def storage_uri_to_url(uri: str) -> str:
325325
return uri
326326

327327

328-
async def retry_pr(wb: WatchedBranch, pr: PR, request: web.Request):
328+
async def retry_pr(wb: WatchedBranch, pr: PR, request: web.Request, userdata: UserData):
329329
app = request.app
330330
session = await aiohttp_session.get_session(request)
331331

@@ -341,6 +341,27 @@ async def retry_pr(wb: WatchedBranch, pr: PR, request: web.Request):
341341

342342
batch_id = pr.batch.id
343343
db = app[AppKeys.DB]
344+
345+
async for job in pr.batch.jobs():
346+
if job['state'] in ('Failed', 'Error'):
347+
await db.execute_insertone(
348+
'''INSERT INTO retried_tests
349+
(batch_id, job_id, job_name, state, exit_code, pr_number, target_branch, source_branch, source_sha, retried_by)
350+
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)''',
351+
(
352+
job['batch_id'],
353+
job['job_id'],
354+
job.get('name'),
355+
job['state'],
356+
job.get('exit_code'),
357+
pr.number,
358+
wb.branch.short_str(),
359+
pr.source_branch.name,
360+
pr.source_sha,
361+
userdata['username'],
362+
),
363+
)
364+
344365
await db.execute_insertone('INSERT INTO invalidated_batches (batch_id) VALUES (%s);', batch_id)
345366
await wb.notify_batch_changed(
346367
db, app[AppKeys.BATCH_CLIENT], app[AppKeys.GH_CLIENT], app[AppKeys.FROZEN_MERGE_DEPLOY]
@@ -353,10 +374,10 @@ async def retry_pr(wb: WatchedBranch, pr: PR, request: web.Request):
353374
@routes.post('/watched_branches/{watched_branch_index}/pr/{pr_number}/retry')
354375
@web_security_headers
355376
@auth.authenticated_developers_only(redirect=False)
356-
async def post_retry_pr(request: web.Request, _) -> NoReturn:
377+
async def post_retry_pr(request: web.Request, userdata: UserData) -> NoReturn:
357378
wb, pr = wb_and_pr_from_request(request)
358379

359-
await asyncio.shield(retry_pr(wb, pr, request))
380+
await asyncio.shield(retry_pr(wb, pr, request, userdata))
360381
raise web.HTTPFound(deploy_config.external_url('ci', f'/watched_branches/{wb.index}/pr/{pr.number}'))
361382

362383

ci/sql/007-retried-tests.sql

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
CREATE TABLE retried_tests (
2+
id BIGINT NOT NULL AUTO_INCREMENT,
3+
batch_id BIGINT NOT NULL,
4+
job_id INT NOT NULL,
5+
job_name VARCHAR(255),
6+
state VARCHAR(50) NOT NULL,
7+
exit_code INT,
8+
pr_number INT NOT NULL,
9+
target_branch VARCHAR(255) NOT NULL,
10+
source_branch VARCHAR(255) NOT NULL,
11+
source_sha VARCHAR(40) NOT NULL,
12+
retried_by VARCHAR(255) NOT NULL,
13+
retried_at TIMESTAMP NOT NULL DEFAULT (UTC_TIMESTAMP),
14+
PRIMARY KEY (id),
15+
INDEX retried_tests_batch_id (batch_id),
16+
INDEX retried_tests_pr_number (pr_number),
17+
INDEX retried_tests_job_name (job_name)
18+
) ENGINE = InnoDB;

ci/sql/estimated-current.sql

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,22 @@ CREATE TABLE IF NOT EXISTS `deployed_services` (
3939
INSERT INTO `active_namespaces` (`namespace`) VALUES (`default`);
4040
INSERT INTO `deployed_services` (`namespace`, `service`) VALUES
4141
('default', 'auth'), ('default', 'batch'), ('default', 'batch-driver'), ('default', 'ci');
42+
43+
CREATE TABLE retried_tests (
44+
id BIGINT NOT NULL AUTO_INCREMENT,
45+
batch_id BIGINT NOT NULL,
46+
job_id INT NOT NULL,
47+
job_name VARCHAR(255),
48+
state VARCHAR(50) NOT NULL,
49+
exit_code INT,
50+
pr_number INT NOT NULL,
51+
target_branch VARCHAR(255) NOT NULL,
52+
source_branch VARCHAR(255) NOT NULL,
53+
source_sha VARCHAR(40) NOT NULL,
54+
retried_by VARCHAR(255) NOT NULL,
55+
retried_at TIMESTAMP NOT NULL DEFAULT (UTC_TIMESTAMP),
56+
PRIMARY KEY (id),
57+
INDEX retried_tests_batch_id (batch_id),
58+
INDEX retried_tests_pr_number (pr_number),
59+
INDEX retried_tests_job_name (job_name)
60+
) ENGINE = InnoDB;

0 commit comments

Comments
 (0)