Commit Graph
156 Commits
Author SHA1 Message Date
Sansan bc7d406e41 Remove Godot OpenAPI generator script
It produced code that doesn't parse in Godot 4. Typed response classes will be generated in MusicPlayer instead (Sansan/MusicPlayer#40).
2026-10-06 16:12:05 +02:00
Sansan 2c3e97190d Prefer UUIDs in the API (Phase 3 of the UUID migration)
CI / docker (push) Successful in 46s
CI / integration (push) Successful in 23s
CI / test (push) Successful in 30s
CI / publish (push) Skipped
- New /api/v1 endpoints: GET /soundtracks, /soundtracks/{uuid},
  /songs/{uuid} and /songs/{uuid}/file (streams the song, Range support,
  locked during sync)
- UUIDs added to every response with soundtracks or songs: queue info and
  list (SoundtrackUuid, SongUuid) and statistics (soundtrack_uuid,
  song_uuid). Existing fields stay for backward compatibility
- Play counts and broken-song removal use song UUIDs instead of
  soundtrack ID + song name, so songs with the same name are counted
  separately
- Statistics return an empty song list for soundtracks without songs
  instead of a single empty entry
- The legacy .id file cleanup stays until Phase 4 (#31)

Closes #29
2026-10-06 15:54:41 +02:00
Sansan 8c974a49cc Merge workflows into one CI pipeline
CI / test (push) Successful in 31s
CI / integration (push) Successful in 39s
CI / publish (push) Skipped
CI / docker (push) Successful in 54s
- Unit tests, integration tests and the Docker build check run in
  parallel on branches and pull requests
- Integration tests run on every push instead of only manually
- Branch builds only build amd64 and check the arm64 cross-compile in the
  test job; both platforms are built and pushed only for version tags,
  after all tests pass
- Docker layers cached through the runner cache, Go module and build
  caches mounted in the Dockerfile
- A newer push to the same branch cancels the running pipeline
2026-10-06 15:35:32 +02:00
Sansan 9db61956d3 Publish Docker image when a version tag is pushed
Build / test (push) Successful in 8s
Build / docker (push) Successful in 49s
Releases are triggered by tags like v5.0.0 instead of version branches.
2026-10-06 15:24:06 +02:00
Sansan bd250ecaee Run tests in CI and build multi-arch Docker images
Build / test (push) Successful in 38s
Build / docker (push) Successful in 2m2s
- Build (main, develop): vet and unit tests, then a linux/amd64 and
  linux/arm64 image build without pushing
- Publish (version branches): same tests, then build and push both
  platforms
- Integration tests (manual): run the testcontainers suite
2026-10-06 15:22:13 +02:00
Sansan 59dfff38bc Clean up build tooling and Dockerfile
- Dockerfile cross-compiles Go for the target platform (amd64/arm64
  without emulation), uses templ pinned in go.mod, runs as uid 1000 on
  alpine and lets FRONTEND_IMAGE pin the frontend version
- justfile: tools via go tool, `test` (unit) and `test-integration`
  (uses the active docker context), no hardcoded paths, no tailwind or
  frontend recipes
- Removed app.yaml, init.sh, tailwind.config.js and the tracked .idea
  folder
2026-10-06 15:21:46 +02:00
Sansan 7b144ae419 Rewrite tests to run without a database
- Unit tests use an in-memory fake database (internal/testutil/fakedb),
  temp folders and httptest; `go test ./...` needs no Docker or env vars
- Integration tests (build tag "integration") start PostgreSQL with
  testcontainers: migrations step by step, SQL dumps (skipped if
  missing) and a full sync against a real database
- Removed tests that only checked copies of the logic or had empty
  bodies, the broken root integration_test.go, compose.test.yaml and
  .env.test with hardcoded paths
- testMusic MP3s replaced with tiny placeholders (sync never decodes
  audio), 194 MB -> 168 KB
2026-10-06 15:20:31 +02:00
Sansan 090e794460 Restructure backend into services and fix security, crash and sync issues
Security
- Serve character images through os.Root so names like ../ can't escape
  the characters folder
- Sync start and /sync/reset are POST only (legacy and /api/v1)
- /api/v1/token/cleanup requires a token, password compared in constant
  time, tokens no longer logged
- Echo's rate limiter replaces the custom one; TRUSTED_PROXIES enables
  X-Forwarded-For for reverse proxies

Crashes and races
- Sync state lives in SyncService with atomics and a mutex instead of
  unsynchronised globals (fixes concurrent map writes during full sync)
- Only one sync can run; /api/v1 sync and music routes are locked during
  sync like the legacy ones
- No log.Fatal outside startup: errors become 4xx/5xx responses
- Search uses an in-order character match instead of unescaped regexes
- Empty queue / no songs return 404 instead of panicking or looping

Behaviour
- Sync result is computed once and stays the same between polls
- Swagger and /openapi serve the embedded spec
- Shutdown stops HTTP before closing the database
- Expired tokens are deleted with a context that outlives the request
- Files are served with Range support and correct content types; audio
  has no write deadline

Performance
- Migration 000006 adds soundtrack.fingerprint (names, sizes, mtimes) so
  unchanged folders are skipped without reading any files
- Songs are reconciled per soundtrack with one query plus needed writes;
  renames keep play counts
- Moved MUSIC_PATH updates soundtrack and song paths
- .id cleanup only runs for changed soundtracks or a full sync
- Classic random uses one SQL query; Gitea release lookups are cached
  with a timeout

Structure
- internal/config reads all environment variables once
- sqlc emits a Querier interface; backend globals become services
  injected into handlers
- One route registration shared by legacy and /api/v1
- Removed dead code (dbHelper.go, unused middleware, duplicate Gitea
  functions, embedded Swagger UI copy) and lib/pq
- templ and swag pinned as go tools
2026-10-06 15:20:14 +02:00
Sansan 75b6f0c1cf Remove frontend source from cmd
The frontend is built separately and copied into the Docker image from
the musicfrontend image.
2026-10-06 15:19:49 +02:00
Sansan 2406fe9eb6 Ignore database dumps
Build / build (push) Failing after 34s
2026-10-05 18:49:15 +02:00
Sansan 581d91f78b Fixed workflow file
Build / build (push) Successful in 39s
Publish / publish (push) Successful in 49s
2026-09-26 17:16:23 +02:00
Sansan a8a2602f50 #9 Major routes refactor and expansion, #15 Added API for statistics, Added search cache backend and functionality tests, Backend sync improvements
Build / build (push) Successful in 56s
2026-09-26 16:48:40 +02:00
Sansan e86c0f8e04 Combine Issue #28 (UUID Phase 2 - NOT NULL) into migration 000005
- Add NOT NULL constraints to soundtrack.uuid, song.uuid, and song.soundtrack_uuid
- Add corresponding DROP NOT NULL in down migration
- Update header comments to reflect combined Phase 1 & 2

This eliminates the need for a separate migration 000007 while maintaining
proper rollback capability. The NOT NULL constraints are added AFTER
all UUID backfills are complete, ensuring data integrity.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-07-28 14:16:04 +02:00
Sansan eda60e0c07 Added fuzzy finder to search, made sync check as middleware, .id file is never used
Build / build (push) Successful in 45s
2026-07-02 09:30:24 +02:00
Sansan a8df738108 #9 Changed the term game to soundtrack everywhere
Build / build (push) Successful in 45s
2026-06-29 18:39:09 +02:00
Sansan dbef39b828 Merge pull request 'Feature/statistics api' (#26) from feature/statistics-api into develop
Build / build (push) Successful in 51s
Reviewed-on: #26
2026-06-14 11:48:36 +02:00
Sansan 4e5bdc4ee2 Fixed some small bugs after merge 2026-06-14 11:30:58 +02:00
Sansan 0894d65ec5 Merge branch 'develop' into feature/statistics-api
# Conflicts:
#	internal/backend/music.go
#	internal/backend/sync.go
#	internal/server/server.go
#	internal/server/syncHandler.go
#	internal/server/sync_handler_test.go
#	internal/server/test_helpers.go
#	internal/server/zz_music_handler_test.go
2026-06-13 11:51:56 +02:00
Sansan 4033899a68 Merge pull request 'Feature/session token api' (#25) from feature/session-token-api into develop
Build / build (push) Successful in 50s
Reviewed-on: #25
2026-06-13 11:30:08 +02:00
Sansan c6a07e69e7 Fixed some small bugs. Frontend is now included in the docker image 2026-06-13 11:26:52 +02:00
Sansan 6d4a034753 Fix duplicate import in routes.go
Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-08 20:44:17 +02:00
SansanandMistral Vibe b0418b4f38 feat: Add id column to song table and prep for UUID migration
- Add id serial4 PK to song table (was composite PK)
- Update queries to use soundtrack_id + path
- Add UUID columns to soundtrack and song (nullable)
- Add migration tracking table

TODO: Run sqlc generate, then create backfill migration (000008)

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-08 20:36:12 +02:00
Sansan 176848bb6d feat: Add deprecation notice for global Dbpool and Ctx variables
- Enhanced TODO comment to clearly mark Dbpool and Ctx as DEPRECATED
- Direct developers to use Database struct from database.go instead
- Migration test already includes manual data insertion (5 games, 8 songs)

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-08 20:36:12 +02:00
SansanandMistral Vibe fb387901cf test: Add migration test with manual data insertion
- TestMigrationsStepByStep: tests incremental migration workflow
  - Step 1: Apply first 4 migrations (creates game, song tables)
  - Step 2: Manually insert 5 games with 8 songs
  - Step 3: Apply migration 5 (rename game→soundtrack)
  - Step 4: Verify data preserved in soundtrack table
- Helper functions: cleanupDB, createTestDB, applyMigrations
- Tests data integrity through full migration cycle

Requires: DB_HOST, DB_PORT, DB_USERNAME, DB_PASSWORD env vars
Run: migrate -path internal/db/migrations -database "postgres://user:pass@host:port/db?sslmode=disable" up N

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-08 20:36:12 +02:00
Sansan 0f29c33b1a test: Add statistics test with manual data insertion
- TestStatisticsEndpoints: tests /api/v1/statistics/summary endpoint
- TestPartialMigrationThenSyncThenComplete: tests migration + sync workflow
- insertTestData: helper to insert 5 soundtracks with 8 songs
- getTestToken: helper to get auth token for tests
- Updated other test files to use FindAllSoundtracks instead of FindAllGames

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-08 20:36:12 +02:00
Sansan cec408187d feat: Rename game to soundtrack throughout codebase
- Database migration: rename game table to soundtrack
- Rename game_name to soundtrack_name, game_id to soundtrack_id
- Update all SQL queries in soundtrack.sql, song.sql, song_list.sql, statistics.sql
- Regenerate sqlc code (soundtrack.sql.go, song.sql.go, etc.)
- Update backend: music.go, sync.go, statistics.go
- Update server: musicHandler.go, syncHandler.go, routes.go
- Update frontend: hello.go
- Keep URL paths as /games for backward compatibility

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-08 20:36:12 +02:00
Sansan c60f40d7e3 feat: Complete DI cleanup - migrate test helpers to Database struct
- Update internal/db/test_helpers.go to use Database struct instead of globals
- Update internal/server/test_helpers.go to use TestDatabase.Pool
- Add TODO comment to old Dbpool/Ctx globals in dbHelper.go
- Remove db.Testf() usage from production code (kept for deprecated /dbtest endpoint)

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-08 20:36:12 +02:00
Sansan 2f407f6eef feat: Add deprecation middleware for legacy endpoints
- Create middleware/deprecation.go with DeprecationMiddleware
- Adds Warning and Deprecation headers to old endpoints
- Apply middleware to all non-/api/v1 routes:
  /version, /dbtest, /health, /character*, /download*, /sync/*,
  /music/*
- Message: 'Deprecated: This endpoint is deprecated. Use /api/v1/ endpoints instead.'

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-08 20:36:12 +02:00
Sansan 4c2db11cc5 feat: Implement Statistics API with 8 endpoints under /api/v1/statistics/
- Add statistics.sql with 8 SQL queries for play count statistics
- Generate repository code via sqlc
- Add backend/statistics.go with business logic
- Add server/statistics_handler.go with Echo handlers
- Register protected routes under /api/v1/statistics/ with token auth
- Endpoints: games/most-played, games/least-played, games/never-played,
  games/last-played, games/oldest-played, songs/most-played,
  songs/least-played, summary

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-08 20:33:29 +02:00
Sansan 06cbad708d feat: Remove global db.Dbpool with dependency injection (Phase 0)
- Add Database struct in internal/db/database.go with Pool, Ctx, and RunMigrations()
- Update server.go to use Database struct with NewServerInstance()
- Add backend.go with InitBackend(), BackendRepo(), BackendCtx(), BackendPool()
- Update music.go and sync.go to use BackendRepo() and BackendCtx() instead of db.Dbpool/db.Ctx
- Update token_handler.go to accept pool parameter
- Update routes.go to use s.db.Pool for middleware
- Update cmd/main.go to use NewServerInstance() and HTTPServer()
- Update test_helpers.go to initialize backend with test database
- Update test files to use backend.BackendPool() and backend.BackendCtx()

Benefits:
- Easier to mock database for unit tests
- Follows Go best practices (dependency injection)
- Better architecture with explicit dependencies
- RunMigrations() replaces old Migrate_db() function

Note: Global db.Dbpool and db.Ctx still exist in dbHelper.go for backward compatibility
with test_helpers.go, but production code no longer uses them.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-08 20:33:29 +02:00
Sansan 89e884fae9 feat: Implement Session Token System with /api/v1 base path
- Add migration 000004 for sessions table and performance indexes
- Create session.sql queries for CRUD operations
- Generate session repository code with sqlc
- Create token auth middleware for Echo framework
- Create token handler with create/delete/cleanup endpoints
- Add /api/v1 router with token authentication infrastructure
- Update dbHelper.go to use Up() instead of Migrate(2)
- Update server.go to initialize token handler
- Existing endpoints remain functional (to be deprecated)

New endpoints:
- POST /api/v1/token - Create new session token
- DELETE /api/v1/token - Invalidate token
- POST /api/v1/token/cleanup - Remove expired sessions

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-08 20:33:29 +02:00
Sansan 24a9111333 feat: Remove global db.Dbpool with dependency injection (Phase 0)
- Add Database struct in internal/db/database.go with Pool, Ctx, and RunMigrations()
- Update server.go to use Database struct with NewServerInstance()
- Add backend.go with InitBackend(), BackendRepo(), BackendCtx(), BackendPool()
- Update music.go and sync.go to use BackendRepo() and BackendCtx() instead of db.Dbpool/db.Ctx
- Update token_handler.go to accept pool parameter
- Update routes.go to use s.db.Pool for middleware
- Update cmd/main.go to use NewServerInstance() and HTTPServer()
- Update test_helpers.go to initialize backend with test database
- Update test files to use backend.BackendPool() and backend.BackendCtx()

Benefits:
- Easier to mock database for unit tests
- Follows Go best practices (dependency injection)
- Better architecture with explicit dependencies
- RunMigrations() replaces old Migrate_db() function

Note: Global db.Dbpool and db.Ctx still exist in dbHelper.go for backward compatibility
with test_helpers.go, but production code no longer uses them.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-08 20:15:38 +02:00
Sansan 6cc014ffa3 feat: Implement Session Token System with /api/v1 base path
- Add migration 000004 for sessions table and performance indexes
- Create session.sql queries for CRUD operations
- Generate session repository code with sqlc
- Create token auth middleware for Echo framework
- Create token handler with create/delete/cleanup endpoints
- Add /api/v1 router with token authentication infrastructure
- Update dbHelper.go to use Up() instead of Migrate(2)
- Update server.go to initialize token handler
- Existing endpoints remain functional (to be deprecated)

New endpoints:
- POST /api/v1/token - Create new session token
- DELETE /api/v1/token - Invalidate token
- POST /api/v1/token/cleanup - Remove expired sessions

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-08 20:15:38 +02:00
Sansan 8f8b555ea5 Refactor handlers and update changelog for 5.0.0-Beta
Build / build (push) Successful in 48s
- Split IndexHandler into HealthHandler, VersionHandler, and CharacterHandler
- Rename index.go to version.go in backend
- Change VersionData.Changelog from string to []string
- Add changelog entries for issues #16-#23
- Remove TestDB function and related code
- Fix import ordering in several files

Closes #21, #22
References #16, #17, #18, #19, #20, #23

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-08 20:08:06 +02:00
Sansan a446dad7b6 Make pool and poolSong global variables
Build / build (push) Successful in 48s
2026-05-26 20:54:12 +02:00
Sansan d152ec1f11 fix: use podman-compose (installed via Homebrew) instead of podman compose
Build / build (push) Successful in 45s
2026-05-23 21:57:15 +02:00
Sansan 7a3934babf fix: use 'podman compose' instead of 'podman-compose'
Build / build (push) Successful in 41s
2026-05-23 20:18:25 +02:00
Sansan 08f539abd9 test: add justfile commands for running integration tests with podman
Build / build (push) Successful in 43s
2026-05-23 20:02:25 +02:00
Sansan 87a1a2d89a test: reduce testMusic size for faster CI runs
Build / build (push) Successful in 47s
2026-05-23 19:41:10 +02:00
Sansan 1ada52f5f8 test: add test data directories (testMusic and testCharacters) 2026-05-23 01:06:43 +02:00
Sansan 92b82da3af test: add simple unit tests for backend and logging packages
Build / build (push) Successful in 31s
2026-05-22 22:49:25 +02:00
Sansan b71072f6c8 fix: remove tailwind from dockerfile and add podman-build command
Build / build (push) Successful in 33s
2026-05-22 22:31:10 +02:00
Sansan d481be04a7 Fix YAML formatting in Gitea workflows
Build / build (push) Failing after 2m7s
2026-05-21 23:45:23 +02:00
Sansan 870f1787cb Fix for workflow 2026-05-21 23:35:26 +02:00
Sansan 89c31c2856 Replace all log.Println and fmt.Printf with Zap structured logging 2026-05-21 23:24:55 +02:00
Sansan f0653489d6 Added some files 2026-05-21 22:25:31 +02:00
Sansan d0fbba86f1 Remove frontend-build from build command 2026-05-21 09:56:23 +02:00
Sansan bd0e7f4a8d Add frontend-build command to justfile 2026-05-21 09:54:12 +02:00
Sansan b5926e3b31 Fix frontend build by updating dependencies and ESLint configuration 2026-05-21 09:51:14 +02:00
Sansan 37909139de Add Zap logging framework with structured logging for Echo and Grafana 2026-05-20 22:29:45 +02:00