diff --git a/pgcommitfest/commitfest/fixtures/commitfest_data.json b/pgcommitfest/commitfest/fixtures/commitfest_data.json index 7398f899..6e5b32ff 100644 --- a/pgcommitfest/commitfest/fixtures/commitfest_data.json +++ b/pgcommitfest/commitfest/fixtures/commitfest_data.json @@ -216,6 +216,27 @@ ] } }, +{ + "model": "commitfest.patch", + "pk": 7, + "fields": { + "name": "Old BufferDesc refcount in PrintBufferDescs and PrintPinnedBufs", + "topic": 3, + "wikilink": "", + "gitlink": "", + "targetversion": null, + "committer": null, + "created": "2025-03-01T22:27:53.214", + "modified": "2025-03-01T22:27:53.221", + "lastmail": "2025-01-18T07:14:02", + "authors": [], + "reviewers": [], + "subscribers": [], + "mailthread_set": [ + 7 + ] + } +}, { "model": "commitfest.patchoncommitfest", "pk": 1, @@ -293,6 +314,17 @@ "status": 6 } }, +{ + "model": "commitfest.patchoncommitfest", + "pk": 8, + "fields": { + "patch": 7, + "commitfest": 2, + "enterdate": "2025-03-01T22:27:53.214", + "leavedate": null, + "status": 1 + } +}, { "model": "commitfest.patchhistory", "pk": 1, @@ -480,6 +512,28 @@ "what": "Closed in commitfest Sample In Progress Commitfest with status: Rejected" } }, +{ + "model": "commitfest.patchhistory", + "pk": 18, + "fields": { + "patch": 7, + "date": "2025-03-01T22:27:53.215", + "by": 1, + "by_cfbot": false, + "what": "Created patch record" + } +}, +{ + "model": "commitfest.patchhistory", + "pk": 19, + "fields": { + "patch": 7, + "date": "2025-03-01T22:27:53.218", + "by": 1, + "by_cfbot": false, + "what": "Attached mail thread example@message-31" + } +}, { "model": "commitfest.mailthread", "pk": 1, @@ -564,6 +618,20 @@ "latestmsgid": "example@message-16" } }, +{ + "model": "commitfest.mailthread", + "pk": 7, + "fields": { + "messageid": "example@message-31", + "subject": "Re: Old BufferDesc refcount in PrintBufferDescs and PrintPinnedBufs", + "firstmessage": "2025-01-18T07:14:02", + "firstauthor": "test@test.com", + "latestmessage": "2025-01-18T07:14:02", + "latestauthor": "test@test.com", + "latestsubject": "Re: Old BufferDesc refcount in PrintBufferDescs and PrintPinnedBufs", + "latestmsgid": "example@message-31" + } +}, { "model": "commitfest.patchstatus", "pk": 1, @@ -638,6 +706,7 @@ "apply_url": "http://cfbot.cputube.org/patch_4573.log", "status": "finished", "needs_rebase_since": null, + "failing_since": null, "created": "2025-01-26T22:06:02.980", "modified": "2025-01-29T22:50:37.805", "version": "", @@ -657,10 +726,11 @@ "commit_id": null, "apply_url": "http://cfbot.cputube.org/patch_4573.log", "status": "failed", - "needs_rebase_since": null, + "needs_rebase_since": "2025-03-01T22:30:42", + "failing_since": "2025-02-01T22:30:42", "created": "2025-01-26T22:11:09.961", - "modified": "2025-01-26T22:20:39.372", - "version": null, + "modified": "2025-03-01T22:59:14.717", + "version": "", "patch_count": null, "first_additions": null, "first_deletions": null, @@ -678,8 +748,9 @@ "apply_url": "http://cfbot.cputube.org/patch_4748.log", "status": "failed", "needs_rebase_since": null, + "failing_since": "2025-03-01T23:18:06", "created": "2025-01-26T22:22:46.602", - "modified": "2025-01-29T22:58:51.032", + "modified": "2025-03-01T23:18:10.856", "version": "", "patch_count": 3, "first_additions": 345, @@ -698,6 +769,7 @@ "apply_url": "http://cfbot.cputube.org/patch_4748.log", "status": "testing", "needs_rebase_since": null, + "failing_since": null, "created": "2025-01-31T13:32:22.017", "modified": "2025-01-31T13:32:22.017", "version": "", @@ -708,6 +780,27 @@ "all_deletions": 14 } }, +{ + "model": "commitfest.cfbotbranch", + "pk": 7, + "fields": { + "branch_id": 12, + "branch_name": "cf/7", + "commit_id": "efg123", + "apply_url": "http://cfbot.cputube.org/patch_7.log", + "status": "timeout", + "needs_rebase_since": null, + "failing_since": "2025-03-01T22:29:07", + "created": "2025-03-01T22:29:25.461", + "modified": "2025-03-01T22:30:14.495", + "version": "", + "patch_count": 1, + "first_additions": 1, + "first_deletions": 2, + "all_additions": 1, + "all_deletions": 2 + } +}, { "model": "commitfest.cfbottask", "pk": 1, diff --git a/pgcommitfest/commitfest/migrations/0010_add_failing_since_column.py b/pgcommitfest/commitfest/migrations/0010_add_failing_since_column.py new file mode 100644 index 00000000..ff5017b4 --- /dev/null +++ b/pgcommitfest/commitfest/migrations/0010_add_failing_since_column.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.19 on 2025-03-01 13:53 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("commitfest", "0009_extra_branch_fields"), + ] + + operations = [ + migrations.AddField( + model_name="cfbotbranch", + name="failing_since", + field=models.DateTimeField(blank=True, null=True), + ), + ] diff --git a/pgcommitfest/commitfest/models.py b/pgcommitfest/commitfest/models.py index 88b184b6..2cf9d8dc 100644 --- a/pgcommitfest/commitfest/models.py +++ b/pgcommitfest/commitfest/models.py @@ -469,6 +469,7 @@ class CfbotBranch(models.Model): # Actually a postgres enum column status = models.TextField(choices=STATUS_CHOICES, null=False) needs_rebase_since = models.DateTimeField(null=True, blank=True) + failing_since = models.DateTimeField(null=True, blank=True) created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) version = models.TextField(null=True, blank=True) diff --git a/pgcommitfest/commitfest/templates/commitfest.html b/pgcommitfest/commitfest/templates/commitfest.html index 419dbe33..bb1e1aa8 100644 --- a/pgcommitfest/commitfest/templates/commitfest.html +++ b/pgcommitfest/commitfest/templates/commitfest.html @@ -64,7 +64,7 @@

