feat(03-01): add shared postgres pool and plugin migrations
Open one pgx stdlib *sql.DB, hand it to GORM, and run per-plugin gormigrate sets with isolated history tables after an ICU pl-PL check. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
96
cmd/summer/runtime.go
Normal file
96
cmd/summer/runtime.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"git.golem15.com/golem15/summercms/bonfire"
|
||||
"git.golem15.com/golem15/summercms/internal/build"
|
||||
)
|
||||
|
||||
func delegateCommand(name, description string) bonfire.Command {
|
||||
return bonfire.Command{
|
||||
Name: name,
|
||||
Description: description,
|
||||
Run: func(ctx context.Context, in bonfire.Input, out bonfire.Output) error {
|
||||
argv := []string{name}
|
||||
argv = append(argv, in.Args()...)
|
||||
return runAppBinary(ctx, argv, out)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func delegateRollbackCommand() bonfire.Command {
|
||||
return bonfire.Command{
|
||||
Name: "migrate:rollback",
|
||||
Description: "Roll back the last migration of a plugin in the app binary",
|
||||
Flags: []bonfire.Flag{{
|
||||
Name: "plugin",
|
||||
Description: "Plugin ID whose last migration to roll back",
|
||||
}},
|
||||
Run: func(ctx context.Context, in bonfire.Input, out bonfire.Output) error {
|
||||
argv := []string{"migrate:rollback"}
|
||||
if plugin, ok := in.Flag("plugin"); ok && plugin != "" {
|
||||
argv = append(argv, "--plugin", plugin)
|
||||
}
|
||||
argv = append(argv, in.Args()...)
|
||||
return runAppBinary(ctx, argv, out)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func runAppBinary(ctx context.Context, argv []string, out bonfire.Output) error {
|
||||
if len(argv) == 0 {
|
||||
return fmt.Errorf("summer: missing app command")
|
||||
}
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
appDir, err := build.FindAppDir(dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m, err := build.LoadManifest(filepath.Join(appDir, "summer.yaml"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bin := filepath.Join(appDir, "bin", m.Binary)
|
||||
if _, err := os.Stat(bin); err != nil {
|
||||
if err := build.App(ctx, appDir, out); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
self, err := os.Executable()
|
||||
if err == nil {
|
||||
if same, _ := sameFile(self, bin); same {
|
||||
return fmt.Errorf("summer: refusing to recurse into %s", bin)
|
||||
}
|
||||
}
|
||||
cmd := exec.CommandContext(ctx, bin, argv...)
|
||||
cmd.Dir = appDir
|
||||
cmd.Stdout = out
|
||||
cmd.Stderr = out
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Env = os.Environ()
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("summer: %s: %w", strings.Join(argv, " "), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func sameFile(a, b string) (bool, error) {
|
||||
ai, err := os.Stat(a)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
bi, err := os.Stat(b)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return os.SameFile(ai, bi), nil
|
||||
}
|
||||
Reference in New Issue
Block a user