#!/bin/bash # 🛠️ PR Tools - Ferramentas Avançadas para Análise de PRs # Autor: Jonas Santos # Versão: 1.0 # Data: Janeiro 2025 set -e # Cores RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' CYAN='\033[0;36m' WHITE='\033[1;37m' NC='\033[0m' # Função para análise de segurança security_analysis() { local branch=$1 local base_branch=${2:-main} echo -e "${RED}🔒 ANÁLISE DE SEGURANÇA${NC}" echo "----------------------------------------" local modified_files=$(git diff --name-only origin/$base_branch origin/$branch 2>/dev/null) # Padrões sensíveis echo -e "${YELLOW}🔍 Verificando padrões sensíveis...${NC}" local security_issues=0 # Buscar por padrões perigosos no código echo "$modified_files" | while read file; do if [ -n "$file" ] && [ -f "$file" ]; then # Verificar senhas hardcoded if git diff origin/$base_branch origin/$branch -- "$file" | grep -i -E "(password|senha)\s*=\s*['\"][^'\"]+['\"]" > /dev/null; then echo -e " 🚨 ${RED}$file: Possível senha hardcoded${NC}" security_issues=$((security_issues + 1)) fi # Verificar API keys if git diff origin/$base_branch origin/$branch -- "$file" | grep -i -E "(api_key|apikey|secret_key)\s*=\s*['\"][^'\"]+['\"]" > /dev/null; then echo -e " 🚨 ${RED}$file: Possível API key exposta${NC}" security_issues=$((security_issues + 1)) fi # Verificar URLs hardcoded de produção if git diff origin/$base_branch origin/$branch -- "$file" | grep -E "https?://[^/]*\.(com|org|net)" > /dev/null; then echo -e " ⚠️ ${YELLOW}$file: URL hardcoded encontrada${NC}" fi # Verificar console.log em produção if git diff origin/$base_branch origin/$branch -- "$file" | grep "console\." > /dev/null; then echo -e " ⚠️ ${YELLOW}$file: console.log encontrado${NC}" fi fi done if [ $security_issues -eq 0 ]; then echo -e " ✅ ${GREEN}Nenhum problema crítico de segurança detectado${NC}" fi } # Função para análise de performance performance_analysis() { local branch=$1 local base_branch=${2:-main} echo -e "\n${BLUE}⚡ ANÁLISE DE PERFORMANCE${NC}" echo "----------------------------------------" local modified_files=$(git diff --name-only origin/$base_branch origin/$branch 2>/dev/null) echo -e "${YELLOW}🔍 Verificando padrões que afetam performance...${NC}" echo "$modified_files" | while read file; do if [ -n "$file" ] && [ -f "$file" ]; then # Verificar loops aninhados if git diff origin/$base_branch origin/$branch -- "$file" | grep -E "for.*for|while.*while" > /dev/null; then echo -e " ⚠️ ${YELLOW}$file: Loops aninhados detectados${NC}" fi # Verificar operações DOM custosas if git diff origin/$base_branch origin/$branch -- "$file" | grep -E "querySelector|getElementById" > /dev/null; then echo -e " ⚠️ ${YELLOW}$file: Operações DOM manuais${NC}" fi # Verificar imports desnecessários if git diff origin/$base_branch origin/$branch -- "$file" | grep -E "import.*\*.*from" > /dev/null; then echo -e " ⚠️ ${YELLOW}$file: Import de toda biblioteca${NC}" fi # Verificar subscribe sem unsubscribe if git diff origin/$base_branch origin/$branch -- "$file" | grep "\.subscribe(" > /dev/null; then if ! git diff origin/$base_branch origin/$branch -- "$file" | grep -E "(unsubscribe|takeUntil|async)" > /dev/null; then echo -e " 🚨 ${RED}$file: Subscribe sem unsubscribe${NC}" fi fi fi done } # Função para análise de dependencies dependency_analysis() { local branch=$1 local base_branch=${2:-main} echo -e "\n${PURPLE}📦 ANÁLISE DE DEPENDÊNCIAS${NC}" echo "----------------------------------------" if git diff --name-only origin/$base_branch origin/$branch | grep -q "package.json"; then echo -e "${YELLOW}🔍 Mudanças em package.json detectadas...${NC}" # Mostrar diferenças em dependencies echo -e "\n${BLUE}Dependências alteradas:${NC}" git diff origin/$base_branch origin/$branch -- package.json | grep -E "^\+.*\".*\":" | sed 's/^+/ ✅ ADICIONADO:/' || true git diff origin/$base_branch origin/$branch -- package.json | grep -E "^\-.*\".*\":" | sed 's/^-/ ❌ REMOVIDO:/' || true # Verificar dependências perigosas echo -e "\n${RED}🚨 Verificando dependências sensíveis:${NC}" if git diff origin/$base_branch origin/$branch -- package.json | grep -E "eval|child_process|fs" > /dev/null; then echo -e " ⚠️ ${YELLOW}Dependência potencialmente perigosa detectada${NC}" else echo -e " ✅ ${GREEN}Nenhuma dependência sensível detectada${NC}" fi else echo -e " ℹ️ ${BLUE}Nenhuma mudança em dependências${NC}" fi } # Função para análise de código duplicado duplicate_code_analysis() { local branch=$1 local base_branch=${2:-main} echo -e "\n${CYAN}🔄 ANÁLISE DE CÓDIGO DUPLICADO${NC}" echo "----------------------------------------" local modified_files=$(git diff --name-only origin/$base_branch origin/$branch 2>/dev/null | grep -E "\.(ts|js)$") if [ -z "$modified_files" ]; then echo -e " ℹ️ ${BLUE}Nenhum arquivo de código para analisar${NC}" return fi echo -e "${YELLOW}🔍 Verificando duplicação de código...${NC}" # Verificar funções similares echo "$modified_files" | while read file; do if [ -n "$file" ] && [ -f "$file" ]; then # Contar funções com nomes similares local functions=$(git diff origin/$base_branch origin/$branch -- "$file" | grep -E "^\+.*function|^\+.*=>" | wc -l) if [ "$functions" -gt 3 ]; then echo -e " ⚠️ ${YELLOW}$file: $functions novas funções (verificar se há duplicação)${NC}" fi fi done } # Função para gerar checklist de PR generate_pr_checklist() { local branch=$1 local base_branch=${2:-main} echo -e "\n${WHITE}📋 CHECKLIST COMPLETO DO PR${NC}" echo "========================================" echo -e "${GREEN}🔍 REVISÃO DE CÓDIGO:${NC}" echo " [ ] Código segue padrões do projeto" echo " [ ] Nomenclatura clara e consistente" echo " [ ] Lógica de negócio está correta" echo " [ ] Tratamento de erros adequado" echo " [ ] Sem código comentado/debug" echo " [ ] Imports organizados" echo -e "\n${YELLOW}🧪 TESTES:${NC}" echo " [ ] Testes unitários criados/atualizados" echo " [ ] Todos os testes passando" echo " [ ] Cobertura de código adequada" echo " [ ] Testes de integração (se necessário)" echo -e "\n${BLUE}🚀 FUNCIONALIDADE:${NC}" echo " [ ] Feature funciona conforme especificado" echo " [ ] Casos edge testados" echo " [ ] Responsividade verificada" echo " [ ] Performance adequada" echo " [ ] Acessibilidade considerada" echo -e "\n${RED}🔒 SEGURANÇA:${NC}" echo " [ ] Sem credenciais hardcoded" echo " [ ] Validação de inputs" echo " [ ] Autorização/autenticação OK" echo " [ ] Sem vazamentos de dados sensíveis" echo -e "\n${PURPLE}📦 DEPENDÊNCIAS:${NC}" echo " [ ] Novas dependências justificadas" echo " [ ] Versões compatíveis" echo " [ ] Bundle size não aumentou muito" echo -e "\n${CYAN}📚 DOCUMENTAÇÃO:${NC}" echo " [ ] README atualizado (se necessário)" echo " [ ] Comentários no código (se complexo)" echo " [ ] Changelog atualizado" echo " [ ] API docs atualizadas" } # Função para comparar branches compare_branches() { local branch1=$1 local branch2=$2 echo -e "${WHITE}🔄 COMPARAÇÃO ENTRE BRANCHES${NC}" echo "========================================" echo -e "${BLUE}Branch 1:${NC} $branch1" echo -e "${BLUE}Branch 2:${NC} $branch2" echo "" # Commits únicos em cada branch echo -e "${YELLOW}📊 Commits únicos:${NC}" echo -e "\n${GREEN}Em $branch1 mas não em $branch2:${NC}" git log --oneline $branch2..$branch1 || echo " Nenhum commit único" echo -e "\n${GREEN}Em $branch2 mas não em $branch1:${NC}" git log --oneline $branch1..$branch2 || echo " Nenhum commit único" # Diferenças de arquivos echo -e "\n${YELLOW}📁 Diferenças de arquivos:${NC}" git diff --name-status $branch1 $branch2 | head -20 } # Função para análise de commit messages analyze_commit_messages() { local branch=$1 local base_branch=${2:-main} echo -e "\n${WHITE}💬 ANÁLISE DE MENSAGENS DE COMMIT${NC}" echo "========================================" local commits=$(git log --format="%s" origin/$base_branch..origin/$branch 2>/dev/null) if [ -z "$commits" ]; then echo -e " ℹ️ ${BLUE}Nenhum commit único encontrado${NC}" return fi echo -e "${YELLOW}🔍 Verificando padrões de commit...${NC}" local good_commits=0 local total_commits=0 echo "$commits" | while read message; do if [ -n "$message" ]; then total_commits=$((total_commits + 1)) # Verificar se segue conventional commits if echo "$message" | grep -E "^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?: " > /dev/null; then echo -e " ✅ ${GREEN}$message${NC}" good_commits=$((good_commits + 1)) else echo -e " ⚠️ ${YELLOW}$message${NC}" fi fi done } # Função principal main() { local command="" local branch1="" local branch2="main" local show_help=false # Parse dos argumentos while [[ $# -gt 0 ]]; do case $1 in security|sec) command="security" branch1="$2" shift 2 ;; performance|perf) command="performance" branch1="$2" shift 2 ;; dependencies|deps) command="dependencies" branch1="$2" shift 2 ;; checklist|check) command="checklist" branch1="$2" shift 2 ;; compare|comp) command="compare" branch1="$2" branch2="$3" shift 3 ;; commits|msg) command="commits" branch1="$2" shift 2 ;; full|all) command="full" branch1="$2" shift 2 ;; -h|--help) show_help=true shift ;; *) if [ -z "$command" ]; then command="full" branch1="$1" fi shift ;; esac done # Mostrar ajuda if [ "$show_help" = true ]; then echo "🛠️ PR Tools - Ferramentas Avançadas para Análise de PRs" echo "" echo "Uso: $0 [argumentos]" echo "" echo "Comandos:" echo " security Análise de segurança" echo " performance Análise de performance" echo " dependencies Análise de dependências" echo " checklist Gerar checklist de PR" echo " compare Comparar branches" echo " commits Análise de mensagens de commit" echo " full Análise completa" echo "" echo "Exemplos:" echo " $0 security feature/new-login" echo " $0 performance feature/optimization" echo " $0 compare feature/a feature/b" echo " $0 full feature/checkbox-vehicle" exit 0 fi # Verificar se é repositório git if ! git rev-parse --git-dir > /dev/null 2>&1; then echo -e "${RED}❌ Erro: Este diretório não é um repositório Git.${NC}" >&2 exit 1 fi # Executar comando case $command in security) security_analysis "$branch1" "$branch2" ;; performance) performance_analysis "$branch1" "$branch2" ;; dependencies) dependency_analysis "$branch1" "$branch2" ;; checklist) generate_pr_checklist "$branch1" "$branch2" ;; compare) compare_branches "$branch1" "$branch2" ;; commits) analyze_commit_messages "$branch1" "$branch2" ;; full) security_analysis "$branch1" "$branch2" performance_analysis "$branch1" "$branch2" dependency_analysis "$branch1" "$branch2" duplicate_code_analysis "$branch1" "$branch2" analyze_commit_messages "$branch1" "$branch2" generate_pr_checklist "$branch1" "$branch2" ;; *) echo -e "${RED}❌ Comando inválido. Use -h para ajuda.${NC}" exit 1 ;; esac } # Executar função principal main "$@"