fix: run journal:image-variants from the application CLI

- the generated CLI publishes no database or uploads bucket for plugin
  commands, so the command stopped with database is not configured
- without a published database it opens database.dsn and publishes it, and
  without a published bucket it opens storage.uploads.bucket_url, closing
  what it opened
This commit is contained in:
Jakub Zych
2026-11-04 19:27:00 +01:00
parent 4f5bd190e5
commit fc3c25530c
4 changed files with 168 additions and 10 deletions

55
console/database.go Normal file
View File

@@ -0,0 +1,55 @@
package console
import (
"context"
"errors"
"git.golem15.com/golem15/summercms/modules/backpack"
"git.golem15.com/golem15/summercms/modules/lagoon"
"git.golem15.com/golem15/summercms/modules/lagoon/attach"
"gocloud.dev/blob"
"gorm.io/gorm"
)
// lookupDB returns the app's database. The generated CLI publishes none for
// plugin commands (only serve and the framework's own commands open one),
// so without a published database it opens database.dsn and publishes it,
// as lagoon's migrate does. done closes a pool this call opened and is a
// no-op otherwise.
func lookupDB(ctx context.Context, app *backpack.App) (*gorm.DB, func(), error) {
if app == nil {
return nil, nil, errors.New("journal: app is nil")
}
if db := mustDB(app); db != nil {
return db, func() {}, nil
}
if lagoon.DSN(app.Config) == "" {
return nil, nil, errors.New("journal: database is not configured (set SUMMER_DATABASE__DSN)")
}
sqlDB, gdb, err := lagoon.OpenFromApp(ctx, app)
if err != nil {
return nil, nil, err
}
if err := lagoon.Publish(app, sqlDB, gdb); err != nil {
_ = sqlDB.Close()
return nil, nil, err
}
return gdb, func() { _ = sqlDB.Close() }, nil
}
// lookupBucket returns the published uploads bucket, or opens
// storage.uploads.bucket_url when the process has none (the generated
// CLI). done closes a bucket this call opened and is a no-op otherwise.
func lookupBucket(ctx context.Context, app *backpack.App) (*blob.Bucket, func(), error) {
if app == nil {
return nil, nil, errors.New("journal: app is nil")
}
if bucket, ok := app.Lookup[*blob.Bucket](); ok && bucket != nil {
return bucket, func() {}, nil
}
bucket, err := attach.OpenBucket(ctx, app.Config)
if err != nil {
return nil, nil, err
}
return bucket, func() { _ = bucket.Close() }, nil
}

View File

@@ -2,13 +2,11 @@ package console
import (
"context"
"errors"
"fmt"
"git.golem15.com/golem15/sm-journal-plugin/classes"
"git.golem15.com/golem15/summercms/modules/backpack"
"git.golem15.com/golem15/summercms/modules/bonfire"
"gocloud.dev/blob"
)
// ImageVariants is journal:image-variants: it writes the thumbnails and
@@ -31,7 +29,11 @@ queued after the upload commits. This command is the backfill: without
--all it takes the images that lack a variant of some width (for example
after adding a width), with --all it checks every featured image. A
variant that exists is never written again, so the command can run any
number of times.`,
number of times.
It runs from the application's CLI as well as next to serve: without a
running server it opens database.dsn and storage.uploads.bucket_url
itself.`,
Flags: []bonfire.Flag{
{Name: "all", Description: "Check every featured image (default: only those missing a width)", Bare: true},
},
@@ -40,14 +42,16 @@ number of times.`,
{Command: "journal:image-variants --all", Description: "Check every featured image"},
},
Run: func(ctx context.Context, in bonfire.Input, out bonfire.Output) error {
db := mustDB(app)
if db == nil {
return errors.New("journal: database is not configured")
db, done, err := lookupDB(ctx, app)
if err != nil {
return err
}
bucket, ok := app.Lookup[*blob.Bucket]()
if !ok || bucket == nil {
return errors.New("journal: the uploads bucket is not configured")
defer done()
bucket, closeBucket, err := lookupBucket(ctx, app)
if err != nil {
return err
}
defer closeBucket()
ids, err := classes.FeaturedImageIDs(db.WithContext(ctx), appConfig(app), flagOn(in, "all"))
if err != nil {
return err