From 902fbec9a00adda90bdeca513576a8e9d6ae4ee3 Mon Sep 17 00:00:00 2001 From: Zimmerberger Markus Date: Wed, 13 Mar 2024 15:44:32 +0100 Subject: [PATCH] Dev in progress --- Confluence Bulk.py | 58 +++++++++++++++++++++ JIRA_EffortbyComments.py | 9 ++-- JIRA_EffortbySubTasks.py | 6 +-- JIRA_SubTasks_byComments.py | 41 ++++++++++----- efforts BAUWB sprint 4 (from comment).xlsx | Bin 0 -> 5609 bytes efforts sprint 2.xlsx | Bin 0 -> 5486 bytes 6 files changed, 93 insertions(+), 21 deletions(-) create mode 100644 Confluence Bulk.py create mode 100644 efforts BAUWB sprint 4 (from comment).xlsx create mode 100644 efforts sprint 2.xlsx diff --git a/Confluence Bulk.py b/Confluence Bulk.py new file mode 100644 index 0000000..b15156c --- /dev/null +++ b/Confluence Bulk.py @@ -0,0 +1,58 @@ +# make page-header of confluence-area unique (add WGWR2) +# zisco 2023-11-10 06:59 + +from distutils.log import INFO +from atlassian import Confluence +import logging +import requests + +logging.basicConfig(filename='confluence bulk.log', + filemode='a', + format='%(asctime)s - %(levelname)s: %(message)s', + level=logging.WARNING, + encoding='utf-8') +logger = logging.getLogger('myLogger') +logger.setLevel(level=logging.INFO) + +confluence_host = "https://confluence.wien.gv.at/" +confluence_pat = "MDI3ODU2NzkzMTAyOsPz47kjJvVdJa1bLpen3W5sB6S5" + +s = requests.Session() +s.headers['Authorization'] = f"Bearer {confluence_pat}" +confluence = Confluence(url=confluence_host, session=s) + +def recurse_child_pages(page_id, level=0): + level += 1 + + child_pages = confluence.get_page_child_by_type(page_id, type='page', start=None, limit=None, expand=None) + for child_page in child_pages: + page_title = child_page["title"] + st = "\t" * level + logger.info(f"{st}Page {page_title}") + if page_title.find('[WGWR3]') != -1: + rename_page_title(child_page["id"], child_page["title"]) + recurse_child_pages(child_page["id"], level=level) + +def rename_page_title(page_id, page_title): + #append 'WGWR2' + #Confluence.update_page(page_id, title='WGWR2_' , body, parent_id=None, type='page', representation='storage', minor_edit=False, full_width=False) + page_title = page_title.replace('[WGWR3]','WGWR3_') + + # Get old page contents + page_content = confluence.get_page_by_id(page_id=page_id, expand='body') # Old page contents + + #Rename and move page, get updated content + #new_page_content = confluence.update_page(old_page_content['id'], title=new_title, body=old_page_content['body'], parent_id=parent_id, type="page", representation="storage") + confluence.update_page(page_id=page_id, title=page_title) #, body=page_content['body']) + logger.info(f"New page title '{page_title}'") + +# get main page +#Confluence.get_page_by_id(page_id, expand=None, status=None, version=None) +#page = Confluence.get_page_child_by_type('Wiener Gebäude- und Wohnungsregister', 'WGWR2') + +#page_id = 118856417 # WGWR2 +page_id = 280660965 # WGWR3 + +recurse_child_pages(page_id=page_id) + +#body = page["body"]["storage"]["value"] \ No newline at end of file diff --git a/JIRA_EffortbyComments.py b/JIRA_EffortbyComments.py index de28613..f7b6a97 100644 --- a/JIRA_EffortbyComments.py +++ b/JIRA_EffortbyComments.py @@ -17,10 +17,11 @@ logging.basicConfig(filename='sprint efforts.log', host = "https://jira.wien.gv.at/" pat = "OTAyMTM3MjY0MjE0Ovz6bu0ti1TlEdSegmmiWiJ2wGeD" -sprint = 9 +sprint = 1 +project = 'WRWGR3' row = 0; col = 0 -workbook = xlsxwriter.Workbook(f'efforts sprint {sprint} (from comment).xlsx') +workbook = xlsxwriter.Workbook(f'efforts {project} sprint {sprint} (from comment).xlsx') worksheet = workbook.add_worksheet('efforts') cell_format = workbook.add_format() @@ -39,8 +40,8 @@ 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('filter=25827') #, expand='changelog') +issues_Jql = jira_server.search_issues('key in (WRGWR-2838, WRGWR-2839)') #, 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)) diff --git a/JIRA_EffortbySubTasks.py b/JIRA_EffortbySubTasks.py index 9853913..e0d4177 100644 --- a/JIRA_EffortbySubTasks.py +++ b/JIRA_EffortbySubTasks.py @@ -16,7 +16,7 @@ logging.basicConfig(filename='sprint efforts.log', host = "https://jira.wien.gv.at/" pat = "OTAyMTM3MjY0MjE0Ovz6bu0ti1TlEdSegmmiWiJ2wGeD" -sprint = 9 +sprint = 2 row = 0; col = 0 workbook = xlsxwriter.Workbook(f'efforts sprint {sprint}.xlsx') @@ -38,8 +38,8 @@ 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 (wrgwr-856, dkarb-367)', expand='changelog') +issues_Jql = jira_server.search_issues('filter=25827') #, expand='changelog') +#issues_Jql = jira_server.search_issues('key in (wrgwr-2838, wrgwr-2839)', 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') diff --git a/JIRA_SubTasks_byComments.py b/JIRA_SubTasks_byComments.py index f6a97c3..a816907 100644 --- a/JIRA_SubTasks_byComments.py +++ b/JIRA_SubTasks_byComments.py @@ -1,6 +1,7 @@ # find comments with estimations out of pre-planning # zisco 2021-09-30 19:50 +from multiprocessing.sharedctypes import Value from types import ClassMethodDescriptorType from jira import JIRA, Issue, Comment, exceptions import re @@ -49,6 +50,14 @@ def create_subtask(issue, parent, type, subtask_sp, estimation_remark): if subtask: raise exceptions.JIRAError except exceptions.JIRAError: + # correct estimation + #subtask.fields('timetracking': {'originalEstimate'}).Value() = subtask_sp + single_issue = jira_server.issue(subtask[0].key) + try: + single_issue.update(fields={'timetracking': {'originalEstimate': '{}d'.format(subtask_sp)}}) + except Exception as e: + logging.info(e) + logging.info(f'Skip creating Sub-Task {type} for {issue} as it already exists') return @@ -90,15 +99,15 @@ logging.basicConfig(filename='sub_task_generator.log', host = "https://jira.wien.gv.at/" pat = "OTAyMTM3MjY0MjE0Ovz6bu0ti1TlEdSegmmiWiJ2wGeD" -sprint = 9 +sprint = 4 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('filter=25827') #, expand='changelog') +#issues_Jql = jira_server.search_issues('key in (WRWGR-2885)') #, 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)) @@ -124,7 +133,7 @@ for issue in issues_Jql: for comment in comments: comment_lines = comment.body.splitlines() - if len(comment_lines) == 5: + if len(comment_lines) == 7: if comment_lines[0][:5] == "Dev B": for comment_line in comment_lines: if comment_line != "": @@ -133,19 +142,23 @@ for issue in issues_Jql: # 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') 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: - subtask_ph = float(comment_line_sub_parts[0]) * 0.5 - estimation_remark = comment_line_sub_parts[1] + if comment_line_parts[1] != u'\xa0': # empty string + if (comment_line_parts[1][-2:] != 'NN'): # NN means NotNecessary + if (comment_line_parts[1][-1:] == '-'): + subtask_ph = 0 + estimation_remark = "(not estimated yet)" else: - if comment_line_sub_parts[0].strip().isnumeric(): + comment_line_sub_parts = comment_line_parts[1].split(' (') + if len(comment_line_sub_parts)>1: subtask_ph = float(comment_line_sub_parts[0]) * 0.5 - estimation_remark = "" + estimation_remark = comment_line_sub_parts[1] 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_sub_parts[0].strip().isnumeric(): + 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": create_subtask(issue, diff --git a/efforts BAUWB sprint 4 (from comment).xlsx b/efforts BAUWB sprint 4 (from comment).xlsx new file mode 100644 index 0000000000000000000000000000000000000000..23392dfed8077c804737a96e13159d8e1101cf3f GIT binary patch literal 5609 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 literal 0 HcmV?d00001