{"id":45215883,"url":"https://github.com/marcelo-davanco/quality-scanner","last_synced_at":"2026-02-20T17:02:52.917Z","repository":{"id":339214092,"uuid":"1157417150","full_name":"marcelo-davanco/quality-scanner","owner":"marcelo-davanco","description":"Quality Scanner — SonarQube + NestJS/TypeScript analysis toolkit with Docker, 8-step scanner, quality gate, and Next.js dashboard","archived":false,"fork":false,"pushed_at":"2026-02-18T15:38:08.000Z","size":311,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"develop","last_synced_at":"2026-02-18T19:21:05.183Z","etag":null,"topics":["code-analysis","code-quality","docker","eslint","nestjs","security","sonarqube","spectral","trivy","typescript"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/marcelo-davanco.png","metadata":{"files":{"readme":"README.es.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-13T19:47:31.000Z","updated_at":"2026-02-18T19:14:54.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/marcelo-davanco/quality-scanner","commit_stats":null,"previous_names":["marcelo-davanco/quality-scanner"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/marcelo-davanco/quality-scanner","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcelo-davanco%2Fquality-scanner","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcelo-davanco%2Fquality-scanner/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcelo-davanco%2Fquality-scanner/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcelo-davanco%2Fquality-scanner/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/marcelo-davanco","download_url":"https://codeload.github.com/marcelo-davanco/quality-scanner/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcelo-davanco%2Fquality-scanner/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29658167,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-20T16:33:43.953Z","status":"ssl_error","status_checked_at":"2026-02-20T16:33:43.598Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["code-analysis","code-quality","docker","eslint","nestjs","security","sonarqube","spectral","trivy","typescript"],"created_at":"2026-02-20T17:02:47.521Z","updated_at":"2026-02-20T17:02:52.911Z","avatar_url":"https://github.com/marcelo-davanco.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Quality Scanner\n\n\u003e 🌐 **Traducciones:** [English](./README.md) · [Português](./README.pt-BR.md) · [中文](./README.zh-CN.md) · [हिन्दी / اردو](./README.hi.md) · [Русский](./README.ru.md)\n\nPipeline de calidad de código basado en Docker para proyectos NestJS/TypeScript, impulsado por SonarQube Community Edition. Ejecuta 10 pasos de análisis automatizados — desde la detección de secretos hasta la seguridad de infraestructura — y genera un informe JSON por cada escaneo.\n\n## Requisitos previos\n\n- **Docker** y **Docker Compose**\n- **Node.js** \u003e= 18\n- **npm** o **yarn**\n\n\u003e ⚠️ En macOS/Linux, aumenta el límite de memoria virtual requerido por SonarQube:\n\u003e ```bash\n\u003e sudo sysctl -w vm.max_map_count=524288\n\u003e ```\n\n## Inicio Rápido\n\n### 1. Configurar variables de entorno\n\n```bash\ncp .env.example .env\n```\n\nEdita `.env` y completa tus valores. El único cambio obligatorio para la primera ejecución es `SONAR_TOKEN` (ver paso 2).\n\n### 2. Iniciar SonarQube\n\n```bash\ndocker compose up -d\n```\n\nEspera ~1 minuto y abre **http://localhost:9000**.\n\n- **Credenciales por defecto:** `admin` / `admin`\n- Se te pedirá cambiar la contraseña en el primer inicio de sesión.\n\n### 3. Generar un Token de Acceso\n\n1. Ve a **My Account** → **Security** → **Generate Tokens**\n2. Crea un token de tipo **Project Analysis Token**\n3. Cópialo y configúralo en `.env`:\n\n```env\nSONAR_TOKEN=tu_token_aqui\n```\n\n### 4. Ejecutar el Scanner\n\n```bash\n# Escanear el directorio actual\n./scan.sh .\n\n# Escanear cualquier proyecto Node.js/NestJS\n./scan.sh /ruta/a/tu/proyecto\n```\n\nEl contenedor del scanner:\n\n1. Instalará las dependencias del proyecto\n2. Ejecutará los 10 pasos de análisis\n3. Guardará los informes JSON en `./reports/\u003cfecha\u003e/\u003cscan-id\u003e/`\n\n### 5. Ver Resultados\n\n- **Dashboard SonarQube:** http://localhost:9000/dashboard?id=tu-proyecto\n- **Informes locales:** `./reports/`\n\n---\n\n## Pasos de Análisis\n\n| Paso | Herramienta | Qué verifica |\n|------|-------------|--------------|\n| 1 | **Gitleaks** | Secretos y credenciales en el código |\n| 2 | **TypeScript** | Errores de compilación |\n| 3 | **ESLint** | Reglas de calidad de código (config centralizada) |\n| 4 | **Prettier** | Formato del código (config centralizada) |\n| 5 | **npm audit** | Vulnerabilidades en dependencias |\n| 6 | **Knip** | Código muerto (exports, archivos, deps no usados) |\n| 7 | **Jest** | Tests + cobertura |\n| 8 | **SonarQube** | Análisis estático + quality gate |\n| 9 | **Spectral** | Validación de contrato OpenAPI *(opcional)* |\n| 10 | **Trivy** | Seguridad de infraestructura (IaC) *(opcional)* |\n\n---\n\n## Quality Gate Local (Pre-Push)\n\nEjecuta las mismas verificaciones localmente antes de hacer push:\n\n```bash\nchmod +x quality-gate.sh\n./quality-gate.sh\n```\n\n---\n\n## API Lint — Validación de Contrato OpenAPI (Paso 9)\n\nValida contratos OpenAPI/Swagger usando **Spectral**.\n\n### Activación\n\n```bash\n# Via variable de entorno\nENABLE_API_LINT=true ./scan.sh /ruta/al/proyecto\n\n# Via docker-compose\nENABLE_API_LINT=true docker compose --profile scan up scanner\n```\n\n### Qué se valida\n\n- Todas las rutas tienen respuesta `400` mapeada\n- Los paths usan `kebab-case` (ej. `/mi-recurso`)\n- Las propiedades de schema usan `camelCase`\n- Toda operación tiene `operationId`, `description`, `summary` y `tags`\n- Los paths no terminan con `/`\n- Las respuestas `200`/`201` tienen `content` definido\n\n### Configuración\n\n| Variable | Valor por defecto | Descripción |\n|----------|-------------------|-------------|\n| `ENABLE_API_LINT` | `false` | Habilitar/deshabilitar este paso |\n| `API_LINT_SEVERITY` | `warn` | `warn` = solo reportar, `error` = bloquear pipeline |\n| `OPENAPI_FILE_PATH` | *(auto-detect)* | Ruta manual al archivo OpenAPI |\n\nEl archivo OpenAPI se detecta automáticamente (`swagger.json`, `openapi.yaml`, etc.). Para personalizar las reglas, edita `scanner/configs/.spectral.yml`. Guía completa en [`scanner/configs/README.md`](./scanner/configs/README.md).\n\n---\n\n## Infra Scan — Seguridad de Infraestructura (Paso 10)\n\nEscanea `Dockerfile`, `docker-compose.yml` y manifiestos de Kubernetes usando **Trivy**.\n\n### Activación\n\n```bash\n# Via variable de entorno\nENABLE_INFRA_SCAN=true ./scan.sh /ruta/al/proyecto\n\n# Via docker-compose\nENABLE_INFRA_SCAN=true docker compose --profile scan up scanner\n```\n\n### Qué se escanea\n\n| Tipo | Archivos detectados | Hallazgos típicos |\n|------|---------------------|-------------------|\n| **Dockerfile** | `Dockerfile`, `Dockerfile.*` | Tag `latest`, sin `USER`, sin `HEALTHCHECK`, uso de `ADD` |\n| **docker-compose** | `docker-compose.yml`, `compose.yaml` | `privileged: true`, puertos expuestos, volúmenes peligrosos |\n| **Kubernetes** | `deployment.yaml`, `service.yaml`, etc. | `hostNetwork`, `securityContext` ausente, sin límites de recursos |\n\n### Configuración\n\n| Variable | Valor por defecto | Descripción |\n|----------|-------------------|-------------|\n| `ENABLE_INFRA_SCAN` | `false` | Habilitar/deshabilitar este paso |\n| `INFRA_SCAN_SEVERITY` | `HIGH` | Severidad mínima de bloqueo: `CRITICAL`, `HIGH`, `MEDIUM`, `LOW` |\n| `SCAN_DOCKERFILE` | `true` | Habilitar escaneo de Dockerfile |\n| `SCAN_K8S` | `true` | Habilitar escaneo de manifiestos Kubernetes |\n| `SCAN_COMPOSE` | `true` | Habilitar escaneo de docker-compose |\n\nPara personalizar las políticas de seguridad, edita `scanner/configs/trivy-policy.yaml`. Guía completa en [`scanner/configs/README.md`](./scanner/configs/README.md).\n\n---\n\n## Comandos Útiles\n\n| Comando | Descripción |\n|---------|-------------|\n| `docker compose up -d` | Iniciar SonarQube |\n| `docker compose down` | Detener SonarQube |\n| `docker compose down -v` | Detener y eliminar todos los datos |\n| `docker compose logs -f sonarqube` | Ver logs de SonarQube |\n| `./scan.sh /ruta/al/proyecto` | Ejecutar análisis completo |\n| `./quality-gate.sh` | Ejecutar verificaciones locales pre-push |\n\n---\n\n## Estructura del Proyecto\n\n```text\nquality-scanner/\n├── docker-compose.yml          # SonarQube + PostgreSQL + Scanner\n├── sonar-project.properties    # Configuración del scanner\n├── quality-gate.sh             # Quality gate local pre-push\n├── run-sonar.sh                # Script standalone de análisis SonarQube\n├── scan.sh                     # Wrapper Docker del scanner\n├── .env.example                # Plantilla de variables de entorno\n├── scanner/\n│   ├── Dockerfile              # Imagen del scanner\n│   ├── entrypoint.sh           # Pipeline de 10 pasos (contenedor)\n│   ├── configs/\n│   │   ├── .eslintrc.js        # Reglas ESLint centralizadas\n│   │   ├── .prettierrc         # Config de formato Prettier\n│   │   ├── .gitleaks.toml      # Reglas de detección de secretos\n│   │   ├── .spectral.yml       # Reglas OpenAPI/Swagger\n│   │   ├── trivy-policy.yaml   # Políticas de seguridad Trivy\n│   │   └── README.md           # Guía de configuración\n│   ├── scripts/\n│   │   ├── swagger-lint.sh     # Script de lint OpenAPI\n│   │   └── infra-scan.sh       # Script de seguridad de infraestructura\n│   └── test/\n│       ├── fixtures/           # Fixtures seguras/inseguras para tests\n│       ├── test-api-lint.sh    # Tests del API Lint\n│       └── test-infra-scan.sh  # Tests del Infra Scan\n├── quality-configs/            # Configs del quality gate local\n├── dashboard/                  # Dashboard de resultados (Next.js)\n├── example-nestjs/             # Proyecto NestJS de ejemplo\n├── .gitignore\n├── LICENSE\n└── README.md\n```\n\n---\n\n## Solución de Problemas\n\n### SonarQube no inicia\n\n```bash\n# Revisar logs\ndocker compose logs sonarqube\n\n# Corrección común en Linux/macOS — aumentar vm.max_map_count\nsudo sysctl -w vm.max_map_count=524288\n```\n\n### Error de memoria insuficiente\n\nAgrega al servicio `sonarqube` en `docker-compose.yml`:\n\n```yaml\ndeploy:\n  resources:\n    limits:\n      memory: 2g\n```\n\n### El scanner no encuentra archivos\n\nAsegúrate de que `sonar-project.properties` esté en la raíz del proyecto y que todas las rutas sean correctas.\n\n---\n\n## Contribuir\n\n¡Las contribuciones son bienvenidas! Lee [CONTRIBUTING.md](./CONTRIBUTING.md) antes de enviar un pull request.\n\n## Licencia\n\n[MIT](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcelo-davanco%2Fquality-scanner","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarcelo-davanco%2Fquality-scanner","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcelo-davanco%2Fquality-scanner/lists"}