I don't hate using Gitlab CI once it's set up; I just hate "put shell scripts in YAML to define how this should work". The least annoying experiences I've had with them are when every entry is literally just a single line that invokes an external script; shell scripting is already annoying enough without having to also spend the time to understand a YAML schema for what order they get invoked in and what environmental variables are in scope (not to mention what the implicit inputs are; a few months ago I tried to add a task to run some check on the commit message for an MR, and I found that even on repositories where the merge commit option is disabled in favor of squashing or fast-forwarding, the top commit message is still a merge commit).