Programming Challenge Day 4 - GitLab

22 Sep 2016

Heads Up Before August 2018 Saber was known as "BugMuncher", so you'll see the name BugMuncher instead of Saber throughout these older posts. You can read more about the name change here - BugMuncher rebrands to Saber.

Day 4 - GitLab

GitLab seems to have very quickly come out of nowhere as a great contender to GitHub and Bitbucket for code hosting. I already have GitHub and Bitbucket integrations for BugMuncher, so of course I needed complete the holy trinity.

I deliberately planned the GitLab integration for Thursday, as Thursday mornings I go climbing with a friend, meaning I’d have less time for today’s integration. I thought GitLab was a good choice, as having already built GitHub and Bitbucket integrations I thought GitLab would be quite easy. It wasn’t.

Somewhat luckily, my climbing session didn’t happen this week, so I had a full day to throw at GitLab.

8:30 am

It’s the same old story, my first move is to look into GitLab’s developer documentation. Although I’d not worked with GitLab before, I knew they’d have a fully featured REST API, as without one they would never have been taken seriously as a GitHub competitor.

While they do have a good REST API, the documentation for it seems strangely hidden. In fact, here’s a good challenge for you: Make sure you’re not logged into GitLab, and go to and try to find the API documentation.

Anyway, once I finally found the documentation (protip: it’s under Enterprise Edition), I found what looked like a pretty standard REST API with OAuth2 support. While GitLab’s actual API documentation is pretty good, the documentation for their OAuth implementation is severely lacking. Eg: they never actually tell you what the API root URL is for their hosted version (it’s just, but I had to guess that).

Worse still, their documentation for OAuth shows access_token coming with refresh_token and expires_in parameters, which implies the access tokens will expire, and need refreshing. However, the docs don’t explicitly say this, nor do they explain how to refresh and access token.

Even more confusing, when I actually did get an access token from the API, it didn’t come with an expires_in parameter, just a refresh token. At that point I had to figure that access tokens don’t actually expire, and their docs are incorrect. Of course I couldn’t just make that assumption, so I decided to build the integration as if tokens don’t expire, and test a token I’d been granted in a few hours to make sure that was the case (it was).

9:00 am

Now that I had a handle on their shitty documentation, I set about building the back end. It wasn’t as simple as I’d hoped, as GitLab can be self-hosted, so I needed to support custom root URLs. I’d already done this my Jira integration, so I at least had a rough idea of what I was doing.

It took about 2 hours to get the back end completed with unit and integration tests.

11:00 am

The front end was the same story as the back end, mostly the same as the GitHub integration I’d already built, but with the addition of being able to specify the API’s root URL. I took an hour for lunch today, which is pretty long for me, and even so, I had the front end finished and ready to be tested on the staging server by 2:30 pm.

2:30 pm

The staging test didn’t show any problems, so it was onto the documentation and making it all live. Then as always, my last trick was to update the homepage to add GitLab to the ever-growing list of integrations. Everything was finished by 3:15 pm.

Total time taken: 5 hours 45 minutes

Not a fan of GitLab’s documentation, but then they do invite people to make pull requests and improve it, so maybe I should do that. The API itself is pretty good though, and even if I had gone climbing I think I still would have been able to get this one done today. Tomorrow is my last day, on which I’ll be tackling Basecamp.

- Matt

Get Meaningful Feedback from your Customers and Team

Discover Trends, Improve User Experience & Identify Bugs

Start my free trial

10 day free trial, no credit card required.