Saltar al contenido

Automatizar tareas repetitivas como desarrollador

Estrategias prácticas para identificar y automatizar tareas repetitivas: scripts de shell, generadores de código, alias de Git y scaffolding.

5 min de lectura
Diagrama de flujo que muestra tareas manuales repetitivas siendo reemplazadas por scripts y herramientas automatizadas

La mayoría de los desarrolladores dedica horas cada semana a tareas que ya ha hecho cientos de veces: crear archivos boilerplate, preparar fixtures de prueba, desplegar a staging, renombrar lotes de archivos. Estas tareas no son difíciles, pero interrumpen. Automatizarlas elimina toda una clase de cambios de contexto y libera tu mente para resolver problemas de verdad.

La regla general: si haces algo más de tres veces, automatízalo. Si la automatización lleva menos tiempo que hacer la tarea cinco veces más a mano, se amortiza rápido. El beneficio secundario es la consistencia: las tareas automatizadas no olvidan pasos ni introducen erratas.

Identificar qué automatizar

Empieza llevando un registro de las tareas repetitivas durante una semana. La mayoría de los desarrolladores se sorprende de cuánto tiempo se va en trabajo mecánico.

markdownmarkdown
## Automation Candidates (1 week log)
 
### High Frequency (daily)
- Creating new React component files (same structure every time)
- Running database migrations before starting dev server
- Switching between Git branches and rebuilding
 
### Medium Frequency (weekly)
- Setting up test fixtures for integration tests
- Generating API client code from OpenAPI specs
- Creating pull request descriptions from commit history
 
### Low Frequency (monthly)
- Spinning up a new microservice from template
- Rotating API keys across environments
- Generating release notes from merged PRs
tstypescript
// ❌ Manual component creation — every single time
// 1. Create src/components/UserProfile/
// 2. Create UserProfile.tsx with boilerplate
// 3. Create UserProfile.test.tsx with test structure
// 4. Create index.ts with export
// 5. Add to component barrel file
// Time: 3-5 minutes, repeated 3x per day = 15 minutes/day
 
// ✅ Automated — one command
// $ gen component UserProfile
// Creates all 4 files with correct structure
// Time: 5 seconds

Alias y funciones de shell

La automatización de menor esfuerzo son los alias y las funciones de shell. Envuelven comandos de varios pasos en una sola invocación.

shbash
# ~/.zshrc or ~/.bashrc
 
# Git shortcuts
alias gs='git status'
alias gco='git checkout'
alias gp='git pull --rebase'
alias gcm='git commit -m'
 
# Development workflow
alias dev='npm run dev'
alias build='npm run build'
alias test='npm run test'
alias lint='npm run lint -- --fix'
 
# Complex workflows as functions
function fresh() {
  # Fresh start: pull latest, install deps, run migrations, start dev
  echo "🔄 Pulling latest changes..."
  git pull --rebase origin main
  echo "📦 Installing dependencies..."
  npm ci
  echo "🗄️  Running migrations..."
  npm run db:migrate
  echo "🚀 Starting dev server..."
  npm run dev
}
 
function branch() {
  # Create a new feature branch from latest main
  local branch_name=$1
  if [ -z "$branch_name" ]; then
    echo "Usage: branch feat/my-feature"
    return 1
  fi
  git checkout main
  git pull --rebase
  git checkout -b "$branch_name"
  echo "Created and switched to $branch_name"
}
shbash
# ❌ Multiple commands every time you start work
git checkout main
git pull --rebase
npm ci
npm run db:migrate
npm run dev
# Time: 2 minutes of typing + waiting
 
# ✅ One command
fresh
# Same result, zero thinking, zero typos

Generadores de código

Para la creación repetitiva de archivos, un generador de código elimina el boilerplate y hace cumplir las convenciones del proyecto.

tstypescript
// scripts/generate-component.ts
import fs from 'fs';
import path from 'path';
 
interface ComponentConfig {
  name: string;
  directory: string;
  withTests: boolean;
  withStories: boolean;
}
 
function generateComponent(config: ComponentConfig): void {
  const dir = path.join(config.directory, config.name);
  fs.mkdirSync(dir, { recursive: true });
 
  // Component file
  const component = `interface ${config.name}Props {
  className?: string;
}
 
export function ${config.name}({ className }: ${config.name}Props) {
  return (
    <div className={className}>
      <h2>${config.name}</h2>
    </div>
  );
}
`;
  fs.writeFileSync(path.join(dir, `${config.name}.tsx`), component);
 
  // Test file
  if (config.withTests) {
    const test = `import { render, screen } from '@testing-library/react';
import { ${config.name} } from './${config.name}';
 
describe('${config.name}', () => {
  it('renders without crashing', () => {
    render(<${config.name} />);
    expect(screen.getByText('${config.name}')).toBeInTheDocument();
  });
});
`;
    fs.writeFileSync(
      path.join(dir, `${config.name}.test.tsx`),
      test
    );
  }
 
  // Index file
  const index = `export { ${config.name} } from './${config.name}';\n`;
  fs.writeFileSync(path.join(dir, 'index.ts'), index);
 
  console.log(`Created ${config.name} in ${dir}`);
}
 
// CLI entry point
const name = process.argv[2];
if (!name) {
  console.error('Usage: tsx scripts/generate-component.ts MyComponent');
  process.exit(1);
}
 
generateComponent({
  name,
  directory: 'src/components',
  withTests: true,
  withStories: false,
});

Git hooks para comprobaciones automatizadas

Los hooks de Git automatizan las comprobaciones de calidad en los momentos adecuados: antes de hacer commit, antes de hacer push. Evitan que los errores comunes lleguen al repositorio.

shbash
# .husky/pre-commit — lint only changed files
npx lint-staged
 
