Several enhancements

This commit is contained in:
Zimmerberger Markus
2024-05-08 08:54:58 +02:00
parent f4d413086b
commit e5189f0d8c
5 changed files with 186 additions and 62 deletions
+17
View File
@@ -0,0 +1,17 @@
from atlassian import Bitbucket
from jira import JIRA
host = "https://bitbucket.wien.gv.at/"
pat = "OTAyMTM3MjY0MjE0Ovz6bu0ti1TlEdSegmmiWiJ2wGeD"
# Initialize Bitbucket instance
#TODO Use token for authentication
bitbucket = Bitbucket(
url=host,
username='zim9003', # Assuming you need authentication
password='3S1punk08_113$', # Use token for authentication
)
repos = bitbucket.repo_list('BAUWB')
for repo in repos:
print(repo)
+101
View File
@@ -0,0 +1,101 @@
# make page-header of confluence-area unique (add WGWR2)
# zisco 2023-11-10 06:59
from distutils.log import INFO
from queue import Full
from sqlite3 import Timestamp
from atlassian import Confluence
import logging
import requests
import json
from datetime import date, datetime
# Custom serializer function
def custom_serializer(obj):
if isinstance(obj, datetime):
#'2024-03-28T09:20:00.000+01:00'
#return obj.strftime('%Y-%m-%dT%H:%M:%S')
return obj.strftime('%Y-%m-%dT%H:%M:%S.000+01:00')
raise TypeError(f'Object of type {type(obj)} is not JSON serializable')
logging.basicConfig(filename='confluence blog timestamp change.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)
# Function to retrieve page content by page ID
def get_page_content(page_id):
blog_page = confluence.get_page_by_id(page_id, expand='body.storage')
space = confluence.get_page_by_id(page_id, expand='space')
return blog_page, space['space']
# Function to create a new page with specified creation date
def create_page_with_creation_date(space, title, body, creation_date):
#headers = {'Content-Type': 'application/json'}
data = {
"type": "page",
"title": title,
"body": {
"storage": {
"value": body,
"representation": "storage"
}
},
"metadata": {
"createdDate": creation_date
}
}
status = confluence.create_page(space=space, title=title, body=body, type='blogpost')
return status
# Function to delete a page by page ID
def delete_page(page_id):
response = confluence.remove_page(page_id=page_id)
return response.status_code == 204
"""
def change_blog_timestamp(page_id):
blog_page = confluence.get_page_by_id(page_id, expand=None, status=None, version=None)
#confluence.update_page(page_id=page_id, Timestamp=datetime.now())
data = {
"history": {
"createdDate": datetime.now()
}
}
json_data = json.dumps(data, default=custom_serializer)
confluence.update_page_property(page_id=page_id, data=json_data)
# 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}'") """
# Example usage
page_id = 317036255 # Jenkins-Blog
new_creation_date = datetime.now()
page_content, space = get_page_content(page_id)
if page_content:
title = page_content["title"]
body = page_content["body"]
new_page_id = create_page_with_creation_date(space['key'], title, body, new_creation_date)
delete_page(page_id)
else:
print("Page not found.")
#change_blog_timestamp(page_id=page_id)
+4 -3
View File
@@ -3,6 +3,7 @@
from types import ClassMethodDescriptorType from types import ClassMethodDescriptorType
from jira import JIRA, Issue, Comment, exceptions from jira import JIRA, Issue, Comment, exceptions
from datetime import date
import re import re
import csv import csv
import xlsxwriter import xlsxwriter
@@ -16,10 +17,10 @@ logging.basicConfig(filename='sprint efforts.log',
host = "https://jira.wien.gv.at/" host = "https://jira.wien.gv.at/"
pat = "OTAyMTM3MjY0MjE0Ovz6bu0ti1TlEdSegmmiWiJ2wGeD" pat = "OTAyMTM3MjY0MjE0Ovz6bu0ti1TlEdSegmmiWiJ2wGeD"
sprint = 2 #sprint = 2
row = 0; col = 0 row = 0; col = 0
workbook = xlsxwriter.Workbook(f'efforts sprint {sprint}.xlsx') workbook = xlsxwriter.Workbook(f'efforts as of preplanning {date.today()}.xlsx')
worksheet = workbook.add_worksheet('efforts') worksheet = workbook.add_worksheet('efforts')
cell_format = workbook.add_format() cell_format = workbook.add_format()
@@ -43,7 +44,7 @@ issues_Jql = jira_server.search_issues('filter=25827') #, expand='changelog')
#issues_Jql = jira_server.search_issues('key in (DKARB-140)') #, 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('Sum effort stored in issue-comments of pre-planning sprint {}'.format(sprint)) logging.info(f'Sum effort stored in issue-comments of pre-planning of {date.today()}')
xsp = lambda s: s or 0 xsp = lambda s: s or 0
issue: Issue issue: Issue
+64 -59
View File
@@ -9,6 +9,7 @@ import csv
import xlsxwriter import xlsxwriter
import logging import logging
from bisect import bisect_left from bisect import bisect_left
from datetime import date
def take_closest(myList, myNumber): def take_closest(myList, myNumber):
""" """
@@ -29,15 +30,18 @@ def take_closest(myList, myNumber):
return before return before
def get_assignee(type, issue): def get_assignee(type, issue):
isBuergerfrontend = False # isBuergerfrontend = False
if type == 'Dev Backend': if (type == 'Dev Backend' or type.startswith('Dev Unit')):
return 'reu9001' # use assignee of story
return 'rab9001'
#return issue.fields.assignee.name
elif type == 'Dev Frontend': elif type == 'Dev Frontend':
for component in issue.fields.components: # for component in issue.fields.components:
isBuergerfrontend = component.name == "Bürgerfrontend" # isBuergerfrontend = component.name == "Bürgerfrontend"
if isBuergerfrontend: # if isBuergerfrontend:
return 'reu9001'
return 'thh9001' return 'thh9001'
elif type == 'Dev Citizen-Frontend':
return 'reu9001'
elif type.startswith('Test-Anpassung'): elif type.startswith('Test-Anpassung'):
return 'osm9005' return 'osm9005'
@@ -99,18 +103,18 @@ 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 = 6
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=25827') #, 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('key in (WRGWR-2932)') #, 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(f'Creating sub-tasks out of estimation of pre-planning of {date.today()}')
xsp = lambda s: s or 0 xsp = lambda s: s or 0
issue: Issue issue: Issue
@@ -123,63 +127,64 @@ for issue in issues_Jql:
if hasattr(issue.fields, 'customfield_10022'): if hasattr(issue.fields, 'customfield_10022'):
sp = xsp(issue.fields.customfield_10022) sp = xsp(issue.fields.customfield_10022)
if sp != 0: # if sp == 0:
logging.info('Ignoring issue {} as there are Story-Points already omitted'.format(issue)) # logging.info('Ignoring issue {} as there are Story-Points already omitted'.format(issue))
else: # else:
single_issue = jira_server.issue(issue.key) single_issue = jira_server.issue(issue.key)
comments = single_issue.fields.comment.comments comments = single_issue.fields.comment.comments
# Find all comments made by me on this issue. # Find all comments made by me on this issue.
for comment in comments: for comment in comments:
comment_lines = comment.body.splitlines() comment_lines = comment.body.splitlines()
if len(comment_lines) == 7: if len(comment_lines) == 9:
if comment_lines[0][:5] == "Dev B": if comment_lines[0][:5] == "Dev B":
for comment_line in comment_lines: for comment_line in comment_lines:
if comment_line != "": if comment_line != "":
# pos = comment_lines[2].find('NN') # pos = comment_lines[2].find('NN')
comment_line_parts = comment_line.split(':') comment_line_parts = comment_line.split(':')
# if 1. Test* != NN create a sub-task (if not existing) # if 1. Test* != NN create a sub-task (if not existing)
if len(comment_line_parts) == 2: if len(comment_line_parts) == 2:
if comment_line_parts[1] != u'\xa0': # empty string if comment_line_parts[1] != u'\xa0': # empty string
if (comment_line_parts[1][-2:] != 'NN'): # NN means NotNecessary if (comment_line_parts[1][-2:] != 'NN'): # NN means NotNecessary, "-"" means we don't know yet (but subtask will be created)
if (comment_line_parts[1][-1:] == '-'): if (comment_line_parts[1][-1:] == '-'):
subtask_ph = 0 subtask_ph = 0
estimation_remark = "(not estimated yet)" estimation_remark = "(not estimated yet)"
else: else:
comment_line_sub_parts = comment_line_parts[1].split(' (') comment_line_sub_parts = comment_line_parts[1].split(' (')
if len(comment_line_sub_parts)>1: if len(comment_line_sub_parts)>1:
if comment_line_sub_parts[0].strip().isnumeric():
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:
if comment_line_sub_parts[0].strip().isnumeric():
subtask_ph = float(comment_line_sub_parts[0]) * 0.5
estimation_remark = ""
else: else:
if comment_line_sub_parts[0].strip().isnumeric(): if comment_line_sub_parts[0].strip() == "tbd":
subtask_ph = float(comment_line_sub_parts[0]) * 0.5 subtask_ph = take_closest([1,2,3,5,8,13,21,42], sp_sum/3)
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,
issue.key, issue.key,
comment_line_parts[0], comment_line_parts[0],
subtask_ph, subtask_ph,
estimation_remark) estimation_remark)
sp_sum += subtask_ph / 0.5 sp_sum += subtask_ph / 0.5
# find corresponding sub-task # find corresponding sub-task
# issuelinks.inwardIssue # issuelinks.inwardIssue
try: try:
if sp != sp_sum: if sp != sp_sum:
issue.update(fields={'customfield_10022': sp_sum}) issue.update(fields={'customfield_10022': sp_sum})
logging.info("Estimated story-points changed to Sum(Sub-Tasks story-points): {}".format(sp_sum, sp_sum)) logging.info("Estimated story-points changed to Sum(Sub-Tasks story-points): {}".format(sp_sum, sp_sum))
except exceptions.JIRAError: except exceptions.JIRAError:
logging.error("Issue {} has no (visible) Story Points-attribute".format(issue.key)) logging.error("Issue {} has no (visible) Story Points-attribute".format(issue.key))
finally: finally:
logging.info('Done {}'.format(issue.key)) logging.info('Done {}'.format(issue.key))
#print('{}: {}, SP: {}'.format(issue.key, issue.fields.summary, sp)) #print('{}: {}, SP: {}'.format(issue.key, issue.fields.summary, sp))
Binary file not shown.