Skip to content

Commit 3bcaf9a

Browse files
feat: add tree_tests_rollup table and migrations (#1830)
1 parent 144becd commit 3bcaf9a

2 files changed

Lines changed: 221 additions & 0 deletions

File tree

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# Generated by Django 5.2.11 on 2026-03-30 18:45
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("kernelCI_app", "0016_alter_treelisting_unique_constraint"),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name="pendingtest",
15+
name="full_status",
16+
field=models.CharField(
17+
blank=True,
18+
choices=[
19+
("PASS", "Pass"),
20+
("FAIL", "Fail"),
21+
("SKIP", "Skip"),
22+
("ERROR", "Error"),
23+
("MISS", "Miss"),
24+
("DONE", "Done"),
25+
],
26+
max_length=10,
27+
null=True,
28+
),
29+
),
30+
migrations.AddField(
31+
model_name="pendingtest",
32+
name="lab",
33+
field=models.TextField(blank=True, null=True),
34+
),
35+
migrations.AddField(
36+
model_name="pendingtest",
37+
name="path",
38+
field=models.TextField(blank=True, null=True),
39+
),
40+
migrations.AddField(
41+
model_name="pendingtest",
42+
name="start_time",
43+
field=models.DateTimeField(blank=True, null=True),
44+
),
45+
migrations.CreateModel(
46+
name="TreeTestsRollup",
47+
fields=[
48+
(
49+
"id",
50+
models.BigAutoField(
51+
auto_created=True,
52+
primary_key=True,
53+
serialize=False,
54+
verbose_name="ID",
55+
),
56+
),
57+
("origin", models.TextField()),
58+
("tree_name", models.TextField(blank=True, null=True)),
59+
("git_repository_branch", models.TextField(blank=True, null=True)),
60+
("git_repository_url", models.TextField(blank=True, null=True)),
61+
("git_commit_hash", models.TextField(blank=True, null=True)),
62+
("path_group", models.TextField()),
63+
("build_config_name", models.TextField()),
64+
("build_architecture", models.TextField()),
65+
("build_compiler", models.TextField()),
66+
("hardware_key", models.TextField()),
67+
("test_platform", models.TextField(blank=True, null=True)),
68+
("test_lab", models.TextField(blank=True, null=True)),
69+
("test_origin", models.TextField(blank=True, null=True)),
70+
("issue_id", models.TextField(blank=True, null=True)),
71+
("issue_version", models.IntegerField(blank=True, null=True)),
72+
("issue_uncategorized", models.BooleanField(default=False)),
73+
("is_boot", models.BooleanField(default=False)),
74+
("pass_tests", models.IntegerField(default=0)),
75+
("fail_tests", models.IntegerField(default=0)),
76+
("skip_tests", models.IntegerField(default=0)),
77+
("error_tests", models.IntegerField(default=0)),
78+
("miss_tests", models.IntegerField(default=0)),
79+
("done_tests", models.IntegerField(default=0)),
80+
("null_tests", models.IntegerField(default=0)),
81+
("total_tests", models.IntegerField(default=0)),
82+
],
83+
options={
84+
"db_table": "tree_tests_rollup",
85+
"indexes": [
86+
models.Index(
87+
fields=[
88+
"origin",
89+
"tree_name",
90+
"git_repository_branch",
91+
"git_repository_url",
92+
"git_commit_hash",
93+
],
94+
name="tree_tests_rollup_scope",
95+
),
96+
models.Index(
97+
fields=["path_group", "total_tests"],
98+
name="tree_tests_rollup_group_total",
99+
),
100+
],
101+
"constraints": [
102+
models.UniqueConstraint(
103+
fields=(
104+
"origin",
105+
"tree_name",
106+
"git_repository_branch",
107+
"git_repository_url",
108+
"git_commit_hash",
109+
"path_group",
110+
"build_config_name",
111+
"build_architecture",
112+
"build_compiler",
113+
"hardware_key",
114+
"test_platform",
115+
"test_lab",
116+
"test_origin",
117+
"issue_id",
118+
"issue_version",
119+
"issue_uncategorized",
120+
),
121+
name="tree_tests_rollup_unique",
122+
nulls_distinct=False,
123+
)
124+
],
125+
},
126+
),
127+
]

