How to detect duplicate screens in Jira - part 3

I've recently introduced my ideas and first and second version of the script for finding duplicate screens in Jira.

Here's the third version, which supports both DC and Cloud Jira. It was neccessary to implement a few changes:

  1. The endpoint for getting list of screens returns data in different format for DC / Cloud - it uses different key ("values" vs. "screens").
  2. This endpoint also returns screens for team-managed projects in Cloud, which is a little bit suprising. But there is no data for tabs and fields for team-managed screens, so I just ignore these. I didn't find any way how to get only screens for company-managed projects.

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)
            print(f"Getting screens, start_at = {start_at}, max_results = {max_results}")
            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()
            # DC response
            if 'screens' in response_data:
                screens.extend(response_data['screens'])
            # Cloud response
            if 'values' in response_data:
                screens.extend(response_data['values'])
            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):
    tabs = []
    try:
        time.sleep(0.25)
        print(f"Getting tabs for screen id {screen_id}")
        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})")
    return tabs


def get_screen_tab_fields(screen_id, tab_id):
    fields = []
    try:
        time.sleep(0.25)
        print(f"Getting fields for screen id {screen_id} and tab id {tab_id}")
        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})")
    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 (DC) or https://mytestjira.atlassian.net (Cloud)')
parser.add_argument('--user', nargs='?', required=True,
                    help='username (DC) or e-mail (cloud)')
parser.add_argument('--password', nargs='?', required=True, metavar='password',
                    help='Password (DC) or token (cloud)')
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?

In the beginning I've decided I will only compare tabs. I think it is time to change this decision and look more into comparison of the whole screens.

2 comments

Tomislav Tobijas _Koios_
Solutions Partner
Solution Partners provide consulting, sales, and technical services on Atlassian products.
October 14, 2024

@Hana Kučerová you might as well start writing a book on this topic 😄

All of this sounds promising - I'll definitely try this out on the cloud platform once I find the time.
Thanks for sharing!

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 16, 2024

Hi @Tomislav Tobijas _Koios_ :-) I'm afraid there won't be many readers... Still, as a former PHP developer, who doesn't have many programming opportunities right now, I'm kinda enjoying this topic :-).

Please, let me know, if you try it. Thank you.

Comment

Log in or Sign up to comment
TAGS
AUG Leaders

Atlassian Community Events