spec: separar responsabilidades feat: agregra pipeline de construccion en gitea
63 lines
4.2 KiB
Markdown
63 lines
4.2 KiB
Markdown
# Design: split-main-into-files
|
|
|
|
## Context
|
|
|
|
El proyecto `outline-mcp` vive íntegramente en `main.go` (425 líneas, paquete `main`), según la decisión D2 del change `create-outline-mcp-server`, que explícitamente anticipaba la extracción a múltiples archivos como refactor futuro. El archivo mezcla tres dominios independientes (cliente HTTP de Outline, handlers de tools MCP, auto-update vía Gitea). No hay tests aún; la verificación actual es `go build`, `golangci-lint run` y prueba manual por stdio.
|
|
|
|
## Goals / Non-Goals
|
|
|
|
**Goals:**
|
|
|
|
- Repartir `main.go` en archivos por responsabilidad dentro del mismo paquete `main`, sin ningún cambio de comportamiento.
|
|
- Dejar el código preparado para añadir tests y nuevas tools sin fricción.
|
|
- Cumplir la promesa de D2: extracción sin impacto en specs de comportamiento ni en el pipeline de release.
|
|
|
|
**Non-Goals:**
|
|
|
|
- Introducir paquetes `internal/` (descartado: no hay necesidad de ocultar API entre dominios con el alcance actual).
|
|
- Añadir tests (cambio posterior; solo se deja el terreno listo).
|
|
- Renombrar o refactorizar funciones, tipos o lógica.
|
|
- Modificar `go.mod`, dependencias, pipeline de release o contrato de nombres de assets.
|
|
|
|
## Decisions
|
|
|
|
### D1: Múltiples archivos en paquete `main` (opción B) frente a `internal/` (opción C)
|
|
|
|
- **Elección**: dividir en archivos del mismo paquete `main`. Estructura resultante:
|
|
- `main.go` — función `main()`, variables de build (`Version`, `GiteaURL`, `RepoOwner`, `RepoName`) y registro de tools.
|
|
- `client.go` — tipo `OutlineClient`, `newOutlineClient`, método `post`.
|
|
- `tools.go` — los cuatro handlers de tools MCP.
|
|
- `updater.go` — `giteaRelease`, `parseVersion`, `versionNewer`, `doUpdate`.
|
|
- **Alternativa** (`internal/outline`, `internal/tools`, `internal/selfupdate`): descartada porque obliga a decidir superficie exportada acoplando los handlers al SDK (`mcp.CallToolResult` en firmas) y no aporta ocultación real con el alcance actual. Queda como refactor futuro si el número de tools crece de forma significativa.
|
|
- **Alternativa** (mantener un solo archivo): descartada; el argumento de bootstrap de D2 ya se cumplió y la mezcla de dominios penaliza la legibilidad y los futuros diffs.
|
|
|
|
### D2 (revisión): se actualiza la decisión del change `create-outline-mcp-server`
|
|
|
|
La D2 original ("todo el código en `main.go`") queda sustituida por esta organización multi-archivo en paquete único. El carácter de monolito deliberado (un único binario, un único paquete) se mantiene; lo que cambia es la distribución física en archivos.
|
|
|
|
### D3: Movimiento mecánico de código, sin reescritura
|
|
|
|
Las funciones y tipos se trasladan íntegras (mismos nombres, firmas, comentarios y directivas `//nolint`). Solo se ajustan los bloques `import` de cada archivo nuevo. Esto minimiza el riesgo del refactor y hace el diff auditable como puro movimiento.
|
|
|
|
### D4: Las variables de build permanecen en `main.go`
|
|
|
|
`Version`, `GiteaURL`, `RepoOwner` y `RepoName` se inyectan con `-ldflags -X main.Version=...` y el paquete sigue siendo `main`, por lo que no hay razón para moverlas. Permanecen junto al entrypoint, que es su punto natural de referencia.
|
|
|
|
## Risks / Trade-offs
|
|
|
|
- [División incorrecta de imports causa fallo de compilación] → Verificación inmediata con `go build ./...` en el contenedor tras cada movimiento; es un error de compilación, no un error silencioso.
|
|
- [`golangci-lint` señala imports sin usar o duplicados] → Ejecutar `golangci-lint run` en el contenedor como parte de la verificación.
|
|
- [Confusión temporal por familiaridad con el archivo único] → El diff es puro movimiento de código; los nombres de archivo (`client.go`, `tools.go`, `updater.go`) se corresponden directamente con los dominios.
|
|
- [Regresión funcional no detectada por compilación] → Prueba manual por stdio del servidor MCP (handshake + tools/list) tras el refactor, igual que en el change original.
|
|
|
|
## Migration Plan
|
|
|
|
1. Crear los tres archivos nuevos moviendo bloques completos desde `main.go`.
|
|
2. Reducir `main.go` a entrypoint + variables de build + registro de tools.
|
|
3. Compilar, lintear y probar por stdio en el contenedor DevPod.
|
|
4. Rollback trivial: `git revert` del commit único del refactor.
|
|
|
|
## Open Questions
|
|
|
|
(ninguna)
|