🔧 Tech Tips Monday: 7 Técnicas de Code Quality Automation que Elevan tu Código

Arrancamos una nueva semana con Tech Tips Monday. Hoy enfoque en automatización de calidad de código: técnicas y herramientas que mantienen tu codebase limpio, consistente y mantenible sin esfuerzo manual.

:high_voltage: 1. Pre-commit Hooks Inteligentes con Husky + Lint-staged

Evita que código problemático llegue al repositorio configurando validaciones automáticas:

// package.json
{
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged",
      "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
    }
  },
  "lint-staged": {
    "*.{js,ts,tsx}": [
      "eslint --fix",
      "prettier --write",
      "jest --bail --findRelatedTests --passWithNoTests"
    ],
    "*.{css,scss,md}": ["prettier --write"],
    "*.{json,yaml,yml}": ["prettier --write"]
  }
}

Configuración avanzada:

# Instalar dependencias
npm install --save-dev husky lint-staged @commitlint/cli @commitlint/config-conventional

# Configurar hooks automáticamente
npx husky-init && npm install
npx husky add .husky/pre-commit "npx lint-staged"

Resultado: Código siempre formateado, tests ejecutados, y commits que siguen convenciones estándar.

:bullseye: 2. Code Coverage Automation con Threshold Enforcement

Mantén coverage alto automáticamente configurando thresholds que bloqueen merges:

// jest.config.js
module.exports = {
  collectCoverage: true,
  coverageThreshold: {
    global: {
      branches: 80,
      functions: 80,
      lines: 80,
      statements: 80
    },
    // Thresholds específicos por directorio
    "./src/utils/": {
      branches: 90,
      functions: 95,
      lines: 95,
      statements: 95
    }
  },
  coverageReporters: ["text", "lcov", "html"],
  collectCoverageFrom: [
    "src/**/*.{js,ts}",
    "!src/**/*.d.ts",
    "!src/**/*.test.{js,ts}",
    "!src/**/index.ts"
  ]
};

GitHub Actions integration:

# .github/workflows/coverage.yml
name: Code Coverage
on: [pull_request]

jobs:
  coverage:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      - name: Install dependencies
        run: npm ci
      - name: Run tests with coverage
        run: npm run test:coverage
      - name: Comment PR with coverage
        uses: romeovs/lcov-reporter-action@v0.3.1
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          lcov-file: ./coverage/lcov.info

:magnifying_glass_tilted_left: 3. Automated Code Review con CodeClimate + SonarQube

Integra análisis automático de código que detecta problemas antes que humanos:

CodeClimate Setup:

# .codeclimate.yml
version: "2"
checks:
  argument-count:
    config:
      threshold: 4
  complex-logic:
    config:
      threshold: 4
  file-lines:
    config:
      threshold: 250
  method-complexity:
    config:
      threshold: 5
  method-count:
    config:
      threshold: 20

plugins:
  eslint:
    enabled: true
    config:
      config: .eslintrc.json
  duplication:
    enabled: true
    config:
      languages:
        - javascript
        - typescript

SonarQube Quality Gates:

# sonar-project.properties
sonar.projectKey=mi-proyecto
sonar.sources=src
sonar.tests=src
sonar.test.inclusions=**/*.test.ts,**/*.spec.ts
sonar.javascript.lcov.reportPaths=coverage/lcov.info
sonar.qualitygate.wait=true

# Quality Gate thresholds
sonar.coverage.minimum=80
sonar.duplicated_lines_density.maximum=3
sonar.maintainability_rating.minimum=A
sonar.reliability_rating.minimum=A
sonar.security_rating.minimum=A

:robot: 4. Dependency Vulnerability Scanning Automation

Mantén dependencias seguras con escaneo automático y updates:

GitHub Dependabot config:

# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
      day: "monday"
      time: "09:00"
    open-pull-requests-limit: 5
    reviewers:
      - "security-team"
    assignees:
      - "lead-developer"
    commit-message:
      prefix: "chore(deps)"
      include: "scope"
    # Auto-merge para patch updates
    auto-merge:
      dependency-type: "development"
      update-type: "semver:patch"

Snyk Integration:

// .snyk
{
  "version": "v1.0.0",
  "ignore": {},
  "patch": {},
  "policies": {
    "SNYK-JS-LODASH-567746": {
      "reason": "False positive - not using vulnerable function",
      "expires": "2024-12-31T23:59:59.999Z"
    }
  }
}

Automated security scanning:

#!/bin/bash
# security-scan.sh
echo "🔒 Ejecutando security scan..."

# Audit npm dependencies
npm audit --audit-level=moderate

# Snyk test
snyk test --severity-threshold=medium

