feat: Set table name based on flag or environment variable (#932)

main
Diego 2025-04-03 12:46:02 +00:00 committed by GitHub
parent b63ff992a7
commit 46ae662098
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 87 additions and 2 deletions

View File

@ -247,6 +247,7 @@ arguments, you can set the following environment variables:
export GOOSE_DRIVER=DRIVER
export GOOSE_DBSTRING=DBSTRING
export GOOSE_MIGRATION_DIR=MIGRATION_DIR
export GOOSE_TABLE=TABLENAME
```
**2. Via `.env` files with corresponding variables. `.env` file example**:
@ -255,6 +256,7 @@ export GOOSE_MIGRATION_DIR=MIGRATION_DIR
GOOSE_DRIVER=postgres
GOOSE_DBSTRING=postgres://admin:admin@localhost:5432/admin_db
GOOSE_MIGRATION_DIR=./migrations
GOOSE_TABLE=custom.goose_migrations
```
Loading from `.env` files is enabled by default. To disable this feature, set the `-env=none` flag.

View File

@ -28,7 +28,7 @@ var (
flags = flag.NewFlagSet("goose", flag.ExitOnError)
dir = flags.String("dir", DefaultMigrationDir, "directory with migration files, (GOOSE_MIGRATION_DIR env variable supported)")
table = flags.String("table", "goose_db_version", "migrations table name")
table = flags.String("table", "", "migrations table name")
verbose = flags.Bool("v", false, "enable verbose mode")
help = flags.Bool("h", false, "print help")
versionFlag = flags.Bool("version", false, "print version")
@ -83,7 +83,9 @@ func main() {
if *sequential {
goose.SetSequential(true)
}
goose.SetTableName(*table)
// The order of precedence should be: flag > env variable > default value.
goose.SetTableName(firstNonEmpty(*table, envConfig.table, goose.DefaultTablename))
args := flags.Args()
@ -421,6 +423,7 @@ type envConfig struct {
driver string
dbstring string
dir string
table string
noColor bool
}
@ -429,6 +432,7 @@ func loadEnvConfig() *envConfig {
return &envConfig{
driver: envOr("GOOSE_DRIVER", ""),
dbstring: envOr("GOOSE_DBSTRING", ""),
table: envOr("GOOSE_TABLE", ""),
dir: envOr("GOOSE_MIGRATION_DIR", DefaultMigrationDir),
// https://no-color.org/
noColor: noColorBool,
@ -440,6 +444,7 @@ func (c *envConfig) listEnvs() []envVar {
{Name: "GOOSE_DRIVER", Value: c.driver},
{Name: "GOOSE_DBSTRING", Value: c.dbstring},
{Name: "GOOSE_MIGRATION_DIR", Value: c.dir},
{Name: "GOOSE_TABLE", Value: c.table},
{Name: "NO_COLOR", Value: strconv.FormatBool(c.noColor)},
}
}
@ -457,3 +462,13 @@ func envOr(key, def string) string {
}
return val
}
// firstNonEmpty returns the first non-empty string from the provided input or an empty string if all are empty.
func firstNonEmpty(values ...string) string {
for _, v := range values {
if v != "" {
return v
}
}
return ""
}

68
cmd/goose/main_test.go Normal file
View File

@ -0,0 +1,68 @@
package main
import (
"testing"
)
func TestFirstNonEmpty(t *testing.T) {
tests := []struct {
name string
input []string
expected string
}{
{
name: "no values",
input: []string{},
expected: "",
},
{
name: "all empty values",
input: []string{"", "", ""},
expected: "",
},
{
name: "single non-empty value at start",
input: []string{"value", "", ""},
expected: "value",
},
{
name: "single non-empty value in middle",
input: []string{"", "value", ""},
expected: "value",
},
{
name: "single non-empty value at end",
input: []string{"", "", "value"},
expected: "value",
},
{
name: "multiple non-empty values",
input: []string{"first", "second", "third"},
expected: "first",
},
{
name: "mixed empty and non-empty values",
input: []string{"", "value1", "", "value2"},
expected: "value1",
},
{
name: "only one value, empty",
input: []string{""},
expected: "",
},
{
name: "only one value, non-empty",
input: []string{"value"},
expected: "value",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := firstNonEmpty(tt.input...)
if result != tt.expected {
t.Errorf("expected %q, got %q", tt.expected, result)
}
})
}
}