gooseglass

package module
v0.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 20, 2026 License: MIT Imports: 12 Imported by: 0

README

Goose Glass Go Reference Go Workflow

An outline of a Goose on a glass pane.

This package creates a few web-pages to migrate a database. It should work with any database Goose has a provider for (PostgreSQL, SQLite, MySQL...). WARNING - It does not have any authorization or authentication on any endpoints.

See the Go Package documentation for this project to see how you can just pass in a goose.Provider and a handler to get some interactive pages.

Example

package main

import (
	"cmp"
	"database/sql"
	"embed"
	"io/fs"
	"log"
	"log/slog"
	"net/http"
	"os"

	"github.com/crhntr/libsqlgoose"
	"github.com/pressly/goose/v3"
	_ "github.com/tursodatabase/libsql-client-go/libsql"
	_ "modernc.org/sqlite"

	"github.com/crhntr/gooseglass"
)

func main() {
	setupLogger()
	log.Println("Starting Migration Server")

	db := openDatabase()
	defer func() {
		if err := db.Close(); err != nil {
			log.Printf("failed to close db connection: %s", err)
		}
	}()

	provider, err := migrationsProvider(db)
	if err != nil {
		log.Fatalf("failed to load migrations: %s", err)
	}
	defer func() {
		if err := provider.Close(); err != nil {
			log.Printf("failed to close provider: %s", err)
		}
	}()

	mux := http.NewServeMux()
	gooseglass.Pages(mux, provider)
	port := cmp.Or(os.Getenv("PORT"), "8081")
	log.Printf("serving on port %s", port)
	log.Fatal(http.ListenAndServe(":"+port, mux))
}

//go:embed migrations/*.sql
var migrations embed.FS

func migrationsProvider(db *sql.DB, opt ...goose.ProviderOption) (*goose.Provider, error) {
	dir, err := fs.Sub(migrations, "migrations")
	if err != nil {
		return nil, err
	}
	opt = append(opt, goose.WithStore(libsqlgoose.NewStore()))
	return goose.NewProvider(libsqlgoose.Dialect, db, dir, opt...)
}

func openDatabase() *sql.DB {
	dbURL, ok := os.LookupEnv("DATABASE_URL")
	if !ok {
		log.Fatal("DATABASE_URL environment variable not set")
	}

	db, err := sql.Open("libsql", dbURL)
	if err != nil {
		log.Fatalf("failed to open db %s: %s", dbURL, err)
	}
	return db
}

func setupLogger() {
	if ll, ok := os.LookupEnv("LOG_LEVEL"); ok {
		var level = slog.LevelInfo
		if err := (&level).UnmarshalText([]byte(ll)); err != nil {
			log.Fatal(err)
		}
		slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
			Level: level,
		})))
		if level >= slog.LevelDebug {
			goose.SetLogger(slog.NewLogLogger(slog.Default().Handler(), level))
			goose.SetVerbose(level >= slog.LevelDebug)
		}
	}
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Pages

func Pages(mux *http.ServeMux, provider Provider)

Types

type Provider added in v0.0.1

type Provider interface {
	Status(ctx context.Context) ([]*goose.MigrationStatus, error)
	Down(ctx context.Context) (*goose.MigrationResult, error)
	DownTo(ctx context.Context, version int64) ([]*goose.MigrationResult, error)
	Up(ctx context.Context) ([]*goose.MigrationResult, error)
	UpTo(ctx context.Context, version int64) ([]*goose.MigrationResult, error)
}

type TemplateRoutePaths

type TemplateRoutePaths struct {
	// contains filtered or unexported fields
}

func (TemplateRoutePaths) Down

func (routePaths TemplateRoutePaths) Down() string

func (TemplateRoutePaths) DownTo added in v0.0.1

func (routePaths TemplateRoutePaths) DownTo(version int64) string

func (TemplateRoutePaths) Status

func (routePaths TemplateRoutePaths) Status() string

func (TemplateRoutePaths) Up

func (routePaths TemplateRoutePaths) Up() string

func (TemplateRoutePaths) UpTo added in v0.0.1

func (routePaths TemplateRoutePaths) UpTo(version int64) string

Directories

Path Synopsis
internal
fake
Code generated by counterfeiter.
Code generated by counterfeiter.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL