Pular para o conteúdo principal

Padrões de Infraestrutura SOLID & Docker

Para manter a infraestrutura do Elo Orgânico, as ferramentas de DevOps e as automações do repositório altamente modulares, extensíveis e robustas, aplicamos os princípios de design SOLID diretamente aos layouts de diretórios, scripts shell, orquestração Docker e pipelines de CI/CD.


1. Aplicação Arquitetural do SOLID

Princípio da Responsabilidade Única (SRP)

Cada diretório e arquivo de configuração deve atender a exatamente um propósito operacional.

  • Separação de Preocupações: Separamos os ambientes de serviço específicos de tempo de execução (runtime) dos scripts de automação executados no host, modelos de esquemas de configuração e arquivos de orquestração.
  • Módulos de CI Reutilizáveis: Os fluxos de trabalho sob .github/workflows/ não devem duplicar a lógica de configuração do ambiente. Comportamentos compartilhados (como execução do node, instalações do PNPM e configurações de cache) são extraídos em GitHub Composite Actions independentes em .github/actions/.

Princípio Aberto/Fechado (OCP)

A infraestrutura deve estar aberta para extensão, mas fechada para modificação.

  • Serviços Plugáveis: Os serviços conteinerizados estão localizados sob um namespace unificado services/. Adicionar uma nova ferramenta ou container downstream exige apenas criar uma pasta independente (por exemplo, services/slack-notifier/) com sua própria configuração de ambiente, deixando os containers existentes do workspace e os scripts de automação intocados.

Princípio de Substituição de Liskov (LSP)

Todos os serviços conteinerizados devem estar em conformidade com um contrato de interface padronizado.

  • Contrato de Layout do Serviço: Cada subdiretório de ferramenta deve implementar uma interface uniforme que consiste em um Dockerfile na raiz, um entrypoint.sh implementando parâmetros padrão de logging e verificação de saúde (healthcheck) e ganchos de volume isolados.
  • API Unificada: Os scripts executados nos containers devem operar sob sinais de processo e associações de ambiente correspondentes.

Princípio da Segregação de Interface (ISP)

Cada serviço deve receber apenas os inputs e privilégios de sistema necessários para realizar sua tarefa específica.

  • Segregação Estrita de Env: Não passe um arquivo .env monolítico contendo todos os segredos do sistema para todos os containers. Em vez disso, defina arquivos de ambiente separados (por exemplo, .env.gh-cli e .env.git-agent) para que cada container opere dentro de sua superfície de segurança mínima.

Princípio da Inversão de Dependência (DIP)

Scripts de alto nível devem depender de interfaces abstratas de ambiente, e não de representações de caminhos físicos do host.

  • Abstração de Caminho: Scripts shell executados dentro de containers nunca devem usar caminhos relativos rígidos (hardcoded) para encontrar configurações na máquina host. Em vez disso, dependem de limites de variáveis de ambiente (como $SECRETS_DIR e $VARIABLES_FILE).
  • Injeção de Dependência: A camada de orquestração (docker-compose.yaml ou o executor do container) mapeia volumes físicos do host para os locais abstratos de arquivos esperados dentro do container.

2. Estrutura de Diretórios Padrão

Abaixo está a estrutura de diretórios exigida para workspaces de ferramentas do repositório (como tools/github/):

tools/github/
├── config/ # Esquemas de configuração e modelos de schemas
│ ├── security/
│ │ ├── .env.actions.secrets.example
│ │ └── variables.json
│ └── schemas/
│ └── secrets.schema.json
├── infrastructure/ # Camada de Orquestração
│ ├── docker/
│ │ ├── compose.yaml # Compositor Central Multi-Serviço
│ │ ├── .env.infra
│ │ └── .env.infra.example
│ └── logs/ # Logs de sistema isolados
├── scripts/ # Automação TS Executada no Host
│ ├── generate-changelog.ts
│ └── generate-roadmap.ts
└── services/ # Módulos de Serviço Plugáveis
├── gh-cli/ # Serviço de Sincronização do GitHub CLI
│ ├── Dockerfile
│ ├── entrypoint.sh # Contrato de entrypoint unificado
│ ├── .env.gh-cli.example
│ └── src/
│ └── sync_repo_secrets_variables.sh
└── git-agent/ # Automação de Commit / Assinatura do Git
├── Dockerfile
├── entrypoint.sh
├── .env.git-agent.example
└── src/

3. Modelos de Implementação

Componente de CI Reutilizável: .github/actions/setup-pnpm-env/action.yml (SRP)

Em vez de duplicar configurações de dependências nos workflows do GitHub, extraia-os em uma ação composta:

name: 'Setup PNPM Environment'
description: 'Installs Node, PNPM, and configures dependency caching'

inputs:
node-version:
description: 'Node.js version to use'
required: false
default: '22'

runs:
using: 'composite'
steps:
- name: Checkout Repository
uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Install pnpm
uses: pnpm/action-setup@v6

- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: ${{ inputs.node-version }}
cache: 'pnpm'

- name: Install Dependencies
shell: bash
run: pnpm install

Contrato de Script Desacoplado: sync_repo_secrets_variables.sh (DIP)

Este script depende estritamente de parâmetros injetados pelo ambiente, abstraindo completamente os caminhos físicos de disco na máquina executora:

#!/usr/bin/env bash

set -euo pipefail

log_info() {
echo "[GH-CLI INFO] $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

log_error() {
echo "[GH-CLI ERROR] $(date '+%Y-%m-%d %H:%M:%S') - $1" >&2
}

# Verifica se as dependências foram injetadas via ambiente
if [[ -z "${SECRETS_DIR:-}" ]]; then
log_error "A variável de ambiente obrigatória SECRETS_DIR não está definida."
exit 1
fi

if [[ -z "${VARIABLES_FILE:-}" ]]; then
log_error "A variável de ambiente obrigatória VARIABLES_FILE não está definida."
exit 1
fi

log_info "Lendo variáveis de: $VARIABLES_FILE"
log_info "Escaneando diretório de segredos: $SECRETS_DIR"

if [[ ! -f "$VARIABLES_FILE" ]]; then
log_error "Arquivo de variáveis não encontrado em: $VARIABLES_FILE"
exit 1
fi

log_info "Sincronização concluída com sucesso."

Orquestrador Desacoplado: compose.yaml (DIP & ISP)

O orquestrador mapeia arquivos físicos locais para os alvos abstratos exigidos pelo limite do container:

services:
gh-cli:
build:
context: ../../services/gh-cli
dockerfile: Dockerfile
container_name: elo-tools-gh-cli
env_file:
- .env.infra
environment:
- SECRETS_DIR=/etc/github-tool/secrets
- VARIABLES_FILE=/etc/github-tool/variables/variables.json
- GITHUB_TOKEN=${GITHUB_TOKEN}
volumes:
- ../../config/security/secrets:/etc/github-tool/secrets:ro
- ../../config/security/variables:/etc/github-tool/variables:ro
- ../../infrastructure/logs:/var/log/gh-cli:rw
restart: 'no'

Benefícios de Extensibilidade

Sob este layout, adicionar um novo container de ferramentas (por exemplo, sentry-uploader ou sonar-scanner) é tão simples quanto colocar uma pasta sob services/, estabelecer seus requisitos de .env e registrá-lo em /infrastructure/docker/compose.yaml. As ações de core, fluxos de trabalho e diretórios de configuração existentes permanecem bloqueados e completamente seguros.