📄 backup_db.sh
🚀 deploy_prod.sh
📊 process_intake.sh
🔎 monitor_services.sh
⚙️ Configuración
backup_db.sh
scripts/infra/backup_db.sh 2 errores 3 warningsDistribución de problemas — backup_db.sh
error (crítico)
2
warning
3
SC2086
línea 14
Double quote to prevent globbing and word splitting
warning
backup_db.sh · antes
PROBLEMA
# Línea 14: variable sin comillas → riesgo de word splitting pg_dump -U $DB_USER -h $DB_HOST $DB_NAME > $BACKUP_FILE
backup_db.sh · después
CORRECCIÓN
pg_dump -U "$DB_USER" -h "$DB_HOST" "$DB_NAME" > "$BACKUP_FILE"
Si
$DB_HOST o $DB_NAME contienen espacios, el comando falla silenciosamente con parámetros corruptos. Siempre citar variables en expansiones.
SC2181
línea 27
Check exit code directly with `if`, not indirectly via $?
warning
backup_db.sh · antesPROBLEMA
pg_dump ... > "$BACKUP_FILE" if [ $? -ne 0 ]; then echo "ERROR: backup fallido" exit 1 fi
backup_db.sh · despuésCORRECCIÓN
if ! pg_dump ... > "$BACKUP_FILE"; then echo "ERROR: backup fallido" exit 1 fi
Usar
$? indirectamente puede fallar si otra instrucción se ejecuta entre medio. Comprueba el código de salida directamente en el if.
SC2009
línea 41
Consider using pgrep instead of grepping ps output
error
backup_db.sh · antesPROBLEMA
# Busca proceso postgres — puede matchear el propio grep PID=$(ps aux | grep -v grep | grep postgres | awk '{print $2}')
backup_db.sh · despuésCORRECCIÓN
# pgrep es más fiable y portable PID=$(pgrep -f postgres)
La cadena
grep | grep -v grep es frágil: en entornos con muchos procesos puede capturar PIDs incorrectos. pgrep es atómico y no tiene ese problema.
SC1091
línea 5
Not following: ./config/db.env: No such file at parse time
error
backup_db.sh · antesPROBLEMA
#!/bin/bash source ./config/db.env # ShellCheck no puede seguir este fichero
backup_db.sh · despuésCORRECCIÓN
#!/bin/bash # shellcheck source=./config/db.env source ./config/db.env # directiva da contexto a ShellCheck
En
.shellcheckrc se añadirá disable=SC1091 globalmente para ficheros externos conocidos como .env. Alternativamente, usa la directiva inline # shellcheck source= para máxima precisión.
SC2015
línea 55
Use if-then instead of A && B || C to avoid false negatives
warning
backup_db.sh · antesPROBLEMA
[ -d "$BACKUP_DIR" ] && echo "dir ok" || mkdir -p "$BACKUP_DIR"
backup_db.sh · despuésCORRECCIÓN
if [ -d "$BACKUP_DIR" ]; then echo "dir ok" else mkdir -p "$BACKUP_DIR" fi
Si el
echo falla por cualquier razón, la cláusula || mkdir se ejecuta igualmente aunque el directorio exista. La forma if/else es inequívoca.⚙️ Configuración generada para NutriSync
📄 .shellcheckrc
proyecto raíz
# NutriSync — ShellCheck config # Generado por CULTIVA IA · 2026-06-16 # Shell objetivo de NutriSync shell=bash # Checks opcionales habilitados enable=avoid-nullary-conditions enable=require-variable-braces enable=check-unassigned-uppercase # SC1091: .env no disponible en parse-time disable=SC1091 # SC2119: args de funciones (falsos positivos) disable=SC2119 # Seguir ficheros externos para análisis external-sources=true
🔄 .github/workflows/shellcheck.yml
CI/CD
name: ShellCheck on: push: branches: [main, staging] pull_request: branches: [main] jobs: shellcheck: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Instalar ShellCheck v0.10.0 run: | sudo apt-get install -y shellcheck - name: Analizar scripts run: | find scripts/ -name "*.sh" \ -exec shellcheck \ --format=gcc \ --exclude=SC1091 {} \; - name: Subir reporte JSON run: | find scripts/ -name "*.sh" \ -exec shellcheck --format=json {} \; \ > shellcheck-report.json if: always() - uses: actions/upload-artifact@v4 with: name: shellcheck-report path: shellcheck-report.json if: always()
🪝 .git/hooks/pre-commit — validación local antes de push
pre-commit
#!/bin/bash # NutriSync pre-commit hook — ShellCheck # Instalar: cp .git/hooks/pre-commit .git/hooks/pre-commit && chmod +x .git/hooks/pre-commit set -euo pipefail FAILED=0 CHECKED=0 # Analiza solo los .sh que cambian en este commit while IFS= read -r script; do CHECKED=$((CHECKED + 1)) echo " 🔍 Checking: $script" if ! shellcheck --exclude=SC1091 "$script"; then echo " ❌ ShellCheck FAILED: $script" FAILED=$((FAILED + 1)) fi done < <(git diff --cached --name-only | grep '\.sh$') if [ "$FAILED" -gt 0 ]; then echo "" echo "⛔ $FAILED script(s) con errores ShellCheck. Corrígelos antes de hacer commit." exit 1 fi if [ "$CHECKED" -gt 0 ]; then echo "✅ ShellCheck OK ($CHECKED scripts revisados)" fi
Resumen de calidad — todos los scripts
backup_db.sh
5 issues
deploy_prod.sh
7 issues
process_intake.sh
4 issues
monitor_services.sh
1 issue
● 3 errores críticos resueltos
● 9 warnings corregidos
● 5 sugerencias implementadas
● Pipeline CI/CD activo en main + staging