aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2020-10-01 13:34:16 +0200
committerDmitry Vyukov <dvyukov@google.com>2020-10-01 15:03:39 +0200
commit8441eb82f3a1a4d03eb0e194e91bc86017ab4466 (patch)
tree848c8b52ed52b775c87ea9d726680743f2bd3332
parent1170210d9cb103aa346ce7260db1c1819cb3c41f (diff)
dashboard/app: add unfix command
Add "#syz unfix" command that undoes "#syz fix" effects and resets any existing fixing commits.
-rw-r--r--dashboard/app/email_test.go29
-rw-r--r--dashboard/app/reporting.go3
-rw-r--r--dashboard/app/reporting_email.go3
-rw-r--r--dashboard/dashapi/dashapi.go25
-rw-r--r--docs/syzbot.md4
-rw-r--r--pkg/email/parser.go51
6 files changed, 80 insertions, 35 deletions
diff --git a/dashboard/app/email_test.go b/dashboard/app/email_test.go
index 5bd46c95e..2e73e61f3 100644
--- a/dashboard/app/email_test.go
+++ b/dashboard/app/email_test.go
@@ -619,3 +619,32 @@ syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.`,
extBugID, crashLogLink, kernelConfigLink))
}
+
+// Test for unfix command which should unmark a bug as fixed by any commits.
+func TestEmailUnfix(t *testing.T) {
+ c := NewCtx(t)
+ defer c.Close()
+
+ build := testBuild(1)
+ c.client2.UploadBuild(build)
+
+ crash := testCrash(build, 1)
+ c.client2.ReportCrash(crash)
+
+ c.expectOK(c.GET("/email_poll"))
+ msg := c.pollEmailBug()
+
+ c.incomingEmail(msg.Sender, "#syz fix: some commit")
+ c.expectNoEmail()
+ c.incomingEmail(msg.Sender, "#syz unfix")
+ c.expectNoEmail()
+
+ build2 := testBuild(2)
+ build2.Manager = build.Manager
+ build2.Commits = []string{"some commit"}
+ c.client2.UploadBuild(build2)
+
+ // The bug should be still unfixed, since we unmarked it.
+ c.client2.ReportCrash(crash)
+ c.expectNoEmail()
+}
diff --git a/dashboard/app/reporting.go b/dashboard/app/reporting.go
index 6f95c3235..775eaf759 100644
--- a/dashboard/app/reporting.go
+++ b/dashboard/app/reporting.go
@@ -831,7 +831,8 @@ func incomingCommandUpdate(c context.Context, now time.Time, cmd *dashapi.BugUpd
if ok, reply, err := incomingCommandCmd(c, now, cmd, bug, dup, bugReporting, final, stateEnt); !ok {
return false, reply, err
}
- if len(cmd.FixCommits) != 0 && (bug.Status == BugStatusOpen || bug.Status == BugStatusDup) {
+ if (len(cmd.FixCommits) != 0 || cmd.ResetFixCommits) &&
+ (bug.Status == BugStatusOpen || bug.Status == BugStatusDup) {
sort.Strings(cmd.FixCommits)
if !reflect.DeepEqual(bug.Commits, cmd.FixCommits) {
bug.updateCommits(cmd.FixCommits, now)
diff --git a/dashboard/app/reporting_email.go b/dashboard/app/reporting_email.go
index 140bee5a2..178a64c30 100644
--- a/dashboard/app/reporting_email.go
+++ b/dashboard/app/reporting_email.go
@@ -311,6 +311,8 @@ func incomingMail(c context.Context, r *http.Request) error {
return replyTo(c, msg, "no commit title", nil)
}
cmd.FixCommits = []string{msg.CommandArgs}
+ case email.CmdUnFix:
+ cmd.ResetFixCommits = true
case email.CmdDup:
if msg.CommandArgs == "" {
return replyTo(c, msg, "no dup title", nil)
@@ -343,6 +345,7 @@ var emailCmdToStatus = map[email.Command]dashapi.BugStatus{
email.CmdInvalid: dashapi.BugStatusInvalid,
email.CmdUnDup: dashapi.BugStatusOpen,
email.CmdFix: dashapi.BugStatusOpen,
+ email.CmdUnFix: dashapi.BugStatusUpdate,
email.CmdDup: dashapi.BugStatusDup,
email.CmdUnCC: dashapi.BugStatusUnCC,
}
diff --git a/dashboard/dashapi/dashapi.go b/dashboard/dashapi/dashapi.go
index a1c5c0f63..04e3058bf 100644
--- a/dashboard/dashapi/dashapi.go
+++ b/dashboard/dashapi/dashapi.go
@@ -365,18 +365,19 @@ type BisectResult struct {
}
type BugUpdate struct {
- ID string // copied from BugReport
- JobID string // copied from BugReport
- ExtID string
- Link string
- Status BugStatus
- ReproLevel ReproLevel
- DupOf string
- OnHold bool // If set for open bugs, don't upstream this bug.
- Notification bool // Reply to a notification.
- FixCommits []string // Titles of commits that fix this bug.
- CC []string // Additional emails to add to CC list in future emails.
- CrashID int64
+ ID string // copied from BugReport
+ JobID string // copied from BugReport
+ ExtID string
+ Link string
+ Status BugStatus
+ ReproLevel ReproLevel
+ DupOf string
+ OnHold bool // If set for open bugs, don't upstream this bug.
+ Notification bool // Reply to a notification.
+ ResetFixCommits bool // Remove all commits (empty FixCommits means leave intact).
+ FixCommits []string // Titles of commits that fix this bug.
+ CC []string // Additional emails to add to CC list in future emails.
+ CrashID int64
}
type BugUpdateReply struct {
diff --git a/docs/syzbot.md b/docs/syzbot.md
index 34f568c29..b947631cc 100644
--- a/docs/syzbot.md
+++ b/docs/syzbot.md
@@ -37,6 +37,10 @@ about its final title, in particular, you don't need to wait for the commit to
be merged into upstream tree. `syzbot` only needs to know the title by which
it will appear in tested trees. In case of an error or a title change, you can
override the commit simply by sending another `#syz fix` command.
+- to undo a previous fix command and remove any fixing commits:
+```
+#syz unfix
+````
- to mark the bug as a duplicate of another `syzbot` bug:
```
#syz dup: exact-subject-of-another-report
diff --git a/pkg/email/parser.go b/pkg/email/parser.go
index 589598ba2..df7cc4717 100644
--- a/pkg/email/parser.go
+++ b/pkg/email/parser.go
@@ -38,6 +38,7 @@ const (
CmdNone
CmdUpstream
CmdFix
+ CmdUnFix
CmdDup
CmdUnDup
CmdTest
@@ -223,28 +224,7 @@ func extractCommand(body string) (cmd Command, str, args string) {
cmdEnd = cmdEnd1
}
str = body[cmdPos : cmdPos+cmdEnd]
- switch str {
- default:
- cmd = CmdUnknown
- case "":
- cmd = CmdNone
- case "upstream":
- cmd = CmdUpstream
- case "fix", "fix:":
- cmd = CmdFix
- case "dup", "dup:":
- cmd = CmdDup
- case "undup":
- cmd = CmdUnDup
- case "test", "test:":
- cmd = CmdTest
- case "invalid":
- cmd = CmdInvalid
- case "uncc", "uncc:":
- cmd = CmdUnCC
- case "test_5_arg_cmd":
- cmd = cmdTest5
- }
+ cmd = strToCmd(str)
// Some email clients split text emails at 80 columns are the transformation is irrevesible.
// We try hard to restore what was there before.
// For "test:" command we know that there must be 2 tokens without spaces.
@@ -260,6 +240,33 @@ func extractCommand(body string) (cmd Command, str, args string) {
return
}
+func strToCmd(str string) Command {
+ switch str {
+ default:
+ return CmdUnknown
+ case "":
+ return CmdNone
+ case "upstream":
+ return CmdUpstream
+ case "fix", "fix:":
+ return CmdFix
+ case "unfix":
+ return CmdUnFix
+ case "dup", "dup:":
+ return CmdDup
+ case "undup":
+ return CmdUnDup
+ case "test", "test:":
+ return CmdTest
+ case "invalid":
+ return CmdInvalid
+ case "uncc", "uncc:":
+ return CmdUnCC
+ case "test_5_arg_cmd":
+ return cmdTest5
+ }
+}
+
func extractArgsTokens(body string, num int) string {
var args []string
for pos := 0; len(args) < num && pos < len(body); {