Versionamento de scripts e change tracking
1. Fundamentos do Versionamento para Scripts Bash
Versionar scripts Bash não é apenas uma boa prática — é uma necessidade para qualquer ambiente que dependa de automação. Sem controle de versão, uma simples alteração mal documentada pode quebrar pipelines inteiros sem possibilidade de rollback rápido. O versionamento oferece rastreabilidade completa: quem modificou o quê, quando e por quê.
A estrutura de diretórios recomendada para um repositório de scripts Bash é:
projeto-scripts/
├── scripts/ # Scripts executáveis principais
├── lib/ # Funções e bibliotecas compartilhadas
├── tests/ # Testes unitários (com bats, shunit2, etc.)
├── CHANGELOG.md # Documentação de mudanças por versão
├── CHANGELOG/ # (opcional) changelogs por release
├── .gitignore # Arquivos ignorados pelo Git
└── README.md
O Git é o sistema de controle de versão padrão da indústria, mas alternativas como Mercurial e SVN ainda são usadas em contextos legados. Para scripts Bash, o Git oferece leveza, branching eficiente e integração com CI/CD.
2. Organização do Repositório com Múltiplos Scripts
Para projetos com múltiplos scripts, duas abordagens são comuns:
- Monorepo: todos os scripts em um único repositório. Vantagens: consistência, reuso de funções
lib/, facilidade de refatoração cruzada. Desvantagem: repositório grande. - Múltiplos repositórios: cada script ou conjunto de scripts em repositórios separados. Vantagem: isolamento. Desvantagem: dificuldade de manutenção de dependências.
A padronização de nomes é crucial. Use kebab-case para scripts (backup-database.sh, deploy-app.sh) e prefixos de domínio (net:ping, fs:clean-temp). Exemplo de função em lib/utils.sh:
# lib/utils.sh
# Função para logging padronizado
log_info() {
echo "[INFO] $(date '+%Y-%m-%d %H:%M:%S') - $*"
}
O .gitignore deve ignorar arquivos temporários, logs e outputs de execução:
# .gitignore
*.log
*.tmp
output/
__pycache__/
*.swp
.env
3. Estratégias de Branching e Fluxo de Trabalho
Adapte o Git Flow para scripts Bash:
main— versão estável e em produçãodevelop— integração de features em desenvolvimentofeature/*— branches para novas funcionalidades (ex.:feature/backup-s3)hotfix/*— correções urgentes em produção (ex.:hotfix/fix-permissions)
Commits semânticos facilitam a geração de changelog:
feat(backup): adiciona suporte a compressão gzip
fix(deploy): corrige permissão do diretório temporário
docs(readme): atualiza instruções de instalação
refactor(utils): extrai função de validação de data
Políticas de merge: todo merge para main ou develop deve passar por revisão de código (pull request) e testes automatizados. Exemplo de comando para criar um branch de feature:
git checkout -b feature/backup-encryption develop
git commit -m "feat(backup): adiciona criptografia AES-256"
git push origin feature/backup-encryption
4. Versionamento Semântico e Tags
Aplique SemVer (MAJOR.MINOR.PATCH) aos scripts Bash:
- MAJOR: mudanças incompatíveis (ex.: alteração de parâmetros obrigatórios)
- MINOR: novas funcionalidades compatíveis (ex.: nova flag
--compress) - PATCH: correções de bugs ou melhorias internas
Crie tags Git para releases:
git tag -a v1.0.0 -m "Release v1.0.0 - Backup com criptografia"
git tag -a v1.1.0-beta -m "Release v1.1.0-beta - Suporte a S3"
git push origin --tags
Para gerar changelog automaticamente a partir de commits e tags, use o comando:
git log --oneline --decorate v1.0.0..v1.1.0
5. Change Tracking e Documentação de Mudanças
Mantenha um CHANGELOG.md com seções por versão, seguindo o padrão Keep a Changelog:
# Changelog
## [1.1.0] - 2024-03-15
### Added
- Suporte a compressão gzip no backup
- Flag --encrypt para criptografia AES-256
### Fixed
- Permissão do diretório temporário em sistemas SELinux
## [1.0.0] - 2024-02-20
### Added
- Funcionalidade básica de backup de banco de dados
- Logs com timestamp
Use git log e git diff para rastrear alterações específicas:
# Ver commits de um arquivo específico
git log --oneline scripts/backup.sh
# Ver diff entre duas versões
git diff v1.0.0..v1.1.0 -- scripts/backup.sh
Inclua um cabeçalho em cada script com versão, autor e histórico:
#!/usr/bin/env bash
# backup.sh - Script de backup de banco de dados
# Versão: 1.1.0
# Autor: Maria Silva <maria@exemplo.com>
# Última modificação: 2024-03-15
# Histórico:
# 1.0.0 - 2024-02-20 - Versão inicial
# 1.1.0 - 2024-03-15 - Adicionado compressão e criptografia
6. Integração com Ferramentas de CI/CD e Linting
Em pipelines CI/CD, valide o versionamento antes de cada deploy:
# Exemplo de checagem em pipeline (GitHub Actions)
- name: Check version tag
run: |
if ! git describe --exact-match HEAD 2>/dev/null; then
echo "Erro: commit não tem tag de versão"
exit 1
fi
Use ShellCheck para linting e testes unitários com bats:
# Instalar ShellCheck
sudo apt install shellcheck
# Verificar script
shellcheck scripts/backup.sh
# Executar testes com bats
bats tests/backup.bats
Automatize o bump de versão com um script auxiliar bump.sh:
#!/usr/bin/env bash
# bump.sh - Incrementa versão e cria tag
VERSION=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
MAJOR=$(echo "$VERSION" | cut -d. -f1 | tr -d 'v')
MINOR=$(echo "$VERSION" | cut -d. -f2)
PATCH=$(echo "$VERSION" | cut -d. -f3)
case "$1" in
major) MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 ;;
minor) MINOR=$((MINOR + 1)); PATCH=0 ;;
patch) PATCH=$((PATCH + 1)) ;;
*) echo "Uso: $0 {major|minor|patch}"; exit 1 ;;
esac
NEW_TAG="v${MAJOR}.${MINOR}.${PATCH}"
git tag -a "$NEW_TAG" -m "Release $NEW_TAG"
git push origin "$NEW_TAG"
echo "Nova tag: $NEW_TAG"
7. Boas Práticas para Colaboração e Revisão
Pull requests devem ter descrição clara das mudanças e impacto nos scripts:
## Descrição
Adiciona suporte a backup incremental com rsync.
## Mudanças
- scripts/backup.sh: nova flag --incremental
- lib/rsync-utils.sh: funções auxiliares para rsync
- tests/backup.bats: testes para backup incremental
## Impacto
- Compatível com versões anteriores (flag opcional)
- Requer rsync instalado no sistema
A revisão de código deve focar em:
- Portabilidade: evite construções específicas de Bash (use
#!/usr/bin/env bash) - Segurança: valide entradas, evite
eval, use aspas em variáveis - Compatibilidade: scripts devem funcionar em Bash 4.x+
Use hooks Git para validar formatação e versionamento:
# .git/hooks/pre-commit
#!/usr/bin/env bash
echo "Executando ShellCheck..."
for file in $(git diff --cached --name-only --diff-filter=ACM | grep '\.sh$'); do
shellcheck "$file" || exit 1
done
8. Exemplos Práticos e Templates
Template de cabeçalho de script com versionamento e changelog inline:
#!/usr/bin/env bash
# deploy.sh - Script de deploy automatizado
# Versão: 2.0.0
# Autor: João Costa <joao@exemplo.com>
# Última modificação: 2024-03-20
# Histórico:
# 1.0.0 - 2024-01-10 - Versão inicial com deploy via scp
# 1.1.0 - 2024-02-05 - Adicionado suporte a rollback
# 2.0.0 - 2024-03-20 - Reescrevido para usar rsync (incompatível com v1.x)
Script para gerar changelog automático a partir de tags:
#!/usr/bin/env bash
# generate-changelog.sh
# Gera changelog entre duas tags
PREV_TAG=$(git describe --tags --abbrev=0 HEAD~1 2>/dev/null || echo "")
CURR_TAG=$(git describe --tags --abbrev=0 HEAD 2>/dev/null || echo "HEAD")
if [ -z "$PREV_TAG" ]; then
echo "## [$CURR_TAG] - $(date +%Y-%m-%d)"
git log --oneline --no-decorate
else
echo "## [$CURR_TAG] - $(date +%Y-%m-%d)"
echo "### Mudanças desde $PREV_TAG"
git log --oneline --no-decorate "$PREV_TAG..$CURR_TAG"
fi
Comandos úteis para o dia a dia:
# Criar tag anotada
git tag -a v1.0.0 -m "Release v1.0.0 - Backup básico"
# Ver histórico com tags
git log --oneline --decorate
# Listar todas as tags
git tag -l
# Ver diff entre duas versões de um script
git diff v1.0.0..v1.1.0 -- scripts/backup.sh
Referências
- Git - Documentação Oficial de Tags — Guia completo sobre criação e gerenciamento de tags no Git, essencial para versionamento semântico.
- Semantic Versioning 2.0.0 — Especificação oficial do versionamento semântico, aplicável a scripts Bash.
- Keep a Changelog — Padrão recomendado para manutenção de changelogs em projetos de software.
- ShellCheck - Ferramenta de Linting para Shell Script — Analisador estático para scripts shell, indispensável para validação de qualidade.
- Git Flow - Estratégia de Branching — Tutorial da Atlassian sobre Git Flow, adaptável para versionamento de scripts.
- Bats - Bash Automated Testing System — Framework de testes unitários para Bash, útil para garantir estabilidade antes de cada release.