Skip to content

Instantly share code, notes, and snippets.

@secretrob
Forked from mvisonneau/gitlab_to_jira.py
Last active March 28, 2024 10:33
Show Gist options
  • Save secretrob/b11791f19bc8f72a9ca87943e283b3c4 to your computer and use it in GitHub Desktop.
Save secretrob/b11791f19bc8f72a9ca87943e283b3c4 to your computer and use it in GitHub Desktop.
GitLab to Jira issue sync
#!/usr/bin/env python
import requests
import gitlab
from jira import JIRA
import urllib3
import json
## Disable urllib3 ssl checks warnings
urllib3.disable_warnings( urllib3.exceptions.InsecureRequestWarning )
##Fill out PROJECT, TOKEN, URL. PROJECT is setup currently as a group name. It will get all issues in a group. URL needs trailing /
## GitLab config
GITLAB_PROJECT = ''
GITLAB_TOKEN = ''
GITLAB_URL = ''
GITLAB_PROJECT_ID = None
GITLAB_IID = None
VERIFY_SSL_CERTIFICATE = True
## Fill out URL, PROJECT, USER, PASS
## JIRA config
JIRA_URL = ''
JIRA_PROJECT = ''
JIRA_USER = ''
JIRA_PASSWORD = ''
JIRA_LABELS = []
## Connect onto GitLab
gitlab = gitlab.Gitlab( GITLAB_URL, GITLAB_TOKEN, api_version=4 )
## Connect onto JIRA
jira = JIRA( JIRA_URL, basic_auth=( JIRA_USER, JIRA_PASSWORD ), options={ 'verify': False } )
## Get GitLab project
gl_group = gitlab.groups.get( GITLAB_PROJECT )
#gl_project = gitlab.projects.get( GITLAB_PROJECT )
## Lookup available transitions for an issue
#print jira.transitions( jira.issue( 'PROJECT-ISSUEID' ) )
## List project issues
for issue in gl_group.issues.list(per_page=150):
#for issue in gl_project.issues.list( all=True ):
found_issues = jira.search_issues( 'project='+JIRA_PROJECT+' AND summary ~ \''+ issue.title.replace( "'", "\\'" ).replace( "-", "" ) +'\'')
if len( found_issues ) == 0:
print '-> Creating issue : %s' % issue.title
author = json.loads(json.dumps(issue.author))
times = json.loads(json.dumps(issue.time_stats))
print "Est: " + str(times['human_time_estimate']) + "\nSpend: " + str(times['human_total_time_spent'])
GITLAB_IID = issue.iid
GITLAB_PROJECT_ID = issue.project_id
issue_dict = {
'project': JIRA_PROJECT,
'summary': issue.title,
'description': "Created by " + author['name'] + " at " + issue.created_at + " :\n" + issue.description if issue.description else "" + "\n" + issue.web_url + "\n\n" + "Est: " + str(times['human_time_estimate']) + "\nSpend: " + str(times['human_total_time_spent']),
'issuetype': { 'name': 'Task' }
}
if len(issue.assignees) > 0:
if 'username' in issue.assignees[0]:
issue_dict['assignee'] = { 'name': issue.assignees[0]['username'] }
jira_issue = jira.issue( jira.create_issue( fields = issue_dict ) )
jira_issue.update( fields = { "labels": JIRA_LABELS } )
print '--> Created issue in Jira : %s' % str(jira_issue)
if issue.state != 'opened':
print '--> Closing issue in Jira'
jira.transition_issue( jira_issue, '31' )
notes = requests.get(
GITLAB_URL + 'api/v4/projects/%s/issues/%s/notes' % (GITLAB_PROJECT_ID,GITLAB_IID),
headers={'PRIVATE-TOKEN': GITLAB_TOKEN},
verify=VERIFY_SSL_CERTIFICATE,
).json()
for note in notes:
note = json.loads(json.dumps(note))
if not note['system']:
comment = jira.add_comment( jira_issue, "Comment from " + note['author']['name'] + " at " + note['created_at'] + " :\n" + note['body'])
print '--> Added comment from %s on issue' % note['author']['name']
else:
print '--> Found JIRA issue ' + str(found_issues[0]) + ' for GL issue : ' + issue.title
@secretrob
Copy link
Author

I found this script and needed it, so I fixed the issues with the current (June 2019) apis to make it run.

@mysiki
Copy link

mysiki commented Jun 23, 2020

Hey, I also need the same script, using your script, it's work ;). I focus on project (not group).

I need to add some change in order to avoid error in Jira serach filter :

    search_filter = 'project='+JIRA_PROJECT+' AND summary ~ \''+ issue.title.replace( "'", "\\'" ).replace( "[", " " ).replace( ">", " " ).replace( "]", " " ).replace( "!", " " ) +'\''
    print '\n Search : %s' %search_filter
   found_issues = jira.search_issues( search_filter )
  • '-' work find in jira search
  • '-->' DO not work (-> OK, <- OK, <-- OK, -- OK), need to be replace by space.
  • '!' is not allow in search'
  • '[' and ']' are not allow

In general, replace it with space instead of "", because filter not work. Example : docker-compose, filter dockercompose not match but filter docker compose match.

@rluvaton
Copy link

Great script!
Are you planning to update the script to support python 3?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment