Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import JIRA sprint names as labels. #381

Merged
merged 5 commits into from Oct 4, 2016
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 9 additions & 5 deletions bugwarrior/docs/services/jira.rst
Expand Up @@ -68,18 +68,22 @@ If your Jira instance is only available over HTTPS, and you're running into

jira.verify_ssl = False

Import Labels as Tags
+++++++++++++++++++++
Import Labels and Sprints as Tags
+++++++++++++++++++++++++++++++++

The Jira issue tracker allows you to attach labels to issues; to
use those labels as tags, you can use the ``jira.import_labels_as_tags``
option::

jira.import_labels_as_tags = True

Also, if you would like to control how these labels are created, you can
specify a template used for converting the Jira label into a Taskwarrior
tag.
You can also import the names of any sprints associated with an issue as tags,
by setting the ``jira.import_sprints_as_tags`` option::

jira.import_sprints_as_tags = True

If you would like to control how these labels are created, you can specify a
template used for converting the Jira label into a Taskwarrior tag.

For example, to prefix all incoming labels with the string 'jira_' (perhaps
to differentiate them from any existing tags you might have), you could
Expand Down
61 changes: 55 additions & 6 deletions bugwarrior/services/jira.py
Expand Up @@ -10,6 +10,9 @@
from bugwarrior.config import asbool, die
from bugwarrior.services import IssueService, Issue

import logging
log = logging.getLogger(__name__)

# The below `ObliviousCookieJar` and `JIRA` classes are MIT Licensed.
# They were taken from this wonderful commit by @GaretJax
# https://github.com/GaretJax/lancet/commit/f175cb2ec9a2135fb78188cf0b9f621b51d88977
Expand All @@ -36,6 +39,16 @@ def _create_http_basic_session(self, username, password):
def close(self):
self._session.close()

def _parse_sprint_string(sprint):
""" Parse the big ugly sprint string stored by JIRA.

They look like:
com.atlassian.greenhopper.service.sprint.Sprint@4c9c41a5[id=2322,rapid
ViewId=1173,state=ACTIVE,name=Sprint 1,startDate=2016-09-06T16:08:07.4
55Z,endDate=2016-09-23T16:08:00.000Z,completeDate=<null>,sequence=2322]
"""
entries = sprint[sprint.index('[')+1:sprint.index(']')].split(',')
return dict([entry.split('=') for entry in entries])

class JiraIssue(Issue):
SUMMARY = 'jirasummary'
Expand Down Expand Up @@ -116,6 +129,28 @@ def get_entry(self):
return timestamp.strftime('%Y%m%dT%H%M%S') + timezone

def get_tags(self):
return self._get_tags_from_labels() + self._get_tags_from_sprints()

def _get_tags_from_sprints(self):
tags = []

if not self.origin['import_sprints_as_tags']:
return tags

context = self.record.copy()
label_template = Template(self.origin['label_template'])

sprints = self.record.get('fields', {}).get(self.origin['sprint_field']) or []
for sprint in sprints:
# Parse this big ugly string.
sprint = _parse_sprint_string(sprint)
# Extract the name and render it into a label
context.update({'label': sprint['name']})
tags.append(label_template.render(context))

return tags

def _get_tags_from_labels(self):
tags = []

if not self.origin['import_labels_as_tags']:
Expand All @@ -125,12 +160,8 @@ def get_tags(self):
label_template = Template(self.origin['label_template'])

for label in self.record.get('fields', {}).get('labels', []):
context.update({
'label': label
})
tags.append(
label_template.render(context)
)
context.update({'label': label})
tags.append(label_template.render(context))

return tags

Expand Down Expand Up @@ -206,10 +237,26 @@ def __init__(self, *args, **kw):
self.import_labels_as_tags = self.config_get_default(
'import_labels_as_tags', default=False, to_type=asbool
)
self.import_sprints_as_tags = self.config_get_default(
'import_sprints_as_tags', default=False, to_type=asbool
)
self.label_template = self.config_get_default(
'label_template', default='{{label}}', to_type=six.text_type
)

self.sprint_field = None
if self.import_sprints_as_tags:
sprint_fields = [field for field in self.jira.fields()
if field['name'] == 'Sprint']
if len(sprint_fields) > 1:
log.warn("More than one sprint custom field found. Ignoring sprints.")
self.import_sprints_as_tags = False
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know anything about jira but why not add multiple sprint tags?

Copy link
Sponsor Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, this is dealt with in b2ca93d

elif len(sprint_fields) < 1:
log.warn("No sprint custom field found. Ignoring sprints.")
self.import_sprints_as_tags = False
else:
self.sprint_field = sprint_fields[0]['id']

@classmethod
def get_keyring_service(cls, config, section):
username = config.get(section, cls._get_key('username'))
Expand All @@ -220,6 +267,8 @@ def get_service_metadata(self):
return {
'url': self.url,
'import_labels_as_tags': self.import_labels_as_tags,
'import_sprints_as_tags': self.import_sprints_as_tags,
'sprint_field': self.sprint_field,
'label_template': self.label_template,
}

Expand Down