CI - GitHub Actions
Conceitos
Seção intitulada “Conceitos”- Workflow — arquivo YAML em
.github/workflows/que descreve um processo automatizado. Um repo pode ter vários. - Evento / gatilho — o que dispara o workflow:
push,pull_request,schedule(cron),workflow_dispatch(manual), entre outros. - Job — unidade de execução que roda em um runner; por padrão jobs correm em paralelo, mas podem depender uns dos outros com
needs. - Step — passo dentro de um job; executa um comando (
run) ou uma action. - Action — unidade reutilizável e versionada (ex.:
actions/checkout@v4,actions/setup-java@v4). - Runner — máquina que executa o job (hospedada pelo GitHub, ex.:
ubuntu-latest, ou self-hosted).
graph TD
A[Evento: push / pull_request] --> B[Workflow]
B --> C[Job: build-and-test]
subgraph "Runner: ubuntu-latest"
C --> D[step: checkout]
D --> E[step: setup-java + cache]
E --> F[step: mvn verify - build + test]
F --> G{Testes passaram?}
end
G -- não --> H[Pipeline vermelho:<br/>bloqueia merge]
G -- sim --> I[Job: build-image - needs build-and-test]
I --> J[Push para registry]
Cache de dependências
Seção intitulada “Cache de dependências”Sem cache, cada execução rebaixa todo o ~/.m2 (ou ~/.gradle) da internet — lento e caro. O actions/setup-java já integra cache do Maven/Gradle; a chave do cache é derivada dos arquivos de build, então só é invalidada quando as dependências mudam. Isso é central para o feedback rápido que a CI promete.
Matriz (matrix)
Seção intitulada “Matriz (matrix)”Executa o mesmo job em várias combinações (ex.: Java 17, 21 e 24) em paralelo, cada uma em seu runner. Útil para validar compatibilidade sem duplicar o YAML.
Secrets
Seção intitulada “Secrets”Credenciais (token do registry, senha de deploy) nunca vão no YAML em texto puro. Ficam em Secrets do repositório/organização e são injetadas como ${{ secrets.NOME }} em runtime, mascaradas nos logs.
Exemplo: pipeline de CI para Spring
Seção intitulada “Exemplo: pipeline de CI para Spring”name: CI
on: push: branches: [ main ] pull_request:
jobs: build-and-test: runs-on: ubuntu-latest strategy: matrix: java: [ '21', '24' ] # matriz: valida em duas versões de JDK steps: - name: Checkout uses: actions/checkout@v4
- name: Setup JDK ${{ matrix.java }} uses: actions/setup-java@v4 with: distribution: temurin java-version: ${{ matrix.java }} cache: maven # cacheia ~/.m2 automaticamente
# 'verify' compila, roda testes unitários e de integração # (Testcontainers usa o Docker já presente no runner ubuntu) - name: Build e testes run: ./mvnw --batch-mode verify
- name: Publica relatório de testes if: always() # roda mesmo se os testes falharem uses: actions/upload-artifact@v4 with: name: surefire-reports-${{ matrix.java }} path: target/surefire-reports/
build-image: runs-on: ubuntu-latest needs: build-and-test # só roda se os testes passaram if: github.ref == 'refs/heads/main' permissions: contents: read packages: write # o GITHUB_TOKEN é read-only por padrão
steps: - uses: actions/checkout@v4
- name: Login no registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} # secret, nunca em texto puro
- name: Build e push da imagem uses: docker/build-push-action@v6 with: context: . push: true tags: ghcr.io/${{ github.repository }}:${{ github.sha }}Note a divisão em dois jobs: build-image declara needs: build-and-test, então a imagem só é construída se a suíte passar — a rede de segurança dos testes barra artefatos quebrados.
CI a testes: a suíte é a rede de segurança
Seção intitulada “CI a testes: a suíte é a rede de segurança”A CI só entrega valor se houver testes de verdade rodando nela. A relação com Testes e TDD é direta: a suíte automatizada é a rede de segurança do pipeline. Um push que quebra o comportamento faz os testes falharem, o job fica vermelho e o merge é bloqueado antes de a regressão chegar ao main.
- A pirâmide de Tipos de Teste - Unit, Integration e E2E guia o que roda no CI: muitos testes unitários rápidos na base, integração no meio (com Testcontainers sobre Docker), poucos E2E no topo.
- O F de “Fast” importa aqui: testes rápidos + cache de dependências = feedback em minutos. Uma suíte lenta corrói a prática — desenvolvedores param de esperar o CI e a integração deixa de ser contínua de fato.
CI x CD
Seção intitulada “CI x CD”Não confunda os dois:
- CI (Continuous Integration) — integrar e validar cada mudança automaticamente: build + testes a cada push. Termina com um artefato validado (ex.: imagem construída).
- CD — duas leituras: Continuous Delivery (o artefato fica sempre pronto para deploy, com a promoção final acionada por um humano) e Continuous Deployment (todo artefato validado vai automaticamente para produção, sem intervenção manual).
Em suma: CI garante que o código está bom; CD cuida de levá-lo até o ambiente. O exemplo acima é CI (com um passo de empacotamento); adicionar um job que promove a imagem para um ambiente seria a fronteira do CD.
Anti-padrões e erros comuns
Seção intitulada “Anti-padrões e erros comuns”- Pipeline verde sem testes reais. Compila mas não exercita a lógica; dá falsa confiança.
- Sem cache de dependências. Cada execução baixa tudo de novo, feedback lento, prática abandonada.
- Segredos em texto puro no YAML. Credenciais expostas no repositório e nos logs; use Secrets.
- Suíte lenta no caminho crítico. Viola o Princípio FIRST; empurra devs a ignorar o CI ou desligar testes.
- Testes flaky tolerados. Falhas intermitentes fazem o time ignorar o vermelho — o pipeline perde autoridade.
needsausente entre jobs. Construir/publicar a imagem sem depender do job de testes deixa artefatos quebrados escaparem.- Rodar todo o pipeline em um único job gigante. Impede paralelismo e reuso; prefira jobs coesos com dependências explícitas.
Relações
Seção intitulada “Relações”- Empacotamento disparado pelo pipeline: Containers - Docker e Docker Compose
- Área geral e fluxo do commit ao deploy: DevOps & Infraestrutura
- Rede de segurança do pipeline: Testes e TDD · Tipos de Teste - Unit, Integration e E2E
- Dependências reais nos testes: Testcontainers
- Feedback rápido: Princípio FIRST
- Deploy independente: Microservices
- Índice: Home
Perguntas de revisão
Seção intitulada “Perguntas de revisão”1. Diferencie workflow, job, step, runner e action no GitHub Actions.
Resposta
Workflow é o processo automatizado descrito em YAML; job é uma unidade que roda em um runner (jobs paralelizam por padrão, encadeáveis com needs); step é um passo dentro do job (um run ou uma action); runner é a máquina que executa o job (ex.: ubuntu-latest); action é uma unidade reutilizável e versionada, como actions/checkout@v4.
2. Por que o cache de dependências é decisivo para a CI e como sua chave costuma ser invalidada?
Resposta
Sem cache, cada execução rebaixa todo o ~/.m2/~/.gradle, tornando o pipeline lento e caro e minando o feedback rápido. A chave do cache é derivada dos arquivos de build (ex.: pom.xml), então só é invalidada quando as dependências efetivamente mudam — mantendo builds rápidos na maioria dos pushes.
3. Em que sentido a suíte de testes é a “rede de segurança” do pipeline, e como isso se liga ao Princípio FIRST?
Resposta
A suíte automatizada (Testes e TDD) roda a cada push; se uma mudança quebra o comportamento, os testes falham, o job fica vermelho e o merge é bloqueado antes da regressão chegar ao main. O F de Fast garante que essa rede dê feedback em minutos — testes lentos corroem a prática porque ninguém espera pelo CI.
4. Qual a diferença entre CI e CD?
Resposta
CI (Continuous Integration) valida cada mudança automaticamente (build + testes a cada push), terminando com um artefato validado. CD é Continuous Delivery (artefato sempre pronto para deploy, promoção final acionada por humano) ou Continuous Deployment (todo artefato validado vai automaticamente a produção). Resumindo: CI garante que o código está bom; CD cuida de levá-lo ao ambiente.