Saltar al contenido

El problema silencioso del código generado con IA

Las herramientas de IA generan código a una velocidad impresionante. Copilot, Claude, ChatGPT… puedes tener una feature funcionando en minutos. Pero velocidad no es sinónimo de calidad.

El resultado habitual es un acumulado silencioso de deuda técnica: código duplicado, funciones demasiado complejas, variables sin usar, vulnerabilidades que nadie revisó y tests que nunca se escribieron. El código funciona, pasa a producción, y nadie vuelve a mirarlo.

SonarQube actúa como el revisor senior que no descansa: analiza tu proyecto de forma estática, detecta bugs, huele code smells y levanta alertas de seguridad, independientemente de si el código lo escribiste tú o lo generó un modelo de IA.

En este artículo vamos a integrarlo en un proyecto Laravel con Laravel Sail, sin salir del entorno Docker. Cuando terminemos, con un solo script podremos lanzar un análisis completo y ver el resultado en el panel web.


¿Qué detecta SonarQube exactamente?

Antes de ponernos con la instalación, vale la pena entender qué nos va a dar SonarQube:

  • Bugs — errores que pueden causar comportamiento incorrecto en producción.

  • Vulnerabilidades — inyecciones SQL, XSS, credenciales expuestas, etc.

  • Code smells — código que funciona pero que dificulta el mantenimiento.

  • Deuda técnica — tiempo estimado de refactorización acumulado.

  • Cobertura de tests — qué porcentaje del código está cubierto por pruebas.

  • Duplicaciones — bloques de código repetidos que deberían estar abstraídos.

La edición Community es gratuita y más que suficiente para proyectos individuales o de equipo pequeño.


Requisitos

  • Laravel con Laravel Sail configurado.

  • Docker corriendo en local.


1. Añadir SonarQube al compose.yaml

Abrimos el compose.yaml y añadimos dos servicios nuevos dentro de services:: el propio SonarQube y su base de datos PostgreSQL.

sonarqube:
    image: "sonarqube:community"
    ports:
        - "${SONARQUBE_PORT:-9000}:9000"
    environment:
        SONAR_JDBC_URL: "jdbc:postgresql://sonarqube-db:5432/sonar"
        SONAR_JDBC_USERNAME: sonar
        SONAR_JDBC_PASSWORD: sonar
    volumes:
        - "sonarqube-data:/opt/sonarqube/data"
        - "sonarqube-extensions:/opt/sonarqube/extensions"
        - "sonarqube-logs:/opt/sonarqube/logs"
    networks:
        - sail
    depends_on:
        sonarqube-db:
            condition: service_healthy

sonarqube-db:
    image: "postgres:16-alpine"
    environment:
        POSTGRES_USER: sonar
        POSTGRES_PASSWORD: sonar
        POSTGRES_DB: sonar
    volumes:
        - "sonarqube-db:/var/lib/postgresql/data"
    networks:
        - sail
    healthcheck:
        test: ["CMD-SHELL", "pg_isready -U sonar"]
        interval: 10s
        retries: 5
        timeout: 5s

También añadimos los volúmenes nuevos en la sección volumes: del mismo archivo:

sonarqube-data:
    driver: local
sonarqube-extensions:
    driver: local
sonarqube-logs:
    driver: local
sonarqube-db:
    driver: local

Levantamos los contenedores nuevos sin tocar los que ya están corriendo:

./vendor/bin/sail up -d sonarqube sonarqube-db

SonarQube tarda entre 30 y 60 segundos en arrancar. La forma más sencilla de saber si está listo es abrir http://localhost:9000 en el navegador y esperar a que cargue el panel de login.


2. Primer acceso y cambio de contraseña

Abrimos el navegador en http://localhost:9000. El panel de SonarQube nos pedirá las credenciales por defecto:

  • Usuario: admin

  • Contraseña: admin

Al hacer login por primera vez, SonarQube nos obliga a cambiar la contraseña. Introducimos la contraseña actual (admin) y la nueva dos veces. Recomendamos guardarla en un gestor de contraseñas.


3. Crear el proyecto y obtener el token

Una vez dentro del panel, hay que crear un proyecto local y generar el token de autenticación que usará el scanner.

  1. En la pantalla de bienvenida, hacemos clic en "Create a local project".

  2. Rellenamos el Project key y el Display name. El project key debe coincidir con el valor que pondremos en sonar-project.properties.

  3. Seleccionamos "Use the global setting" para la rama principal y hacemos clic en Next.

  4. En la pantalla de análisis, elegimos "Locally".

  5. SonarQube nos genera un token. Lo copiamos —solo se muestra una vez—.

Pegamos el token en el .env del proyecto:

