in devapp/release.go [191:324]
func (s *server) updateReleaseData() {
log.Println("Updating release data ...")
s.cMu.Lock()
defer s.cMu.Unlock()
dirToCLs := map[string][]*gerritCL{}
issueToCLs := map[int32][]*gerritCL{}
s.corpus.Gerrit().ForeachProjectUnsorted(func(p *maintner.GerritProject) error {
p.ForeachOpenCL(func(cl *maintner.GerritCL) error {
if strings.HasPrefix(cl.Subject(), prefixDev) {
return nil
}
var (
pkgs, title = ParsePrefixedChangeTitle(projectRoot(p), cl.Subject())
closed bool
closedVersion int32
milestone string
)
for _, m := range cl.Messages {
if closed && closedVersion < m.Version {
closed = false
}
sm := annotationRE.FindStringSubmatch(m.Message)
if sm == nil {
continue
}
val := sm[1]
if val == "close" || val == "closed" {
closedVersion = m.Version
closed = true
} else if milestoneRE.MatchString(val) {
milestone = val
}
}
gcl := &gerritCL{
GerritCL: cl,
NoPrefixTitle: title,
Closed: closed,
Milestone: milestone,
}
for _, r := range cl.GitHubIssueRefs {
issueToCLs[r.Number] = append(issueToCLs[r.Number], gcl)
}
if len(pkgs) == 0 {
dirToCLs[""] = append(dirToCLs[""], gcl)
} else {
for _, p := range pkgs {
dirToCLs[p] = append(dirToCLs[p], gcl)
}
}
return nil
})
return nil
})
// Determine current milestone based on the highest go1.X tag.
var highestGo1X int
s.proj.ForeachNonChangeRef(func(ref string, _ maintner.GitHash) error {
if !strings.HasPrefix(ref, "refs/tags/go1.") {
return nil
}
tagName := ref[len("refs/tags/"):]
if _, x, _, ok := version.ParseTag(tagName); ok && x > highestGo1X {
highestGo1X = x
}
return nil
})
// The title of the current release milestone in GitHub. For example, "Go1.18".
curMilestoneTitle := fmt.Sprintf("Go1.%d", highestGo1X+1)
// The start date of the current release milestone, approximated by taking the
// Go 1.17 release date, and adding 6 months for each successive major release.
var monthsSinceGo117Release = time.Month(6 * (highestGo1X - 17))
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 {
return nil
}
dirs := titleDirs(issue.Title)
if len(dirs) == 0 {
dirToIssues[""] = append(dirToIssues[""], issue)
} else {
for _, d := range dirs {
dirToIssues[d] = append(dirToIssues[d], issue)
}
}
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
}
if issue.HasLabel("release-blocker") {
e.Blockers++
}
e.Open++
}
e.DateStr = t.Format("01-02")
bd.Entries = append(bd.Entries, e)
}
var buf bytes.Buffer
if err := json.NewEncoder(&buf).Encode(bd); err != nil {
log.Printf("json.Encode: %v", err)
}
s.data.release.BurndownJSON = template.JS(buf.String())
s.data.release.Sections = nil
s.appendOpenIssues(dirToIssues, issueToCLs)
s.appendPendingCLs(dirToCLs)
s.appendPendingProposals(issueToCLs)
s.appendClosedIssues()
s.data.release.CurMilestone = curMilestoneTitle
s.data.release.LastUpdated = time.Now().UTC().Format(time.UnixDate)
s.data.release.dirty = false
}