# Check for known vulnerabilities
npm install -g retire
retire --path ./node_modules --outputformat json > security-report.json

echo "✅ Security scan completado"

:bar_chart: 5. Automated Performance Budgets con Lighthouse CI

Evita performance regressions configurando budgets automáticos:

// lighthouse-ci.json
{
  "ci": {
    "collect": {
      "url": ["http://localhost:3000"],
      "startServerCommand": "npm run start",
      "numberOfRuns": 3
    },
    "assert": {
      "assertions": {
        "categories:performance": ["warn", {"minScore": 0.9}],
        "categories:accessibility": ["error", {"minScore": 0.9}],
        "categories:best-practices": ["warn", {"minScore": 0.9}],
        "categories:seo": ["warn", {"minScore": 0.9}],
        
        // Performance budgets específicos
        "first-contentful-paint": ["warn", {"maxNumericValue": 2000}],
        "largest-contentful-paint": ["error", {"maxNumericValue": 2500}],
        "cumulative-layout-shift": ["error", {"maxNumericValue": 0.1}],
        "total-blocking-time": ["warn", {"maxNumericValue": 300}]
      }
    },
    "upload": {
      "target": "lhci",
      "serverBaseUrl": "https://your-lhci-server.com"
    }
  }
}

Bundle size monitoring:

// webpack.config.js
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
  plugins: [
    new BundleAnalyzerPlugin({
      analyzerMode: process.env.CI ? 'static' : 'server',
      openAnalyzer: !process.env.CI,
      generateStatsFile: true,
      statsFilename: 'bundle-stats.json'
    })
  ],
  performance: {
    maxAssetSize: 250000,
    maxEntrypointSize: 250000,
    hints: process.env.NODE_ENV === 'production' ? 'error' : 'warning'
  }
};

:artist_palette: 6. Automated Code Formatting con Prettier + EditorConfig

Elimina discusiones sobre estilo configurando formateo automático:

// .prettierrc
{
  "semi": true,
  "trailingComma": "es5",
  "singleQuote": true,
  "printWidth": 100,
  "tabWidth": 2,
  "useTabs": false,
  "bracketSpacing": true,
  "arrowParens": "avoid",
  "endOfLine": "lf",
  "overrides": [
    {
      "files": "*.md",
      "options": {
        "printWidth": 80,
        "proseWrap": "always"
      }
    }
  ]
}

EditorConfig for consistency:

# .editorconfig
root = true

[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false

[*.{json,yml,yaml}]
indent_size = 2

Auto-format en VS Code:

// .vscode/settings.json
{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true,
    "source.organizeImports": true
  },
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[json]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  }
}

:chart_increasing: 7. Automated Code Metrics Dashboard con GitHub Actions

Tracking automático de métricas de calidad de código:

# .github/workflows/code-metrics.yml
name: Code Metrics Dashboard
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  metrics:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0  # Necesario para análisis histórico
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Generate complexity report
        run: npx complexity-report --output complexity.json src/
      
      - name: Calculate technical debt
        run: npx jscpd --reporters json --output ./reports src/
      
      - name: Generate size analysis
        run: |
          echo "## Code Size Analysis" >> metrics.md
          echo "| Metric | Value |" >> metrics.md
          echo "|--------|-------|" >> metrics.md
          echo "| Total Lines | $(find src -name '*.ts' -o -name '*.js' | xargs wc -l | tail -1 | awk '{print $1}') |" >> metrics.md
          echo "| Files Count | $(find src -name '*.ts' -o -name '*.js' | wc -l) |" >> metrics.md
          echo "| Average File Size | $(echo "scale=2; $(find src -name '*.ts' -o -name '*.js' | xargs wc -l | tail -1 | awk '{print $1}') / $(find src -name '*.ts' -o -name '*.js' | wc -l)" | bc) lines |" >> metrics.md
      
      - name: Comment PR with metrics
        if: github.event_name == 'pull_request'
        uses: actions/github-script@v6
        with:
          script: |
            const fs = require('fs');
            const metrics = fs.readFileSync('metrics.md', 'utf8');
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: metrics
            });

Custom metrics tracking:

// scripts/generate-metrics.js
const fs = require('fs');
const path = require('path');

function analyzeCodebase() {
  const metrics = {
    timestamp: new Date().toISOString(),
    totalFiles: 0,
    totalLines: 0,
    averageComplexity: 0,
    testCoverage: 0,
    duplicatedCode: 0,
    technicalDebt: 0
  };
  
  // Análisis de archivos
  const srcDir = './src';
  const files = getAllFiles(srcDir, ['.ts', '.js']);
  
  metrics.totalFiles = files.length;
  metrics.totalLines = files.reduce((total, file) => {
    return total + countLines(file);
  }, 0);
  
  // Guardar métricas históricas
  const metricsHistory = JSON.parse(
    fs.readFileSync('./metrics-history.json', 'utf8') || '[]'
  );
  
  metricsHistory.push(metrics);
  
  // Mantener solo últimos 30 entries
  if (metricsHistory.length > 30) {
    metricsHistory.splice(0, metricsHistory.length - 30);
  }
  
  fs.writeFileSync('./metrics-history.json', JSON.stringify(metricsHistory, null, 2));
  
  return metrics;
}