backend/kernelCI_app/models.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,11 +317,20 @@ class PendingTest(models.Model):
317317
platform = models.CharField(max_length=100, null=True)
318318
compatible = ArrayField(models.TextField(), null=True)
319319
build_id = models.TextField()
320+
# Keep `status` during the migration phase; removing it would break the
321+
# ingester and process_pending flows that still read/write this field.
320322
status = models.CharField(
321323
max_length=1, choices=SimplifiedStatusChoices.choices, null=True
322324
)
323325
is_boot = models.BooleanField()
324326

327+
path = models.TextField(blank=True, null=True)
328+
start_time = models.DateTimeField(blank=True, null=True)
329+
lab = models.TextField(blank=True, null=True)
330+
full_status = models.CharField(
331+
max_length=10, choices=StatusChoices.choices, blank=True, null=True
332+
)
333+
325334
class Meta:
326335
db_table = "pending_test"
327336

@@ -403,3 +412,88 @@ class Meta:
403412
models.Index(fields=["start_time"], name="tree_listing_start_time"),
404413
models.Index(fields=["checkout_id"], name="tree_listing_checkout_id"),
405414
]
415+
416+
417+
class TreeTestsRollup(models.Model):
418+
"""Rollup of per-status test counts for a single checkout (tree + commit).
419+
420+
One row per unique combination of checkout identity (origin, tree, branch,
421+
repository URL, commit hash), test path group, build dimensions (config,
422+
architecture, compiler), hardware key, test execution context (platform,
423+
lab, origin), optional issue metadata, and whether the row covers boot
424+
tests. The counter fields feed tree-scoped tests views and APIs so clients
425+
can read pre-aggregated totals instead of scanning raw test rows.
426+
"""
427+
428+
origin = models.TextField()
429+
tree_name = models.TextField(blank=True, null=True)
430+
git_repository_branch = models.TextField(blank=True, null=True)
431+
git_repository_url = models.TextField(blank=True, null=True)
432+
git_commit_hash = models.TextField(blank=True, null=True)
433+
434+
path_group = models.TextField()
435+
build_config_name = models.TextField()
436+
build_architecture = models.TextField()
437+
build_compiler = models.TextField()
438+
hardware_key = models.TextField()
439+
test_platform = models.TextField(blank=True, null=True)
440+
test_lab = models.TextField(blank=True, null=True)
441+
test_origin = models.TextField(blank=True, null=True)
442+
443+
issue_id = models.TextField(blank=True, null=True)
444+
issue_version = models.IntegerField(blank=True, null=True)
445+
issue_uncategorized = models.BooleanField(default=False)
446+
447+
is_boot = models.BooleanField(default=False)
448+
449+
pass_tests = models.IntegerField(default=0)
450+
fail_tests = models.IntegerField(default=0)
451+
skip_tests = models.IntegerField(default=0)
452+
error_tests = models.IntegerField(default=0)
453+
miss_tests = models.IntegerField(default=0)
454+
done_tests = models.IntegerField(default=0)
455+
null_tests = models.IntegerField(default=0)
456+
total_tests = models.IntegerField(default=0)
457+
458+
class Meta:
459+
db_table = "tree_tests_rollup"
460+
constraints = [
461+
models.UniqueConstraint(
462+
fields=[
463+
"origin",
464+
"tree_name",
465+
"git_repository_branch",
466+
"git_repository_url",
467+
"git_commit_hash",
468+
"path_group",
469+
"build_config_name",
470+
"build_architecture",
471+
"build_compiler",
472+
"hardware_key",
473+
"test_platform",
474+
"test_lab",
475+
"test_origin",
476+
"issue_id",
477+
"issue_version",
478+
"issue_uncategorized",
479+
],
480+
name="tree_tests_rollup_unique",
481+
nulls_distinct=False,
482+
),
483+
]
484+
indexes = [
485+
models.Index(
486+
fields=[
487+
"origin",
488+
"tree_name",
489+
"git_repository_branch",
490+
"git_repository_url",
491+
"git_commit_hash",
492+
],
493+
name="tree_tests_rollup_scope",
494+
),
495+
models.Index(
496+
fields=["path_group", "total_tests"],
497+
name="tree_tests_rollup_group_total",
498+
),
499+
]

0 commit comments

Comments
 (0)