Caveat: I haven't used Gitlab in a couple of years, but before that, part of my role was to set up Gitlab CI systems for different projects, so I got a lot of hands-on experience back then.
Gitlab CI is 3-4 different systems on top of each other wearing a trenchcoat. Every so often, they realise they can do CI better and come up with a new syntax for everything (see stages, which got extended by dependencies, which got superceded by the needs mechanism, or only/except which got replaced by rules). Obviously, they can't easily remove the old syntax, so pipelines very quickly become a mix of different mechanisms, some old, some new, with weird, unpredictable, and usually poorly documented interactions between them. You can try and only use a restricted subset of well-defined Gitlab CI, but part of the problem with modern DevOps is that most developers are not very experienced with the CI syntax, and will just find snippets on SO that do what they want and leave it there.
Apart from that, the documentation overall tends to be very poor, and the implementations are often buggy or missing functionality (a lot of searches for "Gitlab CI <thing I want to do>" would just link to an open ticket in the Gitlab repo describing exactly the functionality I needed, and dozens of comments going "yeah, this is necessary" and "a silver level customer needs this functionality to continue using Gitlab"). There's also lots of stuff that relies very heavily on being and to configure everything in YAML. other CI systems also have this problem, but often provide mechanisms to write individual tasks in other languages so you distribute, say, the "deploy this Docker image to our k8s cluster" task as a standalone unit written, tested, and reviewed in a real programming language. Gitlab CI has a very basic version of this feature, except it's still all in YAML, it's almost impossible to test, and it's very difficult to configure these tasks at all.
Fwiw, I've done plenty with Gitlab CI, and it's not like it doesn't work. It is perfectly fine if you don't have particularly complex needs, and the runners mechanism seems fairly easy for system administrators to get started with and get working. But overall, the whole system feels only half thought-through, and trying to do anything complex tends to require a lot of hair-pulling and confusion.
> How do you find, for instance, GitHub Actions more advanced?
Being able to easily tap into an ecosystem of existing re-usable functionality (actions) is a great and pretty advanced feature that requires a very different (and more advanced) set of abstractions than running “a bunch of commands in a docker image you specify”.
Not that it’s a perfect system, but a core CI system with a decoupled layer of “things that run on that CI system” is a great model.
For example, the core of GitHub actions doesn’t have anything built-in that clones repositories. That’s a first-party action (component) that GitHub develops, releases and evolves independently. But you can roll your own if you want.
While components look great (and I wasn’t aware!), it’s still just the same old “template-metaprogramming-with-yaml” that includes are:
> Avoid using global keywords in a component. Using these keywords in a component affects all jobs in a pipeline, including jobs directly defined in the main .gitlab-ci.yml or in other included components.
This is very different (and a whole lot less advanced) than being able to run a 3rd party GitHub action written in JavaScript, alongside another running in its own container image, mixed in with your own steps.
Because Gitlab CI bakes everything into one layer it’s much much harder to evolve and extend, and so it fossilizes whilst being unable to shake it’s baggage.
Gitlab CI is 3-4 different systems on top of each other wearing a trenchcoat. Every so often, they realise they can do CI better and come up with a new syntax for everything (see stages, which got extended by dependencies, which got superceded by the needs mechanism, or only/except which got replaced by rules). Obviously, they can't easily remove the old syntax, so pipelines very quickly become a mix of different mechanisms, some old, some new, with weird, unpredictable, and usually poorly documented interactions between them. You can try and only use a restricted subset of well-defined Gitlab CI, but part of the problem with modern DevOps is that most developers are not very experienced with the CI syntax, and will just find snippets on SO that do what they want and leave it there.
Apart from that, the documentation overall tends to be very poor, and the implementations are often buggy or missing functionality (a lot of searches for "Gitlab CI <thing I want to do>" would just link to an open ticket in the Gitlab repo describing exactly the functionality I needed, and dozens of comments going "yeah, this is necessary" and "a silver level customer needs this functionality to continue using Gitlab"). There's also lots of stuff that relies very heavily on being and to configure everything in YAML. other CI systems also have this problem, but often provide mechanisms to write individual tasks in other languages so you distribute, say, the "deploy this Docker image to our k8s cluster" task as a standalone unit written, tested, and reviewed in a real programming language. Gitlab CI has a very basic version of this feature, except it's still all in YAML, it's almost impossible to test, and it's very difficult to configure these tasks at all.
Fwiw, I've done plenty with Gitlab CI, and it's not like it doesn't work. It is perfectly fine if you don't have particularly complex needs, and the runners mechanism seems fairly easy for system administrators to get started with and get working. But overall, the whole system feels only half thought-through, and trying to do anything complex tends to require a lot of hair-pulling and confusion.