SONARQUBE_PORT=9000
SONAR_PROJECT_KEY=project-key
SONAR_TOKEN=sqp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Importante: asegúrate de que el .env está en el .gitignore. Un token filtrado permite analizar o modificar cualquier proyecto en tu instancia de SonarQube.


4. Configurar sonar-project.properties

Este archivo le indica al scanner qué analizar, dónde están los tests y cómo conectar con el servidor. Lo creamos en la raíz del proyecto Laravel:

sonar.projectKey=project-key
sonar.projectName=project-name

# Código fuente y tests
sonar.sources=app
sonar.tests=tests

# Configuración PHP
sonar.language=php
sonar.sourceEncoding=UTF-8

# URL del servidor SonarQube dentro de la red Docker
sonar.host.url=http://sonarqube:9000

La URL apunta a http://sonarqube:9000 —el nombre del servicio en la red Docker de Sail— porque el scanner se ejecutará dentro de esa misma red. Si lo ejecutases desde fuera del entorno Docker, la URL sería http://localhost:9000.


5. Crear el script sonar.sh

En lugar de recordar el comando completo cada vez, encapsulamos todo en un script bash en la raíz del proyecto:

#!/bin/bash
set -e

# Lee el token desde el .env sin necesidad de exportarlo al shell
SONAR_TOKEN=$(grep '^SONAR_TOKEN=' .env | cut -d '=' -f2)

if [ -z "$SONAR_TOKEN" ]; then
    echo "Error: SONAR_TOKEN not found in .env"
    exit 1
fi

docker run --rm \
    --network project_sail \
    -v "$(pwd)":/usr/src \
    -w /usr/src \
    sonarsource/sonar-scanner-cli \
    -Dsonar.token="$SONAR_TOKEN"

El parámetro --network project_sail conecta el contenedor del scanner a la misma red Docker que Sail, lo que le permite resolver el hostname sonarqube. El nombre de la red sigue el patrón {directorio-del-proyecto}_sail. Si no estás seguro del nombre exacto, puedes verificarlo con:

docker network ls

Damos permisos de ejecución al script:

chmod +x sonar.sh

6. Ejecutar el análisis

Con Sail corriendo y el token configurado, lanzamos el scanner:

./sonar.sh

El scanner descargará la imagen sonarsource/sonar-scanner-cli la primera vez, analizará el código y enviará los resultados. Cuando finalice veremos algo como:

INFO: Analysis report uploaded in 318ms
INFO: ANALYSIS SUCCESSFUL, you can find the results at:
INFO: http://localhost:9000/dashboard?id=project-key

7. Interpretar el informe en el panel

Abrimos http://localhost:9000 y navegamos a nuestro proyecto. El dashboard principal muestra el Quality Gate: un semáforo global que indica si el código cumple o no los estándares mínimos configurados.

Las secciones más relevantes son:

  • Reliability — bugs potenciales. La valoración va de A (ninguno) a E (críticos).

  • Security — vulnerabilidades explotables.

  • Maintainability — deuda técnica acumulada expresada en tiempo de refactorización.

  • Coverage — porcentaje del código cubierto por tests.

  • Duplications — porcentaje de código duplicado.

Haciendo clic en cada categoría podemos ver el detalle archivo por archivo, con la línea exacta del problema y una explicación de cómo solucionarlo.


Integrar SonarQube en el flujo de trabajo diario

El mayor valor no está en ejecutarlo una vez, sino en convertirlo en parte del proceso habitual:

  • Ejecutar ./sonar.sh antes de abrir un Pull Request.

  • Añadirlo como paso en el pipeline de CI/CD (GitHub Actions, GitLab CI, etc.).

  • Configurar el Quality Gate para bloquear merges si la calidad baja de un umbral mínimo.

  • Revisar el panel con el equipo en las reuniones de sprint para priorizar la deuda técnica acumulada.


Conclusión

En un contexto donde la IA puede generar cientos de líneas de código en segundos, tener una herramienta que audite la calidad de forma sistemática no es un lujo, es una necesidad. SonarQube no reemplaza la revisión humana, pero elimina el ruido: cuando el código llega a code review, ya ha pasado por un primer filtro objetivo.

Con la configuración que hemos visto —tres archivos y un script bash— el setup completo no lleva más de 15 minutos, y el retorno en visibilidad y calidad es inmediato desde el primer análisis.

school Curso completo

Curso Laravel 12
Completo 2026

El único curso 100% actualizado que incluye Laravel 12, Livewire 3, Vue 3, React 19 e Inertia 2. Aprende con proyectos reales y las últimas funcionalidades.

access_time 8 horas de contenido
layers 4 tecnologías en 1
update 100% actualizado
code Proyectos prácticos
Ver Curso Laravel 12 arrow_forward

star Incluido en cualquier suscripción

Rutas de aprendizaje