|
18 | 18 | psql = psycopg2.connect(database=db_name) |
19 | 19 | psql.autocommit = True |
20 | 20 |
|
| 21 | +# How many branches to query to get flakes for last month |
| 22 | +flake_cnt = 300 |
| 23 | + |
21 | 24 |
|
22 | 25 | @app.route('/') |
23 | 26 | def hello(): |
@@ -190,3 +193,85 @@ def dev_info(): |
190 | 193 | data = [{columns[i]: value for i, value in enumerate(row)} for row in rows] |
191 | 194 |
|
192 | 195 | return data |
| 196 | + |
| 197 | + |
| 198 | +@app.route('/flaky-tests') |
| 199 | +def flaky_tests(): |
| 200 | + """ |
| 201 | + Returns tests that are flaky (first try fails, retry passes, and no crash). |
| 202 | + """ |
| 203 | + global flake_cnt |
| 204 | + limit = request.args.get('limit') |
| 205 | + try: |
| 206 | + limit = int(limit) |
| 207 | + month = False |
| 208 | + except: |
| 209 | + month = True # Default to querying last month |
| 210 | + limit = flake_cnt # Default limit |
| 211 | + |
| 212 | + # Find branches with incomplete results, psql JSON helpers fail for them |
| 213 | + t = datetime.datetime.now() |
| 214 | + with psql.cursor() as cur: |
| 215 | + query = f""" |
| 216 | + SELECT branch |
| 217 | + FROM results |
| 218 | + WHERE json_normal NOT LIKE '%"results": [%' |
| 219 | + GROUP BY branch; |
| 220 | + """ |
| 221 | + |
| 222 | + cur.execute(query) |
| 223 | + rows = cur.fetchall() |
| 224 | + branches = "" |
| 225 | + if rows: |
| 226 | + branches = " AND branch != ".join([""] + [f"'{r[0]}'" for r in rows]) |
| 227 | + print(f"Query for in-prog execs took: {str(datetime.datetime.now() - t)}") |
| 228 | + |
| 229 | + t = datetime.datetime.now() |
| 230 | + with psql.cursor() as cur: |
| 231 | + # Query for tests where first try failed, retry passed, and no crash |
| 232 | + query = f""" |
| 233 | + SELECT remote, executor, test, branch, branch_date |
| 234 | + FROM results, jsonb_to_recordset(json_normal::jsonb->'results') as |
| 235 | + x(test text, result text, retry text, crashes text) |
| 236 | + WHERE x.result = 'fail' |
| 237 | + AND x.retry = 'pass' |
| 238 | + AND x.crashes IS NULL |
| 239 | + {branches} |
| 240 | + ORDER BY branch_date DESC LIMIT {limit}; |
| 241 | + """ |
| 242 | + |
| 243 | + cur.execute(query) |
| 244 | + rows = cur.fetchall() |
| 245 | + |
| 246 | + print(f"Query for flaky tests took: {str(datetime.datetime.now() - t)}") |
| 247 | + |
| 248 | + target_date = datetime.datetime.now() - datetime.timedelta(days=14) |
| 249 | + two_weeks = target_date.strftime("%Y-%m-%d--%H-%M") |
| 250 | + target_date = datetime.datetime.now() - datetime.timedelta(days=28) |
| 251 | + four_weeks = target_date.strftime("%Y-%m-%d--%H-%M") |
| 252 | + cnt = 0 |
| 253 | + res = {} |
| 254 | + for row in rows: |
| 255 | + rem, exe, test, branch, br_date = row |
| 256 | + key = (rem, exe, test) |
| 257 | + if not month: |
| 258 | + res[key] = res.get(key, 0) + 1 |
| 259 | + else: |
| 260 | + if key not in res: |
| 261 | + res[key] = [0, 0] |
| 262 | + if br_date >= two_weeks: |
| 263 | + res[key][0] += 1 |
| 264 | + elif br_date >= four_weeks: |
| 265 | + res[key][1] += 1 |
| 266 | + else: |
| 267 | + break |
| 268 | + cnt += 1 |
| 269 | + # JSON needs a simple array, not a dict |
| 270 | + data = [] |
| 271 | + for k, v in res.items(): |
| 272 | + data.append({"remote": k[0], "executor": k[1], "test": k[2], "count": v}) |
| 273 | + |
| 274 | + if month: |
| 275 | + # Overcount by 30 to account for fluctuation in flakiness |
| 276 | + flake_cnt = cnt + 30 |
| 277 | + return data |
0 commit comments