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()