Skip to content

Commit 68e7672

Browse files
authored
Add Jira-Database data pump (#35)
* Add Jira-Database data pump * adding constants * remove argument * adding columns to the ReportJiraQARequests * missed a column in the report * fix insertion and delete method
1 parent 4a94c56 commit 68e7672

File tree

6 files changed

+141
-22
lines changed

6 files changed

+141
-22
lines changed

__main__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import sys
33

44
from github import GithubClient
5-
from jira import Jira
5+
from jira import JiraClient
66
from testrail import TestRailClient
77
from utils.constants import PROJECTS_ABBREV, REPORT_TYPES
88

@@ -54,8 +54,8 @@ def main():
5454
h.github_issue_regression(args.project)
5555
h = GithubClient()
5656
if args.report_type == 'jira-qa-requests':
57-
h = Jira()
58-
h.filters()
57+
h = JiraClient()
58+
h.jira_qa_requests()
5959

6060

6161
if __name__ == '__main__':

database.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ class ReportGithubIssues(Base):
3535
__table__ = Table('report_github_issues', Base.metadata, autoload=True)
3636

3737

38+
class ReportJiraQARequests(Base):
39+
__table__ = Table('report_jira_qa_requests', Base.metadata, autoload=True) # noqa
40+
41+
3842
class Database:
3943

4044
def __init__(self):

jira.py

Lines changed: 105 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
import os
22
import sys
33

4+
import pandas as pd
5+
46
from lib.jira_conn import JiraAPIClient
7+
from database import (
8+
Database,
9+
ReportJiraQARequests
10+
)
11+
from utils.datetime_utils import DatetimeUtils as dt
12+
from utils.constants import FILTER_ID_ALL_REQUESTS_2022, MAX_RESULT
513

614

715
# JQL query All QA Requests since 2022 filter_id: 13856
8-
FILTER_ID_ALL_REQUESTS_2022 = "13856"
9-
# Fields needed
16+
# Extra fields needed
1017
STORY_POINTS = "customfield_10037"
1118
FIREFOX_RELEASE_TRAIN = "customfield_10155"
1219
ENGINEERING_TEAM = "customfield_10134"
1320
DEFAULT_COLUMNS = "id,key,status,created,summary,labels,assignee,"
14-
MAX_RESULT = "maxResults=100"
1521

1622
JQL_QUERY = 'jql=filter='
1723

@@ -32,6 +38,101 @@ def __init__(self):
3238
# API: Filters
3339
def filters(self):
3440
query = JQL_QUERY + FILTER_ID_ALL_REQUESTS_2022 + '&fields=' \
35-
+ DEFAULT_COLUMNS + STORY_POINTS + FIREFOX_RELEASE_TRAIN \
41+
+ DEFAULT_COLUMNS + ',' + STORY_POINTS + ',' \
42+
+ FIREFOX_RELEASE_TRAIN + ',' \
3643
+ ENGINEERING_TEAM + '&' + MAX_RESULT
44+
3745
return self.client.get_search(query)
46+
47+
48+
class JiraClient(Jira):
49+
def __init__(self):
50+
super().__init__()
51+
self.db = DatabaseJira()
52+
53+
def jira_qa_requests(self):
54+
payload = self.filters()
55+
print("This is the payload returning from filter")
56+
print(payload)
57+
58+
self.db.qa_requests_delete()
59+
60+
data_frame = self.db.report_jira_qa_requests_payload(payload)
61+
print(data_frame)
62+
63+
self.db.report_jira_qa_requests_insert(data_frame)
64+
65+
66+
class DatabaseJira(Database):
67+
68+
def __init__(self):
69+
super().__init__()
70+
self.db = Database()
71+
72+
def qa_requests_delete(self):
73+
""" Wipe out all test suite data.
74+
NOTE: we'll renew this data from Testrail every session."""
75+
print("Delete entries from db first")
76+
self.session.query(ReportJiraQARequests).delete()
77+
self.session.commit()
78+
79+
def report_jira_qa_requests_payload(self, payload):
80+
# Normalize the JSON data
81+
df = pd.json_normalize(payload, sep='_')
82+
83+
# Check if 'jira_assignee_username' exists
84+
# if not use 'alternative_assignee_emailAddress'
85+
if 'fields_assignee_emailAddress' not in df.columns:
86+
df['fields_assignee_emailAddress'] = df.get('fields_assignee', "None") # noqa
87+
else:
88+
df['fields_assignee_emailAddress'] = df['fields_assignee_emailAddress'].fillna("Not Assigned") # noqa
89+
90+
# Drop the alternative column if it exists
91+
if 'fields_assignee' in df.columns:
92+
df.drop(columns=['fields_assignee'], inplace=True)
93+
94+
# Select specific columns
95+
selected_columns = {
96+
'key': 'jira_key',
97+
'fields_summary': 'jira_summary',
98+
'fields_created': 'jira_created_at',
99+
'fields_customfield_10155_value': 'jira_firefox_release_train',
100+
'fields_customfield_10134_value': 'jira_engineering_team',
101+
'fields_customfield_10037': 'jira_story_points',
102+
'fields_status_name': 'jira_status',
103+
'fields_assignee_emailAddress': 'jira_assignee_username',
104+
'fields_labels': 'jira_labels'
105+
}
106+
107+
# Select specific columns
108+
df_selected = df[selected_columns.keys()]
109+
110+
# Rename columns
111+
df_selected = df_selected.rename(columns=selected_columns)
112+
113+
df_selected['jira_created_at'] = df_selected['jira_created_at'].apply(dt.convert_to_utc) # noqa
114+
115+
# Join list of labels into a single string
116+
df_selected['jira_labels'] = df_selected['jira_labels'].apply(lambda x: ','.join(x) if isinstance(x, list) else x) # noqa
117+
118+
# Convert NaN values to 0 and ensure the column is of type int
119+
df_selected['jira_story_points'] = df_selected['jira_story_points'].fillna(0).astype(int) # noqa
120+
121+
return df_selected
122+
123+
def report_jira_qa_requests_insert(self, payload):
124+
print(payload)
125+
126+
for index, row in payload.iterrows():
127+
print(row)
128+
report = ReportJiraQARequests(jira_key=row['jira_key'],
129+
jira_created_at=row['jira_created_at'].date(), # noqa
130+
jira_summary=row['jira_summary'], # noqa
131+
jira_firefox_release_train=row['jira_firefox_release_train'], # noqa
132+
jira_engineering_team=row['jira_engineering_team'], # noqa
133+
jira_story_points=row['jira_story_points'], # noqa
134+
jira_status=row['jira_status'], # noqa
135+
jira_assignee_username=row['jira_assignee_username'], # noqa
136+
jira_labels=row['jira_labels'])
137+
self.session.add(report)
138+
self.session.commit()

lib/jira_conn.py

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,32 +37,35 @@ def __send_request(self, method, query):
3737

3838
# Store all results
3939
all_results = []
40+
params = {}
4041

4142
headers = {"Content-Type": "application/json"}
4243

4344
# Pagination variables
44-
start_at = 0
4545
max_results = 100
46-
total = 1 # Initial value greater than start_at to enter the loop
46+
total = None
47+
params['startAt'] = 0
4748

48-
while start_at < total:
49+
while True:
4950
# Send GET request
5051
response = requests.get(
5152
url,
5253
headers=headers,
53-
auth=HTTPBasicAuth(self.user, self.password))
54-
55-
if response.status_code == 200:
56-
data = response.json()
57-
all_results.extend(data['issues'])
58-
total = data['total'] # Update total based on the response
59-
start_at += max_results # Move to the next page
60-
else:
61-
print(f"Failed to fetch data: {response.status_code}")
62-
print(response.text)
54+
auth=HTTPBasicAuth(self.user, self.password),
55+
params=params)
56+
57+
data = response.json()
58+
all_results.extend(data['issues'])
59+
if total is None:
60+
total = data['total']
61+
62+
# Increment the startAt parameter
63+
params['startAt'] += max_results
64+
65+
# Check if we've retrieved all results
66+
if params['startAt'] >= total:
6367
break
6468

6569
# Print the total number of issues retrieved
6670
print(f"Total issues retrieved: {len(all_results)}")
67-
print(data)
68-
return data
71+
return all_results

utils/constants.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,7 @@
1313
'issue-regression',
1414
'jira-qa-requests'
1515
]
16+
17+
# JQL query All QA Requests since 2022 filter_id: 13856
18+
FILTER_ID_ALL_REQUESTS_2022 = "13856"
19+
MAX_RESULT = "maxResults=100"

utils/datetime_utils.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import pytz
2+
13
from datetime import datetime, timedelta
24

35

@@ -16,6 +18,11 @@ def convert_epoch_to_datetime(int_epoch_date):
1618
ts = datetime.fromtimestamp(int_epoch_date)
1719
return ts.strftime(format_date)
1820

21+
def convert_to_utc(datetime_str):
22+
"""Convert datetime string with timezone offset to UTC."""
23+
dt = datetime.strptime(datetime_str, "%Y-%m-%dT%H:%M:%S.%f%z")
24+
return dt.astimezone(pytz.UTC)
25+
1926
def start_date(num_days, end_date=''):
2027
""" given num_days, calculate a start_date
2128
given an end_date (default: now), calculate a start date num_days

0 commit comments

Comments
 (0)