🔄 O que é CI/CD?
CI (Continuous Integration) é a prática de integrar código frequentemente ao repositório principal, com build e testes automáticos a cada commit. O objetivo é detectar problemas cedo.
CD (Continuous Delivery/Deployment) estende o CI automatizando a entrega do software até produção:
- Continuous Delivery — o artefato está sempre pronto para deploy, mas o acionamento é manual
- Continuous Deployment — cada commit aprovado vai automaticamente para produção
🗺️ Fluxo do Pipeline
Um pipeline CI/CD típico passa pelas seguintes etapas:
⚙️ GitHub Actions
O GitHub Actions é a ferramenta de CI/CD nativa do GitHub. Pipelines são definidos em arquivos YAML dentro de .github/workflows/.
Pipeline completo: build, test e push para ECR
# .github/workflows/ci.yml
name: CI — Build e Push ECR
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
AWS_REGION: us-east-1
ECR_REPOSITORY: minha-app
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout código
uses: actions/checkout@v4
- name: Configurar credenciais AWS
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Login no Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Rodar testes
run: |
npm ci
npm test
- name: Build e push da imagem
env:
REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
# Tag latest também
docker tag $REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG \
$REGISTRY/$ECR_REPOSITORY:latest
docker push $REGISTRY/$ECR_REPOSITORY:latest
Pipeline de deploy após o build:
# .github/workflows/deploy.yml
name: CD — Deploy ECS
on:
workflow_run:
workflows: [CI — Build e Push ECR]
branches: [main]
types: [completed]
jobs:
deploy:
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest
steps:
- name: Configurar AWS
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Deploy no ECS
run: |
aws ecs update-service \
--cluster producao \
--service minha-app \
--force-new-deployment
🚀 AWS CodePipeline
O CodePipeline é o serviço de CI/CD gerenciado da AWS. Integra nativamente com CodeCommit, CodeBuild, CodeDeploy, S3, ECR e ECS.
| Estágio | Serviço AWS | Função |
|---|---|---|
| Source | CodeCommit / GitHub / S3 | Detecta mudanças no repositório |
| Build | CodeBuild | Compila, testa e gera artefatos |
| Test | CodeBuild | Testes automatizados |
| Deploy | CodeDeploy / ECS / CloudFormation | Publica em staging/produção |
| Approval | SNS + Manual | Gate de aprovação humana |
# Criar pipeline via AWS CLI
aws codepipeline create-pipeline \
--pipeline file://pipeline.json \
--region us-east-1
# Ver status do pipeline
aws codepipeline get-pipeline-state \
--name meu-pipeline \
--region us-east-1
# Acionar manualmente
aws codepipeline start-pipeline-execution \
--name meu-pipeline \
--region us-east-1
🔨 AWS CodeBuild — buildspec.yml
O CodeBuild executa builds em containers gerenciados. O arquivo buildspec.yml define os comandos de cada fase:
# buildspec.yml — build de imagem Docker e push para ECR
version: 0.2
env:
variables:
AWS_DEFAULT_REGION: us-east-1
IMAGE_REPO_NAME: minha-app
parameter-store:
IMAGE_TAG: /codebuild/image-tag
phases:
pre_build:
commands:
- echo Fazendo login no ECR...
- aws ecr get-login-password | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
- COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
- IMAGE_TAG=${COMMIT_HASH:=latest}
build:
commands:
- echo Rodando testes...
- npm ci && npm test
- echo Buildando imagem Docker...
- docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG .
- docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
post_build:
commands:
- echo Fazendo push da imagem...
- docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
- printf '[{"name":"minha-app","imageUri":"%s"}]' $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG > imagedefinitions.json
artifacts:
files:
- imagedefinitions.json # usado pelo CodeDeploy para atualizar o ECS
🐳 Deploy Automatizado no ECS
Com a imagem no ECR, o deploy no ECS pode ser feito de forma totalmente automatizada:
# Atualizar serviço ECS com nova imagem (rolling update)
aws ecs update-service \
--cluster meu-cluster \
--service minha-app \
--force-new-deployment \
--region us-east-1
# Aguardar estabilização
aws ecs wait services-stable \
--cluster meu-cluster \
--services minha-app \
--region us-east-1
# Verificar tasks em execução
aws ecs list-tasks \
--cluster meu-cluster \
--service-name minha-app \
--region us-east-1
imagedefinitions.json gerado pelo CodeBuild informa ao CodePipeline qual imagem usar no deploy do ECS — é a "cola" entre os estágios de build e deploy.🎯 Estratégias de Deploy
Escolha a estratégia certa para minimizar risco e downtime:
🔄 Rolling Update
Substitui instâncias antigas gradualmente. Simples, sem custo extra. Risco: versões mistas por alguns minutos.
🔵🟢 Blue/Green
Dois ambientes idênticos. O tráfego é chaveado de uma vez. Rollback instantâneo. Custo: dobra a infra temporariamente.
🐦 Canary
Envia % pequeno do tráfego para a nova versão (ex: 5%). Aumenta gradualmente se estável. Ideal para validar em produção.
🔒 Feature Flags
Deploy do código desativado. Ativa por usuário/grupo sem novo deploy. Máximo controle, requer implementação no código.
| Estratégia | Downtime | Rollback | Custo | Complexidade |
|---|---|---|---|---|
| Rolling | Zero | Lento | Baixo | Baixa |
| Blue/Green | Zero | Instantâneo | Alto | Média |
| Canary | Zero | Rápido | Médio | Alta |
| Feature Flags | Zero | Instantâneo | Baixo | Alta |
✅ Boas Práticas de CI/CD
- Pipeline rápido: mantenha o CI abaixo de 10 minutos — pipelines lentos são ignorados
- Fail fast: coloque os testes mais rápidos primeiro (unitários antes de integração)
- Imutabilidade: nunca altere uma imagem já publicada — sempre gere uma nova com nova tag
- Secrets seguros: use GitHub Secrets, AWS SSM Parameter Store ou Secrets Manager — nunca variáveis hardcoded
- Ambientes separados: dev → staging → produção, com aprovação manual antes de produção
- Notificações: configure alertas no Slack/Teams para falhas no pipeline
- Rollback automatizado: monitore métricas pós-deploy e reverta automaticamente se houver degradação
- Versionamento de artefatos: use o hash do commit como tag da imagem Docker — rastreabilidade total
