Environments e aprovações no GitHub Actions

1. Introdução aos Ambientes (Environments) no GitHub Actions

No ecossistema DevOps, ambientes representam estágios isolados do ciclo de vida de uma aplicação. No GitHub Actions, um Environment é um recurso que agrupa regras de proteção, secrets e variáveis específicos para um destino de deployment — como dev, staging ou production. Essa abstração permite que pipelines de CI/CD reajam de forma diferente conforme o contexto, sem duplicar lógica.

Quando combinamos com Docker e Kubernetes, os ambientes do GitHub Actions mapeiam diretamente para namespaces ou clusters. Por exemplo, o ambiente staging pode apontar para um namespace staging em um cluster compartilhado, enquanto production referencia um cluster dedicado com regras de acesso restritas. Essa separação garante que secrets como KUBECONFIG_PROD ou DOCKER_TAG sejam injetados apenas nos momentos corretos, evitando vazamentos acidentais.

2. Configuração de Environments no Repositório

A criação de ambientes é feita pelo menu Settings > Environments do repositório. Para cada ambiente, é possível definir:

  • Branches protegidos: apenas commits de branches específicos (ex: main, release/*) podem fazer deploy.
  • Revisores obrigatórios: um ou mais usuários ou equipes devem aprovar manualmente antes da execução.
  • Secrets e variáveis: cada ambiente possui seu próprio cofre. Por exemplo:
# Ambiente staging
KUBECONFIG_STAGING: base64 do kubeconfig do cluster staging
DOCKER_TAG: latest

# Ambiente production
KUBECONFIG_PROD: base64 do kubeconfig do cluster production
DOCKER_TAG: v1.2.3

Essa separação evita que credenciais de produção sejam expostas em logs de staging.

3. Aprovações Manuais como Gate de Qualidade

A aprovação manual é um dos mecanismos mais poderosos do GitHub Actions para impor qualidade. Ao configurar um ambiente com revisores obrigatórios, o workflow pausa automaticamente até que todos os aprovadores confirmem a execução.

O fluxo típico para uma entrega segura:

  1. Commit na branch main → dispara CI automático (lint, testes, build Docker).
  2. Deploy automático em staging → job sem aprovação, usando environment: staging.
  3. Job de produção → configurado com environment: production e revisores. O GitHub Actions exibe uma notificação no repositório e envia e-mail para os aprovadores.
  4. Aprovação concedida → o job é executado, realizando o deploy no Kubernetes de produção.

Enquanto a aprovação estiver pendente, o workflow fica em estado "waiting" e pode ser cancelado ou rejeitado.

4. Utilizando Environments no Workflow YAML

A sintaxe para associar um ambiente a um job é direta:

jobs:
  deploy-prod:
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://app.exemplo.com
    steps:
      - name: Deploy to Kubernetes
        run: kubectl apply -f k8s/production.yaml
        env:
          KUBECONFIG: ${{ secrets.KUBECONFIG_PROD }}

O campo environment.name vincula o job ao ambiente configurado. O campo environment.url (opcional) exibe um link para o deployment no GitHub, útil para monitoramento pós-deploy.

Se o ambiente exigir aprovação, o job aguardará até que todos os revisores aprovem. É possível usar needs para encadear jobs e garantir que o deploy em produção só ocorra após o sucesso em staging:

jobs:
  staging:
    environment: staging
    steps:
      - run: echo "Deploy em staging"
  production:
    needs: [staging]
    environment: production
    steps:
      - run: echo "Deploy em produção (após aprovação)"

5. Proteções Avançadas: Regras de Deployment

Além de revisores, o GitHub Actions oferece outras proteções:

  • Wait timer: define um tempo mínimo (em minutos) que o workflow deve esperar antes de executar o job. Útil para rollback automático se algo for detectado nos primeiros minutos.
  • Branches protegidas: combinadas com ambientes, impedem deployment direto em produção sem passar por staging. Por exemplo, apenas a branch main pode fazer deploy em production, e apenas após aprovação.
  • Impedindo bypass: mesmo com permissão de escrita no repositório, um desenvolvedor não pode pular a aprovação manual — a menos que seja um administrador com acesso à configuração do ambiente.

Para ambientes críticos, recomenda-se usar deployment branches específicas (ex: release/*) e exigir revisão de pelo menos duas pessoas.

6. Integração com CI/CD para Kubernetes

Um pipeline completo para Kubernetes usando ambientes e aprovações pode ser estruturado assim:

name: CI/CD Kubernetes

on:
  push:
    branches: [main]

jobs:
  lint-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Lint Dockerfile
        run: docker build --check .
      - name: Run unit tests
        run: npm test

  build:
    needs: [lint-test]
    runs-on: ubuntu-latest
    steps:
      - name: Build and push Docker image
        run: |
          docker build -t registry.exemplo.com/app:${{ github.sha }} .
          docker push registry.exemplo.com/app:${{ github.sha }}

  deploy-staging:
    needs: [build]
    environment:
      name: staging
      url: https://staging.app.exemplo.com
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to staging namespace
        run: |
          kubectl set image deployment/app app=registry.exemplo.com/app:${{ github.sha }} -n staging

  deploy-production:
    needs: [deploy-staging]
    environment:
      name: production
      url: https://app.exemplo.com
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to production namespace
        run: |
          kubectl set image deployment/app app=registry.exemplo.com/app:${{ github.sha }} -n production
        env:
          KUBECONFIG: ${{ secrets.KUBECONFIG_PROD }}

Nesse fluxo, o deploy em staging é automático, enquanto produção aguarda aprovação manual. A imagem Docker é construída uma vez e promovida entre ambientes, garantindo consistência.

7. Boas Práticas e Troubleshooting

Versionamento de ambientes: no Kubernetes, use labels como environment: staging e environment: production nos manifests. Combine com tags de imagem imutáveis (ex: v1.2.3 ou sha-abc123) para rastreabilidade.

Logs e debugging: se uma aprovação ficar pendente por muito tempo, verifique:
- Se os revisores configurados têm acesso ao repositório.
- Se o ambiente não está com Wait timer ativo.
- Se o workflow não foi cancelado por timeout.

Ambientes efêmeros (review apps): para PRs, crie ambientes dinâmicos usando environment.name: pr-${{ github.event.number }}. Cada PR ganha um namespace temporário no Kubernetes, que é destruído ao fechar o PR.

Múltiplos clusters: defina um ambiente por cluster (ex: us-east-prod, eu-west-prod). Cada um com seu KUBECONFIG e revisores específicos.

Secrets centralizados: evite duplicar secrets nos ambientes. Use Actions Secrets no nível do repositório e referencie apenas o necessário em cada ambiente.

Referências