-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from jamasoftware-ps/relationshipConverterNew
Relationship converter new
- Loading branch information
Showing
4 changed files
with
119 additions
and
122 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Ignore venv | ||
venv/ | ||
|
||
# Ignore Python dependency files | ||
*.pyc | ||
__pycache__/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |