Skip to content

Commit 9466aa0

Browse files
authored
Accept river migrate-down --target-version 0 to remove all River tables (#966)
There was a bit of an unfortunate UX quirk in the CLI wherein to remove all River tables you needed to specify a special value of `--target-version -1`. This is a relic of how the CLI uses `rivermigrate` internally, and `rivermigrate`'s options have a `TargetVersion int` that makes 0 a reserved value for when the option is unset. It seems like we can do a little better here for the CLI, so here we add some code that lets 0 or -1 be used as a `--target-version` to apply all down migrations. We do this by changing the CLI default value to the sentinel value -2, which we change back to a real default before forwarding onto `rivermigrate`.
1 parent cce56b9 commit 9466aa0

File tree

3 files changed

+43
-3
lines changed

3 files changed

+43
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717

1818
- Remove unecessary transactions where a single database operation will do. This reduces the number of subtransactions created which can be an operational benefit it many cases. [PR #950](https://github.com/riverqueue/river/pull/950)
1919
- Bring all driver tests into separate package so they don't leak dependencies. This removes dependencies from the top level `river` package that most River installations won't need, thereby reducing the transitive dependency load of most River installations. [PR #955](https://github.com/riverqueue/river/pull/955).
20+
- The River CLI now accepts a `--target-version` of 0 with `river migrate-down` to run all down migrations and remove all River tables (previously, -1 was used for this; -1 still works, but now 0 also works). [PR #966](https://github.com/riverqueue/river/pull/966).
2021

2122
### Fixed
2223

cmd/river/rivercli/river_cli.go

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ to use a development database only.
173173
cmd.Flags().StringVar(&opts.Line, "line", "", "migration line to operate on (default: main)")
174174
cmd.Flags().IntVar(&opts.MaxSteps, "max-steps", 0, "maximum number of steps to migrate")
175175
cmd.Flags().BoolVar(&opts.ShowSQL, "show-sql", false, "show SQL of each migration")
176-
cmd.Flags().IntVar(&opts.TargetVersion, "target-version", 0, "target version to migrate to (final state includes this version, but none after it)")
176+
cmd.Flags().IntVar(&opts.TargetVersion, "target-version", targetVersionCLIFlagDefault, "target version to migrate to (final state includes this version, but none after it); when migrating down, use 0 to apply all down migrations")
177177
}
178178

179179
// migrate-down
@@ -434,7 +434,7 @@ func (c *migrateDown) Run(ctx context.Context, opts *migrateOpts) (bool, error)
434434
res, err := migrator.Migrate(ctx, rivermigrate.DirectionDown, &rivermigrate.MigrateOpts{
435435
DryRun: opts.DryRun,
436436
MaxSteps: opts.MaxSteps,
437-
TargetVersion: opts.TargetVersion,
437+
TargetVersion: targetVersionTranslateDefault(opts.TargetVersion),
438438
})
439439
if err != nil {
440440
return false, err
@@ -645,7 +645,7 @@ func (c *migrateUp) Run(ctx context.Context, opts *migrateOpts) (bool, error) {
645645
res, err := migrator.Migrate(ctx, rivermigrate.DirectionUp, &rivermigrate.MigrateOpts{
646646
DryRun: opts.DryRun,
647647
MaxSteps: opts.MaxSteps,
648-
TargetVersion: opts.TargetVersion,
648+
TargetVersion: targetVersionTranslateDefault(opts.TargetVersion),
649649
})
650650
if err != nil {
651651
return false, err
@@ -721,3 +721,30 @@ func (c *version) Run(ctx context.Context, opts *versionOpts) (bool, error) {
721721

722722
return true, nil
723723
}
724+
725+
// A sentinel value used to represent an unset CLI flag for TargetVersion. See
726+
// comment below for details.
727+
const targetVersionCLIFlagDefault = -2
728+
729+
// Translates a target version from incoming CLI flag to one that goes in the
730+
// rivermigrate package's options. The reason this exists is that get around the
731+
// bad UX required with default values, rivermigrate uses a TargetVersion of 0
732+
// to do nothing, and a TargetVersion of -1 to specify all versions. This is
733+
// suboptimal from a CLI perspective, because when migrating down, it requires
734+
// the caller to know to specify -1 instead of the more natural 0 to down
735+
// migrate everything.
736+
//
737+
// This function translates an incoming CLI option so that a 0 is changed to a
738+
// -1 so that it migrates everything. -1 stays as is. -2 is used as a default
739+
// value (targetVersionCLIFlagDefault) for the CLI flags and is changed to 0 so
740+
// it becomes the default value on the migrate options.
741+
func targetVersionTranslateDefault(targetVersion int) int {
742+
switch targetVersion {
743+
case 0:
744+
return -1
745+
case targetVersionCLIFlagDefault:
746+
return 0
747+
}
748+
749+
return targetVersion
750+
}

cmd/river/rivercli/river_cli_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,3 +556,15 @@ func TestRoundDuration(t *testing.T) {
556556
require.Equal(t, "34.04s", roundDuration(mustParseDuration("34.042234s")).String())
557557
require.Equal(t, "2m34.04s", roundDuration(mustParseDuration("2m34.042234s")).String())
558558
}
559+
560+
func TestTargetVersion(t *testing.T) {
561+
t.Parallel()
562+
563+
require.Equal(t, 1, targetVersionTranslateDefault(1))
564+
require.Equal(t, 2, targetVersionTranslateDefault(2))
565+
require.Equal(t, 3, targetVersionTranslateDefault(3))
566+
567+
require.Equal(t, 0, targetVersionTranslateDefault(-2))
568+
require.Equal(t, -1, targetVersionTranslateDefault(-1))
569+
require.Equal(t, -1, targetVersionTranslateDefault(0))
570+
}

0 commit comments

Comments
 (0)