Masahiko AMANO ba0713151c feat: config, migrations embed, and server entrypoint
- internal/config: typed Config struct loaded from env vars via godotenv;
  all fields from docs (listen addr, JWT, DB, storage, thumbs, import)
- migrations/embed.go: embed FS so goose SQL files are baked into the binary
- cmd/server/main.go: load config → connect pgxpool → goose migrations
  (embedded) → Gin server with GET /health returning 200 OK
- .env.example: documents all required and optional env vars
- go.mod: bump to Go 1.26, add gin/pgx/goose/godotenv as direct deps

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 18:57:17 +03:00

67 lines
1.5 KiB
Go

package main
import (
"context"
"log/slog"
"net/http"
"os"
"github.com/gin-gonic/gin"
"github.com/jackc/pgx/v5/pgxpool"
"github.com/jackc/pgx/v5/stdlib"
"github.com/pressly/goose/v3"
"tanabata/backend/internal/config"
"tanabata/backend/migrations"
)
func main() {
cfg, err := config.Load()
if err != nil {
slog.Error("failed to load config", "err", err)
os.Exit(1)
}
pool, err := pgxpool.New(context.Background(), cfg.DatabaseURL)
if err != nil {
slog.Error("failed to connect to database", "err", err)
os.Exit(1)
}
defer pool.Close()
if err := pool.Ping(context.Background()); err != nil {
slog.Error("database ping failed", "err", err)
os.Exit(1)
}
slog.Info("database connected")
// Run migrations using the embedded FS.
// stdlib.OpenDBFromPool wraps the pool in a *sql.DB without closing
// the pool when the sql.DB is closed.
migDB := stdlib.OpenDBFromPool(pool)
goose.SetBaseFS(migrations.FS)
if err := goose.SetDialect("postgres"); err != nil {
slog.Error("goose dialect error", "err", err)
os.Exit(1)
}
if err := goose.Up(migDB, "."); err != nil {
slog.Error("migrations failed", "err", err)
os.Exit(1)
}
migDB.Close()
slog.Info("migrations applied")
r := gin.New()
r.Use(gin.Recovery())
r.GET("/health", func(c *gin.Context) {
c.Status(http.StatusOK)
})
slog.Info("starting server", "addr", cfg.ListenAddr)
if err := r.Run(cfg.ListenAddr); err != nil {
slog.Error("server error", "err", err)
os.Exit(1)
}
}