Forked from amarruedo/move-issues-from-jira-to-gitlab.py
Created
August 2, 2017 13:22
Revisions
-
amarruedo revised this gist
Apr 27, 2017 . 1 changed file with 44 additions and 11 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -38,8 +38,6 @@ headers={'Content-Type': 'application/json'}, ) users = requests.get( GITLAB_URL + 'api/v4/users', headers={'PRIVATE-TOKEN': GITLAB_TOKEN}, @@ -59,43 +57,78 @@ if not GITLAB_PROJECT_ID: raise Exception("Unable to find %s in gitlab!" % GITLAB_PROJECT) MILESTONES = {} for issue in jira_issues.json()['issues']: jiraKey = issue['key'] reporter = issue['fields']['reporter']['name'] milestone = '' released = False milestoneDescription = None releaseDate = None if issue['fields'].get('fixVersions'): milestone = (issue['fields']['fixVersions'])[0].get('name',0) released = (issue['fields']['fixVersions'])[0].get('released',0) milestoneDescription = (issue['fields']['fixVersions'])[0].get('description',0) releaseDate = (issue['fields']['fixVersions'])[0].get('releaseDate',0) # create milestones milestoneID = None if milestone != '' and milestone not in MILESTONES: milestoneID = requests.post( GITLAB_URL + 'api/v4/projects/%s/milestones' % GITLAB_PROJECT_ID, headers={'PRIVATE-TOKEN': GITLAB_TOKEN}, verify=VERIFY_SSL_CERTIFICATE, data={ 'title': milestone, 'description': milestoneDescription, 'due_date': releaseDate } ).json()['id'] MILESTONES[milestone] = milestoneID if released: res = requests.put( GITLAB_URL + 'api/v4/projects/%s/milestones/%s?state_event=close' % (GITLAB_PROJECT_ID , milestoneID), headers={'PRIVATE-TOKEN': GITLAB_TOKEN}, verify=VERIFY_SSL_CERTIFICATE ).json() assignee = '' if issue['fields'].get('assignee'): assignee = issue['fields']['assignee'].get('name',0) assignee_id = None if assignee != '': for user in users: if user['username'] == assignee: assignee_id = user['id'] break labels = issue['fields']['status']['statusCategory']['name'] + "," + issue['fields']['issuetype']['name'] + "," + issue['fields']['priority']['name'] title = issue['fields']['summary'].replace('#', 'FABRIC - ') description = None if issue['fields']['description'] != None: description = '```\n' + issue['fields']['description'] + '\n```' else: description = issue['fields']['description'] response = requests.post( GITLAB_URL + 'api/v4/projects/%s/issues' % GITLAB_PROJECT_ID, headers={'PRIVATE-TOKEN': GITLAB_TOKEN,'SUDO': GITLAB_USER_NAMES.get(reporter, reporter)}, verify=VERIFY_SSL_CERTIFICATE, data={ 'title': jiraKey + ' ' + title, 'description': description, 'created_at': issue['fields']['created'], 'assignee_id': assignee_id, 'milestone_id': MILESTONES.get(milestone, None), 'labels': labels } ).json() gl_issue = response['id'] if issue['fields']['status']['statusCategory']['name'] == "Done": res = requests.put( -
amarruedo revised this gist
Apr 26, 2017 . 1 changed file with 47 additions and 8 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -2,6 +2,7 @@ from requests.auth import HTTPBasicAuth import re from StringIO import StringIO import urllib JIRA_URL = 'https://your-jira-url.tld/' JIRA_ACCOUNT = ('jira-username', 'jira-password') @@ -31,16 +32,24 @@ } jira_issues = requests.get( JIRA_URL + 'rest/api/2/search?jql=project=%s&maxResults=10000' % JIRA_PROJECT, auth=HTTPBasicAuth(*JIRA_ACCOUNT), verify=VERIFY_SSL_CERTIFICATE, headers={'Content-Type': 'application/json'}, ) # get gitlab users to match issue asignees # since in my case users in Gitlab and Jira are the same (LDAP) the match is straight forward users = requests.get( GITLAB_URL + 'api/v4/users', headers={'PRIVATE-TOKEN': GITLAB_TOKEN}, verify=VERIFY_SSL_CERTIFICATE, ).json() if not GITLAB_PROJECT_ID: # find out the ID of the project. for project in requests.get( GITLAB_URL + 'api/v4/projects', headers={'PRIVATE-TOKEN': GITLAB_TOKEN}, ).json(): if project['path_with_namespace'] == GITLAB_PROJECT: @@ -51,19 +60,49 @@ raise Exception("Unable to find %s in gitlab!" % GITLAB_PROJECT) for issue in jira_issues.json()['issues']: reporter = issue['fields']['reporter']['name'] assignee = '' if issue['fields'].get('assignee'): assignee = issue['fields']['assignee'].get('name',0) # match asignee # all asginees must have proper acces rigths in the gitlab repository, otherwise it will fail assignee_id = None if assignee != '': for user in users: if user['username'] == assignee: assignee_id = user['id'] break # jira issue status, type and priority as labels in gitlab issue # this is usefull in the gitlab issue board labels = issue['fields']['status']['statusCategory']['name'] + "," + issue['fields']['issuetype']['name'] + "," + issue['fields']['priority']['name'] response = requests.post( GITLAB_URL + 'api/v4/projects/%s/issues' % GITLAB_PROJECT_ID, headers={'PRIVATE-TOKEN': GITLAB_TOKEN,'SUDO': GITLAB_USER_NAMES.get(reporter, reporter)}, verify=VERIFY_SSL_CERTIFICATE, data={ 'title': issue['fields']['summary'], 'description': issue['fields']['description'], 'created_at': issue['fields']['created'], 'assignee_id': assignee_id, 'labels': labels } ).json() # close all gitlab issues marked as Done in Jira # I use gitlab root user token so every issue appears closed by the admin user # once every Done issue is closed, I remove "Done" label in gitlab project since it is not usefull anymore. gl_issue = response['id'] if issue['fields']['status']['statusCategory']['name'] == "Done": res = requests.put( GITLAB_URL + 'api/v4/projects/%s/issues/%s?state_event=close' % (GITLAB_PROJECT_ID , response['iid']), headers={'PRIVATE-TOKEN': GITLAB_TOKEN}, verify=VERIFY_SSL_CERTIFICATE ).json() # get comments and attachments issue_info = requests.get( -
florisb revised this gist
Sep 23, 2016 . 1 changed file with 48 additions and 83 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -8,8 +8,6 @@ # the JIRA project ID (short) JIRA_PROJECT = 'PRO' GITLAB_URL = 'http://your-gitlab-url.tld/' # this token will be used whenever the API is invoked and # the script will be unable to match the jira's author of the comment / attachment / issue # this identity will be used instead. @@ -20,31 +18,30 @@ # based on the project name. GITLAB_PROJECT_ID = None # set this to false if JIRA / Gitlab is using self-signed certificate. VERIFY_SSL_CERTIFICATE = True # IMPORTANT !!! # make sure that user (in gitlab) has access to the project you are trying to # import into. Otherwise the API request will fail. # jira user name as key, gitlab as value # if you want dates and times to be correct, make sure every user is (temporarily) admin GITLAB_USER_NAMES = { 'jira': 'gitlab', } jira_issues = requests.get( JIRA_URL + 'rest/api/2/search?jql=project=%s+&maxResults=10000' % JIRA_PROJECT, auth=HTTPBasicAuth(*JIRA_ACCOUNT), verify=VERIFY_SSL_CERTIFICATE, headers={'Content-Type': 'application/json'} ) if not GITLAB_PROJECT_ID: # find out the ID of the project. for project in requests.get( GITLAB_URL + 'api/v3/projects', headers={'PRIVATE-TOKEN': GITLAB_TOKEN}, ).json(): if project['path_with_namespace'] == GITLAB_PROJECT: GITLAB_PROJECT_ID = project['id'] @@ -54,16 +51,17 @@ raise Exception("Unable to find %s in gitlab!" % GITLAB_PROJECT) for issue in jira_issues.json()['issues']: reporter = issue['fields']['reporter']['name'] gl_issue = requests.post( GITLAB_URL + 'api/v3/projects/%s/issues' % GITLAB_PROJECT_ID, headers={'PRIVATE-TOKEN': GITLAB_TOKEN,'SUDO': GITLAB_USER_NAMES.get(reporter, reporter)}, verify=VERIFY_SSL_CERTIFICATE, data={ 'title': issue['fields']['summary'], 'description': issue['fields']['description'], 'created_at': issue['fields']['created'] } ).json()['id'] @@ -80,85 +78,52 @@ note_add = requests.post( GITLAB_URL + 'api/v3/projects/%s/issues/%s/notes' % (GITLAB_PROJECT_ID, gl_issue), headers={'PRIVATE-TOKEN': GITLAB_TOKEN,'SUDO': GITLAB_USER_NAMES.get(author, author)}, verify=VERIFY_SSL_CERTIFICATE, data={ 'body': comment['body'], 'created_at': comment['created'] } ) if len(issue_info['fields']['attachment']): for attachment in issue_info['fields']['attachment']: author = attachment['author']['name'] _file = requests.get( attachment['content'], auth=HTTPBasicAuth(*JIRA_ACCOUNT), verify=VERIFY_SSL_CERTIFICATE, ) _content = StringIO(_file.content) file_info = requests.post( GITLAB_URL + 'api/v3/projects/%s/uploads' % GITLAB_PROJECT_ID, headers={'PRIVATE-TOKEN': GITLAB_TOKEN,'SUDO': GITLAB_USER_NAMES.get(author, author)}, files={ 'file': ( attachment['filename'], _content ) }, verify=VERIFY_SSL_CERTIFICATE ) del _content # now we got the upload URL. Let's post the comment with an # attachment requests.post( GITLAB_URL + 'api/v3/projects/%s/issues/%s/notes' % (GITLAB_PROJECT_ID, gl_issue), headers={'PRIVATE-TOKEN': GITLAB_TOKEN,'SUDO': GITLAB_USER_NAMES.get(author, author)}, verify=VERIFY_SSL_CERTIFICATE, data={ 'body': file_info.json()['markdown'], 'created_at': attachment['created'] } ) print "created issue #%s" % gl_issue print "imported %s issues from project %s" % (len(jira_issues.json()['issues']), JIRA_PROJECT) -
toudi revised this gist
Oct 2, 2015 . 1 changed file with 10 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -92,7 +92,10 @@ with requests.Session() as s: token = re.search( RE_TOKEN, s.get( GITLAB_URL + 'users/sign_in', verify=VERIFY_SSL_CERTIFICATE ).content ).group('token') signin = s.post( @@ -109,7 +112,10 @@ } ) html = s.get( GITLAB_URL + '%s/issues/%s' % (GITLAB_PROJECT, gl_issue), verify=VERIFY_SSL_CERTIFICATE ).content token = re.search(RE_TOKEN, html).group('token') @@ -134,7 +140,8 @@ attachment['filename'], _content ) }, verify=VERIFY_SSL_CERTIFICATE ) del _content -
toudi created this gist
Oct 1, 2015 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,157 @@ import requests from requests.auth import HTTPBasicAuth import re from StringIO import StringIO JIRA_URL = 'https://your-jira-url.tld/' JIRA_ACCOUNT = ('jira-username', 'jira-password') # the JIRA project ID (short) JIRA_PROJECT = 'PRO' GITLAB_URL = 'http://your-gitlab-url.tld/' # this is needed for importing attachments. The script will login to gitlab under the hood. GITLAB_ACCOUNT = ('gitlab-username', 'gitlab-password') # this token will be used whenever the API is invoked and # the script will be unable to match the jira's author of the comment / attachment / issue # this identity will be used instead. GITLAB_TOKEN = 'get-this-token-from-your-profile' # the project in gitlab that you are importing issues to. GITLAB_PROJECT = 'namespaced/project/name' # the numeric project ID. If you don't know it, the script will search for it # based on the project name. GITLAB_PROJECT_ID = None # set this to false if JIRA / Gitlab is using self-signed certificate. VERIFY_SSL_CERTIFICATE = False # IMPORTANT !!! # make sure that user (in gitlab) has access to the project you are trying to # import into. Otherwise the API request will fail. GITLAB_USER_TOKENS = { 'jira-username': 'gitlab-private-token-for-this-user', } RE_TOKEN = "<meta content=\"(?P<token>.*)\" name=\"csrf-token\"" jira_issues = requests.get( JIRA_URL + 'rest/api/2/search?jql=project=%s+AND+resolution=Unresolved+ORDER+BY+priority+DESC&maxResults=10000' % JIRA_PROJECT, auth=HTTPBasicAuth(*JIRA_ACCOUNT), verify=VERIFY_SSL_CERTIFICATE, headers={'Content-Type': 'application/json'} ) if not GITLAB_PROJECT_ID: # find out the ID of the project. for project in requests.get( GITLAB_URL + 'api/v3/projects', headers={'PRIVATE-TOKEN': GITLAB_TOKEN}, verify=VERIFY_SSL_CERTIFICATE ).json(): if project['path_with_namespace'] == GITLAB_PROJECT: GITLAB_PROJECT_ID = project['id'] break if not GITLAB_PROJECT_ID: raise Exception("Unable to find %s in gitlab!" % GITLAB_PROJECT) for issue in jira_issues.json()['issues']: reporter = issue['fields']['reporter']['name'] gl_issue = requests.post( GITLAB_URL + 'api/v3/projects/%s/issues' % GITLAB_PROJECT_ID, headers={'PRIVATE-TOKEN': GITLAB_USER_TOKENS.get(reporter, GITLAB_TOKEN)}, verify=VERIFY_SSL_CERTIFICATE, data={ 'title': issue['fields']['summary'], 'description': issue['fields']['description'] } ).json()['id'] # get comments and attachments issue_info = requests.get( JIRA_URL + 'rest/api/2/issue/%s/?fields=attachment,comment' % issue['id'], auth=HTTPBasicAuth(*JIRA_ACCOUNT), verify=VERIFY_SSL_CERTIFICATE, headers={'Content-Type': 'application/json'} ).json() for comment in issue_info['fields']['comment']['comments']: author = comment['author']['name'] note_add = requests.post( GITLAB_URL + 'api/v3/projects/%s/issues/%s/notes' % (GITLAB_PROJECT_ID, gl_issue), headers={'PRIVATE-TOKEN': GITLAB_USER_TOKENS.get(author, GITLAB_TOKEN)}, verify=VERIFY_SSL_CERTIFICATE, data={ 'body': comment['body'] } ) if len(issue_info['fields']['attachment']): # !!! HACK !!! obtain a session to gitlab in order to get a secret csrftoken with requests.Session() as s: token = re.search( RE_TOKEN, s.get(GITLAB_URL + 'users/sign_in').content ).group('token') signin = s.post( GITLAB_URL + 'users/sign_in', headers={ "Referer": GITLAB_URL }, verify=VERIFY_SSL_CERTIFICATE, data={ 'authenticity_token': token, 'user[login]': GITLAB_ACCOUNT[0], 'user[password]': GITLAB_ACCOUNT[1], 'user[remember_me]': 0 } ) html = s.get(GITLAB_URL + '%s/issues/%s' % (GITLAB_PROJECT, gl_issue)).content token = re.search(RE_TOKEN, html).group('token') for attachment in issue_info['fields']['attachment']: author = attachment['author']['name'] _file = requests.get( attachment['content'], auth=HTTPBasicAuth(*JIRA_ACCOUNT), verify=VERIFY_SSL_CERTIFICATE, ) _content = StringIO(_file.content) file_info = s.post( GITLAB_URL + '%s/uploads' % GITLAB_PROJECT, headers={ 'X-CSRF-Token': token, }, files={ 'file': ( attachment['filename'], _content ) } ) del _content # now we got the upload URL. Let's post the comment with an # attachment requests.post( GITLAB_URL + 'api/v3/projects/%s/issues/%s/notes' % (GITLAB_PROJECT_ID, gl_issue), headers={'PRIVATE-TOKEN': GITLAB_USER_TOKENS.get(author, GITLAB_TOKEN)}, verify=VERIFY_SSL_CERTIFICATE, data={ 'body': '[%s](%s)' % ( attachment['filename'], file_info.json()['link']['url'] ) } ) s.get(GITLAB_URL + 'users/sign_out')