Shared Workflows: minha experiência definindo pipelines reutilizáveis
Source: Dev.to
Motivação
Nos últimos meses trabalhei na definição de um modelo padrão de shared workflows para projetos de backend Node.js e recursos de infraestrutura implantados na AWS. Em organizações com múltiplos times e repositórios, cada projeto costuma inventar seu pipeline (lint, test, build, deploy). Isso gera retrabalho, inconsistências de segurança e custo de manutenção alto. Minha meta foi criar um conjunto de workflows reutilizáveis — fáceis de configurar por repositórios consumidores — que reduzissem duplicação e padronizassem boas práticas.
Arquitetura dos Workflows
Optei por usar reusable workflows do GitHub Actions (on: workflow_call) e separar claramente as responsabilidades:
| Workflow | Responsabilidade |
|---|---|
| CI | lint, install, cache, unit/integration tests, security scan (yarn audit) |
| Infra CI | Terraform fmt / init / plan (shared‑terraform‑ci) |
| CD | build/push para ECR, deploy blue/green em ECS (shared‑backend‑deploy‑ecs) |
| Release | criação automática de branch de release e PR para main (shared‑release‑workflow) |
Essa separação facilita o reaproveitamento: um repositório pode chamar apenas o CI shared, ou o deploy shared, ou ambos através de wrappers.
Consumo do Shared CI
jobs:
ci:
uses: ./.github/workflows/shared-backend-ci.yml
with:
working_directory: app
node_version: '20'
enable_security_scan: true
secrets:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Wrapper que Executa Deploy em Staging e, Em Seguida, Chama o Workflow de Release
jobs:
deploy:
uses: ./.github/workflows/shared-backend-deploy-ecs.yml
with:
environment: staging
tf_backend_bucket: my-staging-state
tf_var_file: envs/staging/variables.tfvars
secrets:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
promote:
needs: deploy
if: ${{ needs.deploy.result == 'success' }}
uses: ./.github/workflows/shared-release.yml
secrets:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Reusable workflows via workflow_call favorecem versão e rollback centralizado. Consumidores apontam para uma tag (@v1) no repositório de shared workflows.
Permissões por Job
Segreguei permissões seguindo o princípio do menor privilégio:
- Jobs de lint/test:
contents: read - Jobs de release/deploy: permissões mais elevadas apenas quando estritamente necessário
Parametrização
Inputs como working_directory, app_path, image_tag e outros permitem que projetos com monorepos ou estruturas diferentes reutilizem os mesmos workflows.
Testes e Validação
- Teste local e validação estática com ferramentas:
actionlintshellcheckcheckov
Essas ferramentas evitaram regressões e problemas de segurança antes do merge.
Documentação e Adoção
- Criei um README conciso com exemplos práticos e nomes de secrets esperados.
- Consumidores adotam os shared workflows mais rápido quando encontram exemplos claros.
Piloto
Validar o modelo em um projeto piloto permitiu:
- Ajustar inputs
- Detectar diferenças (ex.: monorepo precisava de
working_directorydiferente)
Riscos & Mitigação
| Risco | Mitigação |
|---|---|
| Diferenças entre repositórios | Inputs configuráveis e exemplos detalhados |
| Permissões excessivas | Revisão de permissões por job e uso de roles para operações AWS |
| Dependência central | Documentar SLA de alterações e versionar via tags semânticas para evitar breaking changes |
Conclusão
Criar um modelo de shared workflows traz retorno rápido em escala:
- Menos esforço duplicado
- Pipelines padronizados
- Melhorias de segurança centralizadas
A chave do sucesso foi manter o design simples, parametrizável e bem documentado, além de validar por meio de um piloto real.
Recomendações para Iniciantes
- Comece pelo shared CI (lint/test).
- Evolua para um shared deploy com validações de infraestrutura (Terraform).
- Implemente deploys controlados (blue/green, aprovação manual, etc.).