diff --git a/README.md b/README.md index b6e2b58..1543e2a 100644 --- a/README.md +++ b/README.md @@ -114,8 +114,10 @@ fiber migrate --to 3.0.0 ### Options ```text - -t, --to string Migrate to a specific version e.g:3.0.0 Format: X.Y.Z - -h, --help help for migrate + -t, --to string Migrate to a specific version e.g:3.0.0 Format: X.Y.Z + -f, --force Force migration even if already on the version + -s, --skip_go_mod Skip running go mod tidy, download and vendor + -h, --help help for migrate ``` ## fiber upgrade diff --git a/cmd/migrate.go b/cmd/migrate.go index 2f62763..09b576c 100644 --- a/cmd/migrate.go +++ b/cmd/migrate.go @@ -12,8 +12,10 @@ import ( "github.com/gofiber/cli/cmd/internal/migrations" ) -func newMigrateCmd(currentVersionFile string) *cobra.Command { +func newMigrateCmd() *cobra.Command { var targetVersionS string + var force bool + var skipGoMod bool cmd := &cobra.Command{ Use: "migrate", @@ -29,32 +31,46 @@ func newMigrateCmd(currentVersionFile string) *cobra.Command { if err := cmd.MarkFlagRequired("to"); err != nil { panic(err) } + cmd.Flags().BoolVarP(&force, "force", "f", false, "Force migration even if already on version") + cmd.Flags().BoolVarP(&skipGoMod, "skip_go_mod", "s", false, "Skip running go mod tidy, download and vendor") cmd.RunE = func(cmd *cobra.Command, _ []string) error { - return migrateRunE(cmd, currentVersionFile, targetVersionS) + return migrateRunE(cmd, MigrateOptions{ + CurrentVersionFile: currentVersionFile, + TargetVersionS: targetVersionS, + Force: force, + SkipGoMod: skipGoMod, + }) } return cmd } -var migrateCmd = newMigrateCmd("go.mod") +var migrateCmd = newMigrateCmd() -func migrateRunE(cmd *cobra.Command, currentVersionFile, targetVersionS string) error { - currentVersionS, err := currentVersionFromFile(currentVersionFile) +type MigrateOptions struct { + CurrentVersionFile string + TargetVersionS string + Force bool + SkipGoMod bool +} + +func migrateRunE(cmd *cobra.Command, opts MigrateOptions) error { + currentVersionS, err := currentVersionFromFile(opts.CurrentVersionFile) if err != nil { return fmt.Errorf("current fiber project version not found: %w", err) } currentVersionS = strings.TrimPrefix(currentVersionS, "v") currentVersion := semver.MustParse(currentVersionS) - targetVersionS = strings.TrimPrefix(targetVersionS, "v") - targetVersion, err := semver.NewVersion(targetVersionS) + opts.TargetVersionS = strings.TrimPrefix(opts.TargetVersionS, "v") + targetVersion, err := semver.NewVersion(opts.TargetVersionS) if err != nil { - return fmt.Errorf("invalid version for \"%s\": %w", targetVersionS, err) + return fmt.Errorf("invalid version for \"%s\": %w", opts.TargetVersionS, err) } - if !targetVersion.GreaterThan(currentVersion) { - return fmt.Errorf("target version v%s is not greater than current version v%s", targetVersionS, currentVersionS) + if !targetVersion.GreaterThan(currentVersion) && !(opts.Force && targetVersion.Equal(currentVersion)) { + return fmt.Errorf("target version v%s is not greater than current version v%s", opts.TargetVersionS, currentVersionS) } wd, err := os.Getwd() @@ -67,11 +83,13 @@ func migrateRunE(cmd *cobra.Command, currentVersionFile, targetVersionS string) return fmt.Errorf("migration failed %w", err) } - if err := runGoMod(wd); err != nil { - return fmt.Errorf("go mod: %w", err) + if !opts.SkipGoMod { + if err := runGoMod(wd); err != nil { + return fmt.Errorf("go mod: %w", err) + } } - msg := fmt.Sprintf("Migration from Fiber %s to %s", currentVersionS, targetVersionS) + msg := fmt.Sprintf("Migration from Fiber %s to %s", currentVersionS, opts.TargetVersionS) cmd.Println(termenv.String(msg). Foreground(termenv.ANSIBrightBlue)) diff --git a/cmd/migrate_test.go b/cmd/migrate_test.go index 4f97694..dccace6 100644 --- a/cmd/migrate_test.go +++ b/cmd/migrate_test.go @@ -69,7 +69,7 @@ func main() { require.NoError(t, os.Chdir(dir)) defer func() { require.NoError(t, os.Chdir(cwd)) }() - cmd := newMigrateCmd("go.mod") + cmd := newMigrateCmd() setupCmd() defer teardownCmd() out, err := runCobraCmd(cmd, "-t=3.0.0") @@ -138,3 +138,65 @@ require github.com/gofiber/fiber/v2 v2.0.0` needError = true assert.Error(t, runGoMod(dir)) } + +func Test_Migrate_ForceAndSkip(t *testing.T) { + dir := t.TempDir() + gomod := `module example + +go 1.20 + +require github.com/gofiber/fiber/v3 v3.0.0 +` + require.NoError(t, os.WriteFile(filepath.Join(dir, "go.mod"), []byte(gomod), 0o600)) + require.NoError(t, os.WriteFile(filepath.Join(dir, "main.go"), []byte("package main"), 0o600)) + + cwd, err := os.Getwd() + require.NoError(t, err) + require.NoError(t, os.Chdir(dir)) + defer func() { require.NoError(t, os.Chdir(cwd)) }() + + t.Run("without force", func(t *testing.T) { + cmd := newMigrateCmd() + out, err := runCobraCmd(cmd, "-t=3.0.0") + require.Error(t, err) + assert.Contains(t, out, "not greater") + }) + + t.Run("force", func(t *testing.T) { + origExec := execCommand + var cmds []*exec.Cmd + execCommand = func(name string, args ...string) *exec.Cmd { + cs := append([]string{"-test.run=TestHelperProcess", "--", name}, args...) + cmd := exec.Command(os.Args[0], cs...) // #nosec G204 -- safe for test + cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"} + cmds = append(cmds, cmd) + return cmd + } + defer func() { execCommand = origExec }() + + cmd := newMigrateCmd() + out, err := runCobraCmd(cmd, "-t=3.0.0", "-f") + require.NoError(t, err) + assert.Contains(t, out, "Migration from Fiber 3.0.0 to 3.0.0") + assert.Len(t, cmds, 3) + }) + + t.Run("force skip go mod", func(t *testing.T) { + origExec := execCommand + var cmds []*exec.Cmd + execCommand = func(name string, args ...string) *exec.Cmd { + cs := append([]string{"-test.run=TestHelperProcess", "--", name}, args...) + cmd := exec.Command(os.Args[0], cs...) // #nosec G204 -- safe for test + cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"} + cmds = append(cmds, cmd) + return cmd + } + defer func() { execCommand = origExec }() + + cmd := newMigrateCmd() + out, err := runCobraCmd(cmd, "-t=3.0.0", "-f", "-s") + require.NoError(t, err) + assert.Contains(t, out, "Migration from Fiber 3.0.0 to 3.0.0") + assert.Empty(t, cmds) + }) +}