(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

CI/CD Terraform com GitHub Actions: validar e planear

João Barros 24 de July de 2026 3 min de leitura

Automatizar a validação e o planeamento de Terraform com GitHub Actions acelera revisões e reduz erros humanos. Este tutorial mostra como configurar uma pipeline que faz terraform fmt, init, validate e terraform plan e publica o resultado como comentário no Pull Request. Ao automatizar estes passos, consegue detetar problemas antes do merge e dar contexto às decisões de infraestrutura aos revisores — por exemplo, saber que um terraform plan prevê a criação de 3 recursos e a modificação de 1, sem ter de executar comandos localmente.

Pré-requisitos

  • Conta GitHub com repositório (público ou privado). Recomenda-se repositório com branch protegida e políticas de revisão.
  • Conhecimentos básicos de Terraform (ficheiros .tf). Saber executar terraform init, terraform plan e interpretar a saída.
  • Git e GitHub CLI básicos para criar branches e Pull Requests. Um fluxo típico: branch com até 10 alterações .tf por PR é mais fácil de rever.
  • Segredos no GitHub (providers/credentials) quando necessário. Para um repositório com 1-2 providers, adicione as variáveis necessárias como secrets.

Passo 1: Estrutura mínima do repositório Terraform

Crie uma estrutura simples com um main.tf de exemplo. Mantemos o backend local para simplicidade — em produção use um backend remoto (S3, Azure Storage, etc.). Uma estrutura mínima para um módulo ou ambiente pode ser:

# main.tf
resource "null_resource" "exemplo" {
  provisioner "local-exec" {
    command = "echo Hello"
  }
}

Sugestão prática: mantenha o repositório organizado por pastas por ambiente (por exemplo, environments/dev, environments/prod) e limite cada PR a um ambiente quando possível. Para um repositório com 20-50 ficheiros .tf, a pipeline continua a funcionar — o tempo de execução sobe conforme o número de providers e módulos, tipicamente entre 10s a 2min para init+validate em pequenos projectos.

Passo 2: Criar o workflow do GitHub Actions

Criar um workflow em .github/workflows/terraform.yml que execute os passos: checkout, setup-terraform, terraform fmt, terraform init, terraform validate, terraform plan e publicar o plan no PR. Usamos actions oficiais para simplificar e garantir versões estáveis.

name: Terraform CI

on:
  pull_request:
    paths:
      - '**/*.tf'

jobs:
  terraform:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout
      uses: actions/checkout@v4

    - name: Setup Terraform
      uses: hashicorp/setup-terraform@v2
      with:
        terraform_version: 1.5.0

    - name: Terraform fmt
      run: terraform fmt -check -recursive

    - name: Terraform init
      run: terraform init -input=false

    - name: Terraform validate
      run: terraform validate

    - name: Terraform plan
      id: plan
      run: |
        terraform plan -no-color -out=plan.tfplan || true
        terraform show -no-color plan.tfplan > plan.txt || true
        echo "plan-body<> $GITHUB_OUTPUT
        cat plan.txt >> $GITHUB_OUTPUT
        echo "EOF" >> $GITHUB_OUTPUT

    - name: Comment plan on PR
      uses: peter-evans/create-or-update-comment@v3
      with:
        token: ${{ secrets.GITHUB_TOKEN }}
        issue-number: ${{ github.event.pull_request.number }}
        body: |
          **Terraform Plan**

          
Mostrar output do plan (abrir) ``` ${{ steps.plan.outputs.plan-body }} ```

Notas práticas: usar -no-color facilita a leitura em comentários. O passo terraform plan está a usar || true para garantir que, mesmo com exit code>0, capturamos a saída e comentamos no PR — ideal para diagnosticar erros sem bloquear a publicação do comentário.

Passo 3: Configurar segredos e providers

Se o seu Terraform usa providers que requerem credenciais (AWS, Azure, GCP), adicione os segredos no GitHub (Settings > Secrets > Actions). Exemplo para AWS:

- name: Configure AWS creds
  if: env.AWS_REQUIRED == 'true'
  run: |
    echo "AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }}" >> $GITHUB_ENV
    echo "AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }}" >> $GITHUB_ENV

Exemplo prático: para um pequeno projeto, defina 3 secrets (ACCESS_KEY, SECRET_KEY e REGION). Verifique que o token do GitHub Actions tem permissões para comentar PRs (GITHUB_TOKEN tem permissões por defeito, mas para repositórios com restrições pode ser necessário um token pessoal com permissões limitadas).

Passo 4: Lidar com erros comuns

Erros típicos e soluções rápidas:

  • terraform fmt -check falha: executar terraform fmt localmente ou ajustar CI para corrigir automaticamente usando terraform fmt -recursive. Em equipas, configure um pre-commit hook para evitar estes erros — pode reduzir falhas em CI em ~30%.
  • Provider auth falha: confirmar segredos no repositório e variáveis de ambiente no workflow. Verifique também o tempo de vida das chaves (rotina de rotação a cada 90 dias é comum).
  • terraform plan a falhar com exit code >0: capturamos a saída e continuamos a job com || true para poder comentar o plan; analise a saída no comentário. Se o plano falhar por falta de state remoto, verifique backend e locks.

Verificar o resultado

Abra um branch, faça alterações nos .tf e crie um Pull Request. Aceda ao separador Actions do PR e verifique que o workflow correu com sucesso. No próprio Pull Request deverá aparecer um comentário com a saída do terraform plan — se o comentário não aparecer, verifique os logs do passo Comment plan on PR e a permissão do GITHUB_TOKEN. Em projetos com CI médio, o tempo total desde o push até ao comentário é tipicamente 30s–3min.

Conclusão

Com esta pipeline básica de CI para Terraform, ganha automatização nas revisões e reduz riscos de regressão. Próximos passos recomendados: mover o state para um backend remoto (S3/Backend do Azure), adicionar job de terraform fmt automático que corrige ficheiros, e condicionar terraform apply a branches protegidos com aprovação manual. Pequenas melhorias, como bloquear merges sem comentários de plan ou adicionar análise de drift, podem reduzir incidentes em produção em dezenas de percentuais. Dica: quer que inclua um exemplo com backend remoto (S3/Consul/Azure Storage) e locks no workflow?