148 lines
6.0 KiB
Python
148 lines
6.0 KiB
Python
# find comments with estimations out of pre-planning
|
|
# zisco 2021-09-30 19:50
|
|
|
|
from types import ClassMethodDescriptorType
|
|
from jira import JIRA, Issue, Comment, exceptions
|
|
import re
|
|
import csv
|
|
import xlsxwriter
|
|
import logging
|
|
|
|
def get_assignee(type):
|
|
if type == 'Dev Backend':
|
|
#return 'rab9001'
|
|
return 'reu9001'
|
|
elif type == 'Dev Frontend':
|
|
# consider verwaltungsfrontend or bürgerfrontend
|
|
return 'thh9001'
|
|
# return 'reu9001'
|
|
elif type[:14] == 'Test-Anpassung':
|
|
return 'ada9001'
|
|
|
|
def create_subtask(issue, parent, type, subtask_sp):
|
|
escaped = issue.fields.summary.replace('"','\\"')
|
|
print('summary ~ \"{}\"'.format(escaped))
|
|
|
|
subtask = jira_server.search_issues('summary ~ \"{} {}\"'.format(type, escaped))
|
|
if len(subtask) == 0:
|
|
#right = (comment_line.find(':')+2)-len(comment_line)
|
|
#subtask_sp = float(comment_line[right:])
|
|
|
|
# issuetype of testcase-creation/modification should be 'Test'
|
|
# if type == 'Test-Anpassung':
|
|
issue_type = 'Sub-task'
|
|
|
|
assignee = get_assignee(type)
|
|
issue_dict = {
|
|
'project': {'id': 12501},
|
|
'summary': "[{}] {}".format(type, escaped),
|
|
'description': issue.fields.description,
|
|
'issuetype': {'name': issue_type},
|
|
'priority': {'name': issue.fields.priority.name},
|
|
'parent': {'key': parent},
|
|
'labels': issue.fields.labels,
|
|
#'customfield_10022' - Story Points
|
|
'timetracking': {'originalEstimate': "{}d".format(subtask_sp)},
|
|
'assignee': {'name': assignee}
|
|
}
|
|
new_issue = jira_server.create_issue(fields=issue_dict)
|
|
|
|
# consider components
|
|
existingComponents = []
|
|
for component in issue.fields.components:
|
|
existingComponents.append({"name" : component.name})
|
|
new_issue.update(fields={"components": existingComponents})
|
|
#new_issue.update(priority={"name": issue.fields.priority.name})
|
|
|
|
logging.info('Created Sub-Task {}'.format(new_issue))
|
|
else:
|
|
logging.info('Skip creating Sub-Task {} for {} as it already exists'.format(type, issue))
|
|
|
|
logging.basicConfig(filename='sub_task_generator.log',
|
|
filemode='a',
|
|
format='%(asctime)s - %(levelname)s: %(message)s',
|
|
level=logging.INFO,
|
|
encoding='utf-8')
|
|
|
|
host = "https://jira.wien.gv.at/"
|
|
pat = "OTAyMTM3MjY0MjE0Ovz6bu0ti1TlEdSegmmiWiJ2wGeD"
|
|
sprint = 46
|
|
|
|
headers = JIRA.DEFAULT_OPTIONS["headers"].copy()
|
|
headers["Authorization"] = f"Bearer {pat}"
|
|
jira_server = JIRA(server=host, options={"headers": headers})
|
|
|
|
# use filter or single issue
|
|
issues_Jql = jira_server.search_issues('filter=20406') #, expand='changelog')
|
|
#issues_Jql = jira_server.search_issues('key in (WRGWR-1558)') #, expand='changelog')
|
|
#issues_Jql = jira_server.search_issues('labels in (Refinement11012022) AND type not in (Bug) AND status not in (Done) and ("Story Points" is EMPTY or "Story Points" = 0)') #, expand='changelog')
|
|
|
|
logging.info('Creating sub-tasks out of estimation of pre-planning sprint {}'.format(sprint))
|
|
xsp = lambda s: s or 0
|
|
|
|
issue: Issue
|
|
for issue in issues_Jql:
|
|
logging.info('Working on {}'.format(issue))
|
|
sp_sum = 0
|
|
|
|
# only Issues with empty (or 0) story-points
|
|
sp = 0
|
|
if hasattr(issue.fields, 'customfield_10022'):
|
|
sp = xsp(issue.fields.customfield_10022)
|
|
|
|
if sp != 0:
|
|
logging.info('Ignoring issue {} as there are Story-Points already omitted'.format(issue))
|
|
else:
|
|
single_issue = jira_server.issue(issue.key)
|
|
comments = single_issue.fields.comment.comments
|
|
|
|
# Find all comments made by me on this issue.
|
|
for comment in comments:
|
|
comment_lines = comment.body.splitlines()
|
|
|
|
if len(comment_lines) == 5:
|
|
if comment_lines[0][:5] == "Dev B":
|
|
for comment_line in comment_lines:
|
|
if comment_line != "":
|
|
# pos = comment_lines[2].find('NN')
|
|
comment_line_parts = comment_line.split(':')
|
|
|
|
# if 1. Test* != NN create a sub-task (if not existing)
|
|
if len(comment_line_parts) == 2:
|
|
if comment_line_parts[1] != u'\xa0': # empty string
|
|
if comment_line_parts[1][-2:] != 'NN': # NN means NotNecessary
|
|
subtask_ph = float(comment_line_parts[1]) * 0.5
|
|
if comment_line_parts[0][:15] != "Test-Ausführung":
|
|
create_subtask(issue,
|
|
issue.key,
|
|
comment_line_parts[0],
|
|
subtask_ph)
|
|
sp_sum += subtask_ph / 0.5
|
|
|
|
# find corresponding sub-task
|
|
# issuelinks.inwardIssue
|
|
try:
|
|
issue.update(fields={'customfield_10022': sp_sum})
|
|
logging.info("Estimated story-points changed to Sum(Sub-Tasks story-points): {}".format(sp_sum, sp_sum))
|
|
|
|
except exceptions.JIRAError:
|
|
logging.error("Issue {} has no (visible) Story Points-attribute".format(issue.key))
|
|
|
|
finally:
|
|
logging.info('Done {}'.format(issue.key))
|
|
|
|
#print('{}: {}, SP: {}'.format(issue.key, issue.fields.summary, sp))
|
|
|
|
#print('Summe {}: {}'.format(assignee, sp_sum))
|
|
|
|
#print(issues_Jql)
|
|
# changelog = issues_Jql.
|
|
# count = 0
|
|
# for history in changelog.histories:
|
|
# for item in history.items:
|
|
# if item.field == 'status':
|
|
# if item.toString == "Reopened":
|
|
# count = count + 1
|
|
# print(count)
|
|
|