Home > other >  is there a mylyn connector for Gitlab?
is there a mylyn connector for Gitlab?

Time:11-28

I worked with bugzilla and Eclipse, and I used Mylyn to manage issues though Eclipse.

Now I use Gitlab and gitlab issues, I wonder if there is a mylyn connector for Gitlab ?

I knwow that there is this one : gitlab connector , but it is no more usable and I did not found another one.

Did someone face with the same problem and did find a solution ?

CodePudding user response:

After a while I can share my solution, maybe it will help others.

There is no Mylin connector for Gitlab that runs correctly. A solution could be to debug the buggy one but in fact Gitlab is not a powerfull tool to manage issues.

I chose to use Bugzilla at least for three points :

  • the bug workflow is easy to customize and this is an important feature to adapt the bug workflow to the company processes
  • Mylin connector for Bugzilla is avalaible since a long time and runs correctly
  • Bugzilla is still a reference tool

The first step is to define Bugzilla as the issues management tool, this is done through Gitlab UI and the documentation is here.

For me, if an external tool is used, the best is to desactivate Gitlab issues tracking. On your project, go to Settings->General->Visibility, project features and desactivate Issues.

Note: if Bugzilla and Gitlab are deployed on the same host, you have to accept request to localhost. On Gitlab administration, go to Settings->Network->Outbound requests, select the two options about local network.

After that, you can comment your commits with a message containing Ref #id where id is a bug id in Bugzilla. As with Gitlab issue, the commit will contain an hyperlink to the issue but the hyperlink will open Bugzilla bug page.

If you do not go further, you will lost a Gitlab feature : Gitlab issue references all commits related to it.

A solution to have a similar feature with Bugzilla is to add to bug a comment with an hyperlink to commits.

This could be achieve with a server hook, this is described here.

Note : each time you change the gitlab.rb file, do no forget to execute gitlab-ctl reconfigure.

The hook has to manage "standard" commit and merge commits.

The following python code could be seen as a starting point for a such hook. It assumes that development are done on branches named feature/id nd that commits comments contains a string Ref #id. Id is a bug id.

It could be improve:

  • to manage exceptions better
  • to manage more push cases
  • to check more rules such as :
    • the bug has to be in progess
    • the bug assignee has to be the git user who performs the push
    • the bugzilla project has to be the one for the Gitlab project
    • the bug is open on a version that is still under development or debug
    • ....
#!/usr/bin/env python3

import sys
import os
import fileinput
import glob
import subprocess
import requests

#
# Constants
#
G__GIT_CMD      =["git","rev-list","--pretty"]
G__SEP          ="commit "
G__NL           ='\n'
G__AUTHOR       ='Author'
G__AUTHOR_R     ='Author: '
G__DATE         ='Date'
G__DATE_R       ='Date:   '
G__C_MSG        ='message'
G__URL_S        ='https://<<gitlab server url>>/<<project>>/-/commit/'
G__MERGE_S      ='Merge: '
G__MERGE        ='Merge'
G__URL          ='URL'
G__BUGZ_URL     ='http://<<bugzilla url>>/rest/bug/{}/comment'
G__HEADERS      = {'Content-type': 'application/json'}
G__JSON         = {"Bugzilla_login":"<<bugzilla user>>","Bugzilla_password":"<<password>>","comment": "{}"}
G__JSON_MR      = {"Bugzilla_login":"<<bugzilla user>>","Bugzilla_password":"<<password>>","comment": "Merge request {}"}
G__COMMENT_ELEM = 'comment'
G__MSG_REF      ="Ref #"
G__MSG_REF_MR   ="feature/"
G__WHITE        =" "
G__APOS         ="'"

#
# Filters some parts of message that are empty
#
def filter_message_elements(message_elements):
    flag=False
    for message_element in message_elements:
        if len(message_element)!=0:
            flag=True
            
    return flag

#
# Add an element in commit dictionary.
#
# If this is a commit for a merge, an element is added.
#    
def add_commit_in_dict(commits_dict, temp_list, flag_merge):
    url = G__URL_S temp_list[0]

    commits_dict[temp_list[0]]={}    
    commits_dict[temp_list[0]][G__URL]=url 
        
    if False==flag_merge:
        commits_dict[temp_list[0]][G__AUTHOR]=temp_list[1].replace(G__AUTHOR_R,'')
        commits_dict[temp_list[0]][G__DATE]=temp_list[2].replace(G__DATE_R,'')
        commits_dict[temp_list[0]][G__C_MSG]=temp_list[3] 
    else:
        commits_dict[temp_list[0]][G__MERGE]=temp_list[1]
        commits_dict[temp_list[0]][G__AUTHOR]=temp_list[2].replace(G__AUTHOR_R,'')
        commits_dict[temp_list[0]][G__DATE]=temp_list[3].replace(G__DATE_R,'')
        commits_dict[temp_list[0]][G__C_MSG]=temp_list[4]    

