| |
@@ -18,7 +18,6 @@
|
| |
# Authors: Ralph Bean <rbean@redhat.com>
|
| |
|
| |
import distutils.version
|
| |
- import json
|
| |
import operator
|
| |
|
| |
import logging
|
| |
@@ -30,32 +29,33 @@
|
| |
|
| |
log = logging.getLogger(__name__)
|
| |
|
| |
+ remote_link_title = "Upstream issue"
|
| |
|
| |
jira_cache = {}
|
| |
- def get_existing_jira_issues_legacy(downstream, config):
|
| |
- """ This is our old way of matching issues: get all, search by title.
|
| |
|
| |
- This will be phased out and removed in a future release.
|
| |
- """
|
| |
|
| |
- key = json.dumps(downstream)
|
| |
- if not key in jira_cache:
|
| |
- kwargs = sorted(downstream.items(), key=operator.itemgetter(0))
|
| |
- client = jira.client.JIRA(**config['sync2jira']['jira'])
|
| |
- query = " AND ".join([
|
| |
- "=".join([k, v]) for k, v in kwargs
|
| |
- if v is not None
|
| |
- ]) + " AND (resolution is null OR resolution = Duplicate)"
|
| |
- results = client.search_issues(query)
|
| |
- # TODO -- handle pagination here...
|
| |
- jira_cache[key] = results
|
| |
- return jira_cache[key]
|
| |
+ def get_existing_jira_issue(issue, config):
|
| |
+ """ Get a jira issue by the linked remote issue.
|
| |
|
| |
+ This is the new supported way of doing this.
|
| |
+ """
|
| |
+ client = jira.client.JIRA(**config['sync2jira']['jira'])
|
| |
+ query = 'issueFunction in linkedIssuesOfRemote("%s") and ' \
|
| |
+ 'issueFunction in linkedIssuesOfRemote("%s")' % (
|
| |
+ remote_link_title, issue.url)
|
| |
+ client = jira.client.JIRA(**config['sync2jira']['jira'])
|
| |
+ results = client.search_issues(query)
|
| |
+ log.info("Found %i results for query %r" % (len(results), query))
|
| |
+ if results:
|
| |
+ return results[0]
|
| |
+ else:
|
| |
+ return None
|
| |
|
| |
- def get_existing_jira_issue(issue, config):
|
| |
- """ This is the supported way of matching issues.
|
| |
|
| |
- Use the upstream url to uniquely grab individual downstream issues.
|
| |
+ def get_existing_jira_issue_legacy(issue, config):
|
| |
+ """ This is our old way of matching issues: use the special url field.
|
| |
+
|
| |
+ This will be phased out and removed in a future release.
|
| |
"""
|
| |
|
| |
kwargs = dict(issue.downstream.items())
|
| |
@@ -73,6 +73,34 @@
|
| |
else:
|
| |
return None
|
| |
|
| |
+ def _attach_link(config, downstream, remote_link):
|
| |
+ log.info(" Attaching tracking link %r to %r" % (
|
| |
+ remote_link, downstream.key))
|
| |
+ modified_desc = downstream.fields.description + " "
|
| |
+ client = jira.client.JIRA(**config['sync2jira']['jira'])
|
| |
+
|
| |
+ # This is crazy. Querying for application links requires admin perms which
|
| |
+ # we don't have, so duckpunch the client to think it has already made the
|
| |
+ # query.
|
| |
+ client._applicationlinks = [] # Crazy.
|
| |
+
|
| |
+ # Add the link.
|
| |
+ client.add_remote_link(downstream.id, remote_link)
|
| |
+
|
| |
+ # Finally, after we've added the link we have to edit the issue so that it
|
| |
+ # gets re-indexed, otherwise our searches won't work. Also, Handle some
|
| |
+ # weird API changes here...
|
| |
+ log.debug(" Modifying desc of %r to trigger re-index." % downstream.key)
|
| |
+ if jira_version < distutils.version.LooseVersion('0.39'):
|
| |
+ # This is the old busted way
|
| |
+ # https://github.com/pycontribs/jira/issues/65
|
| |
+ downstream.update(fields=dict(fields={'description': modified_desc}))
|
| |
+ else:
|
| |
+ # This is the new, normal way.
|
| |
+ downstream.update({'description': modified_desc})
|
| |
+
|
| |
+ return downstream
|
| |
+
|
| |
|
| |
def upgrade_jira_issue(downstream, issue, config):
|
| |
""" Given an old legacy-style downstream issue...
|
| |
@@ -80,21 +108,15 @@
|
| |
|
| |
Simply mark it with an external-url field value.
|
| |
"""
|
| |
- log.info(" Upgrading %r issue for %r" % (issue.downstream, issue))
|
| |
+ log.info(" Upgrading %r %r issue for %r" % (
|
| |
+ downstream.key, issue.downstream, issue))
|
| |
if config['sync2jira']['testing']:
|
| |
log.info(" Testing flag is true. Skipping actual upgrade.")
|
| |
return
|
| |
|
| |
# Do it!
|
| |
- external_url_field = config['sync2jira']['jira_opts']['external_url_field']
|
| |
- # Handle some weird API changes here...
|
| |
- if jira_version < distutils.version.LooseVersion('0.39'):
|
| |
- # This is the old busted way
|
| |
- # https://github.com/pycontribs/jira/issues/65
|
| |
- downstream.update(fields=dict(fields={external_url_field: issue.url}))
|
| |
- else:
|
| |
- # This is the new, normal way.
|
| |
- downstream.update({external_url_field: issue.url})
|
| |
+ remote_link = dict(url=issue.url, title=remote_link_title)
|
| |
+ _attach_link(config, downstream, remote_link)
|
| |
|
| |
|
| |
def create_jira_issue(issue, config):
|
| |
@@ -114,10 +136,12 @@
|
| |
if issue.downstream['component']:
|
| |
kwargs['components'] = [dict(name=issue.downstream['component'])] # TODO - make this a list in the config
|
| |
|
| |
- external_url_field = config['sync2jira']['jira_opts']['external_url_field']
|
| |
- kwargs[external_url_field] = issue.url
|
| |
+ log.info("Creating issue.")
|
| |
+ downstream = client.create_issue(**kwargs)
|
| |
|
| |
- return client.create_issue(**kwargs)
|
| |
+ remote_link = dict(url=issue.url, title=remote_link_title)
|
| |
+ _attach_link(config, downstream, remote_link)
|
| |
+ return downstream
|
| |
|
| |
|
| |
def sync_with_jira(issue, config):
|
| |
@@ -125,8 +149,9 @@
|
| |
|
| |
# First, check to see if we have a matching issue using the new method.
|
| |
# If we do, then just bail out. No sync needed.
|
| |
- if get_existing_jira_issue(issue, config):
|
| |
- log.info(" Found existing, matching issue downstream.")
|
| |
+ existing = get_existing_jira_issue(issue, config)
|
| |
+ if existing:
|
| |
+ log.info(" Found existing, matching downstream %r." % existing.key)
|
| |
return
|
| |
|
| |
# If we're *not* configured to do legacy matching (upgrade mode) then there
|
| |
@@ -141,13 +166,8 @@
|
| |
# - If we can't find it, create it.
|
| |
# - If we can find it, upgrade it to the new method.
|
| |
log.info(" Looking for matching downstream issue via legacy method.")
|
| |
- existing_issues = get_existing_jira_issues_legacy(issue.downstream, config)
|
| |
- existing_summaries = [i.fields.summary for i in existing_issues]
|
| |
- if issue.title not in existing_summaries:
|
| |
+ match = get_existing_jira_issue_legacy(issue, config)
|
| |
+ if not match:
|
| |
create_jira_issue(issue, config)
|
| |
else:
|
| |
- downstream = [
|
| |
- i for i in existing_issues
|
| |
- if i.fields.summary == issue.title
|
| |
- ][0]
|
| |
- upgrade_jira_issue(downstream, issue, config)
|
| |
+ upgrade_jira_issue(match, issue, config)
|
| |
This fixes #9, finally!
/cc @ausil