Several minor enhancements
This commit is contained in:
@@ -0,0 +1,81 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
logging.basicConfig(filename='sprint efforts.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 = 9
|
||||||
|
|
||||||
|
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=24707') #, expand='changelog')
|
||||||
|
#issues_Jql = jira_server.search_issues('key in (DKARB-140)') #, 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('Sum effort stored in issue-comments 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)
|
||||||
|
|
||||||
|
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 != "":
|
||||||
|
logging.info(f"{comment_line}")
|
||||||
|
# pos = comment_lines[2].find('NN')
|
||||||
|
comment_line_parts = comment_line.split(':')
|
||||||
|
|
||||||
|
if len(comment_line_parts) == 2:
|
||||||
|
if comment_line_parts[1] != u'\xa0': # empty string
|
||||||
|
if (comment_line_parts[1][-2:] != 'NN') and (comment_line_parts[1][-1:] != '-'): # NN means NotNecessary
|
||||||
|
comment_line_sub_parts = comment_line_parts[1].split(' (')
|
||||||
|
if len(comment_line_sub_parts)>1:
|
||||||
|
if comment_line_sub_parts[0].isnumeric():
|
||||||
|
subtask_ph = float(comment_line_sub_parts[0]) * 0.5
|
||||||
|
estimation_remark = comment_line_sub_parts[1]
|
||||||
|
else:
|
||||||
|
subtask_ph = 0
|
||||||
|
else:
|
||||||
|
if comment_line_sub_parts[1].isnumeric():
|
||||||
|
subtask_ph = float(comment_line_parts[1]) * 0.5
|
||||||
|
estimation_remark = ""
|
||||||
|
else:
|
||||||
|
subtask_ph = 0
|
||||||
|
#logging.info(f"Effort {comment_line_sub_parts[0]}")
|
||||||
|
sp_sum += subtask_ph / 0.5
|
||||||
|
try:
|
||||||
|
if sp != sp_sum:
|
||||||
|
logging.info(f"Estimated story-points changed to Sum(Sub-Tasks story-points): {sp_sum}")
|
||||||
|
|
||||||
|
except exceptions.JIRAError:
|
||||||
|
logging.error("Issue {} has no (visible) Story Points-attribute".format(issue.key))
|
||||||
@@ -7,6 +7,25 @@ import re
|
|||||||
import csv
|
import csv
|
||||||
import xlsxwriter
|
import xlsxwriter
|
||||||
import logging
|
import logging
|
||||||
|
from bisect import bisect_left
|
||||||
|
|
||||||
|
def take_closest(myList, myNumber):
|
||||||
|
"""
|
||||||
|
Assumes myList is sorted. Returns closest value to myNumber.
|
||||||
|
|
||||||
|
If two numbers are equally close, return the smallest number.
|
||||||
|
"""
|
||||||
|
pos = bisect_left(myList, myNumber)
|
||||||
|
if pos == 0:
|
||||||
|
return myList[0]
|
||||||
|
if pos == len(myList):
|
||||||
|
return myList[-1]
|
||||||
|
before = myList[pos - 1]
|
||||||
|
after = myList[pos]
|
||||||
|
if after - myNumber < myNumber - before:
|
||||||
|
return after
|
||||||
|
else:
|
||||||
|
return before
|
||||||
|
|
||||||
def get_assignee(type, issue):
|
def get_assignee(type, issue):
|
||||||
isBuergerfrontend = False
|
isBuergerfrontend = False
|
||||||
@@ -19,7 +38,7 @@ def get_assignee(type, issue):
|
|||||||
return 'reu9001'
|
return 'reu9001'
|
||||||
return 'thh9001'
|
return 'thh9001'
|
||||||
elif type.startswith('Test-Anpassung'):
|
elif type.startswith('Test-Anpassung'):
|
||||||
return 'ada9001'
|
return 'osm9005'
|
||||||
|
|
||||||
def create_subtask(issue, parent, type, subtask_sp, estimation_remark):
|
def create_subtask(issue, parent, type, subtask_sp, estimation_remark):
|
||||||
escaped = issue.fields.summary.replace('"', r'\"')
|
escaped = issue.fields.summary.replace('"', r'\"')
|
||||||
@@ -71,15 +90,15 @@ logging.basicConfig(filename='sub_task_generator.log',
|
|||||||
|
|
||||||
host = "https://jira.wien.gv.at/"
|
host = "https://jira.wien.gv.at/"
|
||||||
pat = "OTAyMTM3MjY0MjE0Ovz6bu0ti1TlEdSegmmiWiJ2wGeD"
|
pat = "OTAyMTM3MjY0MjE0Ovz6bu0ti1TlEdSegmmiWiJ2wGeD"
|
||||||
sprint = 4
|
sprint = 9
|
||||||
|
|
||||||
headers = JIRA.DEFAULT_OPTIONS["headers"].copy()
|
headers = JIRA.DEFAULT_OPTIONS["headers"].copy()
|
||||||
headers["Authorization"] = f"Bearer {pat}"
|
headers["Authorization"] = f"Bearer {pat}"
|
||||||
jira_server = JIRA(server=host, options={"headers": headers})
|
jira_server = JIRA(server=host, options={"headers": headers})
|
||||||
|
|
||||||
# use filter or single issue
|
# use filter or single issue
|
||||||
issues_Jql = jira_server.search_issues('filter=22140') #, expand='changelog')
|
issues_Jql = jira_server.search_issues('filter=24707') #, expand='changelog')
|
||||||
#issues_Jql = jira_server.search_issues('key in (DKARB-34)') #, expand='changelog')
|
#issues_Jql = jira_server.search_issues('key in (DKARB-140)') #, 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')
|
#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))
|
logging.info('Creating sub-tasks out of estimation of pre-planning sprint {}'.format(sprint))
|
||||||
@@ -121,8 +140,12 @@ for issue in issues_Jql:
|
|||||||
subtask_ph = float(comment_line_sub_parts[0]) * 0.5
|
subtask_ph = float(comment_line_sub_parts[0]) * 0.5
|
||||||
estimation_remark = comment_line_sub_parts[1]
|
estimation_remark = comment_line_sub_parts[1]
|
||||||
else:
|
else:
|
||||||
subtask_ph = float(comment_line_parts[1]) * 0.5
|
if comment_line_sub_parts[0].strip().isnumeric():
|
||||||
estimation_remark = ""
|
subtask_ph = float(comment_line_sub_parts[0]) * 0.5
|
||||||
|
estimation_remark = ""
|
||||||
|
else:
|
||||||
|
if comment_line_sub_parts[0].strip() == "tbd":
|
||||||
|
subtask_ph = take_closest([1,2,3,5,8,13,21,42], sp_sum/3)
|
||||||
|
|
||||||
if comment_line_parts[0][:15] != "Test-Ausführung":
|
if comment_line_parts[0][:15] != "Test-Ausführung":
|
||||||
create_subtask(issue,
|
create_subtask(issue,
|
||||||
|
|||||||
Reference in New Issue
Block a user