Experiemntal CLI - initial commit
This PR stubs out a newcli package for goose. There are no changes with the existing goose CLI code and everything is gated behind a feature flag GOOSE_CLI=1.
Some highlights
Help for every command (--help and -h)
$ GOOSE_CLI=1 goose --help
Will output nicely formatted help (currently only supports the goose status command, but others will quickly follow)
JSON support (--json)
It supports --json out-of-the-box, e.g.,
$ GOOSE_CLI=1 ./bin/goose status --dir ./testdata/migrations --dbstring=sqlite:./test.db --json | jq
Returns output that can be used programmatically, recently brought up by @witsch in https://github.com/pressly/goose/pull/420#issuecomment-2016640171, but requested for a long time https://github.com/pressly/goose/issues/225, https://github.com/pressly/goose/issues/350, etc.
{
"migrations": [
{
"state": "pending",
"source": {
"type": "sql",
"path": "00001_users_table.sql",
"version": 1
}
}
],
"has_pending": true
}
Driver and dialect automatically inferred from dbstring
We can infer the dialect based on the supplied DSN (called --dbstring).
Previously goose had the caller supply a driver name AND a dbstring, but the former is not necessary and we already know ahead of time which databases we support so we can used a handy package to map that connection string to a dialect, https://github.com/xo/dburl#database-schemes-aliases-and-drivers.
- [ ] Can we make this backwards compatible with
goose [OPTIONS] DRIVER DBSTRING COMMANDwhere the DRIVER AND DBSTRING are automatically converted to--dbstring?
Use a lightweight framework for composing CLI
...
Expose the CLI code to users
These 2 functions will be available to users so they can integrate goose into their own applications and get the same CLI experience. Should resolve a few requests like this one https://github.com/pressly/goose/pull/646
// Main is the entry point for the CLI.
//
// If an error is returned, it is printed to stderr and the process exits with a non-zero exit code.
// The process is also canceled when an interrupt signal is received. This function and does not
// return.
func Main(opts ...Options) {
}
// Run runs the CLI with the provided arguments. The arguments should not include the command name
// itself, only the arguments to the command, use os.Args[1:].
//
// Options can be used to customize the behavior of the CLI, such as setting the environment,
// redirecting stdout and stderr, and providing a custom filesystem such as embed.FS.
func Run(ctx context.Context, args []string, opts ...Options) error {
}