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.
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.
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
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
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"
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'
}
};
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"
}
}
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);
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"
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
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%)
Desafío de la Semana
Implementa al menos 3 de estas técnicas:
-
Configura pre-commit hooks que bloqueen código mal formateado
-
Establece coverage thresholds que fallen builds si coverage baja
-
Integra automated code review con CodeClimate o similar
-
Configura dependency scanning automático
-
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