Skip to content

Commit

Permalink
devapp: account {,de}milestoned events in issue burndown chart
Browse files Browse the repository at this point in the history
Previously the calculation of open issues over previous days only took
into account when the issue was created and closed, but not that issues
may have been added to or removed from the current development milestone
over their lifetime.

This was especially noticeable when relui moved 100 open issues from
Go1.21 to Go1.22, yet the burndown graph made it seem like there had
always been around 225 issues in it, pretty misleading. :( maintner
already tracks milestoned and demilestoned events along with event
creation time, so take them into account to de-gaslight the graph.

Change-Id: Iba3f3f68e4ddc140d5612317c02bdfefe4693d8d
Reviewed-on: https://go-review.googlesource.com/c/build/+/517716
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
  • Loading branch information
dmitshur authored and gopherbot committed Aug 11, 2023
1 parent b316f91 commit 049da80
Showing 1 changed file with 47 additions and 13 deletions.
60 changes: 47 additions & 13 deletions devapp/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package main
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"html/template"
"log"
Expand Down Expand Up @@ -265,22 +266,12 @@ func (s *server) updateReleaseData() {
curMilestoneStart := time.Date(2021, time.August+monthsSinceGo117Release, 1, 0, 0, 0, 0, time.UTC)

dirToIssues := map[string][]*maintner.GitHubIssue{}
var curMilestoneIssues []*maintner.GitHubIssue
s.repo.ForeachIssue(func(issue *maintner.GitHubIssue) error {
// Only include issues in active milestones.
if issue.Milestone.IsUnknown() || issue.Milestone.Closed || issue.Milestone.IsNone() {
return nil
}

if issue.Milestone.Title == curMilestoneTitle {
curMilestoneIssues = append(curMilestoneIssues, issue)
}

// Only open issues are displayed on the page using dirToIssues.
if issue.Closed {
// Only open issues in active milestones are displayed on the page using dirToIssues.
if issue.Closed ||
issue.Milestone.IsUnknown() || issue.Milestone.Closed || issue.Milestone.IsNone() {
return nil
}

dirs := titleDirs(issue.Title)
if len(dirs) == 0 {
dirToIssues[""] = append(dirToIssues[""], issue)
Expand All @@ -292,13 +283,52 @@ func (s *server) updateReleaseData() {
return nil
})

// Find issues that have been in the current milestone.
var curMilestoneIssues []*maintner.GitHubIssue
s.repo.ForeachIssue(func(issue *maintner.GitHubIssue) error {
if issue.Closed && issue.ClosedAt.Before(curMilestoneStart) {
// Old issue, couldn't be relevant to current milestone.
return nil
}
if !issue.Milestone.IsUnknown() && issue.Milestone.Title == curMilestoneTitle {
// Easy case: the issue is still in current milestone.
curMilestoneIssues = append(curMilestoneIssues, issue)
return nil
}
// Check if the issue was ever in the current milestone.
issue.ForeachEvent(func(e *maintner.GitHubIssueEvent) error {
if e.Type == "milestoned" && e.Milestone == curMilestoneTitle {
curMilestoneIssues = append(curMilestoneIssues, issue)
return errStopIteration
}
return nil
})
return nil
})

bd := burndownData{Milestone: curMilestoneTitle}
for t, now := curMilestoneStart, time.Now(); t.Before(now); t = t.Add(24 * time.Hour) {
var e burndownEntry
for _, issue := range curMilestoneIssues {
if issue.Created.After(t) || (issue.Closed && issue.ClosedAt.Before(t)) {
continue
}
var inCurMilestoneAtT bool
issue.ForeachEvent(func(e *maintner.GitHubIssueEvent) error {
if e.Created.After(t) {
return errStopIteration
}
switch e.Type {
case "milestoned":
inCurMilestoneAtT = e.Milestone == curMilestoneTitle
case "demilestoned":
inCurMilestoneAtT = false
}
return nil
})
if !inCurMilestoneAtT {
continue
}
if issue.HasLabel("release-blocker") {
e.Blockers++
}
Expand Down Expand Up @@ -522,3 +552,7 @@ func (s *server) handleRelease(t *template.Template, w http.ResponseWriter, r *h
return
}
}

// errStopIteration is used to stop iteration over issues or comments.
// It has no special meaning.
var errStopIteration = errors.New("stop iteration")

0 comments on commit 049da80

Please sign in to comment.