fix: stabilization batch 4 — generator wiring, time.Time imports, error formatting, CI YAML#60
Merged
Merged
Conversation
… imports, error formatting, CI YAML
Cross-cutting compile/vet/test fixes found by exhaustively exercising every
generator command against real projects (init → feature/entity/usecase/
repository/handler/di) across all databases and building the output.
Critical compile breakers (now build+vet+test clean for sqlite, postgres,
mysql, postgres-json, sqlserver, mongodb):
- DI/feature/integrate/test wiring referenced NewPostgres<Entity>Repository for
every backend, but the repository generator emits NewPostgresJSON…/NewSQLServer…
/NewMongo… etc. Introduce repoConstructorPrefix(database) and use it in di.go
(container + Wire set), feature.go and test_integration.go so the generated
container compiles for every DB instead of only Postgres.
- feature created a new DI container with a hardcoded "postgres" database and
never threaded the real database through updateDIContainer/addFeatureToDI/
addSetupMethodsToDI. Thread it through.
- SQLite projects run on GORM (gorm.io/driver/sqlite) so main.go/DI hold a
*gorm.DB, but the repository was generated with a bespoke database/sql
(*sql.DB) implementation that could never be injected. Route SQLite through
the shared GORM "Postgres" generator (as MySQL already is). Remove the now
dead SQLite-with-fields/finder generators.
- MongoDB main.go exposes mongoClient (*mongo.Client), not db, so the injected
container scaffold (NewContainer(db)) failed to compile. Derive the
*mongo.Database from mongoClient when wiring the container.
- usecase DTOs with a time.Time field emitted `time.Time` without importing
"time" (dto.go: undefined: time). Import "time" when DTOs use it.
- entity unit tests omitted the "time" import for time.Time fields, used an
invalid composite literal (Priority{}) for the string-based custom-type stubs
the entity generator emits, and asserted Equal(time.Now(), field) which can
never pass. Add the import when needed, use a string conversion zero literal,
and assert the time field is non-zero instead.
Other generator fixes:
- repository implementations for SQLite/SQL Server/DynamoDB/Elasticsearch wrote
literal `%%w` (escaped percent, so errors were never wrapped) and SQL Server
FindByID wrote `fmt.Errorf("%s not found")` with no argument — both fail
`go vet`. Emit `%w` and substitute the entity name.
- `goca ci` generated an invalid test.yml: the step-level `env:` block was
indented at 6 spaces while sibling step keys use 8, so the workflow failed to
parse. Fix indentation.
- adding a --cache feature to an existing DI container emitted c.redisClient /
time references the container did not provide; only wire the cache decorator
when a decorator file exists and the container has a redisClient field,
otherwise wire the bare repository so the project always compiles.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Stabilization batch 4 — deep audit + cross-cutting fixes
This continues the stabilization effort (batches 1–3). I exhaustively exercised every generator command against real, freshly-generated projects —
init,entity,usecase,repository,handler,feature,di,integrate,interfaces,mocks,messages,middleware,test-integration,ci,config,analyze,doctor,upgrade,template— across all database backends, then compiled (go build/go vet), ran the generated tests, and read the output for correctness. Findings were reproduced before fixing.✅ Verified result of this PR
A full feature pipeline (
init → feature User --fields "...,joined:time.Time" --validation) now builds + vets + passes generated tests on all six databases —sqlite, postgres, mysql, postgres-json, sqlserver, mongodb(matrix: 6/6 pass, previously several failed to compile). Two-feature projects and--cacheprojects also compile and test clean. Fullgo test ./...on the goca repo is green.Fixed in this PR
Critical compile breakers
di,feature,integrateandtest-integrationall referencedNewPostgres<Entity>Repository, but the repository generator emitsNewPostgresJSON…,NewSQLServer…,NewMongo…, etc. →undefined: repository.NewPostgres…for postgres-json/sqlserver/sqlite/mongodb. Introduced a singlerepoConstructorPrefix(database)helper used everywhere.featurehardcoded"postgres"when creating a new DI container and never threaded the chosen--databasethroughupdateDIContainer/addFeatureToDI/addSetupMethodsToDI.main.go/DI hold a*gorm.DB(gorm.io/driver/sqlite), but the repository used a bespokedatabase/sql(*sql.DB) impl that could never be injected. Routed SQLite through the shared GORM generator (as MySQL already is). Default DB now works end-to-end.NewContainer(db)but mongomain.goexposesmongoClient(nodb). Now derivesmongoClient.Database(cfg.Database.Name).time.Timeemittedtime.Timefields without importing"time"→dto.go: undefined: time.--tests) failed to compile / always failed for common fields: missing"time"import, invalidPriority{}composite literal for string-based custom-type stubs, andassert.Equal(time.Now(), field)that can never pass. Now importstimewhen needed, uses a string-conversion zero literal, and asserts the field is non-zero.go vetbreakers%%w(soerrwas never wrapped) and SQL ServerFindByIDwrotefmt.Errorf("%s not found")with no argument. Emit%w/ substitute the entity name.Other
goca ciproduced an invalidtest.yml— the step-levelenv:block was indented at 6 spaces while sibling step keys use 8, so GitHub Actions rejected the file. Fixed indentation; now valid YAML.--cacheadded to an existing DI container emittedc.redisClient/timereferences the container didn't provide. Now only wires the decorator when a decorator file exists and the container has aredisClientfield; otherwise wires the bare repo so the project always compiles.Tests updated/added accordingly (
addSetupMethodsToDIcache pre-conditions, DB-threading callers).Documented but NOT fixed here (follow-up batch 5)
Reproduced during the audit; left for a focused follow-up to keep this PR reviewable:
handler --type grpc/feature --handlers grpc: the//go:build protoserver imports apbpackage that is never generated;go mod tidy/go vetignore build tags and fail to resolve it, breaking the whole module. Needs a no-op stub package or to defer the server file untilprotocruns.--cache(first feature): decorator file is generated but thegenerateDIpath is called withcache=false, so the decorator/redis client are never wired (orphaned). Needs full redisClient scaffolding inNewContainer+main.go.--middleware-types/--middleware: generates aninternal/middlewarepackage that is never imported; routes duplicate inlinecors/loggingand never applyrecovery. In some pathsroutes.gocallsmiddleware.CORS(...)without importing the package.interfaces --handler/--all: emitsundefined: User(references a bare*User);--repository/--usecaseinterfaces drift from the real generated implementations.usecase.GetUserOutput,usecase.ListUsersOutput); comment-only, soswag initfails but build is fine.FindAll/FullTextSearchdecode the response then return an empty slice (always empty results).init --template: all templates produce byte-identical Go code (only.goca.yamldiffers); microservice/monolith/enterprise features not delivered..goca.yamldatabase.portis always5432; template.goca.yamlhardcodestype: postgresregardless of--database.goca template init+ edit) are never consumed by generation.usecase --dto-validation,repository --implementation,handler --validationhave no observable effect.messageswriteserrorstomessages.goand constants tointernal/constants/(mismatch vs docs);--dry-runcreates empty dirs.test-integration --databasedoesn't affecthelpers.go(always imports all drivers).middleware/config validate/config init/template show/doctorprint errors but exit0(breaks CI gating).wiki/(Gin vs gorilla/mux, default db, JWT version, file layout).🤖 Generated with Claude Code