Skip to content
Permalink
Browse files
[FLINK-22032] introduce dry-run mode and add actual actions to rule 3
  • Loading branch information
knaufk committed Apr 12, 2021
1 parent 6f4e13c commit 0561a81f9b9d7db4a277db1465090b97a0c21936
Showing 4 changed files with 106 additions and 12 deletions.
@@ -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

@@ -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.'

@@ -3,14 +3,18 @@
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,26 +23,62 @@ def has_recently_updated_subtask(self, parent, updated_within_days):
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()
self.mark_stale_tickets_stale()

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 @@ def close_tickets_marked_stale(self):
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,25 +116,59 @@ def mark_stale_tickets_stale(self):
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",
username="flink-jira-bot",
password=os.environ["JIRA_PASSWORD"],
)

rule_3 = Rule3(jira, config)
rule_3 = Rule3(jira, config, args.dryrun)
rule_3.run()
@@ -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

0 comments on commit 0561a81

Please sign in to comment.