Skip to content

feat: generate base SQL schema for GORM modules and check it in doctor - #57

Merged
juancadev-io merged 1 commit into
mainfrom
feat/gorm-base-schema-and-doctor-check
Sep 2, 2026
Merged

juancadev-io merged 1 commit into
mainfrom
feat/gorm-base-schema-and-doctor-check

Conversation

@juancadev-io

Copy link
Copy Markdown
Contributor

El problema

Un proyecto recién creado con --gorm devolvía 500 en todos los endpoints. El generador escribía el repositorio, la entidad y el controlador, pero nada creaba nunca la tabla que consultan. El servidor arrancaba con buen aspecto y fallaba en la primera petición, sin pista de por qué.

Es el primer camino que recomienda la documentación, así que lo encuentra cualquiera en su primera hora.

Por qué no AutoMigrate

Es la solución habitual y no es la que se usa aquí. Dejar que el proceso altere el esquema al arrancar no es aceptable cuando la base de datos se aprovisiona por adelantado. El CLI ahora emite el DDL como un archivo que una persona revisa y aplica:

db/schema/<tabla>.sql

El motor se resuelve en este orden: DATABASE_ENGINE en .envdatabase.engine en application.properties (con los placeholders resueltos) → sqlite.

Tipos por dialecto para sqlite, postgres, mysql, mariadb y sqlserver. Este último necesita la forma IF OBJECT_ID porque no tiene CREATE TABLE IF NOT EXISTS. Un motor desconocido genera archivo igualmente, con tipos ANSI y un comentario de aviso de que no están verificados.

TableName() fijado en la entidad

Sin él GORM deriva el nombre del tipo Go — TasksEntitytasks_entities — que no coincidiría con el DDL. Fijándolo, los dos nombres se renombran juntos o no se renombran.

keel doctor: comprobación 7

Un módulo con GORM y sin archivo de esquema ahora es error. Resuelve la tabla igual que lo haría GORM, leyendo por AST la struct que embebe database.EntityBase, en vez de adivinarla del nombre del directorio. Importa: el mensaje tiene que nombrar la tabla que la aplicación consulta de verdad, y con el directorio se equivocaba (orderitems en lugar de order_item_entities).

Dos arreglos de doctor que salieron en la misma auditoría

  • Aprobaba un directorio vacío y salía 0. Que no haya ni keel.toml ni go.mod es ahora error duro: no hay proyecto que evaluar.
  • Los archivos opcionales ausentes marcaban aviso pero dejaban el veredicto en verde, así que un proyecto con carencias reales se reportaba sano.

⚠️ Un test cambiado, no añadido. TestDoctor_MissingKeelToml afirmaba el primero de esos dos bugs: usaba un directorio temporal vacío y esperaba éxito. Confundía "falta keel.toml" con "no hay proyecto", así que está partido en dos tests, uno por caso, en vez de retocado. Merece una mirada en la revisión.

Verificación

CRUD completo contra un proyecto generado desde cero: 201 → 200 → 200 → 204. Generación en postgres comprobada aparte, pluralización (order-itemorder_items) y resolución por AST con directorio ≠ tabla.

go vet limpio, go build ./... OK, 18 paquetes de tests en verde, 0 fallos.

Nota: en local, go test ./... -coverprofile=... -covermode=atomic sale con 1 en tres paquetes que no tienen ningún test, porque al módulo de toolchain de mi máquina le falta la herramienta covdata. Es una carencia de mi instalación, no del código; con el SDK completo de setup-go no debería reproducirse. Si el CI falla ahí, es eso y no otra cosa.

gofmt -l señala internal/keeltoml/keeltoml_test.go, que ya venía así de main y no lo toca este PR — lo dejo fuera para no mezclar.

A project scaffolded with `keel new --gorm` returned 500 on every endpoint.
The generator wrote the repository, the entity and the controller, but
nothing ever created the table they query, so the first request against a
fresh project failed and the cause was invisible: the server started fine.

The usual fix is AutoMigrate. This does not use it. Letting the process
alter the schema on boot is not acceptable where the database is
provisioned ahead of time, so the CLI now emits the DDL as a file a person
reviews and applies:

  db/schema/<table>.sql

Generated from the engine resolved in this order — DATABASE_ENGINE in
.env, then database.engine in application.properties (placeholders
resolved), then sqlite. Types are per dialect: sqlite, postgres, mysql,
mariadb and sqlserver, which needs the IF OBJECT_ID form because it has no
CREATE TABLE IF NOT EXISTS. An unknown engine still emits a file, with
ANSI types and a warning comment saying the types are unverified.

The entity template now pins TableName(). Without it GORM derives the name
from the Go type — TasksEntity becomes tasks_entities — which would not
match the DDL. Pinning it makes the two renameable together or not at all.

`keel doctor` gains check 7: a GORM-backed module with no schema file is an
error. It finds the table the same way GORM would, reading the struct that
embeds database.EntityBase via AST rather than guessing from the directory
name, so the message names the table the application actually queries.

Two related doctor fixes, both surfaced by the same audit:

- It approved an empty directory and exited 0. Absence of both keel.toml
  and go.mod is now a hard error: there is no project to grade.
- Missing optional files set a warning but left the verdict green, so a
  project with real gaps was reported healthy.

TestDoctor_MissingKeelToml asserted the first of those, using an empty temp
dir and expecting success. It conflated "no keel.toml" with "no project",
so it is split into one test per case rather than amended.
@juancadev-io
juancadev-io merged commit 138fbea into main Sep 2, 2026
1 check passed
@juancadev-io
juancadev-io deleted the feat/gorm-base-schema-and-doctor-check branch September 2, 2026 13:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant