-
Notifications
You must be signed in to change notification settings - Fork 496
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hierarchical release note feature functions #435
Changes from 2 commits
d020597
3f67cdb
3b596e6
a05dc4c
4c4eb7d
313b952
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"regexp" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/google/go-github/github" | ||
) | ||
|
||
type dictSIG map[string]dictArea | ||
type dictArea map[string]dictIssue | ||
type dictIssue map[int]dictPR | ||
type dictPR map[int]bool | ||
|
||
func hierarchicalNoteLayout(f *os.File, dict dictSIG, issueMap map[int]*github.Issue) { | ||
for sig, areas := range dict { | ||
f.WriteString(fmt.Sprintf(" - %s\n\n", strings.Title(sig))) | ||
for area, issues := range areas { | ||
f.WriteString(fmt.Sprintf(" - %s\n\n", strings.Title(area))) | ||
for issue, prs := range issues { | ||
if issue >= 0 { | ||
f.WriteString(fmt.Sprintf(" - %s (#%d)\n", *issueMap[issue].Title, issue)) | ||
} else { | ||
f.WriteString(fmt.Sprintf(" - NullIssue\n")) | ||
} | ||
for pr := range prs { | ||
f.WriteString(fmt.Sprintf(" * %s (#%d, @%s)\n", extractReleaseNote(issueMap[pr]), pr, *issueMap[pr].User.Login)) | ||
} | ||
f.WriteString("\n") | ||
} | ||
} | ||
} | ||
} | ||
|
||
// createHierarchicalNote given release PRs and issue map, creates hierarchical release note | ||
// map[SIG]map[Area]map[Issue]PR. | ||
func createHierarchicalNote(prs []int, issueMap map[int]*github.Issue) dictSIG { | ||
var dict = dictSIG{} | ||
|
||
for _, pr := range prs { | ||
issues := extractFixedIssues(*issueMap[pr].Body) | ||
if len(issues) == 0 { | ||
setNoteDict(dict, "nullSig", "nullArea", -1, pr) | ||
continue | ||
} | ||
for _, i := range issues { | ||
sigs := extractIssueSIGs(issueMap[i]) | ||
area := extractIssueArea(issueMap[i]) | ||
if len(sigs) == 0 { | ||
setNoteDict(dict, "nullSig", area, i, pr) | ||
continue | ||
} | ||
for _, s := range sigs { | ||
setNoteDict(dict, s, area, i, pr) | ||
} | ||
} | ||
} | ||
|
||
return dict | ||
} | ||
|
||
// setNoteDict sets the entry dict[sig][area][issue][pr] to be true, initializes nil maps along | ||
// the way. | ||
func setNoteDict(dict dictSIG, sig, area string, issue, pr int) { | ||
if dict[sig] == nil { | ||
dict[sig] = dictArea{} | ||
} | ||
if dict[sig][area] == nil { | ||
dict[sig][area] = dictIssue{} | ||
} | ||
if dict[sig][area][issue] == nil { | ||
dict[sig][area][issue] = dictPR{} | ||
} | ||
dict[sig][area][issue][pr] = true | ||
} | ||
|
||
// extractFixedIssues parses the fixed issues' id from PR body. | ||
func extractFixedIssues(msg string) []int { | ||
var issues = make([]int, 0) | ||
re, _ := regexp.Compile("fixes #([0-9]+)") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. note that github not only supports There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and it can also fixes issue in other repo, e.g., |
||
matches := re.FindAllStringSubmatch(msg, -1) | ||
for _, match := range matches { | ||
id, _ := strconv.Atoi(match[1]) | ||
issues = append(issues, id) | ||
} | ||
|
||
return issues | ||
} | ||
|
||
// extractIssueSIGs gets the SIGs of the input issue (if there is any) | ||
func extractIssueSIGs(i *github.Issue) []string { | ||
var sigs = make([]string, 0) | ||
for _, l := range i.Labels { | ||
if strings.HasPrefix(*l.Name, "sig/") { | ||
sigs = append(sigs, (*l.Name)[4:]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not using TrimPrefix here? |
||
} | ||
} | ||
|
||
return sigs | ||
} | ||
|
||
// extractIssueSIGs gets the Areas of the input issue and returns as a single string. If the issue | ||
// doesn't have any Area label, the function returns "nullArea". | ||
func extractIssueArea(i *github.Issue) string { | ||
var areas = make([]string, 0) | ||
for _, l := range i.Labels { | ||
if strings.HasPrefix(*l.Name, "area/") { | ||
areas = append(areas, (*l.Name)[5:]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does github api guarantee anything about the order of the labels returned? I am wondering because if two issues have labels "area/Alpha" and "area/Beta" and the labels can be in any order, then they might be put into different area buckets in the final document, even though they have the same areas There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jennybuckley I think it guarantees alphabetical order. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also |
||
} | ||
} | ||
|
||
if len(areas) == 0 { | ||
return "nullArea" | ||
} | ||
|
||
return strings.Join(areas, " & ") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we could use extractIssueSIGs(issueMap[pr]) and extractIssueArea(issueMap[pr]) instead of "nullSig" and "nullArea" to still sort these issues, since many prs don't link to an issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jennybuckley In our design doc we want the automation to enforce every release-note PR linking to at least one issue. But I agree that the rule seems to be not applied yet. I pushed an update to use SIG & area labels from PRs with no issue associated.