Hi! I’ve been working with GitLab (currently 11.6.10-ee) in an enterprise setting for about 6 months now. Here are some tips before starting with GitLab CI.
1. Go with Jenkins instead
GitLab has received a lot of hype recently and I really wanted to use it. But now I regret it and I wish I’d gone with Jenkins instead.
The CI engine lacks (or used to lack) a lot of features that I already took for granted, like: includes (introduced in 11.4), pipeline runtime parameters (in 10.8) and limiting concurrent pipelines of the same branch to 1 (still under discussion).
In Gitlab’s favor, I must say that it’s really robust and has some nice features. For example, docker:dind service (docker in docker) is really robust and easy to use in pipelines. Gitlab CI also documents clearly what it can or cannot do. I just wish I read some of that documentation before proceeding.
2. Get a really short haircut
A combination of YAML and a GitLab interpreter is extremely frustrating. You might think you’re well off if you perfectly understand standard YAML multiline operators |, ,|-, >, >-.
Unfortunately, this is not the case.
Syntax is a GitLab-specific flavor of YAML, which will make you pull your hair out sometimes.
Therefore I wish I invested in a really short haircut before starting with GitLab CI.
Don’t try this at home, kids
- Single echo command that outputs to multiple lines
- Bash for loop on multiple lines without spamming semicolons
- Set +/- u/e in bash YAML template (.hidden_job: &gonnaignoremodes)
3. Forget about access control
If you use GitLab CI you are clearly one lucky unicorn in this industry.
Access control is for dinosaurs.
If you ever think about access control, stop thinking about access control and think awesome instead.
Furthermore, when a dinosaur asks you to grant the enterprise site reliability engineering (or ops) team role-based access to deploy apps to staging or production, make them global admins. They’ll be happy with that.
In GitLab, variables have exactly 2 modes. Either they’re protected and available in protected branches, or they’re not protected at all. This is easy to solve by elevating all ops people in admin roles and keeping those dev unicorns at bay with developer level access. I mean, why would a developer ever need access to the master branch?
4. Avoid shared deployment processes
GitLab CI currently allows you to include a remote YAML file as your pipeline definition. However, you may only include one file that does not have nested includes (before version 11.7).
A remote file include does not support authentication. You may define YAML templates (.) and anchors (&). However, you may only reference templates and anchors in the same file. In other words, you may not include templates or anchors. Instead, you must resolve them on the remote file before including them. Without passing any parameters to include.
The outcome is that you can't define 2 alternative build jobs, for example, from which the end user may choose, but only one.
In addition to that, GitLab CI works in stages. A pipeline must define stages (build, test, deploy) and jobs that are run in those stages. If you define a stage without a job, the pipeline crashes. If you define a job that is not in any stage, the pipeline crashes.
This could happen for example if the pipeline template defines a code analysis job but the end users don’t include the stage as their editor already does the same job better.
A dinosaur might of course argue that they then deserve to burn in hell like wrong-minded heretics. I would suspect that we don’t all agree on that though.
Forget about shared pipelines or jobs
If you do not believe in one exact size that fits all, then forget about shared pipelines or jobs. On the other hand though, we’re microservice unicorns and our snowflake applications do not have any shared steps in their pipelines so who cares.
(Psst. Shared release processes are for dinosaurs.)
Workaround (if you are a dinosaur and insist on sharing)
Write code that generates a different YAML file for each possible combination of central job templates and uploads them onto an artifact storage. The end users may then include their favorite pipeline from there.
Or use sed. Sed is always amazing.
Not to say sed is different to code. Sed is code. Sed is everything.
5. Watch Inception
In addition to being a good movie, Inception will give you the essential mindset for wrapping other tools under your GitLab pipeline.
For example, it doesn’t matter how flawed the includes are if you’re only invoking Ansible that further includes all your favorite roles from your organization’s private galaxy.
Alternatively, you could have a collection of Perl or Bash scripts that you clone from artifact storage. That is, if you’re a dinosaur and don’t trust unicorn tools like Ansible, Octopus, Chef, Puppet, or anything made with Golang or Ruby.
That's it. I'll be speaking at the Next-gen CI night in Copenhagen on Tuesday 9 April so if you're in town, come say hi!