Skip to content

Instantly share code, notes, and snippets.

@sttts
Created August 19, 2020 18:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sttts/d558405ecaaa23eadb6d48cee2158993 to your computer and use it in GitHub Desktop.
Save sttts/d558405ecaaa23eadb6d48cee2158993 to your computer and use it in GitHub Desktop.
diff --git a/pkg/operator/stalecontroller/stale_controller.go b/pkg/operator/stalecontroller/stale_controller.go
index a9b979c..c3db448 100644
--- a/pkg/operator/stalecontroller/stale_controller.go
+++ b/pkg/operator/stalecontroller/stale_controller.go
@@ -25,6 +25,8 @@ var priorityTransitions = []config.Transition{
{From: "unspecified", To: "low"},
}
+const MinimumStaleDuration = time.Hour * 24 * 30
+
type StaleController struct {
controller.ControllerContext
config config.OperatorConfig
@@ -57,15 +59,35 @@ func (c *StaleController) handleBug(bug bugzilla.Bug) (*bugzilla.BugUpdate, erro
return &bugUpdate, nil
}
+var botCommentKeywords = []string{
+ "PM Score",
+ "UpcomingSprint",
+ "This bug will be evaluated during the next sprint and prioritized appropriately.",
+ "I am working on other high priority items. I will get to this bug next sprint.",
+ "This bug will be evaluated next sprint.",
+}
+
func (c *StaleController) sync(ctx context.Context, syncCtx factory.SyncContext) error {
client := c.NewBugzillaClient(ctx)
slackClient := c.SlackClient(ctx)
- staleBugs, err := getStaleBugs(client, c.config)
+ candidates, err := getPotentiallyStaleBugs(client, c.config)
if err != nil {
syncCtx.Recorder().Warningf("BuglistFailed", err.Error())
return err
}
+ klog.V(4).Infof("Got %d potentially stale bugs.", len(candidates))
+
+ var staleBugs []*bugzilla.Bug
+ for _, bug := range candidates {
+ if lastSignificantChangeAt, err := LastSignificantChangeAt(client, bug); err != nil {
+ syncCtx.Recorder().Warningf("GetCachedBugComments", fmt.Errorf("skipping bug #%d: %v", bug.ID, err).Error())
+ continue
+ } else if lastSignificantChangeAt.Before(time.Now().Add(-MinimumStaleDuration)) {
+ staleBugs = append(staleBugs, bug)
+ }
+ }
+
var errors []error
notifications := map[string][]string{}
@@ -94,7 +116,7 @@ func (c *StaleController) sync(ctx context.Context, syncCtx factory.SyncContext)
}
for target, messages := range notifications {
- message := fmt.Sprintf("Hi there!\nThese bugs you are assigned to were just marked as _LifecycleStale_:\n\n%s\n\nPlease review these and remove this flag if you think they are still valid bugs.",
+ message := fmt.Sprintf("Hi there!\nThese bugs you are assigned to or you created were just marked as _LifecycleStale_:\n\n%s\n\nPlease review these and remove this flag if you think they are still valid bugs.",
strings.Join(messages, "\n"))
if err := slackClient.MessageEmail(target, message); err != nil {
@@ -103,19 +125,61 @@ func (c *StaleController) sync(ctx context.Context, syncCtx factory.SyncContext)
}
if len(notifications) > 0 {
- syncCtx.Recorder().Event("StaleBugs", fmt.Sprintf("Following notifications sent:\n%s\n", strings.Join(staleBugLinks, "\n")))
+ syncCtx.Recorder().Event("StaleCommentsBugs", fmt.Sprintf("Following notifications sent:\n%s\n", strings.Join(staleBugLinks, "\n")))
}
return errutil.NewAggregate(errors)
}
-func getStaleBugs(client cache.BugzillaClient, c config.OperatorConfig) ([]*bugzilla.Bug, error) {
+func LastSignificantChangeAt(client cache.BugzillaClient, bug *bugzilla.Bug) (time.Time, error) {
+ comments, err := client.GetCachedBugComments(bug.ID, bug.LastChangeTime)
+ if err != nil {
+ return time.Time{}, fmt.Errorf("GetCachedBugComments failed: %v", err)
+ }
+
+ createdAt, err := time.Parse(time.RFC3339, bug.CreationTime)
+ if err != nil {
+ return time.Time{}, fmt.Errorf("creation time %q parse error: %v", bug.ID, err)
+ }
+
+ lastSignificantChangeAt := createdAt
+NextComment:
+ for _, cmt := range comments {
+ shortText := strings.Split(cmt.Text, "\n")[0]
+
+ for _, keyword := range botCommentKeywords {
+ if strings.Contains(cmt.Text, keyword) {
+ klog.V(4).Infof("Ignoring bot comment for #%d due to keyword %q: %s", bug.ID, keyword, shortText)
+ continue NextComment
+ }
+ }
+
+ createdAt, err := time.Parse(time.RFC3339, cmt.Time)
+ if err != nil {
+ klog.Warningf("Skipping comment #%d of bug #%d because of time %q parse error: %v", cmt.Count, bug.ID, cmt.Time, err)
+ continue
+ }
+ if createdAt.After(lastSignificantChangeAt) {
+ lastSignificantChangeAt = createdAt
+ break
+ }
+ }
+
+ return lastSignificantChangeAt, nil
+}
+
+func getPotentiallyStaleBugs(client cache.BugzillaClient, c config.OperatorConfig) ([]*bugzilla.Bug, error) {
return client.Search(bugzilla.Query{
Classification: []string{"Red Hat"},
Product: []string{"OpenShift Container Platform"},
Status: []string{"NEW", "ASSIGNED", "POST", "ON_DEV"},
Component: c.Components.List(),
Advanced: []bugzilla.AdvancedQuery{
+ {
+ Field: "whiteboard",
+ Op: "notsubstring",
+ Value: "LifecycleStale",
+ },
{
Field: "external_bugzilla.description",
Op: "notsubstring",
@@ -126,11 +190,6 @@ func getStaleBugs(client cache.BugzillaClient, c config.OperatorConfig) ([]*bugz
Op: "notsubstring",
Value: "Github",
},
- {
- Field: "days_elapsed",
- Op: "greaterthaneq",
- Value: "30",
- },
{
Field: "bug_severity",
Op: "notequals",
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment