I recently got tasked with setting up a new Jenkins box within my organization, and having it work with our GitLab hosted Git repositories. We had previously had some rudimentary interaction between these two sides, with webhooks from our GitLab repo calling our Jenkins instance, using the GitLab Webhook Plugin. This worked alright, based on the branch specification in the Jenkins jobs it would perform the build/test when changes were made in the repo.
The downside to this method is that there isn’t any feedback in GitLab. I’ve recently worked on a project for my masters where we had a GitHub repo working with CircleCI, and with every commit to GitHub our build/test would run and we would get nice graphical statuses in GitHub. Below shows
It would sure be nice if I could get similar integration between GitLab and Jenkins. When I looked around at GitLab’s documentation, it mentioned that it supported connections to Jenkins, but only in the Enterprise Edition, which isn’t coming to our organization any time soon…bummer. It also mentioned that the Community Edition does work with GitLab’s own CI runner, but we have a bunch of other things that only run in Jenkins (we still have clearcase projects around here), so we couldn’t just move to that.
Luckily, while I was looking around for the Jenkins GitLab Webhook Plugin that we had used previously, I stumbled across the Jenkins GitLab Plugin. At first I thought it might just be another plugin that works similar to the webhook plugin, but after digging a bit deeper into the README on its GitHub Page, I realized that this was performing a similar service to what I was looking for!
To start the process, I installed Jenkins 2.7.2 as a service on windows (from the .msi installer), with the default plugins (includes the Git Plugin). I then installed the GitLab Plugin (version 1.4.0). While I’m naming versions, we’re currently running GitLab CE 8.11.2. The machine has Git 2.9.2 installed on it.
I next created a SSH key pair on the machine, which put the keys in C:\Users\MY_USER\.ssh\ (id_rsa for the private key and id_rsa.pub for the public key). I added the public key as a deploy key to my GitLab project(s). I then added my private key as a Jenkins Credential.
Once I had setup the ssh private key, which allows Jenkins to connect to the git host over ssh (i.e. git clone git@server:user/repo.git), I needed to setup API Access for Jenkins to get metadata from GitLab.
Once the API Access has been setup, we can configure the connection between Jenkins and GitLab. This happens in the Mange Jenkins -> Configure System menu.
Now that our connection between Jenkins and GitLab is setup, we need to create a job. I’ve only worked with freestyle jobs, so if you’re doing a pipeline you’ll be on your own from here on out.
We need to specify the name as “origin”, which will be used by the other sections. For the Refspec we need to input:
+refs/heads/*:refs/remotes/origin/* +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/*
I haven’t completely figured out how this works, but it seems to be correct for my use cases.
For the Branch Specifier we need
origin/${gitlabSourceBranch}
which will be filled in based on the web hook we’ll be setting up next.
That’s everything from the Jenkins side. Now we need to setup the GitLab side to trigger the builds. We’ll do this with webhooks, and we’ll need one per Jenkins job.
Now everything should be set! If you push a commit to the repository, you should see the Jenkins job start running. Once the job completes, you should see the status next to the commit in GitLab.
This setup works great for individual commits that are pushed into the repo. However, it also works fine for handling merge requests (despite some of the wording on the Jenkins GitLab Plugin’s readme page). I was able to have merge requests from separate branches in the same repo as well as from forked repos trigger builds and show the resulting status.
All in all, I’ve been very happy with the use of the Jenkins GitLab plugin to support CI between Jenkins and GitLab. It was definitely an unexpected bonus after reading about how you need the EE of GitLab to hook to Jenkins, apparently that isn’t completely true.
The one issue that I have with it is that the Jenkins jobs are hooked too closely to the GitLab integration. For instance, I can’t just click the Build Now button on a Jenkins job using the integration, as it can’t find the origin/${gitLabSourceBranch} in the repo, since that variable is only set when a webhook request comes in. It would be nice if I could try to re-build a failed build (some of our projects are, sadly, too complex for deterministic testing behavior), but that isn’t in the cards. I’ve made separate jobs for running manual (or scheduled builds), but their status doesn’t show up back in GitLab.
Edit 2018–01–19: Thanks to Chelsea Greger for pointing out that the issue I mentioned in the above paragraph (now quoted, I can’t figure out how to do a strike-through) can be overcome by setting the job up as a parameterized job, with a parameter for “gitLabSourceBranch” (default to “master” if desired). This allows the job to be manually run.