Saltar al contenido
# 📄 Fase 8 — Renderer Markdown: Informes Accionables ## 🤔 ¿Qué hago? ¿Cómo lo hago? ¿Y para qué lo hago? **¿Qué hago?** Genero un informe en formato Markdown cuando se usa `--format markdown` (o `--format md`). El informe agrupa los antipatrones detectados por regla y convierte cada finding en un checkbox `- [ ]` Markdown. **¿Cómo lo hago?** Dos nuevos renderers en el paquete `internal/renderer`: - `MarkdownRenderer` — para el comando `scan` (recibe `[]model.Finding`) - `OrgMarkdownRenderer` — para el comando `scan-org` (recibe `*model.OrgReport`) Ambos renderers se conectan en `cmd/antipatterns/main.go` bajo `case "markdown", "md":`. El informe se escribe a `stdout` por defecto; con `--output report.md` se vuelca a fichero. **¿Para qué lo hago?** Los formatos `console`, `json` y `sarif` cubren visualización terminal, pipelines y GitHub Code Scanning. Ninguno genera un artefacto persistible y accionable pensado para revisión humana. El formato Markdown resuelve el ciclo completo: **detectar → documentar → corregir** sin salir del editor. --- ## 📊 Diagrama de flujo ```mermaid flowchart TD A[antipatterns scan ./repo --format markdown] --> B[scanner.Run] B --> C{findings?} C -- 0 --> D["✅ No anti-patterns found."] C -- N --> E[groupByRule — orden alfabético] E --> F[Cabecera + tabla resumen] F --> G["Sección por regla\n## {emoji} \`rule\` — N finding(s)"] G --> H["- [ ] \`file:line\` — mensaje"] H --> I[stdout / --output report.md] A2[antipatterns scan-org profile --format markdown] --> B2[orgscanner.Run] B2 --> C2[OrgMarkdownRenderer.Render] C2 --> J[Cabecera + tabla resumen por repo] J --> K["## 📦 \`org/repo\`\n### {emoji} \`rule\` — N finding(s)\n- [ ] ..."] K --> I ``` --- ## 📝 Estructura del informe — `scan` ```markdown # 🔍 Anti-pattern Report > **Path:** `/path/to/repo` > **Date:** 2026-07-24 > **Tool:** antipatterns v1.2.0 ## 📊 Resumen **Total: 28 finding(s)** | Regla | Severidad | Findings | | --- | --- | --- | | `cyclomatic_complexity` | 🟡 medium | 3 | | `duplication` | 🟡 medium | 10 | | `large_function` | 🟡 medium | 15 | --- ## 🟡 `cyclomatic_complexity` — 3 finding(s) - [ ] **`internal/scanner/scanner.go:73`** — function Run: cyclomatic complexity 18 (threshold 15) - [ ] **`cmd/antipatterns/main.go:42`** — function scanCmd: cyclomatic complexity 16 (threshold 15) ## 🟡 `large_function` — 15 finding(s) - [ ] **`internal/adapter/jscpd.go:35`** — function Jscpd has 72 lines (threshold 60) ``` --- ## 🌐 Estructura del informe — `scan-org` ```markdown # 🌐 Org Anti-pattern Report > **Org:** `Ka0s-Klaus` > **Date:** 2026-07-24 > **Tool:** antipatterns v1.2.0 > **Repos:** 3 | **Total findings:** 42 ## 📊 Resumen por repositorio | Repo | Estado | Findings | Top rule | | --- | --- | --- | --- | | `Ka0s-Klaus/repo-a` | ⚠️ | 28 | `large_function` | | `Ka0s-Klaus/repo-b` | ✅ | 0 | — | | `Ka0s-Klaus/repo-c` | ❌ error | — | clone failed | --- ## 📦 `Ka0s-Klaus/repo-a` ### 🟡 `large_function` — 15 finding(s) - [ ] **`cmd/main.go:42`** — function scanCmd has 87 lines (threshold 60) ``` --- ## 🚀 Uso ### Generar informe en terminal ```bash antipatterns scan ./mi-repo --format markdown ``` ### Guardar en fichero ```bash antipatterns scan ./mi-repo --format markdown --output report.md ``` ### Con verbose — ver progreso y luego el informe ```bash antipatterns scan ./mi-repo --format markdown --verbose --output report.md ``` ### Alias `md` ```bash antipatterns scan ./mi-repo --format md --output report.md ``` ### Scan de org con informe Markdown ```bash antipatterns scan-org my-profile --format markdown --output org-report.md ``` --- ## 🏗️ Cambios técnicos | Fichero | Tipo | Descripción | | --- | --- | --- | | `internal/renderer/markdown.go` | NUEVO | `MarkdownRenderer` para `scan` | | `internal/renderer/org_markdown.go` | NUEVO | `OrgMarkdownRenderer` para `scan-org` | | `internal/renderer/markdown_test.go` | NUEVO | 7 tests para `MarkdownRenderer` | | `internal/renderer/org_markdown_test.go` | NUEVO | 6 tests para `OrgMarkdownRenderer` | | `cmd/antipatterns/main.go` | MODIFICADO | `case "markdown", "md":` en `scan` y `scan-org` | ### Función compartida `groupByRule` Definida en `markdown.go`, accesible desde `org_markdown.go` por pertenecer al mismo paquete. Agrupa `[]model.Finding` por `Rule` y devuelve el slice de reglas en orden alfabético. ```go func groupByRule(findings []model.Finding) ([]string, map[string][]model.Finding) ``` ### Emojis de severidad | Severidad | Emoji | | --- | --- | | `info` | 🔵 | | `low` | 🟢 | | `medium` | 🟡 | | `high` | 🟠 | | `critical` | 🔴 | --- ## 🔗 Documentos relacionados - [fase-7-verbose-oss-local.md](fase-7-verbose-oss-local.md) — Flag `--verbose` + separación stdout/stderr - [fase-2-adaptadores-oss.md](fase-2-adaptadores-oss.md) — Adaptadores OSS y `ErrToolNotFound` - [fase-5-publicacion.md](fase-5-publicacion.md) — Proceso de release con GoReleaser - [fase-3-sarif-action.md](fase-3-sarif-action.md) — Renderer SARIF (formato para CI)