# .husky/commit-msg — enforce commit message format
#!/bin/sh
COMMIT_MSG=$(cat "$1")
PATTERN="^(feat|fix|docs|style|refactor|perf|test|chore|ci|revert)(\(.+\))?: .{1,100}$"
 
if ! echo "$COMMIT_MSG" | grep -qE "$PATTERN"; then
  echo "❌ Commit message does not match conventional format."
  echo "   Expected: type(scope): description"
  echo "   Example: feat(auth): add password reset flow"
  exit 1
fi
jsonjson
// lint-staged.config.json — auto-format on commit
{
  "*.{ts,tsx}": ["eslint --fix", "prettier --write"],
  "*.{css,scss}": ["prettier --write"],
  "*.md": ["prettier --write"]
}

Automatización de bases de datos y APIs

Automatiza las operaciones repetitivas de base de datos y la generación de clientes de API para eliminar el trabajo manual de sincronización.

shbash
#!/bin/bash
# scripts/sync-staging.sh — pull staging database for local development
 
set -euo pipefail
 
DB_NAME="myapp_dev"
STAGING_URL="${STAGING_DATABASE_URL:?Set STAGING_DATABASE_URL}"
 
echo "⬇️  Dumping staging database..."
pg_dump "$STAGING_URL" \
  --no-owner \
  --no-privileges \
  --exclude-table='sessions' \
  --exclude-table='audit_logs' \
  > /tmp/staging_dump.sql
 
echo "🗑️  Dropping local database..."
dropdb --if-exists "$DB_NAME"
createdb "$DB_NAME"
 
echo "📥 Restoring to local..."
psql "$DB_NAME" < /tmp/staging_dump.sql
 
echo "🔒 Anonymizing PII..."
psql "$DB_NAME" <<SQL
  UPDATE users SET
    email = 'user_' || id || '@test.local',
    first_name = 'Test',
    last_name = 'User_' || id;
SQL
 
rm /tmp/staging_dump.sql
echo "✅ Local database synced with anonymized staging data"
tstypescript
// scripts/generate-api-client.ts
// Auto-generate TypeScript API client from OpenAPI spec
 
import { execSync } from 'child_process';
 
const SPEC_URL = 'https://api.example.com/openapi.json';
const OUTPUT_DIR = 'src/api/generated';
 
// Generate client using openapi-typescript-codegen
execSync(
  `npx openapi-typescript-codegen \
    --input ${SPEC_URL} \
    --output ${OUTPUT_DIR} \
    --client fetch \
    --useOptions`,
  { stdio: 'inherit' }
);
 
console.log(`API client generated in ${OUTPUT_DIR}`);

Scaffolding de proyectos

Para equipos que crean nuevos servicios o paquetes con regularidad, una herramienta de scaffolding garantiza que cada proyecto empiece con la misma estructura, configuraciones y pipelines de CI.

tstypescript
// scripts/scaffold-service.ts
import fs from 'fs';
import path from 'path';
 
interface ServiceConfig {
  name: string;
  port: number;
  hasDatabase: boolean;
  hasRedis: boolean;
}
 
function scaffoldService(config: ServiceConfig): void {
  const base = path.join('services', config.name);
 
  const structure: Record<string, string> = {
    'src/index.ts': generateEntryPoint(config),
    'src/routes/health.ts': generateHealthRoute(config),
    'Dockerfile': generateDockerfile(config),
    'docker-compose.yml': generateDockerCompose(config),
    '.env.example': generateEnvExample(config),
    'tsconfig.json': JSON.stringify(tsconfig, null, 2),
    'package.json': JSON.stringify(
      generatePackageJson(config),
      null,
      2
    ),
  };
 
  for (const [filePath, content] of Object.entries(structure)) {
    const fullPath = path.join(base, filePath);
    fs.mkdirSync(path.dirname(fullPath), { recursive: true });
    fs.writeFileSync(fullPath, content);
  }
 
  console.log(`Scaffolded service '${config.name}' in ${base}/`);
  console.log(`Next steps:`);
  console.log(`  cd ${base}`);
  console.log(`  npm install`);
  console.log(`  npm run dev`);
}
shbash
# ❌ Manual service creation
# 1. Create directory structure (5 min)
# 2. Copy and modify Dockerfile from another service (10 min)
# 3. Set up tsconfig, package.json, eslint config (15 min)
# 4. Create health check route (5 min)
# 5. Set up docker-compose with database (10 min)
# 6. Configure CI pipeline (15 min)
# Time: ~1 hour, inconsistent across services
 
# ✅ Scaffolded in seconds
npx tsx scripts/scaffold-service.ts --name user-service --port 3001 --db --redis
# Time: 10 seconds, consistent every time

Conclusiones clave

  1. Registra las tareas repetitivas durante una semana — no puedes automatizar lo que no has identificado; la frecuencia y el coste en tiempo te sorprenderán
  2. Empieza con alias de shell — la forma más rápida de eliminar comandos de varios pasos; cinco minutos de configuración ahorran meses de teclear
  3. Crea generadores de código para el boilerplate — cualquier estructura de archivos creada más de tres veces debería tener un generador
  4. Automatiza las sincronizaciones de base de datos con anonimización — los datos de staging en desarrollo local aceleran la depuración sin exponer PII
  5. Usa scaffolding para proyectos nuevos — cada servicio o paquete nuevo debería partir de una plantilla consistente, no de un copia-pega de otro proyecto
  6. Invierte en automatización de forma proporcional — dedica 30 minutos a automatizar algo que haces a diario, no algo que haces una vez al año
Wilfredo Rujel

Wilfredo Rujel

Ingeniero de Software Full Stack

Compartir esta publicaciónX