function getAllFiles(dir, extensions) {
  let files = [];
  const items = fs.readdirSync(dir);
  
  for (const item of items) {
    const fullPath = path.join(dir, item);
    if (fs.statSync(fullPath).isDirectory()) {
      files = files.concat(getAllFiles(fullPath, extensions));
    } else if (extensions.some(ext => item.endsWith(ext))) {
      files.push(fullPath);
    }
  }
  
  return files;
}

function countLines(file) {
  return fs.readFileSync(file, 'utf8').split('\n').length;
}

// Ejecutar análisis
const metrics = analyzeCodebase();
console.log('📊 Code Metrics Generated:', metrics);

:light_bulb: Configuración Integral: El Setup Completo

Script de instalación automática:

#!/bin/bash
# setup-code-quality.sh

echo "🔧 Configurando automatización de code quality..."

# Instalar herramientas esenciales
npm install --save-dev \
  husky \
  lint-staged \
  @commitlint/cli \
  @commitlint/config-conventional \
  prettier \
  eslint \
  jest \
  @jest/globals

# Configurar Husky
npx husky-init
npx husky add .husky/pre-commit "npx lint-staged"
npx husky add .husky/commit-msg "npx commitlint --edit \$1"

# Crear archivos de configuración
cat > .commitlintrc.json << EOF
{
  "extends": ["@commitlint/config-conventional"],
  "rules": {
    "type-enum": [2, "always", ["feat", "fix", "docs", "style", "refactor", "test", "chore"]],
    "subject-max-length": [2, "always", 50]
  }
}
EOF

cat > .eslintrc.json << EOF
{
  "extends": ["eslint:recommended", "@typescript-eslint/recommended"],
  "rules": {
    "complexity": ["error", 10],
    "max-lines": ["error", 300],
    "max-params": ["error", 4],
    "no-console": "warn"
  }
}
EOF

echo "✅ Code quality automation configurado!"
echo "🚀 Próximos pasos:"
echo "  1. Personaliza .eslintrc.json según tu stack"
echo "  2. Configura thresholds de coverage en jest.config.js"
echo "  3. Integra con tu CI/CD pipeline"

:bullseye: Plan de Implementación Gradual

Semana 1: Fundamentos

  • Configurar Prettier + ESLint automático

  • Instalar pre-commit hooks básicos

  • Establecer code coverage baseline

Semana 2: Automatización CI/CD

  • Integrar quality gates en pipeline

  • Configurar dependency scanning

  • Setup performance budgets

Semana 3: Métricas y Monitoring

  • Implementar code metrics dashboard

  • Configurar alertas de calidad

  • Establecer improvement goals

Semana 4: Optimización

  • Refinar thresholds basado en datos

  • Automatizar technical debt tracking

  • Documentar best practices para el equipo

:bar_chart: Métricas de Éxito

Antes de automatización:

  • Tiempo en code review: ~2 horas por PR

  • Bugs en production: ~15 por sprint

  • Inconsistencias de estilo: ~40% de PRs

  • Coverage promedio: ~65%

Después de automatización:

  • Tiempo en code review: ~30 minutos por PR (-75%)

  • Bugs en production: ~4 por sprint (-73%)

  • Inconsistencias de estilo: ~5% de PRs (-87%)

  • Coverage promedio: ~85% (+20%)

:speech_balloon: Desafío de la Semana

Implementa al menos 3 de estas técnicas:

  1. Configura pre-commit hooks que bloqueen código mal formateado

  2. Establece coverage thresholds que fallen builds si coverage baja

  3. Integra automated code review con CodeClimate o similar

  4. Configura dependency scanning automático

  5. Implementa performance budgets en tu build process

Bonus: Comparte tus métricas de code quality antes y después de implementar automation.

La automatización de code quality no es sobre perfeccionismo - es sobre crear sistemas que mantengan estándares altos sin fricción humana. Código de calidad consistente lleva a menos bugs, easier maintenance, y developer happiness.

¿Qué técnicas de code quality automation han tenido más impacto en sus proyectos? ¿Cuáles son sus métricas favoritas para tracking code health?

techtipsmonday codequality automation devops #Testing #CI-CD productivity #CleanCode