From b091d07d7257dcbdf57018b79e716ffd2a7fb00e Mon Sep 17 00:00:00 2001 From: Frederik Benoist Date: Sat, 8 Jul 2023 17:58:02 +0200 Subject: [PATCH] script pour gitlab --- backit_gitlab.py | 281 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 backit_gitlab.py diff --git a/backit_gitlab.py b/backit_gitlab.py new file mode 100644 index 0000000..604b630 --- /dev/null +++ b/backit_gitlab.py @@ -0,0 +1,281 @@ +import requests +from fogbugz import FogBugz +import os +import urllib +import re +import base64 +import mimetypes +import time + +GITLAB_INSTANCE_URL = 'https://gitlab.com' +GITLAB_API_TOKEN = 'glpat-UkUD1NfVdpvyBACgzMDZ' +GITLAB_PROJECT_ID = 39832947 +OWNER = 'fbenoist68' +REPO = 'mobileportal' +S_FOGBUGZ_URL = 'https://mobileretail.fogbugz.com/' +S_EMAIL = 'frederik.benoist@gfi.fr' +S_PASSWORD = '6brOc-gAr6' +MAX_BUGS = 999 + +def delete_issue(project_id, issue_iid): + url = f'{GITLAB_INSTANCE_URL}/api/v4/projects/{project_id}/issues/{issue_iid}' + + headers = { + 'Private-Token': GITLAB_API_TOKEN + } + + response = requests.delete(url, headers=headers) + + if response.status_code == 204: + ##print(f'Issue with IID {issue_iid} deleted successfully.') + pass + else: + print(f'Failed to delete issue with IID {issue_iid}:', response.text) + +def delete_all_issues(project_id): + url = f'{GITLAB_INSTANCE_URL}/api/v4/projects/{project_id}/issues' + headers = { + 'Private-Token': GITLAB_API_TOKEN + } + + remaining_issues = True + + while remaining_issues: + response = requests.get(url, headers=headers) + + if response.status_code != 200: + print('Failed to retrieve issues:', response.text) + break + + issues = response.json() + + if len(issues) == 0: + # Il n'y a plus d'issues, la suppression est terminée + print('All issues deleted successfully.') + break + + for issue in issues: + delete_issue(project_id, issue['iid']) + + +def create_gitlab_issue(title, description): + headers = { + 'Private-Token': GITLAB_API_TOKEN + } + + data = { + 'title': title, + 'description': description + } + + url = f'{GITLAB_INSTANCE_URL}/api/v4/projects/{OWNER}%2F{REPO}/issues' + response = requests.post(url, json=data, headers=headers) + + if response.status_code == 201: + ##print('Issue created successfully.') + return response.json()['iid'] + else: + print('Failed to create issue:', response.text) + return None + +def create_gitlab_comment(issue_number, comment): + headers = { + 'Private-Token': GITLAB_API_TOKEN + } + + data = { + 'body': comment + } + + url = f'{GITLAB_INSTANCE_URL}/api/v4/projects/{OWNER}%2F{REPO}/issues/{issue_number}/notes' + response = requests.post(url, json=data, headers=headers) + + if response.status_code == 201: + ##print('Comment created successfully.') + return response.json()['id'] + else: + print('Failed to create comment:', response.text) + return None + +def upload_attachment_to_gitlab_project(filename, attachment_data): + #url = f'{GITLAB_INSTANCE_URL}/api/v4/projects/{OWNER}%2F{REPO}/uploads' + url = f'{GITLAB_INSTANCE_URL}/api/v4/projects/{GITLAB_PROJECT_ID}/uploads' + + # Encode les données binaires en base64 + attachment_data_base64 = base64.b64encode(attachment_data).decode('utf-8') + + # Determine the content type based on the file extension + mimetype, _ = mimetypes.guess_type(filename) + + files = { + 'file': (filename, attachment_data, mimetype or 'application/octet-stream') + } + + response = requests.post(url, files=files, headers={'Private-Token': GITLAB_API_TOKEN}) + + if response.status_code == 201: + ##print('Attachment uploaded successfully.') + + # Obtenir l'URL de téléchargement depuis la réponse + download_url = response.json().get('url') + return download_url + else: + print('Failed to upload attachment:', response.text) + return None + +def update_gitlab_comment(comment_id, body): + headers = { + 'Private-Token': GITLAB_API_TOKEN + } + + data = { + 'body': body + } + + url = f'{GITLAB_INSTANCE_URL}/api/v4/projects/{OWNER}%2F{REPO}/issues/comments/{comment_id}' + response = requests.put(url, json=data, headers=headers) + + if response.status_code == 200: + # # print('Comment updated successfully.') + pass + else: + print('Failed to update comment:', response.text) + +def get_issue_id(issue): + return int(issue['ixBug']) + +def get_event_id(event): + return int(event['ixBugEvent']) + +def main(): + # Utilisation de la fonction pour supprimer toutes les issues d'un projet spécifique + # delete_all_issues(GITLAB_PROJECT_ID) + + fb = FogBugz(S_FOGBUGZ_URL) + fb.logon(S_EMAIL, S_PASSWORD) + + resp = fb.search(q='type:"Cases"', cols='ixBug', max=MAX_BUGS) + + for case in sorted(resp.cases.findAll('case'), key=get_issue_id, reverse=False): + ixBug = int(case['ixBug']) + if ixBug >= 590: + time.sleep(1) # Pause d'une seconde + + print(ixBug) + + respBug = fb.search(q='%s' % ixBug, cols='sTitle,sPersonAssignedTo,sProject,sArea,sCategory,sPriority,events') + xmlBug = respBug.cases.findAll('case')[0] + + BACKUP_DIR = '/Users/fbenoist68/Code/python/fogbugz/fogbackup' + BACKUP_DIR += '/' + xmlBug.sProject.string if xmlBug.sProject.string else '' + + if not os.path.exists(BACKUP_DIR): + os.makedirs(BACKUP_DIR) + + BACKUP_DIR += '/' + str(xmlBug['ixBug']) + + if not os.path.exists(BACKUP_DIR): + os.makedirs(BACKUP_DIR) + + # Create GitLab issue + issue_title = f"[FogBugz #{ixBug}] {xmlBug.sTitle.string if xmlBug.sTitle.string else ''}" + issue_body = f"Assigned To: {xmlBug.sPersonAssignedTo.string}\n" + issue_body += f"Project: {xmlBug.sProject.string}\n" + issue_body += f"Area: {xmlBug.sArea.string}\n" + issue_body += f"Category: {xmlBug.sCategory.string}\n" + issue_body += f"Priority: {xmlBug.sPriority.string}\n" + + issue_number = create_gitlab_issue(issue_title, issue_body) + + if issue_number is not None: + # Create Gitea comment for each event in reverse !! + for event in sorted(xmlBug.events.findAll('event'), key=get_event_id, reverse=True): + bugEvent = {} + bugEvent['ixBugEvent'] = int(event['ixBugEvent']) + bugEvent['sVerb'] = event.sVerb.string if event.sVerb.string else '' + bugEvent['dt'] = event.dt.string if event.dt.string else '' + bugEvent['s'] = event.s.string if event.s.string else '' + bugEvent['sChanges'] = event.sChanges.string if event.sChanges.string else '' + bugEvent['evtDescription'] = event.evtDescription.string if event.evtDescription.string else '' + bugEvent['sPerson'] = event.sPerson.string if event.sPerson.string else '' + + if event.s and event.s.string: + bugEvent['s'] = event.s.string.encode('ascii', 'ignore').decode('utf-8') + else: + bugEvent['s'] = '' + + if event.sHtml and event.sHtml.string: + bugEvent['sHtml'] = event.sHtml.string.encode('ascii', 'ignore').decode('utf-8') + else: + bugEvent['sHtml'] = '' + + comment = f"Event ID: {bugEvent['ixBugEvent']}\n" + comment += f"Date: {bugEvent['dt']}\n" + comment += f"Person: {bugEvent['sPerson']}\n" + comment += f"Description: {bugEvent['evtDescription']}\n\n\n" + + # Afficher sHtml s'il n'est pas vide, sinon afficher s + content = bugEvent['sHtml'] if bugEvent['sHtml'] else bugEvent['s'] + comment += f"{content}" + + new_links = {} + + for att in event.rgAttachments: + # # print('Downloading attachment: ' + att.sFileName.string) + str1 = att.sURL.string + str2 = 'ixAttachment=' + loc1 = str1.find(str2) + len(str2) + loc2 = str1.find('&sFileName') + + str3 = ';sFileName=' + loc3 = str1.find(str3) + len(str3) + loc4 = str1.find('&sTicket') + + theURL = S_FOGBUGZ_URL # + att.sURL.string + theURL += 'default.asp?' + theURL += 'ixAttachment=' + str1[loc1:loc2] + theURL += '&pg=pgDownload&pgType=pgFile&sFilename=' + str1[loc3:loc4] + theURL += '&token=rnl0t87rp34rfg6q0u0rgbhe85v5r8' + + # fix the replace + newFileName = att.sFileName.string.replace('/', '') + newFileName = newFileName.replace(':', '') + newFileName = BACKUP_DIR + '/' + newFileName + # # print(newFileName) + urllib.request.urlretrieve(theURL, newFileName) + + with open(newFileName, 'rb') as attachment_file: + attachment_data = attachment_file.read() + + # # print('Uploading screenshot:', att.sFileName.string) + download_url = upload_attachment_to_gitlab_project(att.sFileName.string, attachment_data) + + if download_url: + # Stocker le nouveau lien avec l'ID de l'attachement comme clé + new_links[str1[loc1:loc2]] = download_url + + if new_links: + # Remplacer les liens d'attachement dans sHtml avec les nouvelles URLs + updated_sHtml = comment + + for att_id, download_url in new_links.items(): + # Utilisation d'une expression régulière pour trouver les liens img avec ixAttachment=574 + pattern = fr']*?ixAttachment={att_id}[^>]*>' + + # Testez si le motif correspond à la chaîne de texte + match = re.search(pattern, updated_sHtml) + + # Remplacement de tous les liens correspondant au modèle par le nouveau download_url + if match: + updated_sHtml = re.sub(pattern, f'', updated_sHtml) + else: + updated_sHtml += f'\n' + + comment_id = create_gitlab_comment(issue_number=issue_number, comment=updated_sHtml) + else: + comment_id = create_gitlab_comment(issue_number=issue_number, comment=comment) + + # # print('comment id',comment_id); + + fb.view(ixBug=ixBug) +main() \ No newline at end of file