2018/11/25

A stupid way to semi automate steps for creating Merge Request on gitlab

Hello all. I have been away for writing a blog a while. Today, I would like to share how I semi automate steps for creating a MR on gitlab via command line.

Show me source codes

This is simply a script for filling information, for regular MR contents, and open a browser, which is a GUI for me to verify the contents, to fire MR. It, however, saves my time for filling boring and redundant MR contents. Here we go.

import subprocess

# Where is your project: NAMESPACE/REPO_NAME
MR_URL_ARGVS = {
    'NAMESPACE': 'mondwan',
    'REPO_NAME': 'scripts_for_creating_gitlab_mr',
}

# What will be the arguments for the MR URL
MR_SETTINGS = {
    # 'source_branch': 'feature_branch_1',
    'target_branch': 'master',
    # 'force_remove_source_branch': 'true',
    'title': 'New%20MR',
    # User ID in the gitlab
    'assignee_id': '1158561',
}

# The base url
MR_URL_BASE = \
    'https://gitlab.com/{NAMESPACE}/{REPO_NAME}/merge_requests/new?'.format(
        **MR_URL_ARGVS
    )

# Fill up source branch by current branch name via system git command
currentBranchName = subprocess.check_output(
    'git rev-parse --abbrev-ref HEAD'.split(' ')
).strip('\n')
MR_SETTINGS['source_branch'] = currentBranchName

# Create params list for the MR which will be pasted at the END of URL
getParams = '&'.join([
    'merge_request%%5B%s%%5D=%s' % (k, v) for k, v in MR_SETTINGS.items()
])

# The final url
url = MR_URL_BASE + getParams

# Launch a browser for given url with command line in ubuntu
print 'gnome-open "%s"' % url
Below explain how it works part by part.

How it works

If you studied carefully, gitlab accept a hand made URL for creating Merge request.
We can prefill whatever information in that MR if we can craft a specific URL.
Below is how to craft the first part of the URL, where variables are the namespace and repository name.

# Where is your project: NAMESPACE/REPO_NAME
MR_URL_ARGVS = {
    'NAMESPACE': 'mondwan',
    'REPO_NAME': 'scripts_for_creating_gitlab_mr',
}

# The base url
MR_URL_BASE = \
    'https://gitlab.com/{NAMESPACE}/{REPO_NAME}/merge_requests/new?'.format(
        **MR_URL_ARGVS
    )
The next question is how can I fill text into a field like title, contents, or source branch. Get Params is the answer.
For example, if you append string merge_request%5Btitle%5D=New%20MR at the end of the URL, title of that page will be New MR.
Below shows how to create a MR where title is New MR, assigned to an user with id 1158561, and set master to be the target branch

# What will be the arguments for the MR URL
MR_SETTINGS = {
    # 'source_branch': 'feature_branch_1',
    'target_branch': 'master',
    # 'force_remove_source_branch': 'true',
    'title': 'New%20MR',
    # User ID in the gitlab
    'assignee_id': '1158561',
}



# Create params list for the MR which will be pasted at the END of URL
getParams = '&'.join([
    'merge_request%%5B%s%%5D=%s' % (k, v) for k, v in MR_SETTINGS.items()
])
You may wonder how can I know what should be the key in order to fill up a field. The answer is looking them up via your browser’s console. For example, I would like to look up the key of source branch. I will see something like that in the console after watching the corresponding DOM element from the HTML.
As you can see in the diagram, we can locate merge_request[source_branch] in the HTML. That’s the key (source_branch) we need.
For me, it will be convenient if my script is able to fetch the name of current branch and put that in to the source branch field.

# Fill up source branch by current branch name via system git command
currentBranchName = subprocess.check_output(
    'git rev-parse --abbrev-ref HEAD'.split(' ')
).strip('\n')
MR_SETTINGS['source_branch'] = currentBranchName
Finally, I would like to launch a browser through command line by using gnome-open

 # The final url
url = MR_URL_BASE + getParams

# Launch a browser for given url with command line in ubuntu
print 'gnome-open "%s"' % url
Then, I can copy and paste that URL into the command line. A browser, for me it is Firefox, will be jumped out eventually in Ubuntu.

The repository for this script

Alternative

For advance developers, you may try to automate the entire process by using official APIs. For python developers, you can try to code them up with this cli library.
Although I have not tried to code this alternative, I guess this is much more time consuming than my approach, in term of time spent on development, listed above. One thing, however, I can sure is that this alternative is much more efficient than my approach.

Change logs

20181125: Add alternative section, refine some of the wordings