| |
@@ -26,8 +26,10 @@
|
| |
import jira.client
|
| |
from jira import JIRAError
|
| |
from datetime import datetime
|
| |
+ import jinja2
|
| |
|
| |
from sync2jira.intermediary import Issue
|
| |
+ from sync2jira.mailer import send_mail
|
| |
|
| |
# The date the service was upgraded
|
| |
# This is used to ensure legacy comments are not touched
|
| |
@@ -36,6 +38,7 @@
|
| |
log = logging.getLogger(__name__)
|
| |
|
| |
remote_link_title = "Upstream issue"
|
| |
+ duplicate_issues_subject = 'FYI: Duplicate Sync2jira Issues'
|
| |
|
| |
jira_cache = {}
|
| |
|
| |
@@ -127,6 +130,7 @@
|
| |
# We need to ensure that we are not catching a dropped issue
|
| |
# Loop through the results of the query and make sure the ids match
|
| |
final_results = []
|
| |
+
|
| |
for result in results_of_query:
|
| |
# If the queried JIRA issue has the id of the upstream issue or the same title
|
| |
if issue.id in result.fields.description or issue.title == result.fields.summary:
|
| |
@@ -161,11 +165,114 @@
|
| |
|
| |
# Return the final_results
|
| |
log.debug("Found %i results for query %r", len(final_results), query)
|
| |
+
|
| |
+ # Alert the owner
|
| |
+ if issue.downstream.get('owner'):
|
| |
+ alert_user_of_duplicate_issues(issue, final_results,
|
| |
+ results_of_query,
|
| |
+ config, client)
|
| |
return final_results
|
| |
else:
|
| |
return results_of_query
|
| |
|
| |
|
| |
+ def alert_user_of_duplicate_issues(issue, final_result, results_of_query,
|
| |
+ config, client):
|
| |
+ """
|
| |
+ Alerts owner of duplicate downstream issues
|
| |
+ Args:
|
| |
+ issue (sync2jira.intermediate.Issue): Upstream Issue object
|
| |
+ final_result (list): Issue selected by matching algorithm
|
| |
+ results_of_query (list): Result of JQL query
|
| |
+ config (dict): Config dict
|
| |
+ client (jira.client.JIRA): JIRA client
|
| |
+ Returns:
|
| |
+ Nothing
|
| |
+ """
|
| |
+ # First remove final_result from results_of_query
|
| |
+ results_of_query.remove(final_result[0])
|
| |
+
|
| |
+ # Check that all duplicate issues are closed
|
| |
+ updated_results = []
|
| |
+ for result in results_of_query:
|
| |
+ if result.fields.status.name != 'Closed':
|
| |
+ updated_results.append(result)
|
| |
+ if not updated_results:
|
| |
+ # Nothing to alert the owner of
|
| |
+ return
|
| |
+
|
| |
+ # Get base URL
|
| |
+ jira_instance = issue.downstream.get('jira_instance', False)
|
| |
+ if not jira_instance:
|
| |
+ jira_instance = config['sync2jira'].get('default_jira_instance', False)
|
| |
+ if not jira_instance:
|
| |
+ log.error(" No jira_instance for issue and there is no default in the config")
|
| |
+ raise Exception
|
| |
+ base_url = config['sync2jira']['jira'][jira_instance]['options']['server'] + '/browse/'
|
| |
+
|
| |
+ # Format the updated results
|
| |
+ template_ready = []
|
| |
+ for update in updated_results:
|
| |
+ url = base_url + update.key
|
| |
+ new_entry = {'url': url, 'title': update.key}
|
| |
+ template_ready.append(new_entry)
|
| |
+
|
| |
+ # Get owner name and email from Jira
|
| |
+ ret = client.search_users(issue.downstream.get('owner'))
|
| |
+ if len(ret) > 1:
|
| |
+ log.warning(' Found multiple users for username %s' % issue.downstream.get('owner'))
|
| |
+ found = False
|
| |
+ for person in ret:
|
| |
+ if person.key == issue.downstream.get('owner'):
|
| |
+ ret = [person]
|
| |
+ found = True
|
| |
+ break
|
| |
+ if not found:
|
| |
+ log.warning(' Could not find JIRA user for username %s' % issue.downstream.get('owner'))
|
| |
+
|
| |
+ user = {'name': ret[0].displayName, 'email': ret[0].emailAddress}
|
| |
+
|
| |
+ # Format selected issue
|
| |
+ selected_issue = {'url': base_url + final_result[0].key,
|
| |
+ 'title': final_result[0].key}
|
| |
+
|
| |
+ # Get admin information
|
| |
+ admins = []
|
| |
+ admin_template = []
|
| |
+ for admin in config['sync2jira']['admins']:
|
| |
+ ret = client.search_users(admin)
|
| |
+ if len(ret) > 1:
|
| |
+ log.warning(' Found multiple users for admin %s' % issue.downstream.get('owner'))
|
| |
+ found = False
|
| |
+ for person in ret:
|
| |
+ if person.key == issue.downstream.get('owner'):
|
| |
+ ret = [person]
|
| |
+ found = True
|
| |
+ break
|
| |
+ if not found:
|
| |
+ log.warning(' Could not find JIRA user for admin %s' % issue.downstream.get('owner'))
|
| |
+ admins.append(ret[0].emailAddress)
|
| |
+ admin_template.append({'name': ret[0].displayName, 'email': ret[0].emailAddress})
|
| |
+
|
| |
+ # Create and send email
|
| |
+ templateLoader = jinja2.FileSystemLoader(searchpath='sync2jira/')
|
| |
+ templateEnv = jinja2.Environment(loader=templateLoader)
|
| |
+ template = templateEnv.get_template('email_template.jinja')
|
| |
+ html_text = template.render(user=user,
|
| |
+ admins=admin_template,
|
| |
+ issue=issue,
|
| |
+ selected_issue=selected_issue,
|
| |
+ duplicate_issues=template_ready)
|
| |
+
|
| |
+ # Send mail
|
| |
+ send_mail(recipients=[user['email']],
|
| |
+ cc=admins,
|
| |
+ subject=duplicate_issues_subject,
|
| |
+ text=html_text)
|
| |
+ log.info(' Alerted %s about %s duplicate issue(s)' %
|
| |
+ (user['email'], len(template_ready)))
|
| |
+
|
| |
+
|
| |
def find_username(issue, config):
|
| |
"""
|
| |
Finds JIRA username for an issue object
|
| |
When the optional owner field is set sync2jira will alert the owner (via email) if any duplicate issues are not closed.