Open bevzzz opened 6 days ago
Using plugin looks interesting, but risky and it does not work on Windows :( But I actually had similar idea.
An alternative can be to provide buncli
as a package that contains the cli.App
, e,g.
package buncli
func New(options ...Option) *cli.App {}
And then we can provide some command that creates an initial app structure/dirs or just some repo with a bunch of folders/files that uses the buncli
package, e.g.
package main
import "github.com/uptace/bun/buncli"
func main() {
app := buncli.New(buncli.WithAutoMigrator(...))
app.Run()
}
Then user can directly modify main.go
to register models etc.
WDYT?
Using plugin looks interesting, but risky
Sharing this really useful summary of caveats to look out for from someone who tried using the plugins productively.
I agree that making this the default solution would prove too quite tricky.
[...] does not work on Windows. An alternative can be to provide
buncli
as a package that contains the cli.App ... some command that creates an initial app structure/dirs
Yep, that's the way to go, I'll focus on this approach.
Summary
Motivation
To provide a default CLI utility for Bun users to interact with (Auto-)Migrator. Our Migrations guide currently has users build their own binary, but it would be great to eliminate this step for those that do not have any special logic on top of "my models have changed, please generate migrations for it".
Related proposal: https://github.com/uptrace/bun/issues/875
Implementation
As per the current docs, the migration binary has to be co-located with the user's
migrations/
package and compiled together to access the registered / discovered migrations:To distribute
bundb
as a standalone binary, we need to be able to load objects from the users' packages dynamically. This is achieved by leveragingplugin
package from the Go's standard library. The implementation details are handled bybundb
(it will build the user's package in-buildmode=plugin
to then be able to import symbols from it at runtime), so that the users won't have to deal with any of it.The setup required to use AutoMigrator is only a little different from the current on:
Bonus: this method works for accessing
Migrations
and using them with the usual Migrator pretty much out of the box.Besides that, this is a just a plain old CLI built with
urfave/cli/v2
.How to test locally
After checking out this branch locally:
main.go
file:Example main.go
```go package library import ( "github.com/uptrace/bun" ) type Book struct { ISBN string `bun:",pk"` } type Author struct { bun.BaseModel `bun:"table:writers"` ID int64 `bun:",pk,identity"` FirstName string `bun:",notnull"` LastName string `bun:",notnull"` } ```Declare Bun models which AutoMigrator should target:
bundb
out:Discussion
Currently
Models []interface{}
is the only AutoMigrator configuration that's expressed "in Go" and other options can be passed via command-line flags. Do we want to also allow the users to configure their own AutoMigrator completely (including the database connections, etc) themselves and just export it in theirmigrations
package? I.e. usemigrations.AutoMigrator
if one is exported., ignoring all related CLI options?How much logging do we want? I'm thinking:
"created 2 migration files: 20240301_public.up.sql and 20240301_public.down.sql"
or `"nothing to migrate, ok"-v | --verbose
to enable query logging (setBUNDEBUG=2
) or something like that--silent
to disable logging altogetherDo we want to have a mechanism for persisting config locally? For example, the user runs
bundb init --create-directory=db-migrations
. If we storedirectory=db-migrations
in a local config file, they can run subsequent commands without passing any flags:bundb auto migrate
.If a config file sounds like an overkill, we could store these to the env variables (those won't be persisted between shell sessions)
On the naming
We didn't want to potentially clash with bun.js CLI, we decided to add some sort of a qualified, e.g. "bungo". Then I saw that migrate example calls its application
bun db
, so I borrowed it directly from there, omitting the space.