Add zero-dependency SQLite mode so users can run Erupe without
PostgreSQL. A transparent db.DB wrapper auto-translates PostgreSQL
SQL ($N placeholders, now(), ::casts, ILIKE, public. prefix,
TRUNCATE) for SQLite at runtime — all 28 repo files use the wrapper
with no per-query changes needed.
Setup wizard gains two new steps: quest file detection with download
link, and gameplay presets (solo/small/community/rebalanced). The API
server gets a /dashboard endpoint with auto-refreshing stats.
CI release workflow now builds and pushes Docker images to GHCR
alongside binary artifacts on tag push.
Key changes:
- common/db: DB/Tx wrapper with 6 SQL translation rules
- server/migrations/sqlite: full SQLite schema (0001-0005)
- config: Database.Driver field ("postgres" or "sqlite")
- main.go: SQLite connection with WAL mode, single writer
- server/setup: quest check + preset selection steps
- server/api: /dashboard with live stats
- .github/workflows: Docker in release, deduplicate docker.yml
Add 148 integration tests exercising actual SQL against PostgreSQL for
all previously untested repository files. Includes 6 new fixture helpers
in testhelpers_db.go and CI PostgreSQL service configuration.
Discovered and documented existing RecordPurchase SQL bug (ambiguous
column reference in ON CONFLICT clause).
Only the database password is truly mandatory to get started, but
config.example.json was 267 lines with 90+ options. Newcomers faced a
wall of settings with no indication of what matters.
Add registerDefaults() with all sane defaults via Viper so a minimal
config (just DB credentials) produces a fully working server. Gameplay
multipliers default to 1.0 instead of Go's zero value 0.0, which
previously zeroed out all quest rewards for minimal configs. Uses
dot-notation defaults for GameplayOptions/DebugOptions so users can
override individual fields without losing other defaults.
- Shrink config.example.json from 267 to 10 lines
- Rename full original to config.reference.json as documentation
- Simplify wizard buildDefaultConfig() from ~220 to ~12 lines
- Fix latent bug: SaveDumps default used wrong key DevModeOptions
- Add tests: minimal config, backward compat, single-field override
- Update release workflow, README, CONTRIBUTING, docker/README
Replace 4 independent schema management code paths (Docker shell
script, setup wizard pg_restore, test helpers, manual psql) with a
single migration runner embedded in the server binary.
The new server/migrations/ package uses Go embed to bundle all SQL
schemas. On startup, Migrate() creates a schema_version tracking
table, detects existing databases (auto-marks baseline as applied),
and runs pending migrations in transactions.
Key changes:
- Consolidated init.sql + 9.2-update + 33 patches into 0001_init.sql
- Setup wizard simplified to single "Apply schema" checkbox
- Test helpers use migrations.Migrate() instead of pg_restore
- Docker no longer needs schema volume mounts or init script
- Seed data (shops, events, gacha) embedded and applied via API
- Future migrations just add 0002_*.sql files — no manual steps
Fix errcheck violations across 11 repo files by wrapping deferred
rows.Close() and tx.Rollback() calls to discard the error return.
Fix unchecked Scan/Exec calls in guild store tests. Fix staticcheck
SA9003 empty branch in test helpers.
Add 6 mock-based unit tests for GetCharacterSaveData covering nil
savedata, sql.ErrNoRows, DB errors, compressed round-trip,
new-character skip, and config mode/pointer propagation.
Replace concrete pointer types on the Server struct with interfaces to
decouple handlers from PostgreSQL implementations. This enables mock/stub
injection for unit tests and opens the door to alternative storage
backends (SQLite, in-memory).
Also adds 9 missing repo initializations to SetTestDB() (event,
achievement, shop, cafe, goocoo, diva, misc, scenario, mercenary)
to match NewServer().
- testhelpers_db: retry truncateAllTables up to 3 times on deadlock,
which occurs when previous tests' goroutines still hold DB connections
- handlers_rengoku_integration_test: restore rengoku_score table after
TestRengokuData_SaveOnDBError drops it, preventing cascading failures
in all subsequent rengoku tests
- client_connection_simulation_test: fix TestClientConnection_PacketDuringLogout
to accept both race outcomes (save-wins or logout-wins) since both
handlers independently load from DB and last-writer-wins is valid
Eliminate 18 direct s.server.db calls from handlers_items.go,
handlers_distitem.go, and handlers_session.go by moving queries into
dedicated repository types.
New repositories:
- StampRepository (7 methods, stamps table)
- DistributionRepository (4 methods, distribution/distribution_items)
- SessionRepository (4 methods, sign_sessions/servers)
Also adds ClearTreasureHunt and InsertKillLog to GuildRepository,
which already owns those tables for read operations.
Three fixes for the channelserver test suite:
- Add net.ErrClosed check in acceptClients() so a closed listener
breaks the loop immediately instead of spinning and logging warnings.
This is correct production behavior too.
- Remove -c flag from pg_restore that conflicted with CleanTestDB's
prior DROP, causing "gook DROP CONSTRAINT" errors. Clean the schema
with DROP SCHEMA CASCADE instead of per-table drops.
- Use sync.Once to apply the test schema once per binary run, then
TRUNCATE tables for isolation. Reduces ~60 pg_restore + 29-patch
cycles to a single setup pass.
Move all direct DB access from handlers_rengoku.go (11 calls) and
handlers_mail.go (10 calls) into dedicated repository types, continuing
the established extraction pattern.
RengokuRepository provides UpsertScore and GetRanking, replacing a
3-call check/insert/update sequence and an 8-case switch of nearly
identical queries respectively.
MailRepository provides SendMail, SendMailTx, GetListForCharacter,
GetByID, MarkRead, MarkDeleted, SetLocked, and MarkItemReceived.
The old Mail.Send(), Mail.MarkRead(), GetMailListForCharacter, and
GetMailByID free functions are removed. Guild handlers that sent mail
via Mail.Send(s, ...) now call mailRepo directly.
Move all direct DB calls from handlers_festa.go (23 calls across 8
tables) and handlers_tower.go (16 calls across 4 tables) into
dedicated repository structs following the established pattern.
FestaRepository (14 methods): lifecycle cleanup, event management,
team souls, trial stats/rankings, user state, voting, registration,
soul submission, prize claiming/enumeration.
TowerRepository (12 methods): personal tower data (skills, progress,
gems), guild tenrouirai progress/scores/page advancement, tower RP.
Also fix pre-existing nil pointer panics in integration tests by
adding SetTestDB helper that initializes both the DB connection and
all repositories, and wire the done channel in createTestServerWithDB
to prevent Shutdown panics.
Add 34 tests covering all previously-untested GuildRepository methods:
invitations/scouts, guild posts, alliances, adventures, treasure
hunts, meals, kill tracking, and edge cases like disband with
alliance cleanup.
Fix test schema setup to apply the 9.2 update schema after init.sql,
which bridges v9.1.0 to v9.2.0 and resolves 9 pre-existing test
failures caused by missing columns (rp_today, created_at, etc.).
Make patch schemas 14 and 19 idempotent so they no longer fail when
applied against a schema that already has the target state (e.g.
festival_color type already renamed, legacy column names).
Per anti-patterns.md item #9, guild-related SQL was scattered across
~15 handler files with no repository abstraction. Following the same
pattern established by CharacterRepository, this centralizes all
guilds, guild_characters, and guild_applications table access into a
single GuildRepository (~30 methods).
guild_model.go and handlers_guild_member.go are trimmed to types and
pure business logic only. All handler files (guild_*, festa, mail,
house, mercenary, rengoku) now call s.server.guildRepo methods
instead of direct DB queries or methods on domain objects.
Add explicit error discards (_ =) for Close() calls on network
connections, SQL rows, and file handles across 28 files. Also add
.golangci.yml with standard linter defaults to match CI configuration.
Re-enable the golangci-lint job in CI (disabled Oct 2025), update to
Go 1.25 and golangci-lint-action v7. Fix errcheck, gosimple S1009,
staticcheck SA4031 and SA2001 errors across 54 files. Remaining ~39
lint errors will be addressed in follow-up commits.