feat(02-01): add migration infrastructure with golang-migrate and embedded SQL

- RunMigrations applies versioned SQL files via golang-migrate + embed.FS (iofs)
- ErrNoChange handled correctly - not treated as failure
- Migration 0001 creates full current schema with CREATE TABLE IF NOT EXISTS
- All three tables (updates, tags, tag_assignments) with acknowledged_at and ON DELETE CASCADE
- Uses database/sqlite sub-package (modernc.org/sqlite, no CGO)
- go mod tidy applied after adding dependencies
This commit is contained in:
2026-03-23 21:56:34 +01:00
parent 57bf3bdfe5
commit 6506d93eea
5 changed files with 112 additions and 4 deletions

View File

@@ -0,0 +1,36 @@
package diunwebhook
import (
"database/sql"
"embed"
"errors"
"github.com/golang-migrate/migrate/v4"
sqlitemigrate "github.com/golang-migrate/migrate/v4/database/sqlite"
"github.com/golang-migrate/migrate/v4/source/iofs"
_ "modernc.org/sqlite"
)
//go:embed migrations/sqlite
var sqliteMigrations embed.FS
// RunMigrations applies all pending schema migrations to the given SQLite database.
// Returns nil if all migrations applied successfully or if database is already up to date.
func RunMigrations(db *sql.DB) error {
src, err := iofs.New(sqliteMigrations, "migrations/sqlite")
if err != nil {
return err
}
driver, err := sqlitemigrate.WithInstance(db, &sqlitemigrate.Config{})
if err != nil {
return err
}
m, err := migrate.NewWithInstance("iofs", src, "sqlite", driver)
if err != nil {
return err
}
if err := m.Up(); err != nil && !errors.Is(err, migrate.ErrNoChange) {
return err
}
return nil
}

View File

@@ -0,0 +1,3 @@
DROP TABLE IF EXISTS tag_assignments;
DROP TABLE IF EXISTS tags;
DROP TABLE IF EXISTS updates;

View File

@@ -0,0 +1,28 @@
CREATE TABLE IF NOT EXISTS updates (
image TEXT PRIMARY KEY,
diun_version TEXT NOT NULL DEFAULT '',
hostname TEXT NOT NULL DEFAULT '',
status TEXT NOT NULL DEFAULT '',
provider TEXT NOT NULL DEFAULT '',
hub_link TEXT NOT NULL DEFAULT '',
mime_type TEXT NOT NULL DEFAULT '',
digest TEXT NOT NULL DEFAULT '',
created TEXT NOT NULL DEFAULT '',
platform TEXT NOT NULL DEFAULT '',
ctn_name TEXT NOT NULL DEFAULT '',
ctn_id TEXT NOT NULL DEFAULT '',
ctn_state TEXT NOT NULL DEFAULT '',
ctn_status TEXT NOT NULL DEFAULT '',
received_at TEXT NOT NULL,
acknowledged_at TEXT
);
CREATE TABLE IF NOT EXISTS tags (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE
);
CREATE TABLE IF NOT EXISTS tag_assignments (
image TEXT PRIMARY KEY,
tag_id INTEGER NOT NULL REFERENCES tags(id) ON DELETE CASCADE
);