Git e CI/CD: triggers e automações

1. Fundamentos da Integração entre Git e CI/CD

1.1. O papel do Git como fonte de verdade para pipelines

O Git funciona como a única fonte de verdade (single source of truth) para pipelines de CI/CD. Cada commit, branch ou tag representa um estado do código que pode disparar automaticamente uma sequência de ações — desde testes unitários até deploys em produção. A integração entre Git e CI/CD elimina processos manuais e garante que cada alteração seja validada de forma consistente.

1.2. Conceito de webhooks: como o Git notifica o servidor de CI

Webhooks são chamadas HTTP que o servidor Git envia para o servidor de CI sempre que um evento ocorre. Quando um desenvolvedor faz um push, o GitHub, GitLab ou Bitbucket envia um payload JSON contendo informações como o SHA do commit, branch alterada e autor. O servidor de CI então interpreta esses dados e decide qual pipeline executar.

# Exemplo de payload de webhook (push event)
{
  "ref": "refs/heads/main",
  "after": "abc123def456",
  "commits": [
    {
      "id": "abc123def456",
      "message": "Adiciona validação de formulário",
      "author": { "name": "Maria Silva" }
    }
  ]
}

1.3. Estrutura de eventos: push, pull_request, tag, release

Os principais eventos que disparam pipelines são:

  • push: qualquer envio de commits para uma branch
  • pull_request: abertura, sincronização ou fechamento de PR
  • tag: criação de tags (geralmente usadas para releases)
  • release: publicação de uma release no repositório

Cada evento carrega metadados específicos que permitem filtragem precisa.

2. Triggers Baseados em Branches e Tags

2.1. Disparo seletivo por branch

É possível configurar pipelines para executar apenas em branches específicas, evitando processamento desnecessário em branches de trabalho.

# Exemplo GitHub Actions: executar apenas na main
on:
  push:
    branches:
      - main
      - develop
      - 'feature/*'

2.2. Utilizando tags semânticas como gatilho para deploy

Tags seguindo versão semântica (v1.0.0, v2.1.3) são ideais para disparar pipelines de deploy em produção.

# Disparar pipeline apenas quando uma tag v* for criada
on:
  push:
    tags:
      - 'v*'

2.3. Estratégias para evitar loops infinitos

Quando um pipeline faz push de volta para o repositório (ex: atualizar versão), pode criar um loop infinito. A solução é usar palavras-chave como [skip ci] na mensagem do commit.

# Commit que não deve disparar pipeline
git commit -m "Atualiza versão para 1.2.0 [skip ci]"

# Configuração para ignorar commits com [skip ci]
on:
  push:
    branches:
      - main
  paths-ignore:
    - 'CHANGELOG.md'

3. Filtros de Caminho (Path Filters) e Otimização

3.1. Disparo condicional com paths e paths-ignore

Filtros de caminho permitem executar pipelines apenas quando arquivos relevantes são alterados.

# Executar testes apenas se código fonte mudou
on:
  push:
    paths:
      - 'src/**'
      - 'tests/**'
    paths-ignore:
      - 'docs/**'
      - '*.md'

3.2. Exemplo prático: rodar testes apenas para código alterado

# pipeline.yml
name: Testes seletivos
on:
  pull_request:
    paths:
      - 'backend/**'
      - 'frontend/**'

jobs:
  test-backend:
    if: contains(github.event.pull_request.changed_files, 'backend/')
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: cd backend && npm test

  test-frontend:
    if: contains(github.event.pull_request.changed_files, 'frontend/')
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: cd frontend && npm test

3.3. Combinando filtros de caminho com branches específicas

on:
  push:
    branches:
      - main
    paths:
      - 'src/**'

Isso garante que apenas pushes para main que alterem src/ disparem o pipeline.

4. Automação de Merge e Pull Requests

4.1. Pipelines em PRs: validação antes do merge

Pull requests são o momento ideal para validar qualidade do código antes da integração.

on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm run lint

  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm test

4.2. Merge automático condicional

Com status checks aprovados, é possível automatizar o merge de PRs.

# Configuração no GitHub (via branch protection rules)
# 1. Habilitar "Require status checks before merging"
# 2. Selecionar "lint" e "test" como checks necessários
# 3. Habilitar "Allow auto-merge"

4.3. Uso de merge_group (GitHub Merge Queue)

O merge queue agrupa PRs aprovados e os testa juntos antes do merge.

on:
  merge_group:
    types: [checks_requested]

jobs:
  test-merge-queue:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm run test:integration

5. Estratégias de Deploy Automatizado

5.1. Deploy contínuo a partir de branches de release

on:
  push:
    branches:
      - release/*
      - main

jobs:
  deploy-staging:
    if: startsWith(github.ref, 'refs/heads/release/')
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploy para staging..."

  deploy-production:
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploy para produção..."

5.2. Promoção de artefatos entre ambientes

# Etapa 1: Build e armazenamento
- name: Upload artifact
  uses: actions/upload-artifact@v4
  with:
    name: build-${{ github.sha }}
    path: dist/

# Etapa 2: Download para deploy em staging
- name: Download artifact
  uses: actions/download-artifact@v4
  with:
    name: build-${{ github.sha }}

5.3. Rollback automático via reversão de commits ou tags

# Script de rollback via reversão de commit
git revert --no-commit HEAD~3..HEAD
git commit -m "Rollback para versão estável [skip ci]"
git push origin main

6. Segurança e Boas Práticas em Automações

6.1. Uso de secrets e variáveis de ambiente no pipeline

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy para produção
        env:
          API_TOKEN: ${{ secrets.PRODUCTION_API_TOKEN }}
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
        run: ./deploy.sh

6.2. Controle de acesso: tokens com escopo mínimo

Crie tokens de acesso pessoal (PAT) com permissões específicas para cada pipeline, evitando escopos amplos como repo completo quando apenas contents: write é necessário.

6.3. Validação de commits assinados (GPG) como pré-requisito

# Configuração no repositório GitHub
# Settings > Branches > Add rule > Require signed commits

# Verificação no pipeline
jobs:
  verify-signature:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: |
          git verify-commit HEAD || exit 1

7. Monitoramento e Logs de Pipelines

7.1. Rastreamento de execuções via SHA do commit

Cada execução de pipeline está vinculada ao SHA do commit que a disparou. Use esse identificador para correlacionar mudanças com resultados.

# No pipeline, o SHA está disponível como:
echo "Commit: ${{ github.sha }}"
echo "Branch: ${{ github.ref_name }}"

7.2. Notificações automáticas baseadas em status

on:
  workflow_run:
    workflows: ["Testes"]
    types:
      - completed

jobs:
  notify:
    runs-on: ubuntu-latest
    steps:
      - name: Notificar Slack
        if: ${{ github.event.workflow_run.conclusion == 'failure' }}
        uses: slackapi/slack-github-action@v1
        with:
          payload: |
            {
              "text": "Pipeline falhou no commit ${{ github.event.workflow_run.head_sha }}"
            }
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

7.3. Análise de falhas: reexecução e debug com informações do Git

# Reexecutar pipeline com debug habilitado
# Adicione ACTIONS_STEP_DEBUG como secret com valor 'true'

# Logs detalhados do Git
- name: Debug Git info
  run: |
    git log --oneline -5
    git diff --name-only HEAD~1 HEAD

Referências