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:28 UTC
[flink-jira-bot] 06/47: [FLINK-22032] introduce dry-run mode and
add actual actions to rule 3
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 0561a81f9b9d7db4a277db1465090b97a0c21936
Author: Konstantin Knauf <kn...@gmail.com>
AuthorDate: Fri Apr 9 14:15:15 2021 +0200
[FLINK-22032] introduce dry-run mode and add actual actions to rule 3
---
Makefile | 6 ++++
config.yaml | 6 ++--
flink_jira_bot.py | 102 +++++++++++++++++++++++++++++++++++++++++++++++++-----
requirements.txt | 4 ++-
4 files changed, 106 insertions(+), 12 deletions(-)
diff --git a/Makefile b/Makefile
index 677c9cc..adfff3d 100644
--- a/Makefile
+++ b/Makefile
@@ -11,6 +11,12 @@ $(VENV)/bin/activate: requirements.txt
# venv is a shortcut target
venv: $(VENV)/bin/activate
+help: venv
+ ./$(VENV)/bin/python3 flink_jira_bot.py --help
+
+dry-run: venv
+ ./$(VENV)/bin/python3 flink_jira_bot.py -d
+
run: venv
./$(VENV)/bin/python3 flink_jira_bot.py
diff --git a/config.yaml b/config.yaml
index d77f815..727da38 100644
--- a/config.yaml
+++ b/config.yaml
@@ -1,6 +1,8 @@
stale_minor:
stale_days: 180
warning_days: 7
- label: "stale-minor"
- comment: 'This issue (and any of its Sub-Tasks) has not been updated for {stale_days} days. So, it has been labeled "{label}". If you are still affected by this bug or are still interested in this issue, please give an update and remove the label. In {warning_days} days the issue will be closed automatically.'
+ warning_label: "stale-minor"
+ warning_comment: 'This issue and all of its Sub-Tasks have not been updated for {stale_days} days. So, it has been labeled "{warning_label}". If you are still affected by this bug or are still interested in this issue, please give an update and remove the label. In {warning_days} days the issue will be closed automatically.'
+ 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.'
diff --git a/flink_jira_bot.py b/flink_jira_bot.py
index a092399..05541ca 100644
--- a/flink_jira_bot.py
+++ b/flink_jira_bot.py
@@ -3,14 +3,18 @@ import logging
import confuse
import os
import abc
+import sys
+from argparse import ArgumentParser
+from pathlib import Path
class FlinkJiraRule:
__metaclass__ = abc.ABCMeta
- def __init__(self, jira_client, config):
+ def __init__(self, jira_client, config, is_dry_run):
self.jira_client = jira_client
self.config = config
+ self.is_dry_run = is_dry_run
def has_recently_updated_subtask(self, parent, updated_within_days):
find_subtasks_updated_within = (
@@ -19,18 +23,54 @@ class FlinkJiraRule:
issues = self.jira_client.jql(find_subtasks_updated_within, limit=1)
return issues["total"] > 0
+ def add_label(self, issue, label):
+ labels = issue["fields"]["labels"] + [label]
+ fields = {"labels": labels}
+ key = issue["key"]
+
+ if not self.is_dry_run:
+ self.jira.update_issue_field(key, fields)
+ else:
+ logging.info(f'DRY RUN ({key}): Adding label "{label}".')
+
+ def replace_label(self, issue, old_label, new_label):
+ labels = issue["fields"]["labels"] + [new_label]
+ labels.remove(old_label)
+ fields = {"labels": labels}
+ key = issue["key"]
+
+ if not self.is_dry_run:
+ self.jira.update_issue_field(key, fields)
+ else:
+ logging.info(
+ f'DRY RUN ({key}): Replace label "{old_label}" for "{new_label}".'
+ )
+
+ def add_comment(self, key, comment):
+ if not self.is_dry_run:
+ jira.issue_add_comment(key, comment)
+ else:
+ logging.info(f'DRY_RUN ({key}): Adding comment "{comment}".')
+
+ def close_issue(self, key):
+ if not self.is_dry_run:
+ jira.issue_transition(key, "Closed")
+ else:
+ logging.info(f"DRY_RUN (({key})): Closing.")
+
@abc.abstractmethod
def run(self):
return
class Rule3(FlinkJiraRule):
- def __init__(self, jira_client, config):
- super().__init__(jira_client, config)
+ def __init__(self, jira_client, config, is_dry_run):
+ super().__init__(jira_client, config, is_dry_run)
self.stale_days = config["stale_minor"]["stale_days"].get()
self.warning_days = config["stale_minor"]["warning_days"].get()
- self.label = config["stale_minor"]["label"].get()
- self.comment = config["stale_minor"]["comment"].get()
+ self.warning_label = config["stale_minor"]["warning_label"].get()
+ self.done_label = config["stale_minor"]["done_label"].get()
+ self.warning_comment = config["stale_minor"]["warning_comment"].get()
def run(self):
self.close_tickets_marked_stale()
@@ -38,7 +78,7 @@ class Rule3(FlinkJiraRule):
def close_tickets_marked_stale(self):
- minor_tickets_marked_stale = f'project=FLINK AND Priority = Minor AND resolution = Unresolved AND labels in ("{self.label}") AND updated < startOfDay(-{self.warning_days}d)'
+ minor_tickets_marked_stale = f'project=FLINK AND Priority = Minor AND resolution = Unresolved AND labels in ("{self.warning_label}") AND updated < startOfDay(-{self.warning_days}d)'
logging.info(
f"Looking for minor tickets, which were previously marked as stale: {minor_tickets_marked_stale}"
)
@@ -50,6 +90,16 @@ class Rule3(FlinkJiraRule):
f"Found https://issues.apache.org/jira/browse/{key}. It is now closed 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.close_issue(key)
+
def mark_stale_tickets_stale(self):
stale_minor_tickets = f"project = FLINK AND Priority = Minor AND resolution = Unresolved AND updated < startOfDay(-{self.stale_days}d)"
@@ -66,19 +116,53 @@ class Rule3(FlinkJiraRule):
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.debug(
+ logging.info(
f"Found https://issues.apache.org/jira/browse/{key}, but is has recently updated Subtasks. Ignoring for now."
)
+def is_dry_run():
+ opts = [opt for opt in sys.argv[1:] if opt.startswith("-")]
+ return "-d" in opts
+
+
+def get_args():
+ parser = ArgumentParser(description="Apache Flink Jira Bot")
+ parser.add_argument(
+ "-d",
+ "--dry-run",
+ dest="dryrun",
+ action="store_true",
+ help="no action on Jira, only logging",
+ )
+ parser.add_argument(
+ "-c",
+ "--config",
+ type=Path,
+ default=Path("config.yaml"),
+ help="path to config file (default: config.yaml)",
+ )
+ return parser.parse_args()
+
+
if __name__ == "__main__":
logging.getLogger().setLevel(logging.INFO)
+ args = get_args()
+
config = confuse.Configuration("flink-jira-bot", __name__)
- config.set_file("config.yaml")
+ config.set_file(args.config)
jira = Jira(
url="https://issues.apache.org/jira",
@@ -86,5 +170,5 @@ if __name__ == "__main__":
password=os.environ["JIRA_PASSWORD"],
)
- rule_3 = Rule3(jira, config)
+ rule_3 = Rule3(jira, config, args.dryrun)
rule_3.run()
diff --git a/requirements.txt b/requirements.txt
index c5e1dd1..336352b 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,6 +1,6 @@
appdirs==1.4.4
atlassian-python-api==3.8.0
-black @ git+git://github.com/psf/black@e114ef5514e95cb9908b38c2397978f2070c1b0e
+black==20.8b1
certifi==2020.12.5
chardet==4.0.0
click==7.1.2
@@ -17,5 +17,7 @@ requests==2.25.1
requests-oauthlib==1.3.0
six==1.15.0
toml==0.10.2
+typed-ast==1.4.3
+typing-extensions==3.7.4.3
urllib3==1.26.4
wrapt==1.12.1