How to detect duplicate screens in Jira - part 2

In the previous article I've introduced my ideas and first version of the script for finding duplicate screens in Jira.

Here's the second version with these improvements:

  1. The code has been divided into the functions
  2. The function for getting screens (get_screens()) now supports pagination, which means you always process all screens, even though there are hundreds or thousands of screens
  3. The hard-coded parameters for Jira URL, username and password has been transformed into the command line arguments, so you need to run the script like this:
    py script.py --url=https://my.testjira.com --user=username --password=password --sort
    The last argument has impact on the sorting of tab fields. If you omit it, the tab fields will be left as is, if you add it, the tab fields will be sorted before the comparison. If tab fields are sorted, then the tabs are marked as duplicate if they only have the same set of fields. If they are not sorted, they also need to have the same order.

Python Script

import time
import requests
import hashlib
import argparse


def get_screens():
start_at = 0
max_results = 100
screens = []
while True:
try:
time.sleep(0.25)
params = {"startAt": start_at, "maxResults": max_results}
headers = {"Accept": "application/json"}
response = requests.get(f"{base_url}/rest/api/2/screens",
headers=headers,
params=params,
auth=(user, password))
response.raise_for_status()
response_data = response.json()
screens.extend(response_data['screens'])
if start_at + max_results >= response_data['total']:
break
start_at += max_results
except requests.exceptions.RequestException as e:
print(f"Failed to get screens. ({e})")
exit(255)
return screens


def get_screen_tabs(screen_id):
try:
time.sleep(0.25)
headers = {"Accept": "application/json"}
response = requests.get(f"{base_url}/rest/api/2/screens/{screen_id}/tabs",
headers=headers,
auth=(user, password))
response.raise_for_status()
tabs = response.json()
except requests.exceptions.RequestException as e:
print(f"Failed to get tabs for screen id {screen_id}. ({e})")
exit(255)
return tabs


def get_screen_tab_fields(screen_id, tab_id):
try:
time.sleep(0.25)
headers = {"Accept": "application/json"}
response = requests.get(f"{base_url}/rest/api/2/screens/{screen_id}/tabs/{tab_id}/fields",
headers=headers,
auth=(user, password))
response.raise_for_status()
fields = response.json()
except requests.exceptions.RequestException as e:
print(f"Failed to get fields for screen id {screen_id} and tab id {tab_id}. ({e})")
exit(255)
return fields


def get_screen_tab_identifier(screen_id, tab_id):
fields = get_screen_tab_fields(screen_id, tab_id)
fields_list = []
for field in fields:
fields_list.append(field["id"])
if sort:
fields_list.sort()
return hashlib.md5(str(fields_list).encode()).hexdigest()


def get_screen_tab_title(screen_id, screen_name, tab_id, tab_name):
return str(screen_id) + ": " + screen_name + ", " + str(tab_id) + ": " + tab_name


def get_screen_tabs_groups():
screen_tabs_groups = {}
screens = get_screens()
for screen in screens:
screen_id = screen["id"]
screen_name = screen["name"]
tabs = get_screen_tabs(screen_id)
for tab in tabs:
tab_id = tab["id"]
tab_name = tab["name"]
screen_tab_identifier = get_screen_tab_identifier(screen_id, tab_id)
screen_tab_title = get_screen_tab_title(screen_id, screen_name, tab_id, tab_name)
if screen_tab_identifier in screen_tabs_groups.keys():
screen_tabs_groups[screen_tab_identifier].append(screen_tab_title)
else:
screen_tabs_groups[screen_tab_identifier] = [screen_tab_title]
return screen_tabs_groups


def export_screen_tabs_groups(screen_tabs_groups):
filename = "tabs.txt"
with open(filename, 'a') as f:
f.truncate(0)
for screen_tabs_group_key in screen_tabs_groups:
f.write(str(screen_tabs_group_key) + "\n")
for screen_tabs_group_item in screen_tabs_groups[screen_tabs_group_key]:
f.write(str(screen_tabs_group_item) + "\n")
f.write("\n\n")
f.close()


def execute():
screen_tabs_groups = get_screen_tabs_groups()
export_screen_tabs_groups(screen_tabs_groups)


parser = argparse.ArgumentParser()
parser.add_argument('--url', nargs='?', required=True,
help='https://my.testjira.com')
parser.add_argument('--user', nargs='?', required=True,
help='username')
parser.add_argument('--password', nargs='?', required=True, metavar='password',
help='Password')
parser.add_argument('--sort', action='store_true',
help='Tab fields are sorted before comparison')
args = parser.parse_args()

base_url = args.url
user = args.user
password = args.password
sort = args.sort if args.sort else False

execute()

What's next?

I have plans to test the script for cloud too and if changes are needed, implement them.

4 comments

Raúl Carrera López September 8, 2024

Thank you very much, Hana, for this great contribution!

Hana Kučerová
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
September 10, 2024

Thank you, @Raúl Carrera López !

M Amine
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
September 19, 2024

I really appreciate this wonderful contribution!

Like Hana Kučerová likes this
Hana Kučerová
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
October 10, 2024

Thanks a lot, @M Amine !

Comment

Log in or Sign up to comment
TAGS
AUG Leaders

Atlassian Community Events