diff --git a/bugwarrior/services/gitlab.py b/bugwarrior/services/gitlab.py index 7dc8d11d..85d3ea33 100644 --- a/bugwarrior/services/gitlab.py +++ b/bugwarrior/services/gitlab.py @@ -12,6 +12,7 @@ import re import requests import six +import os from jinja2 import Template @@ -149,13 +150,15 @@ def to_taskwarrior(self): self.record['id'] if self.extra['type'] == 'todo' else self.record['iid']) priority = self.get_priority() - title = ( - 'Todo from %s for %s' % (author['name'], self.extra['project']) - if self.extra['type'] == 'todo' else self.record['title']) + # title = ( + # 'Todo from %s for %s' % (author['name'], self.extra['project']) + # if self.extra['type'] == 'todo' else self.record['title']) description = ( self.record['body'] if self.extra['type'] == 'todo' else self.record['description']) + title = ( description if self.extra['type'] == 'todo' else self.record['title']) + if milestone and ( self.extra['type'] == 'issue' or (self.extra['type'] == 'merge_request' and duedate is None)): diff --git a/bugwarrior/services/jira.py b/bugwarrior/services/jira.py index 6de07ca0..a4492675 100644 --- a/bugwarrior/services/jira.py +++ b/bugwarrior/services/jira.py @@ -54,7 +54,8 @@ def _parse_sprint_string(sprint): fields = sum((entry.rsplit(',', 1) for entry in entries), []) return dict(zip(fields[::2], fields[1::2])) - +import re +regex = re.compile('Sprint\d*') class JiraIssue(Issue): ISSUE_TYPE = 'jiraissuetype' SUMMARY = 'jirasummary' @@ -66,8 +67,20 @@ class JiraIssue(Issue): CREATED_AT = 'jiracreatedts' STATUS = 'jirastatus' SUBTASKS = 'jirasubtasks' + EPIC = 'jiraparent' + POINTS = 'estimate' + ASSIGNEE = 'jiraassignee' + REPORTER = 'jirareporter' UDAS = { + EPIC: { + 'type': 'string', + 'label': 'Epic Parent' + }, + POINTS: { + 'type': 'string', + 'label': 'Story Points' + }, ISSUE_TYPE: { 'type': 'string', 'label': 'Issue Type' @@ -108,6 +121,14 @@ class JiraIssue(Issue): 'type': 'string', 'label': "Jira Subtasks" }, + ASSIGNEE: { + 'type': 'string', + 'label': "Jira Assignee" + }, + REPORTER: { + 'type': 'string', + 'label': "Jira Reporter" + }, } UNIQUE_KEY = (URL, ) @@ -142,6 +163,10 @@ def to_taskwarrior(self): self.FIX_VERSION: self.get_fix_version(), self.STATUS: self.get_status(), self.SUBTASKS: self.get_subtasks(), + self.ASSIGNEE: self.get_assignee(), + self.REPORTER: self.get_reporter(), + self.EPIC: self.extra.get('jiraparent'), + self.POINTS: self.extra.get('jirapoints'), } def get_entry(self): @@ -176,7 +201,10 @@ def _get_tags_from_sprints(self): sprints = self.__get_sprints() for sprint in sprints: # Extract the name and render it into a label - context.update({'label': sprint['name'].replace(' ', '')}) + NAME = sprint['name'].replace(' ', '') + if MATCH := regex.findall(NAME): + NAME = MATCH[0] + context.update({'label': NAME}) tags.append(label_template.render(context)) return tags @@ -269,6 +297,16 @@ def get_subtasks(self): def get_issue_type(self): return self.record['fields']['issuetype']['name'] + def get_assignee(self): + # email address "better" than accountId (hex) or displayName (with spaces) + record = self.record['fields']['assignee'] + return record.get('emailAddress') or record.get('displayName') + + def get_reporter(self): + # email address "better" than accountId (hex) or displayName (with spaces) + record = self.record['fields']['reporter'] + return record.get('emailAddress') or record.get('displayName') + class JiraService(IssueService): ISSUE_CLASS = JiraIssue @@ -357,6 +395,22 @@ def annotations(self, issue, issue_obj): issue_obj.get_processed_url(issue_obj.get_url()) ) + + def get_parent(self, iss): + if p := getattr(iss.fields, 'parent', None): + return next(self.jira.search_issues(f'KEY={p.key}')) + + + def find_parent(self, iss): + parentType = None + parent = iss + while parentType != 'Epic': + if parent := self.get_parent(parent): + parentType = parent.fields.issuetype.name + else: + return + return parent + def issues(self): cases = self.jira.search_issues(self.query, maxResults=None) @@ -365,9 +419,12 @@ def issues(self): jira_version = self.config.getint(self.target, 'jira.version') for case in cases: + issue = self.get_issue_for_record(case.raw) extra = { 'jira_version': jira_version, + 'jiraparent': getattr(self.find_parent(case), 'key', None), + 'jirapoints': getattr(case.fields, 'customfield_10002', None), } if jira_version > 4: extra.update({ diff --git a/tests/test_jira.py b/tests/test_jira.py index a2bb23bf..08ee4be1 100644 --- a/tests/test_jira.py +++ b/tests/test_jira.py @@ -43,7 +43,9 @@ class TestJiraIssue(AbstractServiceTest, ServiceTest): 'fixVersions': [{'name': '1.2.3'}], 'issuetype': {'name': 'Epic'}, 'status': {'name': 'Open'}, - 'subtasks': [{'key': 'DONUT-%s' % subtask} for subtask in arbitrary_subtask_ids] + 'subtasks': [{'key': 'DONUT-%s' % subtask} for subtask in arbitrary_subtask_ids], + 'assignee': {'displayName': 'Super P', 'emailAddress': 'potato@tomatocom'}, + 'reporter': {'displayName': 'Super T', 'emailAddress': 'tomato@potatocom'}, }, 'key': '%s-%s' % (arbitrary_project, arbitrary_id, ), } @@ -90,6 +92,8 @@ def test_to_taskwarrior(self): 'jiraissuetype': 'Epic', 'jirastatus': 'Open', 'jirasubtasks': 'DONUT-11,DONUT-12', + 'jiraassignee': 'potato@tomatocom', + 'jirareporter': 'tomato@potatocom', issue.URL: arbitrary_url, issue.FOREIGN_ID: self.arbitrary_record['key'],