861 def staging_request(self, filename, normalize, data, password):
862 """
863 Upload a testing payload storage to a staging globaltag and create or update a jira issue
864
865 Parameters:
866 filename (str): filename of the testing payload storage file that should be uploaded
867 normalize (Union[bool, str]): if True the payload root files will be
868 normalized to have the same checksum for the same content, if
869 normalize is a string in addition the file name in the root file
870 metadata will be set to it
871 data (dict): a dictionary with the information provided by the user:
872
873 * task: category of globaltag, either main, online, prompt, data, mc, or analysis
874 * tag: the globaltag name
875 * request: type of request, either Update, New, or Modification. The latter two imply task == main because
876 if new payload classes are introduced or payload classes are modified then they will first be included in
877 the main globaltag. Here a synchronization of code and payload changes has to be managed.
878 If new or modified payload classes should be included in other globaltags they must already be in a release.
879 * pull-request: number of the pull request containing new or modified payload classes,
880 only for request == New or Modified
881 * backward-compatibility: description of what happens if the old payload is encountered by the updated code,
882 only for request == Modified
883 * forward-compatibility: description of what happens if a new payload is encountered by the existing code,
884 only for request == Modified
885 * release: the required release version
886 * reason: the reason for the request
887 * description: a detailed description for the globaltag manager
888 * issue: identifier of an existing jira issue (optional)
889 * user: name of the user
890 * time: time stamp of the request
891
892 password: the password for access to jira or the access token and secret for oauth access
893
894 Returns:
895 True if the upload and jira issue creation/upload was successful
896 """
897
898
899 data['tag'] = upload_global_tag(data['task'])
900 if data['tag'] is None:
901 data['tag'] = f"temp_{data['task']}_{data['user']}_{data['time']}"
902
903
904 if not self.has_globalTag(data['tag']):
905 if not self.create_globalTag(data['tag'], data['reason'], data['user']):
906 return False
907
908
909 B2INFO(f"Uploading testing database {filename} to globaltag {data['tag']}")
910 entries = []
911 if not self.upload(filename, data['tag'], normalize, uploaded_entries=entries):
912 return False
913
914
915 if data['issue']:
916 issue = data['issue']
917 else:
918 issue = jira_global_tag_v2(data['task'])
919 if issue is None:
920 issue = {"components": [{"name": "globaltag"}]}
921
922
923 if type(issue) is tuple:
924 description = issue[1].format(**data)
925 issue = issue[0]
926 else:
927 description = f"""
928|*Upload globaltag* | {data['tag']} |
929|*Request reason* | {data['reason']} |
930|*Required release* | {data['release']} |
931|*Type of request* | {data['request']} |
932"""
933 if 'pull-request' in data.keys():
934 description += f"|*Pull request* | \\#{data['pull-request']} |\n"
935 if 'backward-compatibility' in data.keys():
936 description += f"|*Backward compatibility* | \\#{data['backward-compatibility']} |\n"
937 if 'forward-compatibility' in data.keys():
938 description += f"|*Forward compatibility* | \\#{data['forward-compatibility']} |\n"
939 description += '|*Details* |' + ''.join(data['details']) + ' |\n'
940 if data['task'] == 'online':
941 description += '|*Impact on data taking*|' + ''.join(data['data_taking']) + ' |\n'
942
943
944 description += '\nPayloads\n||Name||Revision||IoV||\n'
945 for entry in entries:
946 description += f"|{entry.module} | {entry.revision} | ({entry.iov_str()}) |\n"
947
948
949 if type(issue) is dict:
950 issue["description"] = description
951 if "summary" in issue.keys():
952 issue["summary"] = issue["summary"].format(**data)
953 else:
954 issue["summary"] = f"Globaltag request for {data['task']} by {data['user']} at {data['time']}"
955 if "project" not in issue.keys():
956 issue["project"] = {"key": "BII"}
957 if "issuetype" not in issue.keys():
958 issue["issuetype"] = {"name": "Task"}
959 if data["task"] == "main":
960 issue["labels"] = ["TUPPR"]
961
962 B2INFO(f"Creating jira issue for {data['task']} globaltag request")
963 if isinstance(password, str):
964 response = requests.post('https://agira.desy.de/rest/api/latest/issue', auth=(data['user'], password),
965 json={'fields': issue})
966 else:
967 fields = {'issue': json.dumps(issue)}
968 if 'user' in data.keys():
969 fields['user'] = data['user']
970 if password:
971 fields['token'] = password[0]
972 fields['secret'] = password[1]
973 response = requests.post('https://b2-master.belle2.org/cgi-bin/jira_issue.py', data=fields)
974 if response.status_code in range(200, 210):
975 B2INFO(f"Issue successfully created: https://agira.desy.de/browse/{response.json()['key']}")
976 else:
977 B2ERROR('The creation of the issue failed: ' + requests.status_codes._codes[response.status_code][0])
978 return False
979
980
981 else:
982
983
984 new_issue_config = jira_global_tag_v2(data['task'])
985 if isinstance(new_issue_config, dict) and "assignee" in new_issue_config:
986 user = new_issue_config['assignee'].get('name', None)
987 if user is not None and isinstance(password, str):
988 response = requests.post(f'https://agira.desy.de/rest/api/latest/issue/{issue}/watchers',
989 auth=(data['user'], password), json=user)
990 if response.status_code in range(200, 210):
991 B2INFO(f"Added {user} as watcher to {issue}")
992 else:
993 B2WARNING(f"Could not add {user} as watcher to {issue}: {response.status_code}")
994
995 B2INFO(f"Commenting on jira issue {issue} for {data['task']} globaltag request")
996 if isinstance(password, str):
997 response = requests.post(f'https://agira.desy.de/rest/api/latest/issue/{issue}/comment',
998 auth=(data['user'], password), json={'body': description})
999 else:
1000 fields = {'id': issue, 'user': user, 'comment': description}
1001 if password:
1002 fields['token'] = password[0]
1003 fields['secret'] = password[1]
1004 response = requests.post('https://b2-master.belle2.org/cgi-bin/jira_issue.py', data=fields)
1005 if response.status_code in range(200, 210):
1006 B2INFO(f"Issue successfully updated: https://agira.desy.de/browse/{issue}")
1007 else:
1008 B2ERROR('The commenting of the issue failed: ' + requests.status_codes._codes[response.status_code][0])
1009 return False
1010
1011 return True
1012
1013