Skip to content

Commit

Permalink
Merge pull request #2 from jamasoftware-ps/relationshipConverterNew
Browse files Browse the repository at this point in the history
Relationship converter new
  • Loading branch information
trobinson-jama authored Jun 26, 2023
2 parents a11f7cd + 64a42d4 commit eedd587
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 122 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Ignore venv
venv/

# Ignore Python dependency files
*.pyc
__pycache__/
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ Please visit [dev.jamasoftware.com](http://dev.jamasoftware.com) for additional
Please note that this script is distrubuted as-is as an example and will likely require modification to work for your specific use-case. This example omits error checking. Jama Support will not assist with the use or modification of the script.

### Before you begin
- Install Python 2.7 or higher and the requests library. [Python](https://www.python.org/) and [Requests](http://docs.python-requests.org/en/latest/)
- Install Python 3.7 or higher. To install all dependencies from requirements.txt file, run pip3 install.
- [Python Download](https://www.python.org/)

### Setup
1. As always, set up a test environment and project to test the script.
Expand Down
216 changes: 95 additions & 121 deletions relationship_converter.py
Original file line number Diff line number Diff line change
@@ -1,173 +1,147 @@
import sys
import logging
import datetime
import os
from py_jama_rest_client.client import JamaClient, APIException

#######--CONFIG--#######
username = "username"
password = "password"
base_url = "{base_url}/rest/latest/"
project_id = 20183 # project ID to modify relationship types in
username = "exampleUsername"
password = "examplePassword"
client_id = "yourClientId"
client_secret = "yourClientSecret"
base_url = "https://yourBaseUrl"
project_id = 123 # project ID to modify relationship types in
oauth = True

# follow the examples below to convert relationships between other itemTypes in Jama

# example of converting all 'Related to' relationships between epics (upstream) and features (downstream) into
# 'Epic to Feature' relationships
# example of converting all 'Related to' relationships between requirements (upstream) and texts (downstream) into
# 'Verified By' relationships
epicToFeature = {}
epicToFeature.__setitem__("from_item_type_id", "89025") # epic itemType ID
epicToFeature.__setitem__("to_item_type_id", "89008") # feature itemType ID
epicToFeature.__setitem__("from_item_type_id", "24") # requirement itemType ID
epicToFeature.__setitem__("to_item_type_id", "33") # text itemType ID
epicToFeature.__setitem__("old_relationship_type", "Related to") # old relationship name
epicToFeature.__setitem__("new_relationship_type", "Epic to Feature") # new relationship name
epicToFeature.__setitem__("new_relationship_type", "Verified By") # new relationship name

# example of converting all 'Related to' relationships between features (upstream) and stories (downstream) into
# 'Feature to Story' relationships
featureToStory = {}
featureToStory.__setitem__("from_item_type_id", "89008") # feature itemType ID
featureToStory.__setitem__("to_item_type_id", "89014") # story itemType ID
featureToStory.__setitem__("old_relationship_type", "Related to") # old relationship name
featureToStory.__setitem__("new_relationship_type", "Feature to Story") # new relationship name
testcaseToRequirement = {}
testcaseToRequirement.__setitem__("from_item_type_id", "26") # test case itemType ID
testcaseToRequirement.__setitem__("to_item_type_id", "24") # requirement itemType ID
testcaseToRequirement.__setitem__("old_relationship_type", "Related to") # old relationship name
testcaseToRequirement.__setitem__("new_relationship_type", "Caused by") # new relationship name

#####--END CONFIG--#####

import requests
import json
import sys
logger = logging.getLogger(__name__)


def init_logging():
try:
os.makedirs('logs')
except FileExistsError:
pass
current_date_time = datetime.datetime.now().strftime("%Y-%m-%d %H_%M_%S")
log_file = 'logs/harm-severity-updater_' + str(current_date_time) + '.log'
logging.basicConfig(filename=log_file, level=logging.INFO)
logging.getLogger().addHandler(logging.StreamHandler(sys.stdout))


def main():
convert(epicToFeature)
convert(featureToStory)
convert(testcaseToRequirement)


def create_jama_client():
credentials = (username, password)
if oauth:
credentials = (client_id, client_secret)

global jama_client
jama_client = JamaClient(host_domain=base_url, credentials=credentials, oauth=oauth)

def convert(conversionMapping):

new_relationship_type_id = get_relationship_type_id(conversionMapping.get("new_relationship_type"))
if conversionMapping.get("old_relationship_type") == "Any":
def convert(conversion_mapping):

new_relationship_type_id = get_relationship_type_id(conversion_mapping.get("new_relationship_type"))
if conversion_mapping.get("old_relationship_type") == "Any":
old_relationship_type_id = -1
else:
old_relationship_type_id = get_relationship_type_id(conversionMapping.get("old_relationship_type"))
get_items_of_type( project_id,
conversionMapping.get("from_item_type_id"),
conversionMapping.get("to_item_type_id"),
new_relationship_type_id,
old_relationship_type_id)
old_relationship_type_id = get_relationship_type_id(conversion_mapping.get("old_relationship_type"))
get_items_of_type(project_id,
conversion_mapping.get("from_item_type_id"),
conversion_mapping.get("to_item_type_id"),
new_relationship_type_id,
old_relationship_type_id)


def get_relationship_type_id(type_name):
remaining_results = -1
start_index = 0

while remaining_results != 0:
start_at = "startAt=" + str(start_index)

url = base_url + "relationshiptypes?" + start_at
response = requests.get(url, auth=(username, password))
if response.status_code >= 400:
print response.text

json_response = json.loads(response.text)

if "pageInfo" in json_response["meta"]:
page_info = json_response["meta"]["pageInfo"]
total_results = page_info["totalResults"]
result_count = page_info["resultCount"]
remaining_results = total_results - (start_index + result_count)
start_index += 20
else:
remaining_results = 0;

relationship_types = json_response["data"]
for relationship_type in relationship_types:
if relationship_type["name"] == type_name:
return relationship_type["id"]

print "Unable to locate relationship type: " + str(type_name)
relationship_types = jama_client.get_relationship_types()
for relationship_type in relationship_types:
if relationship_type["name"] == type_name:
return relationship_type["id"]

print("Unable to locate relationship type: " + str(type_name))
sys.exit(1)


def get_items_of_type(project_id, from_type, to_type, new_type, old_type):
successes = 0
attempts = 0
remaining_results = -1
start_index = 0

print "Checking items:"

while remaining_results != 0:
start_at = "startAt=" + str(start_index)
print("Checking items:")

url = base_url + "abstractitems?" + start_at + "&project=" + str(project_id) + "&itemType=" + str(from_type)
response = requests.get(url, auth=(username, password))
if response.status_code >= 400:
print response.text
json_response = json.loads(response.text)
items = jama_client.get_abstract_items(project=[project_id], item_type=[int(from_type)])

page_info = json_response["meta"]["pageInfo"]
total_results = page_info["totalResults"]
result_count = page_info["resultCount"]
remaining_results = total_results - (start_index + result_count)
start_index += 20

items = json_response["data"]
for item in items:
for item in items:
try:
attempts += 1
sys.stdout.write("\r{0} / {1}".format(attempts, total_results))
sys.stdout.write("\r{0} / {1}".format(attempts, len(items)))
sys.stdout.flush()
successes += evaluate_relationships(project_id, item["id"], to_type, old_type, new_type)
successes += evaluate_relationships(jama_client, project_id, item, to_type, old_type, new_type)
except APIException as err:
logger.error(msg="Unable to process item {}.".format(item))

print("\nSuccessfully updated {0} relationships".format(successes))

print "\nSuccesfully updated {0} relationships".format(successes)

def evaluate_relationships(project_id, from_item, to_type, old_type, new_type):
def evaluate_relationships(jama_client, project_id, from_item, to_type, old_type, new_type):
relationships = jama_client.get_relationships(project_id)
successes = 0
remaining_results = -1
start_index = 0

while remaining_results != 0:
start_at = "startAt=" + str(start_index)
url = base_url + "items/" + str(from_item) + "/downstreamrelationships?" + start_at
response = requests.get(url, auth=(username, password))
if response.status_code >= 400:
print response.text
json_response = json.loads(response.text)

if "pageInfo" in json_response["meta"]:
page_info = json_response["meta"]["pageInfo"]
total_results = page_info["totalResults"]
result_count = page_info["resultCount"]
remaining_results = total_results - (start_index + result_count)
start_index += 20
else:
remaining_results = 0;

relationships = json_response["data"]
for relationship in relationships:

for relationship in relationships:
try:
to_item = relationship["toItem"]
relationship_type = relationship["relationshipType"]
if relationship_type != new_type and is_item_of_type(to_item, to_type):
if relationship_type != new_type and is_item_of_type(to_item, int(to_type)):
if old_type == -1 or old_type == relationship_type:
print "\nUpdating relationship " + str(relationship["id"]) + " from relationshipType " + str(old_type) + " to relationshipType " + str(new_type)
print("\nUpdating relationship " + str(relationship["id"]) + " from relationshipType " + str(
old_type) + " to relationshipType " + str(new_type))
successes += update_relationship(relationship["id"], from_item, to_item, new_type)
except APIException as err:
logger.error(msg="Unable to process relationship {}.".format(relationship["id"]))
logger.error(msg=str(err))

return successes


def is_item_of_type(item_id, type_id):
url = base_url + "abstractitems/" + str(item_id)
response = requests.get(url, auth=(username, password))
if response.status_code >= 400:
print response.text
json_response = json.loads(response.text)
returnValue = type_id == str(json_response["data"]["itemType"])
return returnValue
# return type_id == json_response["data"]["itemType"]
item = jama_client.get_item(item_id)
return type_id == int(item["itemType"])


def update_relationship(relationship_id, from_item, to_item, relationship_type):
payload = {
"fromItem": from_item,
"toItem": to_item,
"relationshipType": relationship_type
}
url = base_url + "relationships/" + str(relationship_id)
response = requests.put(url, json=payload, auth=(username, password))
if response.status_code >= 400:
print response.text
try:
jama_client.put_relationship(relationship_id=relationship_id, from_item=from_item["id"], to_item=to_item,
relationship_type=relationship_type)
return 1
except APIException as err:
logger.error(msg="Unable to update relationship {}".format(relationship_id))
logger.error(msg=str(err))
return 0
return 1


if __name__ == '__main__':
sys.exit(main())
init_logging()
create_jama_client()
main()
16 changes: 16 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
beautifulsoup4==4.9.3
bs4==0.0.1
certifi==2021.5.30
chardet==4.0.0
colorama==0.4.4
halo==0.0.31
idna==2.10
log-symbols==0.0.14
progress==1.5
py-jama-rest-client==1.17.1
requests==2.25.1
six==1.16.0
soupsieve==2.2.1
spinners==0.0.24
termcolor==1.1.0
urllib3==1.26.5

0 comments on commit eedd587

Please sign in to comment.