aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2023-07-05 12:03:33 +0200
committerAleksandr Nogikh <nogikh@google.com>2023-07-06 09:36:39 +0000
commit1a2f6297df2e11f3ef37e97803568cb1b9ef875b (patch)
tree3f0dab82ef851a44a3d7af6e96542ab81aaecdb2
parentc6509052a04c3ba3d383b17946ebd6cdbb9ca89c (diff)
dashboard: order bugs in a report by their priority
Display high prio bugs on top of the list and low prio bugs at the bottom.
-rw-r--r--dashboard/app/label.go31
-rw-r--r--dashboard/app/reporting_lists.go4
-rw-r--r--dashboard/app/subsystem_test.go93
-rw-r--r--dashboard/app/util_test.go8
4 files changed, 134 insertions, 2 deletions
diff --git a/dashboard/app/label.go b/dashboard/app/label.go
index 0b911bdc3..01d360755 100644
--- a/dashboard/app/label.go
+++ b/dashboard/app/label.go
@@ -20,13 +20,25 @@ const (
MissingBackportLabel BugLabelType = "missing-backport"
)
+type BugPrio string
+
+const (
+ LowPrioBug BugPrio = "low"
+ NormalPrioBug BugPrio = "normal"
+ HighPrioBug BugPrio = "high"
+)
+
type oneOf []string
type subsetOf []string
type trueFalse struct{}
func makeLabelSet(c context.Context, ns string) *labelSet {
ret := map[BugLabelType]interface{}{
- PriorityLabel: oneOf([]string{"low", "normal", "high"}),
+ PriorityLabel: oneOf([]string{
+ string(LowPrioBug),
+ string(NormalPrioBug),
+ string(HighPrioBug),
+ }),
NoRemindersLabel: trueFalse{},
MissingBackportLabel: trueFalse{},
}
@@ -223,3 +235,20 @@ func (bug *Bug) HasUserLabel(label BugLabelType) bool {
}
return false
}
+
+func (bug *Bug) prio() BugPrio {
+ for _, label := range bug.LabelValues(PriorityLabel) {
+ return BugPrio(label.Value)
+ }
+ return NormalPrioBug
+}
+
+var bugPrioOrder = map[BugPrio]int{
+ LowPrioBug: 1,
+ NormalPrioBug: 2,
+ HighPrioBug: 3,
+}
+
+func (bp BugPrio) LessThan(other BugPrio) bool {
+ return bugPrioOrder[bp] < bugPrioOrder[other]
+}
diff --git a/dashboard/app/reporting_lists.go b/dashboard/app/reporting_lists.go
index b8cc15d2b..7e9abef81 100644
--- a/dashboard/app/reporting_lists.go
+++ b/dashboard/app/reporting_lists.go
@@ -300,6 +300,10 @@ func querySubsystemReport(c context.Context, subsystem *Subsystem, reporting *Re
})
takeBugs := append(withRepro, noRepro[:takeNoRepro]...)
sort.Slice(takeBugs, func(i, j int) bool {
+ firstPrio, secondPrio := takeBugs[i].prio(), takeBugs[j].prio()
+ if firstPrio != secondPrio {
+ return !firstPrio.LessThan(secondPrio)
+ }
if takeBugs[i].NumCrashes != takeBugs[j].NumCrashes {
return takeBugs[i].NumCrashes > takeBugs[j].NumCrashes
}
diff --git a/dashboard/app/subsystem_test.go b/dashboard/app/subsystem_test.go
index 806c37cf2..9eb6dde56 100644
--- a/dashboard/app/subsystem_test.go
+++ b/dashboard/app/subsystem_test.go
@@ -920,3 +920,96 @@ To regenerate the report, reply with:
You may send multiple commands in a single email message.
`, bugToExtID["WARNING: a first"], bugToExtID["WARNING: a second"]))
}
+
+// nolint: goconst
+func TestRemindersPriority(t *testing.T) {
+ c := NewCtx(t)
+ defer c.Close()
+
+ client := c.makeClient(clientSubsystemRemind, keySubsystemRemind, true)
+ mailingList := config.Namespaces["subsystem-reminders"].Reporting[1].Config.(*EmailConfig).Email
+ build := testBuild(1)
+ client.UploadBuild(build)
+
+ // WARNING: a first, low prio, has repro
+ aFirst := testCrash(build, 1)
+ aFirst.Title = `WARNING: a first`
+ aFirst.GuiltyFiles = []string{"a.c"}
+ aFirst.ReproOpts = []byte("some opts")
+ aFirst.ReproSyz = []byte("getpid()")
+ client.ReportCrash(aFirst)
+ sender, firstExtID := client.pollEmailAndExtID()
+ c.incomingEmail(sender, "#syz set prio: low\n",
+ EmailOptFrom("test@requester.com"), EmailOptCC([]string{mailingList}))
+ c.advanceTime(time.Hour)
+
+ // WARNING: a second, normal prio
+ aSecond := testCrash(build, 1)
+ aSecond.Title = `WARNING: a second`
+ aSecond.GuiltyFiles = []string{"a.c"}
+ client.ReportCrash(aSecond)
+ secondExtID := client.pollEmailExtID()
+ c.advanceTime(time.Hour)
+
+ // WARNING: a third, high prio
+ aThird := testCrash(build, 1)
+ aThird.Title = `WARNING: a third`
+ aThird.GuiltyFiles = []string{"a.c"}
+ client.ReportCrash(aThird)
+ sender, thirdExtID := client.pollEmailAndExtID()
+ c.incomingEmail(sender, "#syz set prio: high\n",
+ EmailOptFrom("test@requester.com"), EmailOptCC([]string{mailingList}))
+ c.advanceTime(time.Hour)
+
+ // Report bugs once more to pretend they're still valid.
+ c.advanceTime(time.Hour * 24 * 10)
+ client.ReportCrash(aFirst)
+ client.ReportCrash(aSecond)
+ client.ReportCrash(aThird)
+
+ _, err := c.GET("/cron/subsystem_reports")
+ c.expectOK(err)
+
+ reply := client.pollEmailBug()
+ // Verify that the second bug is not present.
+ c.expectEQ(reply.Body, fmt.Sprintf(`Hello subsystemA maintainers/developers,
+
+This is a 30-day syzbot report for the subsystemA subsystem.
+All related reports/information can be found at:
+https://testapp.appspot.com/subsystem-reminders/s/subsystemA
+
+During the period, 3 new issues were detected and 0 were fixed.
+In total, 3 issues are still open.
+
+Some of the still happening issues:
+
+Ref Crashes Repro Title
+<1> 2 No WARNING: a third
+ https://testapp.appspot.com/bug?extid=%[1]v
+<2> 2 No WARNING: a second
+ https://testapp.appspot.com/bug?extid=%[2]v
+<3> 2 Yes WARNING: a first
+ https://testapp.appspot.com/bug?extid=%[3]v
+
+The report will be sent to: [subsystemA@list.com subsystemA@person.com].
+
+---
+This report is generated by a bot. It may contain errors.
+See https://goo.gl/tpsmEJ for more information about syzbot.
+syzbot engineers can be reached at syzkaller@googlegroups.com.
+
+To disable reminders for individual bugs, reply with the following command:
+#syz set <Ref> no-reminders
+
+To change bug's subsystems, reply with:
+#syz set <Ref> subsystems: new-subsystem
+
+If the report looks fine to you, reply with:
+#syz upstream
+
+To regenerate the report, reply with:
+#syz regenerate
+
+You may send multiple commands in a single email message.
+`, thirdExtID, secondExtID, firstExtID))
+}
diff --git a/dashboard/app/util_test.go b/dashboard/app/util_test.go
index 790984fc6..54b63e949 100644
--- a/dashboard/app/util_test.go
+++ b/dashboard/app/util_test.go
@@ -398,12 +398,18 @@ func (c *Ctx) pollEmailBug() *aemail.Message {
func (c *Ctx) pollEmailExtID() string {
c.t.Helper()
+ _, extBugID := c.pollEmailAndExtID()
+ return extBugID
+}
+
+func (c *Ctx) pollEmailAndExtID() (string, string) {
+ c.t.Helper()
msg := c.pollEmailBug()
_, extBugID, err := email.RemoveAddrContext(msg.Sender)
if err != nil {
c.t.Fatalf("failed to remove addr context: %v", err)
}
- return extBugID
+ return msg.Sender, extBugID
}
func (c *Ctx) expectNoEmail() {