You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flink.apache.org by kn...@apache.org on 2021/05/19 08:09:48 UTC

[flink-jira-bot] 26/47: [FLINK-22034] add rule for stale major+ tickets

This is an automated email from the ASF dual-hosted git repository.

knaufk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/flink-jira-bot.git

commit aa8c557fa1d1623b1c05d9c247fab2dd12a50533
Author: Konstantin Knauf <kn...@gmail.com>
AuthorDate: Wed Apr 21 13:16:15 2021 +0200

    [FLINK-22034] add rule for stale major+ tickets
---
 config.yaml                  |  23 ++++++++++
 flink_jira_bot.py            |  13 ++++++
 flink_jira_rule.py           |   7 +++
 stale_major_or_above_rule.py | 107 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 150 insertions(+)

diff --git a/config.yaml b/config.yaml
index d1cb3bb..d0e7aff 100644
--- a/config.yaml
+++ b/config.yaml
@@ -32,3 +32,26 @@ stale_minor:
     done_label: "auto-closed"
     done_comment: 'This issue has been labeled "{warning_label}" for {warning_days} days. It is closed now. If you are still affected by this or would like to raise the priority of this ticket please re-open, removing the label "{done_label}" and raise the ticket priority accordingly.'
 
+stale_blocker:
+    stale_days: 1
+    warning_days: 7
+    warning_label: "stale-blocker"
+    warning_comment: 'This Blockers is unassigned and itself and all of its Sub-Tasks have not been updated for {stale_days} days. So, it has been labeled "{warning_label}". If this ticket is a Blocker, please either assign yourself or give an update. Afterwards, please remove the label. In {warning_days} days the issue will be deprioritized.'
+    done_label: "auto-deprioritized-blocker"
+    done_comment: 'This issue has been labeled "{warning_label}" for {warning_days} days. It is deprioritized now. If this ticket is actually a Blocker, please raise the ticket priority again and assign yourself or revive the public discussion.'
+
+stale_critical:
+    stale_days: 7
+    warning_days: 7
+    warning_label: "stale-critical"
+    warning_comment: 'This critical issue is unassigned and itself and all of its Sub-Tasks have not been updated for {stale_days} days. So, it has been labeled "{warning_label}". If this ticket is indeed critical, please either assign yourself or give an update. Afterwards, please remove the label. In {warning_days} days the issue will be deprioritized.'
+    done_label: "auto-deprioritized-critical"
+    done_comment: 'This issue has been labeled "{warning_label}" for {warning_days} days. It is deprioritized now. If this ticket is actually critical, please raise the ticket priority again and assign yourself or revive the public discussion.'
+
+stale_major:
+    stale_days: 30
+    warning_days: 7
+    warning_label: "stale-major"
+    warning_comment: 'This major issue is unassigned and itself and all of its Sub-Tasks have not been updated for {stale_days} days. So, it has been labeled "{warning_label}". If this ticket is indeed "major", please either assign yourself or give an update. Afterwards, please remove the label. In {warning_days} days the issue will be deprioritized.'
+    done_label: "auto-deprioritized-major"
+    done_comment: 'This issue has been labeled "{warning_label}" for {warning_days} days. It is deprioritized now. If this ticket is actually "major", please raise the ticket priority again and assign yourself or revive the public discussion.'
diff --git a/flink_jira_bot.py b/flink_jira_bot.py
index 211f855..80a58e9 100644
--- a/flink_jira_bot.py
+++ b/flink_jira_bot.py
@@ -24,6 +24,7 @@ from argparse import ArgumentParser
 from pathlib import Path
 
 from stale_assigned_rule import StaleAssignedRule
+from stale_major_or_above_rule import StaleMajorOrAboveRule
 from stale_minor_rule import StaleMinorRule
 
 
@@ -63,5 +64,17 @@ if __name__ == "__main__":
 
     stale_assigned_rule = StaleAssignedRule(jira, jira_bot_config, args.dryrun)
     stale_minor_rule = StaleMinorRule(jira, jira_bot_config, args.dryrun)
+    stale_major_rule = StaleMajorOrAboveRule(
+        jira, jira_bot_config, args.dryrun, "Major"
+    )
+    stale_critical_rule = StaleMajorOrAboveRule(
+        jira, jira_bot_config, args.dryrun, "Critical"
+    )
+    stale_blocker_rule = StaleMajorOrAboveRule(
+        jira, jira_bot_config, args.dryrun, "Blocker"
+    )
     stale_assigned_rule.run()
     stale_minor_rule.run()
