aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2019-02-13 14:57:30 +0100
committerDmitry Vyukov <dvyukov@google.com>2019-02-13 15:58:42 +0100
commit0f51729bc4b8b7bdf4767eb88d2c124183639dde (patch)
treea106283d120109f3207bbdc63f8c89e745c6754a
parentf16dce862ba8b48c3148dcff51d89aec0a6b3c8f (diff)
dashboard/app: record last activity and fix times
It would be useful to record last activity time for bugs (e.g. for pings) and when a fix is provided for statistics purposes. Fixes #673
-rw-r--r--dashboard/app/api.go1
-rw-r--r--dashboard/app/entities.go2
-rw-r--r--dashboard/app/fix_test.go39
-rw-r--r--dashboard/app/jobs.go42
-rw-r--r--dashboard/app/jobs_test.go1
-rw-r--r--dashboard/app/reporting.go2
6 files changed, 66 insertions, 21 deletions
diff --git a/dashboard/app/api.go b/dashboard/app/api.go
index 5c84ad75e..5de4178f0 100644
--- a/dashboard/app/api.go
+++ b/dashboard/app/api.go
@@ -410,6 +410,7 @@ func addCommitsToBug(c context.Context, bug *Bug, manager string, managers []str
}
if len(fixCommits) != 0 && !reflect.DeepEqual(bug.Commits, fixCommits) {
bug.Commits = fixCommits
+ bug.FixTime = now
bug.PatchedOn = nil
}
bug.PatchedOn = append(bug.PatchedOn, manager)
diff --git a/dashboard/app/entities.go b/dashboard/app/entities.go
index 152a12506..3ffe09b7d 100644
--- a/dashboard/app/entities.go
+++ b/dashboard/app/entities.go
@@ -78,6 +78,8 @@ type Bug struct {
LastTime time.Time
LastSavedCrash time.Time
LastReproTime time.Time
+ FixTime time.Time // when we become aware of the fixing commit
+ LastActivity time.Time // last time we observed any activity related to the bug
Closed time.Time
Reporting []BugReporting
Commits []string
diff --git a/dashboard/app/fix_test.go b/dashboard/app/fix_test.go
index 420d28149..b0c7bee2b 100644
--- a/dashboard/app/fix_test.go
+++ b/dashboard/app/fix_test.go
@@ -159,9 +159,15 @@ func TestReFixed(t *testing.T) {
builderPollResp, _ := c.client.BuilderPoll(build1.Manager)
c.expectEQ(len(builderPollResp.PendingCommits), 0)
+ c.advanceTime(time.Hour)
rep := c.client.pollBug()
+ bug, _, _ := c.loadBug(rep.ID)
+ c.expectEQ(bug.LastActivity, c.mockedTime)
+ c.expectEQ(bug.FixTime, time.Time{})
+
// Specify fixing commit for the bug.
+ c.advanceTime(time.Hour)
reply, _ := c.client.ReportingUpdate(&dashapi.BugUpdate{
ID: rep.ID,
Status: dashapi.BugStatusOpen,
@@ -169,12 +175,45 @@ func TestReFixed(t *testing.T) {
})
c.expectEQ(reply.OK, true)
+ bug, _, _ = c.loadBug(rep.ID)
+ c.expectEQ(bug.LastActivity, c.mockedTime)
+ c.expectEQ(bug.FixTime, c.mockedTime)
+
+ c.advanceTime(time.Hour)
+ reply, _ = c.client.ReportingUpdate(&dashapi.BugUpdate{
+ ID: rep.ID,
+ Status: dashapi.BugStatusOpen,
+ FixCommits: []string{"the right one"},
+ })
+ c.expectEQ(reply.OK, true)
+
+ bug, _, _ = c.loadBug(rep.ID)
+ c.expectEQ(bug.LastActivity, c.mockedTime)
+ c.expectEQ(bug.FixTime, c.mockedTime)
+
+ // No updates, just check that LastActivity time is updated, FixTime preserved.
+ fixTime := c.mockedTime
+ c.advanceTime(time.Hour)
+ reply, _ = c.client.ReportingUpdate(&dashapi.BugUpdate{
+ ID: rep.ID,
+ Status: dashapi.BugStatusOpen,
+ })
+ c.expectEQ(reply.OK, true)
+ bug, _, _ = c.loadBug(rep.ID)
+ c.expectEQ(bug.LastActivity, c.mockedTime)
+ c.expectEQ(bug.FixTime, fixTime)
+
+ // Send the same fixing commit, check that LastActivity time is updated, FixTime preserved.
+ c.advanceTime(time.Hour)
reply, _ = c.client.ReportingUpdate(&dashapi.BugUpdate{
ID: rep.ID,
Status: dashapi.BugStatusOpen,
FixCommits: []string{"the right one"},
})
c.expectEQ(reply.OK, true)
+ bug, _, _ = c.loadBug(rep.ID)
+ c.expectEQ(bug.LastActivity, c.mockedTime)
+ c.expectEQ(bug.FixTime, fixTime)
builderPollResp, _ = c.client.BuilderPoll(build1.Manager)
c.expectEQ(len(builderPollResp.PendingCommits), 1)
diff --git a/dashboard/app/jobs.go b/dashboard/app/jobs.go
index 808c79182..7427f05dd 100644
--- a/dashboard/app/jobs.go
+++ b/dashboard/app/jobs.go
@@ -40,33 +40,33 @@ func handleTestRequest(c context.Context, bugID, user, extID, link, patch, repo,
return fmt.Sprintf("can't find the associated bug (do you have %v in To/CC?)", myEmail)
}
bugReporting, _ := bugReportingByID(bug, bugID)
- reply, err := addTestJob(c, bug, bugKey, bugReporting, user, extID, link, patch, repo, branch, jobCC)
+ now := timeNow(c)
+ reply, err := addTestJob(c, bug, bugKey, bugReporting, user, extID, link, patch, repo, branch, jobCC, now)
if err != nil {
log.Errorf(c, "test request failed: %v", err)
if reply == "" {
reply = internalError
}
}
- // Update bug CC list in any case.
- if !stringsInList(strings.Split(bugReporting.CC, "|"), jobCC) {
- tx := func(c context.Context) error {
- bug := new(Bug)
- if err := datastore.Get(c, bugKey, bug); err != nil {
- return err
- }
- bugReporting = bugReportingByName(bug, bugReporting.Name)
- bugCC := strings.Split(bugReporting.CC, "|")
- merged := email.MergeEmailLists(bugCC, jobCC)
- bugReporting.CC = strings.Join(merged, "|")
- if _, err := datastore.Put(c, bugKey, bug); err != nil {
- return fmt.Errorf("failed to put bug: %v", err)
- }
- return nil
+ // Update bug CC and last activity time.
+ tx := func(c context.Context) error {
+ bug := new(Bug)
+ if err := datastore.Get(c, bugKey, bug); err != nil {
+ return err
}
- if err := datastore.RunInTransaction(c, tx, nil); err != nil {
- // We've already stored the job, so just log the error.
- log.Errorf(c, "failed to update bug: %v", err)
+ bug.LastActivity = now
+ bugReporting = bugReportingByName(bug, bugReporting.Name)
+ bugCC := strings.Split(bugReporting.CC, "|")
+ merged := email.MergeEmailLists(bugCC, jobCC)
+ bugReporting.CC = strings.Join(merged, "|")
+ if _, err := datastore.Put(c, bugKey, bug); err != nil {
+ return fmt.Errorf("failed to put bug: %v", err)
}
+ return nil
+ }
+ if err := datastore.RunInTransaction(c, tx, nil); err != nil {
+ // We've already stored the job, so just log the error.
+ log.Errorf(c, "failed to update bug: %v", err)
}
if link != "" {
reply = "" // don't send duplicate error reply
@@ -75,7 +75,7 @@ func handleTestRequest(c context.Context, bugID, user, extID, link, patch, repo,
}
func addTestJob(c context.Context, bug *Bug, bugKey *datastore.Key, bugReporting *BugReporting,
- user, extID, link, patch, repo, branch string, jobCC []string) (string, error) {
+ user, extID, link, patch, repo, branch string, jobCC []string, now time.Time) (string, error) {
crash, crashKey, err := findCrashForBug(c, bug)
if err != nil {
return "", err
@@ -103,7 +103,7 @@ func addTestJob(c context.Context, bug *Bug, bugKey *datastore.Key, bugReporting
}
job := &Job{
- Created: timeNow(c),
+ Created: now,
User: user,
CC: jobCC,
Reporting: bugReporting.Name,
diff --git a/dashboard/app/jobs_test.go b/dashboard/app/jobs_test.go
index d5ad69d92..66d7b399f 100644
--- a/dashboard/app/jobs_test.go
+++ b/dashboard/app/jobs_test.go
@@ -85,6 +85,7 @@ func TestJob(t *testing.T) {
pollResp, _ := c.client2.JobPoll([]string{build.Manager})
c.expectEQ(pollResp.ID, "")
+ // This submits actual test request.
c.incomingEmail(sender, "#syz test: git://git.git/git.git kernel-branch\n"+patch,
EmailOptMessageID(1), EmailOptFrom("test@requester.com"),
EmailOptCC([]string{"somebody@else.com"}))
diff --git a/dashboard/app/reporting.go b/dashboard/app/reporting.go
index fafd9c8a3..32d3fc8e6 100644
--- a/dashboard/app/reporting.go
+++ b/dashboard/app/reporting.go
@@ -512,6 +512,7 @@ func incomingCommandTx(c context.Context, now time.Time, cmd *dashapi.BugUpdate,
sort.Strings(cmd.FixCommits)
if !reflect.DeepEqual(bug.Commits, cmd.FixCommits) {
bug.Commits = cmd.FixCommits
+ bug.FixTime = now
bug.PatchedOn = nil
}
}
@@ -546,6 +547,7 @@ func incomingCommandTx(c context.Context, now time.Time, cmd *dashapi.BugUpdate,
if bug.Status != BugStatusDup {
bug.DupOf = ""
}
+ bug.LastActivity = now
if _, err := datastore.Put(c, bugKey, bug); err != nil {
return false, internalError, fmt.Errorf("failed to put bug: %v", err)
}