{{p.is_open|yesno:"Active patches,Closed patches"}}

ID{%if sortkey == 4%}
{%elif sortkey == -4%}
{%endif%} Status Ver - CI status + CI status{%if sortkey == 7%}
{%elif sortkey == -7%}
{%endif%} Stats{%if sortkey == 6%}
{%elif sortkey == -6%}
{%endif%} Author Reviewers @@ -91,34 +91,36 @@

{{p.is_open|yesno:"Active patches,Closed patches"}}

{{p.status|patchstatusstring}} {%if p.targetversion%}{{p.targetversion}}{%endif%} - {%if not p.cfbot_results %} + {%with p.cfbot_results as cfb%} + {%if not cfb %} Not processed - {%elif p.cfbot_results.needs_rebase %} - + {%elif p.needs_rebase_since %} + Needs rebase! {%else%} - {%if p.cfbot_results.failed > 0 or p.cfbot_results.branch_status == 'failed' or p.cfbot_results.branch_status == 'timeout' %} + title="View CI history. {%if p.failing_since%}Failing since {{p.failing_since|timesince}}. {%endif%}{%if cfb.failed_task_names %}Failed jobs: {{cfb.failed_task_names}}{%endif%}"> + {%if cfb.failed > 0 or cfb.branch_status == 'failed' or cfb.branch_status == 'timeout' %} - {%elif p.cfbot_results.completed < p.cfbot_results.total %} + {%elif cfb.completed < cfb.total %} {%else%} {%endif%} - {{p.cfbot_results.completed}}/{{p.cfbot_results.total}} + {{cfb.completed}}/{{cfb.total}} {%endif%} - {%if p.cfbot_results and p.cfbot_results.all_additions is not none %} - +{{ p.cfbot_results.all_additions }}−{{ p.cfbot_results.all_deletions }} + {%if cfb and cfb.all_additions is not none %} + +{{ cfb.all_additions }}−{{ cfb.all_deletions }} {%endif%} + {%endwith%} {{p.author_names|default:''}} {{p.reviewer_names|default:''}} {{p.committer|default:''}} diff --git a/pgcommitfest/commitfest/templates/patch.html b/pgcommitfest/commitfest/templates/patch.html index 5a2da17c..971c9381 100644 --- a/pgcommitfest/commitfest/templates/patch.html +++ b/pgcommitfest/commitfest/templates/patch.html @@ -17,10 +17,10 @@ {%if not cfbot_branch %} Not processed - {%elif not cfbot_branch.commit_id %} + {%elif cfbot_branch.needs_rebase_since %} Needs rebase! - Additional links previous successfully applied patch (outdated): + Needs rebase since {{cfbot_branch.needs_rebase_since|timesince}}. {%if cfbot_branch.failing_since and cfbot_branch.failing_since != cfbot_branch.needs_rebase_since %}Failing since {{cfbot_branch.failing_since|timesince}}. {%endif%}
Additional links previous successfully applied patch (outdated):
Summary diff --git a/pgcommitfest/commitfest/views.py b/pgcommitfest/commitfest/views.py index 90dbe6a0..f5337785 100644 --- a/pgcommitfest/commitfest/views.py +++ b/pgcommitfest/commitfest/views.py @@ -265,6 +265,10 @@ def commitfest(request, cfid): ) elif sortkey == -6: orderby_str = "branch.all_additions + branch.all_deletions DESC NULLS LAST, created DESC" + elif sortkey == 7: + orderby_str = "branch.failing_since DESC NULLS FIRST, branch.created DESC" + elif sortkey == -7: + orderby_str = "branch.failing_since NULLS LAST, branch.created" else: orderby_str = "p.id" sortkey = 0 @@ -294,6 +298,8 @@ def commitfest(request, cfid): (SELECT string_agg(first_name || ' ' || last_name || ' (' || username || ')', ', ') FROM auth_user INNER JOIN commitfest_patch_authors cpa ON cpa.user_id=auth_user.id WHERE cpa.patch_id=p.id) AS author_names, (SELECT string_agg(first_name || ' ' || last_name || ' (' || username || ')', ', ') FROM auth_user INNER JOIN commitfest_patch_reviewers cpr ON cpr.user_id=auth_user.id WHERE cpr.patch_id=p.id) AS reviewer_names, (SELECT count(1) FROM commitfest_patchoncommitfest pcf WHERE pcf.patch_id=p.id) AS num_cfs, +branch.needs_rebase_since, +branch.failing_since, ( SELECT row_to_json(t) as cfbot_results from ( @@ -303,12 +309,9 @@ def commitfest(request, cfid): count(*) FILTER (WHERE task.status in ('ABORTED', 'ERRORED', 'FAILED')) failed, count(*) total, string_agg(task.task_name, ', ') FILTER (WHERE task.status in ('ABORTED', 'ERRORED', 'FAILED')) as failed_task_names, - branch.commit_id IS NULL as needs_rebase, branch.status as branch_status, branch.apply_url, branch.patch_count, - branch.first_additions, - branch.first_deletions, branch.all_additions, branch.all_deletions FROM commitfest_cfbotbranch branch @@ -1250,13 +1253,14 @@ def cfbot_ingest(message): # CONFLICT does not allow us to return that). We need to know the previous # state so we can skip sending notifications if the needs_rebase status did # not change. + needs_save = False needs_rebase = branch_status["commit_id"] is None if bool(branch_in_db.needs_rebase_since) is not needs_rebase: if needs_rebase: branch_in_db.needs_rebase_since = datetime.now() else: branch_in_db.needs_rebase_since = None - branch_in_db.save() + needs_save = True if needs_rebase: PatchHistory( @@ -1270,6 +1274,27 @@ def cfbot_ingest(message): what="Patch does not need rebase anymore", ).save_and_notify(authors_only=True) + # Similarly, we change the failing_since field using a separate UPDATE + failing = branch_status["status"] in ("failed", "timeout") or needs_rebase + finished = branch_status["status"] == "finished" + + if "task_status" in message and message["task_status"]["status"] in ( + "ABORTED", + "ERRORED", + "FAILED", + ): + failing = True + + if (failing or finished) and bool(branch_in_db.failing_since) is not failing: + if failing: + branch_in_db.failing_since = datetime.now() + else: + branch_in_db.failing_since = None + needs_save = True + + if needs_save: + branch_in_db.save() + @csrf_exempt def cfbot_notify(request):