GitHub Actions: criando seu primeiro workflow
1. Introdução ao GitHub Actions no contexto DevOps
GitHub Actions é a plataforma de automação nativa do GitHub que permite construir, testar e implantar código diretamente a partir do repositório. No ecossistema DevOps, ela se destaca por sua integração profunda com o versionamento, eliminando a necessidade de ferramentas externas para gatilhos de CI/CD.
Comparada a outras ferramentas como Jenkins (que exige infraestrutura dedicada e plugins complexos), GitLab CI (poderosa, mas vinculada ao ecossistema GitLab) ou CircleCI (excelente performance, porém custo elevado em escala), o GitHub Actions oferece vantagens significativas para pipelines com Docker e Kubernetes: execução em runners gerenciados, marketplace rico em actions prontas para containerização e orquestração, e integração nativa com secrets e ambientes.
Para equipes que já utilizam GitHub como repositório central, a adoção do Actions reduz a complexidade operacional — um único gatilho de push pode construir uma imagem Docker, publicá-la em um registry e atualizar um deployment no Kubernetes sem intervenção manual.
2. Estrutura de um workflow: conceitos fundamentais
Um workflow é definido em um arquivo YAML dentro do diretório .github/workflows/. Cada workflow é composto por três elementos principais:
Eventos determinam quando o workflow é executado. Os mais comuns são push (dispara em commits), pull_request (abre ou atualiza PR) e schedule (execução cron). Exemplo:
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '0 6 * * 1' # toda segunda-feira às 6h UTC
Jobs são unidades de trabalho que rodam em runners (máquinas virtuais com Linux, Windows ou macOS). Cada job pode conter múltiplos steps — comandos ou actions reutilizáveis. Boas práticas incluem separar jobs por responsabilidade (build, teste, deploy) e usar dependências entre eles com needs.
Runners podem ser os fornecidos pelo GitHub (ubuntu-latest, windows-latest) ou auto-hospedados para maior controle.
3. Criando seu primeiro workflow: build e push de imagem Docker
Vamos criar um workflow que constrói uma imagem Docker e a publica no Docker Hub. Primeiro, configure os secrets no repositório: DOCKER_USERNAME e DOCKER_PASSWORD.
Arquivo .github/workflows/docker-build.yml:
name: Build and Push Docker Image
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ secrets.DOCKER_USERNAME }}/my-app:latest
Este workflow utiliza docker/setup-buildx-action para habilitar builds multi-plataforma e docker/build-push-action que gerencia o cache e o push automaticamente. A autenticação via secrets garante que credenciais nunca apareçam nos logs.
4. Integração com testes e lint automatizados
Antes de publicar a imagem, é prudente executar testes e verificar a qualidade do código. Adicione um job de teste ao workflow:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run unit tests in container
run: docker compose run --rm app pytest
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Lint Dockerfile
uses: hadolint/hadolint-action@v3.1.0
with:
dockerfile: Dockerfile
- name: Lint YAML files
uses: ibiqlik/action-yamllint@v3
with:
config_file: .yamllint.yml
O hadolint analisa boas práticas em Dockerfiles (como ordem de instruções, uso de usuários não-root). O yamllint garante consistência nos arquivos YAML do Kubernetes e do próprio workflow. Essas validações evitam problemas em estágios avançados do pipeline.
5. Deploy automatizado em Kubernetes via workflow
Com a imagem publicada, o próximo passo é atualizar um deployment no cluster Kubernetes. O workflow abaixo utiliza kubectl autenticado via kubeconfig armazenado em secret:
deploy:
runs-on: ubuntu-latest
needs: [build, test, lint]
steps:
- name: Configure kubectl
run: |
mkdir -p $HOME/.kube
echo "${{ secrets.KUBE_CONFIG }}" > $HOME/.kube/config
- name: Update deployment image
run: |
kubectl set image deployment/my-app \
my-container=${{ secrets.DOCKER_USERNAME }}/my-app:${{ github.sha }}
- name: Verify rollout
run: |
kubectl rollout status deployment/my-app --timeout=120s
Para projetos que usam Helm, a action deliverybot/helm facilita o deploy com charts versionados. Já com Kustomize, é possível usar kustomize edit set image antes de aplicar. Estratégias de rollback podem ser implementadas com kubectl rollout undo caso a verificação de status falhe.
6. Gerenciamento de variáveis, secrets e ambientes
O GitHub Actions oferece três níveis de armazenamento seguro:
- Secrets (Settings > Secrets and variables > Actions): para tokens, senhas e chaves SSH. São criptografados e mascarados nos logs.
- Variáveis de ambiente: podem ser definidas no nível do repositório, ambiente ou workflow.
- Ambientes (Environments): permitem criar regras de proteção, como aprovação manual antes do deploy em produção.
Exemplo de uso com ambientes:
deploy-staging:
runs-on: ubuntu-latest
environment:
name: staging
url: https://staging.myapp.com
steps:
- name: Deploy to staging
run: echo "Deploying to staging"
Boas práticas incluem nunca hardcodar valores sensíveis, usar ${{ secrets.NOME }} em vez de variáveis de ambiente para credenciais, e limitar o escopo de secrets por ambiente.
7. Monitoramento e otimização do workflow
Logs centralizados: Para depuração em produção, integre o workflow com Loki via Promtail. Uma action customizada pode enviar logs estruturados para um endpoint:
- name: Send logs to Loki
run: |
curl -X POST http://loki:3100/loki/api/v1/push \
-H "Content-Type: application/json" \
-d '{"streams": [{"stream": {"job": "github-actions"}, "values": [["'$(date +%s%N)'", "Build completed"]]}]}'
Cache de camadas Docker: Para acelerar builds recorrentes, utilize o cache nativo do docker/build-push-action:
- name: Build and push with cache
uses: docker/build-push-action@v5
with:
cache-from: type=gha
cache-to: type=gha,mode=max
Isso reduz o tempo de build de minutos para segundos em execuções subsequentes.
Limitação de tempo e paralelismo: Defina timeout-minutes por job (padrão 360) e utilize strategy.matrix para paralelizar testes em múltiplas versões:
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']
steps:
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
Conclusão
Criar um workflow no GitHub Actions para pipelines DevOps com Docker e Kubernetes é um processo direto, mas que exige atenção a detalhes como segurança, cache e validações. A estrutura apresentada — build com Buildx, testes em container, lint automatizado, deploy via kubectl e monitoramento — forma uma base sólida para projetos de qualquer escala. Comece com um workflow simples e evolua gradualmente, adicionando ambientes, matrizes de teste e integrações com Helm ou Kustomize conforme a necessidade.
Referências
- GitHub Actions Documentation - Workflow Syntax — Referência oficial sobre a estrutura YAML de workflows, eventos, jobs e steps.
- Docker Build Push Action - GitHub Marketplace — Action oficial para build e push de imagens Docker com suporte a cache e multi-plataforma.
- hadolint - Dockerfile Linter — Ferramenta de linting para Dockerfiles, disponível como action no marketplace.
- Deploy to Kubernetes with kubectl - GitHub Guide — Guia oficial do GitHub para deploy em clusters Kubernetes usando kubectl e kubeconfig.
- Using environments for deployment - GitHub Docs — Documentação sobre ambientes protegidos, regras de aprovação e variáveis por ambiente.
- Caching Docker layers in GitHub Actions — Guia da Docker Inc. sobre como usar cache de camadas para acelerar builds em pipelines.