Conceitos Iniciais
A primeira coisa que precisamos entender é como funciona a organização dos códigos dentro da plataforma do Gitlab.
Grupos e Projetos
No GitLab, a estrutura de organização dos códigos é baseada em grupos e repositórios, o que facilita o gerenciamento de times, permissões e projetos.
-
Grupos: Um grupo é como uma pasta principal que pode conter vários projetos (repositórios) e até outros subgrupos. Ele serve para agrupar tudo que pertence a um mesmo time, produto ou área da empresa.- Permissões podem ser atribuídas no nível do grupo, e todos os projetos herdam essas permissões.
- Ajudam na organização por áreas (ex: frontend, backend, devsecops) e também na aplicação de políticas e configurações em conjunto.
- Essa é uma das maiores vantagens que vejo do GitLab contra o GitHub.
-
Subgrupos: São como subpastas dentro de um grupo. Na verdade são outros grupos dentro de grupos.- Permitem uma organização ainda mais granular (ex: empresa/backend/serviços).
- Úteis para empresas grandes ou com muitos times.
-
Repositórios(Projetos)- Um repositório, chamado de projeto no GitLab, é onde realmente vive o código-fonte, o histórico de commits, pipelines, issues e tudo mais relacionado àquele projeto específico.
- Cada projeto tem seu próprio controle de versionamento Git.
- Pode conter CI/CD configurado via .gitlab-ci.yml.
- Pode ser público ou privado, e seguir
regras herdadas do grupo.
empresa/
├── plataforma/ # grupo
│ ├── api-auth # repo
│ ├── dashboard # repo
│ └── infra/ # subgrupo
│ ├── terraform-network # repo
│ └── terraform-vm # repo
├── frontend/ # grupo
│ └── landing-page # repo
└── backend/ # grupo
├── user-service # repo
└── payment-service # repo
A hierarquia de grupos no GitLab é essencial quando pensamos em escala e padronização dentro de uma organização. Grupos permitem centralizar configurações que serão herdadas automaticamente por todos os repositórios filhos. Isso inclui desde variáveis de ambiente, templates, até permissões de acesso e configurações de segurança.
Quando configuramos um pipeline em um projeto, podemos definir variáveis e regras diretamente nele. No entanto, ao utilizar grupos, conseguimos aplicar configurações globais que serão replicadas para todos os projetos daquele grupo, evitando repetição e facilitando o gerenciamento.
Toda vez que um pipeline é executado, ele utiliza um Runner, que é a força computacional responsável por rodar os jobs. Esses runners podem ser compartilhados (em nível de grupo) ou dedicados (em nível de projeto), e é possível associar variáveis de ambiente no grupo, que são automaticamente lidas por qualquer runner que execute pipelines nos projetos filhos.
Ou seja, a organização por grupos não é só uma questão visual ou estrutural — ela é fundamental para escalar, padronizar e manter a governança dos pipelines e dos ambientes de execução dentro do GitLab.
Runners
O GitLab Runner é um serviço responsável por executar os jobs definidos dentro dos pipelines (.gitlab-ci.yml). Em outras palavras: o runner é quem coloca a mão na massa quando um pipeline é disparado.
Tipos de Runners
-
Shared Runners (compartilhados): Configurados pela instância do GitLab, disponíveis para múltiplos grupos e projetos.
-
Group Runners: Associados diretamente a um grupo. Todos os repositórios (projetos) dentro desse grupo podem utilizá-lo.
-
Project Runners: Exclusivos de um projeto específico. Só aquele projeto pode utilizá-lo.
Essa divisão permite flexibilidade e controle, principalmente quando falamos de times diferentes, workloads distintos ou ambientes com requisitos específicos.
O runner é o ambiente onde o código será executado durante a pipeline. Esse ambiente pode ser genérico ou específico, dependendo da necessidade do projeto.
Por exemplo, podemos ter um runner que inicia com uma imagem básica, como um Ubuntu "cru", sem nenhuma ferramenta instalada. Durante a execução dos jobs, o próprio pipeline se encarrega de instalar tudo o que for necessário — como dependências, linguagens e ferramentas — antes de rodar o projeto.
Por outro lado, podemos usar imagens pré-configuradas com tudo que o projeto precisa. Se vamos rodar o projeto A, podemos usar um container A com todas as tecnologias já instaladas. Se o projeto B é um app em Node.js, podemos usar uma imagem oficial node que já vem com o Node.js pronto para uso. Isso acelera a execução e evita repetição de instalação.
Em alguns casos, pode fazer sentido usar apenas uma imagem base e deixar que cada projeto configure o que precisa via pipeline. Isso dá mais flexibilidade, mas pode aumentar o tempo de execução e exigir mais manutenção.
Não existe certo ou errado — o que existe é arquitetura e governança. Cada organização tem seus próprios requisitos de segurança e compliance, e isso pode impactar diretamente como os runners são configurados e utilizados.
Por exemplo, em alguns ambientes mais restritos, pode não ser permitido rodar imagens personalizadas por questões de auditoria ou rastreabilidade. Nesses casos, a personalização precisa acontecer em tempo de execução, dentro do próprio job.
E o que isso tem a ver com os tipos de runner?
- Um runner compartilhado (shared), usado por vários projetos, deve ser o mais genérico e neutro possível, garantindo compatibilidade ampla e segurança.
- Um runner de grupo já permite um nível maior de personalização, pois está sob o controle de uma equipe específica e pode ser adaptado às tecnologias comuns daquele grupo.
- Um runner de projeto pode ser altamente especializado, criado sob medida para as necessidades daquele projeto específico — inclusive com imagens customizadas e ferramentas pré-instaladas.
Durante a definição de uma pipeline escolhemos quais os runners vamos utilizar, mas isso é mais pra frente.
Onde rodam os Runners?
Os runners não são obrigatoriamente executados em containers, mas na prática, o uso de containers é muito comum porque facilita o isolamento, a portabilidade e a automação.
Um runner nada mais é do que um serviço que se comunica com o GitLab, pronto para clonar um repositório e executar o código de uma pipeline. Se é um serviço em um sistema operacional, o que temos normalmente?
| Executor | Roda onde? | Usa container? |
|---|---|---|
| shell | No próprio host (como bash) | ❌ Não |
| docker | Dentro de containers Docker | ✅ Sim |
| docker+machine | Em containers Docker criados sob demanda | ✅ Sim |
| kubernetes | Em pods dentro de um cluster | ✅ Sim (pods) |
| ssh | Em um servidor remoto via SSH | ❌ Não |
| custom | Você define | Depende |
Por que usar containers então?
- Isolamento: Nada de sujeira entre builds.
- Segurança: Cada job em um ambiente controlado.
- Portabilidade: O mesmo container roda em qualquer lugar.
- Reprodutibilidade: "Na minha máquina funciona" perde força.
Não é obrigatório que o runner use container, mas na maioria das vezes, é o caminho mais seguro, limpo e escalável. E a escolha do executor tem tudo a ver com a estratégia da sua infra e com o nível de controle que você quer ter.
Variáveis de Ambiente dos Runners
Um runner carrega as variáveis de ambiente definidas em um projeto. Quando você define variáveis de ambiente em um projeto no GitLab (definidas por projeto ou herdadas de grupos pais), essas variáveis são associadas ao runner durante a execução de uma pipeline para aquele projeto específico. Isso significa que, ao rodar a pipeline, o runner terá acesso a essas variáveis e poderá utilizá-las durante a execução dos jobs.
Você pode definir variáveis de ambiente diretamente na interface do GitLab, dentro do seu projeto ou de grupos. Essas variáveis podem ser usadas para armazenar informações como credenciais de API, chaves de autenticação, configurações de banco de dados, entre outras.
Essas variáveis ficam disponíveis para qualquer job dentro desse projeto, desde que o runner esteja executando a pipeline.
Quando a pipeline do projeto é disparada, o runner que estiver configurado para esse projeto (pode ser um runner específico para o projeto ou um runner compartilhado) carrega as variáveis de ambiente definidas.
O runner passa essas variáveis para o ambiente de execução onde o job está sendo executado, seja em um container Docker, em um servidor via SSH ou outro tipo de executor.
Gatilhos de Pipeline
Acima foi comando o seguinte trecho "Quando a pipeline do projeto é disparada" e você pode estar se perguntando como isso funciona. Quem identifica os gatilhos (triggers) é o próprio Gitlab de acordo com eventos que acontecem em um repositório. Quando o Gitlab identificar um evento ele irá olhar no arquivo .gitlab-ci.yml e ver como esta a configuração e se ele deve ou não disparar o pipeline baseado nas regras que você definiu.
Algumas possíveis triggers:
-
Push para o Repositório: A maneira mais comum de disparar uma pipeline é através de um push para o repositório. Sempre que há um novo commit enviado para o repositório (um push), o GitLab dispara automaticamente a pipeline para executar os jobs definidos no arquivo .gitlab-ci.yml.- Exemplo: Toda vez que você fizer um push em uma branch (por exemplo, main ou develop), a pipeline será executada. -O que acontece: O GitLab vai buscar o arquivo .gitlab-ci.yml e disparar a pipeline com os jobs definidos nesse arquivo.
- É possível executar quando um push seja feito para qualquer branch ou algum branch específica.
-
Merge Requests(MRs): Quando você cria ou atualiza um merge request no GitLab, uma pipeline pode ser automaticamente disparada para validar as mudanças antes de mesclá-las na branch de destino. Isso ajuda a garantir que o código proposto esteja funcionando corretamente antes de ser integrado.- Exemplo: Sempre que um merge request é aberto, a pipeline é executada automaticamente para testar e verificar o código da branch que está sendo mesclada.
- O que acontece: A pipeline é executada para validar o código que será integrado e garantir que ele está em conformidade com as regras de qualidade e testes definidos no .gitlab-ci.yml.
- É possível executar quando um merge for aberto, mas também podendo especificar para qual branch é esse merge.
-
Triggers Manuais: Você pode configurar triggers manuais para que as pipelines sejam disparadas somente quando um usuário acionar manualmente. Isso é útil para ações que não precisam ser executadas a cada commit, como deploys ou testes específicos que não fazem parte do fluxo padrão.- Exemplo: Um job de deploy que só é disparado quando um responsável autoriza, clicando no botão de "Play" na interface do GitLab.
- que acontece: O job é executado apenas quando o usuário solicita explicitamente, proporcionando maior controle sobre quando as ações são feitas.
-
GitLab CI/CD Pipeline Schedules(Agendamentos): Você pode configurar agendamentos de pipeline, que permitem que uma pipeline seja disparada em intervalos regulares ou em horários específicos. Isso é útil para tarefas de manutenção, como atualizações de dependências ou builds periódicos.- Exemplo: Uma pipeline pode ser configurada para rodar todas as noites às 3h da manhã para fazer uma limpeza ou atualizar dependências.
- O que acontece: A pipeline será disparada automaticamente com base na programação definida, sem intervenção manual.
-
Triggers via API: O GitLab permite disparar pipelines de fora do sistema, utilizando triggers via API. Com isso, você pode integrar o GitLab com outros sistemas e ferramentas que precisam disparar pipelines em momentos específicos ou após certos eventos.- Exemplo: Uma ferramenta de monitoramento pode disparar uma pipeline quando uma nova versão do software for detectada ou quando um novo commit for realizado.
- O que acontece: Você utiliza um token de trigger gerado pelo GitLab para fazer um POST via API e disparar a pipeline de forma externa.
-
Push em Branches Específicas: É possível configurar as pipelines para serem disparadas apenas quando um push for feito em uma branch específica. Isso pode ser feito configurando o .gitlab-ci.yml para escutar mudanças em branches específicas.-
Exemplo: Se você quiser que a pipeline seja executada apenas quando um commit for feito na branch main (ou em outra branch específica), você pode configurar a pipeline para disparar apenas nessas circunstâncias.
-
O que acontece: A pipeline será executada somente se o push ocorrer nas branches que você configurou no arquivo .gitlab-ci.yml.
-
-
Pipeline Trigger via Webhooks: Outra maneira de disparar uma pipeline é utilizando webhooks. Um webhook permite que você envie um pedido HTTP para um endpoint do GitLab sempre que um evento ocorre em outro sistema. Isso é útil quando você quer integrar o GitLab com outras ferramentas externas que podem acionar uma pipeline.- Exemplo: Se você estiver utilizando uma ferramenta de monitoramento de código, como o Sentry, ou uma ferramenta de CI externa, ela pode disparar uma pipeline no GitLab quando detectar um evento específico.
- O que acontece: O webhook envia uma solicitação para o GitLab, que por sua vez dispara a pipeline com base nas condições configuradas.
Podem existir outros, mas esses são os principais e mais utilizados.
Todas essas configurações devem estar no arquivo .gitlab-ci.yml na raíz do repositório (projeto)