feat: generate base SQL schema for GORM modules and check it in doctor - #57
Merged
Merged
Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
El problema
Un proyecto recién creado con
--gormdevolví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
AutoMigrateEs 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:
El motor se resuelve en este orden:
DATABASE_ENGINEen.env→database.engineenapplication.properties(con los placeholders resueltos) →sqlite.Tipos por dialecto para sqlite, postgres, mysql, mariadb y sqlserver. Este último necesita la forma
IF OBJECT_IDporque no tieneCREATE 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 entidadSin él GORM deriva el nombre del tipo Go —
TasksEntity→tasks_entities— que no coincidiría con el DDL. Fijándolo, los dos nombres se renombran juntos o no se renombran.keel doctor: comprobación 7Un 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 (orderitemsen lugar deorder_item_entities).Dos arreglos de
doctorque salieron en la misma auditoríakeel.tomlnigo.modes ahora error duro: no hay proyecto que evaluar.Verificación
CRUD completo contra un proyecto generado desde cero:
201 → 200 → 200 → 204. Generación en postgres comprobada aparte, pluralización (order-item→order_items) y resolución por AST con directorio ≠ tabla.go vetlimpio,go build ./...OK, 18 paquetes de tests en verde, 0 fallos.Nota: en local,
go test ./... -coverprofile=... -covermode=atomicsale con 1 en tres paquetes que no tienen ningún test, porque al módulo de toolchain de mi máquina le falta la herramientacovdata. Es una carencia de mi instalación, no del código; con el SDK completo desetup-gono debería reproducirse. Si el CI falla ahí, es eso y no otra cosa.gofmt -lseñalainternal/keeltoml/keeltoml_test.go, que ya venía así demainy no lo toca este PR — lo dejo fuera para no mezclar.