How to detect duplicate screens in Jira - part 5

I've recently introduced my ideas and firstsecond, third, and fourth version of the script for finding duplicate screens in Jira.

Here's the fifth version, which not only compares the screens but also the screen schemes.

Unfortunately, there’s no REST API method to get information about screen schemes for DC, so this part only works for cloud. If two screen schemes have the same or duplicate screens for all four issue operations (default, create, edit, view), they are considered as duplicate.

For example, if we have the first screen scheme defined like this:

  • default: Screen A

  • create: Screen B

and the second screen scheme defined like this:

  • default: Screen A*

  • create: Screen B,

if screen A and screen A* are considered as duplicate, the screen schemes are also considered as duplicate.

Python Script

import time
import requests
import hashlib
import argparse


def get_screen_schemes():
    start_at = 0
    max_results = 100
    screen_schemes = []
    while True:
        try:
            time.sleep(0.25)
            print(f"Getting screen schemes, 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/screenscheme",
                                    headers=headers,
                                    params=params,
                                    auth=(user, password))
            response.raise_for_status()
            response_data = response.json()
            screen_schemes.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 screen schemes. ({e})")
            exit(255)
    return screen_schemes


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_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_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_items_list_md5(list_to_encode):
    return hashlib.md5(str(list_to_encode).encode()).hexdigest()


def get_screen_scheme_title(screen_scheme_id, screen_scheme_name):
    return str(screen_scheme_id) + ": " + screen_scheme_name


def get_screen_title(screen_id, screen_name):
    return str(screen_id) + ": " + screen_name


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


def export_screen_schemes_groups(screen_schemes_groups):
    print(f"Exporting screen schemes groups")
    export_items_groups("screen_schemes.txt", screen_schemes_groups)


def export_screens_groups(screens_groups):
    print(f"Exporting screens groups")
    export_items_groups("screens.txt", screens_groups)


def export_tabs_groups(tabs_groups):
    print(f"Exporting tabs groups")
    export_items_groups("tabs.txt", tabs_groups)


def export_items_groups(filename, items_groups):
    with open(filename, 'a') as f:
        f.truncate(0)
        for item_group_key in items_groups:
            f.write(str(item_group_key) + "\n")
            for item_group_item in items_groups[item_group_key]:
                f.write(str(item_group_item) + "\n")
            f.write("\n\n")
    f.close()


def execute():
    screens_identifiers = {}

    tabs_groups = {}
    screens_groups = {}

    screens = get_screens()
    for screen in screens:
        screen_items_list = []
        tabs = get_tabs(screen["id"])
        for tab in tabs:
            tab_items_list = []
            fields = get_fields(screen["id"], tab["id"])
            for field in fields:
                tab_items_list.append(field["id"])
                screen_items_list.append(field["id"])

            tab_items_list.sort()
            tab_identifier = get_items_list_md5(tab_items_list)
            tab_title = get_tab_title(screen["id"], screen["name"], tab["id"], tab["name"])
            if tab_identifier in tabs_groups.keys():
                tabs_groups[tab_identifier].append(tab_title)
            else:
                tabs_groups[tab_identifier] = [tab_title]

        screen_items_list.sort()
        screen_identifier = get_items_list_md5(screen_items_list)
        screen_title = get_screen_title(screen["id"], screen["name"])
        if screen_identifier in screens_groups.keys():
            screens_groups[screen_identifier].append(screen_title)
        else:
            screens_groups[screen_identifier] = [screen_title]

        screens_identifiers[screen["id"]] = screen_identifier

    export_tabs_groups(tabs_groups)
    export_screens_groups(screens_groups)

    screen_schemes_groups = {}
    screen_schemes = get_screen_schemes()
    for screen_scheme in screen_schemes:
        screen_scheme_items_list = [screens_identifiers[screen_scheme["screens"]['default']],
                                    screens_identifiers[screen_scheme["screens"][
                                        'create' if 'create' in screen_scheme["screens"] else 'default'
                                    ]],
                                    screens_identifiers[screen_scheme["screens"][
                                        'edit' if 'edit' in screen_scheme["screens"] else 'default'
                                    ]],
                                    screens_identifiers[screen_scheme["screens"][
                                        'view' if 'view' in screen_scheme["screens"] else 'default'
                                    ]]]

        screen_scheme_identifier = get_items_list_md5(screen_scheme_items_list)
        screen_scheme_title = get_screen_scheme_title(screen_scheme["id"], screen_scheme["name"])
        if screen_scheme_identifier in screen_schemes_groups.keys():
            screen_schemes_groups[screen_scheme_identifier].append(screen_scheme_title)
        else:
            screen_schemes_groups[screen_scheme_identifier] = [screen_scheme_title]

    export_screen_schemes_groups(screen_schemes_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)')
args = parser.parse_args()

base_url = args.url
user = args.user
password = args.password

execute()

What's next?

I would like to look more into issue type screen schemes, whether there is a possibility to compare them too.

0 comments

Comment

Log in or Sign up to comment
TAGS
AUG Leaders

Atlassian Community Events