From 6c77aee7488f41e331fb0a5f2f51f687a9c6e2c4 Mon Sep 17 00:00:00 2001 From: Elliott Minns Date: Thu, 7 Nov 2024 14:45:01 -0600 Subject: [PATCH] Use go:embed for migrations --- Dockerfile | 3 --- internal/app/app.go | 15 +++++++++------ internal/database/database.go | 17 +++++++++-------- main.go | 6 +++++- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/Dockerfile b/Dockerfile index 863e22d..f3925e2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -72,12 +72,9 @@ USER appuser # Copy the executable from the "build" stage. COPY --from=build /bin/server /bin/ -COPY ./migrations ./migrations COPY ./templates ./templates COPY ./static ./static -ENV MIGRATIONS_URL=file://migrations - # Expose the port that the application listens on. EXPOSE 8080 diff --git a/internal/app/app.go b/internal/app/app.go index 4d77697..69f0b40 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "html/template" + "io/fs" "log/slog" "net/http" "os" @@ -18,13 +19,14 @@ import ( ) type App struct { - logger *slog.Logger - router *http.ServeMux - db *pgxpool.Pool - rdb *redis.Client + logger *slog.Logger + router *http.ServeMux + db *pgxpool.Pool + rdb *redis.Client + migrations fs.FS } -func New(logger *slog.Logger) *App { +func New(logger *slog.Logger, migrations fs.FS) *App { router := http.NewServeMux() redisAddr, exists := os.LookupEnv("REDIS_ADDR") @@ -38,13 +40,14 @@ func New(logger *slog.Logger) *App { rdb: redis.NewClient(&redis.Options{ Addr: redisAddr, }), + migrations: migrations, } return app } func (a *App) Start(ctx context.Context) error { - db, err := database.Connect(ctx, a.logger) + db, err := database.Connect(ctx, a.logger, a.migrations) if err != nil { return fmt.Errorf("failed to connect to db: %w", err) } diff --git a/internal/database/database.go b/internal/database/database.go index 7857aae..138bcb9 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -4,12 +4,13 @@ import ( "context" "errors" "fmt" + "io/fs" "log/slog" "os" "github.com/golang-migrate/migrate/v4" _ "github.com/golang-migrate/migrate/v4/database/postgres" - _ "github.com/golang-migrate/migrate/v4/source/file" + "github.com/golang-migrate/migrate/v4/source/iofs" "github.com/jackc/pgx/v5/pgxpool" "github.com/dreamsofcode-io/guestbook/internal/config" @@ -60,7 +61,7 @@ func dbURL() (string, error) { return cfg.URL(), nil } -func Connect(ctx context.Context, logger *slog.Logger) (*pgxpool.Pool, error) { +func Connect(ctx context.Context, logger *slog.Logger, migrations fs.FS) (*pgxpool.Pool, error) { config, err := loadConfig() if err != nil { return nil, err @@ -73,17 +74,17 @@ func Connect(ctx context.Context, logger *slog.Logger) (*pgxpool.Pool, error) { logger.Debug("Running migrations") - migrationsURL, exists := os.LookupEnv("MIGRATIONS_PATH") - if !exists { - migrationsURL = "file://migrations" - } - url, err := dbURL() if err != nil { return nil, err } - migrator, err := migrate.New(migrationsURL, url) + source, err := iofs.New(migrations, "migrations") + if err != nil { + return nil, fmt.Errorf("failed to create source: %w", err) + } + + migrator, err := migrate.NewWithSourceInstance("iofs", source, url) if err != nil { return nil, fmt.Errorf("migrate new: %s", err) } diff --git a/main.go b/main.go index fc6f9d4..cc72a08 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( "context" + "embed" "log/slog" "os" "os/signal" @@ -10,6 +11,9 @@ import ( "github.com/joho/godotenv" ) +//go:embed migrations/*.sql +var migrations embed.FS + func main() { godotenv.Load() @@ -17,7 +21,7 @@ func main() { ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt) defer cancel() - a := app.New(logger) + a := app.New(logger, migrations) if err := a.Start(ctx); err != nil { logger.Error("failed to start server", slog.Any("error", err))