Rules
Antes de começar a falar de rules
saiba que ela é uma evolução de algo que ainda é utilizado mas esta em desuso chamado only
.
Antes era utilizado duas coisas juntas (only e expect) que hoje resolvemos só com rules. Use rules sempre que possível. only tá de saída
.
Só para entender o contexto do que tinhamos antes...
job:
script: echo "Rodando job"
only:
- main # Roda só na branch main
- tags
only:
roda o job somente quando o commit vem de certas condições (branch, tag, etc).
Ou except...
job:
script: echo "Rodando job"
except:
- develop
except:
não roda o job se cair em alguma dessas condições.
Limitações:
- Não temos if ou lógica condicional usando only e except.
- Não podemos fazer lógicas combinadas utilizando as variáveis.
Então esquece isso e vamos direto pro que nos dá mais poder, rules
.
job:
script:
...
rules: [] # É uma lista
- As regras são avaliadas em ordem, a que der match primeiro define o comportamento do job.
- Super customizável com expressões, variáveis, tags, branch, MR, etc.
Uma tabela rápida para entender diferença.
Aspecto | only / except | rules |
---|---|---|
Suporte oficial | Depreciado | Atual e recomendado |
Flexibilidade | Baixa | Alta |
Condicional (if) | Não | Sim |
Ordem de avaliação | Limitada | Sequencial e lógica |
MR detection | Limitada | Avançada |
Expressividade | Baixa | Alta |
Only e except só estam presentes por uma questão de retrocompatiblidade e nada mais.
Documentação Oficial Only e Except
A estrutura do um bloco rules é a seguinte.
job:
script:
...
rules:
- if: <expressão>
when: [on_success | on_failure | manual | always | never | delayed]
start_in: <tempo>
allow_failure: true/false
exists:
- <caminho/do/arquivo>
changes:
- <arquivo ou pasta>
variables:
- <variável>
Campo | Obrigatório? | Descrição |
---|---|---|
if | ❌ | Expressão booleana usando variáveis do GitLab ($CI_*, etc). |
when | ❌ | Define quando o job será executado (on_success, manual, etc). |
start_in | ❌ | Usado com when: delayed (ex: "5 minutes"). |
allow_failure | ❌ | Se true, falha no job não quebra o pipeline. |
exists | ❌ | Roda o job se o(s) arquivo(s) existir(em). |
changes | ❌ | Roda o job se os arquivos listados foram modificados. |
variables | ❌ | Lista de variáveis obrigatórias para essa regra ser aplicada. |
when
Temos uma item importante ai que além de estar dentro de rules também pode ser declarado fora (diretamente no job) que é o when
. Primeiro vamos entender o que ele faz e depois entender a diferença entre usar em rules e fora dele.
Valor de when | Comportamento |
---|---|
on_success | Executa o job somente se nenhum job anterior falhar. (Padrão) |
on_failure | Executa o job somente se algum job anterior falhar. |
never | Nunca executa o job, independentemente de qualquer condição. Só pode ser usado em rules , afinal não faria sentido |
always | Executa o job sempre, mesmo que jobs anteriores falhem. |
manual | O job fica aguardando execução manual (aparece botão no GitLab UI). |
delayed | O job é executado com atraso, conforme o tempo definido em start_in:. |
Exemplo e when: manual
seria que alguém o deploy para ir para em produção.
job_manual:
script: echo "Executando o deploy..."
when: manual
Exemplo delayed + start_in
seria em dar um tempo entre o deploy em staging e o deploy em produção para que dê tempo de testar e se alguém perceber um erro dá tempo ir cancelar o job antes que rode. Se usar de delayed, o start_in é obrigatório
.
job_delayed:
script: echo "Executando o deploy..."
when: delayed
start_in: 10 minutes
Um exemplo de always poderia ser enviar uma notificação ao final do pipeline mesmo se ele falhar, por exemplo enviar um email e uma notificação no slack. Se quiser que só envie se falhar então poderia ser on_failure.
Quando declaramos o when fora das rules o que estamos fazendo na verdade é colocando o mesmo when para todas as rules. Isso serve para deixar o rules mais limpo.
job:
script: echo "Rodando"
when: manual
rules:
- if: Condição 1
- if: Condição 2
Ou seja, é a mesma coisa que fazer isso.
job:
script: echo "Rodando"
rules:
- if: Condição 1
when: manual
- if: Condição 2
when: manual
Porém podemos fazer sobreescrever para alguma regra específica. Nesse caso o job sempre é manual, as se for na branch develop então roda direto sem intervenção.
job:
script: echo "Deployando"
when: manual
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
- if: '$CI_COMMIT_BRANCH == "staging"'
- if: '$CI_COMMIT_BRANCH == "develop"'
when: on_success
allow_failure
O mesmo vale para allow_failure, que pode ser definido diretamente no nível do job ou individualmente dentro de cada regra em rules. Quando definido no nível do job, o valor será aplicado como padrão para todas as rules.
Por default
, allow_failure é false
, ou seja: se o job falhar, o pipeline também será considerado com falha. Quando definido como true, o job pode falhar sem quebrar o pipeline, permitindo que os próximos jobs continuem normalmente.
Isso é útil, por exemplo, para testes experimentais, análises estáticas ou qualquer etapa não crítica que você não quer que bloqueie o restante da execução.
exists, changes e variables
Muitas vezes código sofre mudanças que não mudam nada no ambiente, um ótimo exemplo disso é fazer uma alteração no README.md. Pra que vamos fazer deploy?
No bloco de rules, além de if, você pode usar exists e changes, que são formas de ativar um job com base na presença ou modificação de arquivos.
job:
script: "Criando uma imagem"
when: manual
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
exists:
- Dockerfile
- .dockerignore
job:
script: "Criando uma imagem"
when: manual
rules: # Observe que pode existir que o IF. tanto changes quanto exists.
- changes: # Se algum desses arquivos sofrer mudanças
- src/**
- config/*.yaml
Já o bloco variables, como vimos antes, serve para definir variáveis personalizadas.
deploy:
stage: deploy
image: alpine
script:
- echo "Deploy iniciando com TOKEN=$TOKEN"
environment:
name: $DEPLOY_ENV
rules:
- if: '$CI_COMMIT_BRANCH == "develop"'
variables:
DEPLOY_ENV: develop
- if: '$CI_COMMIT_BRANCH == "main"'