+    stale_major_rule.run()
+    stale_critical_rule.run()
+    stale_blocker_rule.run()
diff --git a/flink_jira_rule.py b/flink_jira_rule.py
index 9960aca..566fce7 100644
--- a/flink_jira_rule.py
+++ b/flink_jira_rule.py
@@ -98,6 +98,13 @@ class FlinkJiraRule:
         else:
             logging.info(f"DRY_RUN (({key})): Unassigning.")
 
+    def set_priority(self, key, priority):
+        if not self.is_dry_run:
+            fields = {"priority": {"name": priority}}
+            self.jira_client.update_issue_field(key, fields)
+        else:
+            logging.info(f"DRY_RUN (({key})): Setting to {priority}")
+
     @abc.abstractmethod
     def run(self):
         return
diff --git a/stale_major_or_above_rule.py b/stale_major_or_above_rule.py
new file mode 100644
index 0000000..de3cb17
--- /dev/null
+++ b/stale_major_or_above_rule.py
@@ -0,0 +1,107 @@
+################################################################################
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+# limitations under the License.
+################################################################################
+
+import logging
+
+from flink_jira_rule import FlinkJiraRule
+
+
+class StaleMajorOrAboveRule(FlinkJiraRule):
+    """
+    Tickets major and above need an assignee, or an update within {stale_<blocker|critical|major>.stale_days},
+    otherwise the priority will be reduced after a warning period of {stale_<blocker|critical|major>.warning_days} days.
+    An update of on of the Sub-Tasks counts as an update to the ticket.
+    Before this happens the assignee/reporter/watchers are notified that the ticket is about to become stale and will
+    be deprioritized.
+    The time periods before warning differ based on the priority:
+    """
+
+    def __init__(self, jira_client, config, is_dry_run, priority):
+        super().__init__(jira_client, config, is_dry_run)
+        self.stale_days = config[f"stale_{priority.lower()}"]["stale_days"].get()
+        self.warning_days = config[f"stale_{priority.lower()}"]["warning_days"].get()
+        self.warning_label = config[f"stale_{priority.lower()}"]["warning_label"].get()
+        self.done_label = config[f"stale_{priority.lower()}"]["done_label"].get()
+        self.done_comment = config[f"stale_{priority.lower()}"]["done_comment"].get()
+        self.warning_comment = config[f"stale_{priority.lower()}"][
+            "warning_comment"
+        ].get()
+        self.priority = priority
+
+    LOWER_PRIORITIES = {"Blocker": "Critical", "Critical": "Major", "Major": "Minor"}
+
+    def run(self):
+        self.close_tickets_marked_stale()
+        self.mark_stale_tickets_stale()
+
+    def close_tickets_marked_stale(self):
+
+        tickets_marked_stale = (
+            f"project=FLINK AND Priority = {self.priority} AND resolution = Unresolved AND labels in "
+            f'("{self.warning_label}") AND updated < startOfDay(-{self.warning_days}d)'
+        )
+        logging.info(
+            f"Looking for {self.priority} tickets, which were previously marked as {self.warning_label}."
+        )
+        issues = self.get_issues(tickets_marked_stale)
+
+        for issue in issues:
+            key = issue["key"]
+            logging.info(
+                f"Found https://issues.apache.org/jira/browse/{key}. It is now deprioritized due to inactivity."
+            )
+
+            formatted_comment = self.done_comment.format(
+                warning_days=self.warning_days,
+                warning_label=self.warning_label,
+                done_label=self.done_label,
+            )
+
+            self.add_comment(key, formatted_comment)
+            self.replace_label(issue, self.warning_label, self.done_label)
+            self.set_priority(key, self.LOWER_PRIORITIES[self.priority])
+
+    def mark_stale_tickets_stale(self):
+
+        stale_tickets = f"project=FLINK AND priority = {self.priority} AND resolution = Unresolved AND assignee is " \
+                        f"empty AND updated < startOfDay(-{self.stale_days}d)"
+        logging.info(f"Looking for {self.priority} tickets, which are stale.")
+        issues = self.get_issues(stale_tickets)
+
+        for issue in issues:
+            key = issue["key"]
+            issue = self.jira_client.get_issue(key)
+
+            if not self.has_recently_updated_subtask(key, self.stale_days):
+                logging.info(
+                    f"Found https://issues.apache.org/jira/browse/{key}. It is marked stale now."
+                )
+                formatted_comment = self.warning_comment.format(
+                    stale_days=self.stale_days,
+                    warning_days=self.warning_days,
+                    warning_label=self.warning_label,
+                )
+
+                self.add_label(issue, self.warning_label)
+                self.add_comment(key, formatted_comment)
+
+            else:
+                logging.info(
+                    f"Found https://issues.apache.org/jira/browse/{key}, but is has recently updated Subtasks. "
+                    f"Ignoring for now."
+                )