#
# Fill commits data
#
def fills_commit_data(commits_dict, fileinput_line):
    params=fileinput_line[:-1].split()
    
    try:
        # Git command to get commits list
        cmd=G__GIT_CMD [params[1],"^" params[0]]
        rev_message = subprocess.run(cmd,stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
        
        # loop on commits
        messages_list=rev_message.stdout.split(G__SEP)        
        for message in messages_list:
            if len(message)==0:
                continue           
            message_elements = message.split(G__NL)  
            # filters empty message
            flag=filter_message_elements(message_elements)
            if not flag:
                continue
                
            # Extracts commit data and detects merge commit
            temp_list=[]
            flag_merge=False
            for message_element in message_elements: 
                text = message_element.strip()
                if 0!=len(text):
                    temp_list.append(text)
                    if -1!=text.find(G__MERGE):
                        flag_merge=True
            # adds the commit in commits dictionary
            add_commit_in_dict(commits_dict, temp_list, flag_merge)
          
    except Exception as inst:
        sys.exit(1)

#
# Extract the bug id from the commit message
#
def find_bug_id(message):
    issue_int=-1
    pos=message.find(G__MSG_REF)

    if pos==-1:
        sys.exit(1)
        
    issue_nb=message[pos len(G__MSG_REF):]
    pos2=issue_nb.find(G__WHITE)
    issue_nb=issue_nb[:pos2]
    try:
        issue_int=int(issue_nb)
    except ValueError:
        sys.exit(1)
    
    return(issue_int)
#
# Extract the bug id from the commit message
# in case of merge request
#
def find_bug_id_mr(message):
    issue_int=-1
    pos=message.find(G__MSG_REF_MR)    

    if pos==-1:
        sys.exit(1)
        
    issue_nb=message[pos len(G__MSG_REF_MR):]
    pos2=issue_nb.find(G__APOS)
    issue_nb=issue_nb[:pos2]
    try:
        issue_int=int(issue_nb)
    except ValueError:
        sys.exit(1)
    
    return(issue_int)
    
#
# Checks if the commit list contains a merge request commit
#    
def is_merge_request(commits_dict):
    flag=False
    
    for key in commits_dict:
        if G__MERGE in commits_dict[key]:
            flag=True
            break
            
    return flag

#
# Add a comment to a bug
#
def add_comment_to_bug( commit_data):

    bug_id = find_bug_id(commit_data[G__C_MSG])
    
    url = G__BUGZ_URL.format(str(bug_id))
    
    G__JSON[G__COMMENT_ELEM] = G__JSON[G__COMMENT_ELEM].format(commit_data[G__URL])
    response = requests.post(url, json=G__JSON, headers=G__HEADERS)

#
# add a comment in case of merge request
#
def add_mr_comment_to_bug(commits_dict):
    
    commit_data=None
    for key in commits_dict:
        if G__MERGE in commits_dict[key]:
            commit_data=commits_dict[key]
            break
   
    bug_id = find_bug_id_mr(commit_data[G__C_MSG])

    url = G__BUGZ_URL.format(str(bug_id))    

    G__JSON_MR[G__COMMENT_ELEM] = G__JSON_MR[G__COMMENT_ELEM].format(commit_data[G__URL])
    response = requests.post(url, json=G__JSON_MR, headers=G__HEADERS)
   
#
# Main program
#            
def main():

    # dictionary containing all commits
    commits_dict={}
    
    # loop on inputs referencing data changes
    for fileinput_line in sys.stdin:
        fills_commit_data(commits_dict, fileinput_line)
    
    # find if this is merge request or not
    flag_merge_request = is_merge_request(commits_dict)
    
    if False==flag_merge_request:
        # loop on commit to add comments to bugs
        for key in commits_dict.keys():
            add_comment_to_bug(commits_dict[key])
    else:
        # in case of merge request, only the merge commit has to be added
        # others commits have been processed before
        add_mr_comment_to_bug(commits_dict) 
         

if __name__ == "__main__":
    main()
  • Related