-
Notifications
You must be signed in to change notification settings - Fork 4
/
story_utils.go
137 lines (118 loc) · 3.63 KB
/
story_utils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package github
import (
// Stdlib
"fmt"
// Internal
"github.com/salsaflow/salsaflow/modules/common"
// Other
"github.com/google/go-github/github"
)
// toCommonStories turns []*github.Issue into []common.Story
func toCommonStories(issues []*github.Issue, tracker *issueTracker) []common.Story {
commonStories := make([]common.Story, len(issues))
for i, issue := range issues {
if issue != nil {
commonStories[i] = &story{issue, tracker}
}
}
return commonStories
}
// labeled returns true when the given issue is labeled with the given label.
func labeled(issue *github.Issue, label string) bool {
for _, l := range issue.Labels {
if *l.Name == label {
return true
}
}
return false
}
// pruneStateLabels gets the label slice passed in and splits it
// into the state labels as used by SalsaFlow and the rest.
func pruneStateLabels(
config *moduleConfig,
labels []github.Label,
) (remainingLabels, prunedLabels []github.Label) {
stateLabels := map[string]struct{}{
config.ApprovedLabel: struct{}{},
config.BeingImplementedLabel: struct{}{},
config.ImplementedLabel: struct{}{},
config.ReviewedLabel: struct{}{},
config.SkipReviewLabel: struct{}{},
config.PassedTestingLabel: struct{}{},
config.FailedTestingLabel: struct{}{},
config.SkipTestingLabel: struct{}{},
config.StagedLabel: struct{}{},
config.RejectedLabel: struct{}{},
}
var (
remaining = make([]github.Label, 0, len(labels))
pruned = make([]github.Label, 0, len(labels))
)
for _, label := range labels {
if _, ok := stateLabels[*label.Name]; ok {
pruned = append(pruned, label)
} else {
remaining = append(remaining, label)
}
}
return remaining, pruned
}
// abstractState gets the given GitHub issues and returns the associated abstract state.
func abstractState(issue *github.Issue, config *moduleConfig) common.StoryState {
if *issue.State == "closed" {
return common.StoryStateAccepted
}
var (
approvedLabel = config.ApprovedLabel
beingImplementedLabel = config.BeingImplementedLabel
implementedLabel = config.ImplementedLabel
reviewedLabel = config.ReviewedLabel
skipReviewLabel = config.SkipReviewLabel
passedTestingLabel = config.PassedTestingLabel
skipTestingLabel = config.SkipTestingLabel
stagedLabel = config.StagedLabel
rejectedLabel = config.RejectedLabel
)
for _, label := range issue.Labels {
switch *label.Name {
case approvedLabel:
return common.StoryStateApproved
case beingImplementedLabel:
return common.StoryStateBeingImplemented
case implementedLabel:
return common.StoryStateImplemented
case reviewedLabel:
fallthrough
case skipReviewLabel:
fallthrough
case passedTestingLabel:
fallthrough
case skipTestingLabel:
reviewed := labeled(issue, reviewedLabel) || labeled(issue, skipReviewLabel)
tested := labeled(issue, passedTestingLabel) || labeled(issue, skipTestingLabel)
switch {
case reviewed && tested:
return common.StoryStateTested
case reviewed:
return common.StoryStateReviewed
case tested:
return common.StoryStateImplemented
}
case stagedLabel:
return common.StoryStateStaged
case rejectedLabel:
return common.StoryStateRejected
}
}
panic(fmt.Errorf("issue #%v: unknown abstract state", *issue.Number))
}
// filterIssues is just the regular filter function for *github.Issue type.
func filterIssues(issues []*github.Issue, filter func(*github.Issue) bool) []*github.Issue {
iss := make([]*github.Issue, 0, len(issues))
for _, issue := range issues {
if filter(issue) {
iss = append(iss, issue)
}
}
return iss
}