From 64a772546c4ccded96c856dffecded58993aa327 Mon Sep 17 00:00:00 2001 From: Pawel Kosiec Date: Fri, 26 Jan 2024 12:32:02 +0100 Subject: [PATCH] Reorganize migrate constaints check and add unit tests --- cmd/cli/cmd/migrate.go | 32 +------- go.mod | 2 +- internal/cli/migrate/compatibility.go | 40 ++++++++++ internal/cli/migrate/compatibility_test.go | 93 ++++++++++++++++++++++ 4 files changed, 138 insertions(+), 29 deletions(-) create mode 100644 internal/cli/migrate/compatibility.go create mode 100644 internal/cli/migrate/compatibility_test.go diff --git a/cmd/cli/cmd/migrate.go b/cmd/cli/cmd/migrate.go index 81322380d..7d0f9e130 100644 --- a/cmd/cli/cmd/migrate.go +++ b/cmd/cli/cmd/migrate.go @@ -6,7 +6,6 @@ import ( "github.com/AlecAivazis/survey/v2" "github.com/fatih/color" - semver "github.com/hashicorp/go-version" "github.com/pkg/browser" "github.com/spf13/cobra" "go.szostok.io/version" @@ -20,10 +19,6 @@ import ( "github.com/kubeshop/botkube/internal/kubex" ) -var ( - botkubeMinVersionConstraint = ">= 1.0" -) - // NewMigrate returns a cobra.Command for migrate the OS into Cloud. func NewMigrate() *cobra.Command { var opts migrate.Options @@ -68,18 +63,11 @@ func NewMigrate() *cobra.Command { status.Infof("Checking if Botkube version %q can be migrated safely", botkubeVersionStr) - botkubeVersionConstraints := getBotkubeVersionConstraints() - constraint, err := semver.NewConstraint(botkubeVersionConstraints) - if err != nil { - return fmt.Errorf("unable to parse Botkube semver version constraints: %w", err) - } - - botkubeVersion, err := semver.NewVersion(botkubeVersionStr) + botkubeVersionConstraints := migrate.BotkubeVersionConstraints() + isCompatible, err := migrate.IsCompatible(botkubeVersionConstraints, botkubeVersionStr) if err != nil { - return fmt.Errorf("unable to parse botkube version %s as semver: %w", botkubeVersion, err) + status.Infof("Unable to check if Botkube version %q is within range of Botkube version constraints %q: %w", botkubeVersionStr, botkubeVersionConstraints, err) } - - isCompatible := constraint.Check(botkubeVersion) if !isCompatible && !opts.AutoApprove { run := false @@ -90,7 +78,7 @@ func NewMigrate() *cobra.Command { Botkube version constraints for the currently installed CLI: %s We recommend upgrading your CLI to the latest version. In order to do so, navigate to https://docs.botkube.io/. - Do you wish to continue?`, version.Get().Version, botkubeVersion, botkubeVersionConstraints), + Do you wish to continue?`, version.Get().Version, botkubeVersionStr, botkubeVersionConstraints), Default: false, } @@ -151,15 +139,3 @@ func NewMigrate() *cobra.Command { return migrate } - -func getBotkubeVersionConstraints() string { - cliVer := version.Get().Version - cliVersion, err := semver.NewVersion(cliVer) - - botkubeMaxVersionConstraint := "" - if err == nil { - botkubeMaxVersionConstraint = fmt.Sprintf(", <= %s", cliVersion.String()) - } - - return fmt.Sprintf("%s%s", botkubeMinVersionConstraint, botkubeMaxVersionConstraint) -} diff --git a/go.mod b/go.mod index 8ffa30253..558fb6f72 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/AlecAivazis/survey/v2 v2.3.7 github.com/DanielTitkov/go-adaptive-cards v0.2.2 github.com/MakeNowJust/heredoc v1.0.0 + github.com/Masterminds/semver/v3 v3.2.1 github.com/Masterminds/sprig/v3 v3.2.3 github.com/PullRequestInc/go-gpt3 v1.2.0 github.com/alexflint/go-arg v1.4.3 @@ -104,7 +105,6 @@ require ( github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/BurntSushi/toml v1.3.2 // indirect github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver/v3 v3.2.1 // indirect github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/hcsshim v0.11.0 // indirect github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect diff --git a/internal/cli/migrate/compatibility.go b/internal/cli/migrate/compatibility.go new file mode 100644 index 000000000..dc3d47125 --- /dev/null +++ b/internal/cli/migrate/compatibility.go @@ -0,0 +1,40 @@ +package migrate + +import ( + "fmt" + + "github.com/Masterminds/semver/v3" + "go.szostok.io/version" +) + +const ( + botkubeMinVersionConstraint = ">= 1.0" +) + +// BotkubeVersionConstraints returns Botkube version constraints as a string. +func BotkubeVersionConstraints() string { + botkubeMaxVersionConstraint := "" + + cliVer := version.Get().Version + cliVersion, err := semver.NewVersion(cliVer) + if err == nil { + botkubeMaxVersionConstraint = fmt.Sprintf(", <= %s", cliVersion.String()) + } + + return fmt.Sprintf("%s%s", botkubeMinVersionConstraint, botkubeMaxVersionConstraint) +} + +// IsCompatible checks if Botkube version is compatible with the migrate command. +func IsCompatible(botkubeVersionConstraintsStr string, botkubeVersionStr string) (bool, error) { + constraint, err := semver.NewConstraint(botkubeVersionConstraintsStr) + if err != nil { + return false, fmt.Errorf("unable to parse Botkube semver version constraints: %w", err) + } + + botkubeVersion, err := semver.NewVersion(botkubeVersionStr) + if err != nil { + return false, fmt.Errorf("unable to parse botkube version %s as semver: %w", botkubeVersion, err) + } + + return constraint.Check(botkubeVersion), nil +} diff --git a/internal/cli/migrate/compatibility_test.go b/internal/cli/migrate/compatibility_test.go new file mode 100644 index 000000000..47c9cdb99 --- /dev/null +++ b/internal/cli/migrate/compatibility_test.go @@ -0,0 +1,93 @@ +package migrate + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestIsCompatible(t *testing.T) { + testCases := []struct { + Name string + BotkubeVersionConstraintsStr string + BotkubeVersionStr string + ExpectedResult bool + ExpectedErrMessage string + }{ + // TODO: The following test cases should pass, but they don't because of the bug in the `semver` library. + // See: https://github.com/Masterminds/semver/issues/177 + // The problem occurs only in the RC releases, so this isn't a huge issue for us. + // + //{ + // Name: "RC within range", + // BotkubeVersionStr: "1.8.0-rc.1", + // BotkubeVersionConstraintsStr: ">= 1.0, <= 1.8.0-rc.1", + // ExpectedResult: true, + // ExpectedErrMessage: "", + //}, + //{ + // Name: "RC within range 2", + // BotkubeVersionStr: "1.8.0-rc.1", + // BotkubeVersionConstraintsStr: ">= 1.0, <= 1.8.0", + // ExpectedResult: true, + // ExpectedErrMessage: "", + //}, + { + Name: "Final version out of range", + BotkubeVersionStr: "1.8.0", + BotkubeVersionConstraintsStr: ">= 1.0, <= 1.8.0-rc.1", + ExpectedResult: false, + ExpectedErrMessage: "", + }, + { + Name: "Final version within range", + BotkubeVersionStr: "1.8.0", + BotkubeVersionConstraintsStr: ">= 1.0, <= 1.8.0", + ExpectedResult: true, + ExpectedErrMessage: "", + }, + { + Name: "Lowest version within range", + BotkubeVersionStr: "1.0.0", + BotkubeVersionConstraintsStr: ">= 1.0, <= 1.8.0", + ExpectedResult: true, + ExpectedErrMessage: "", + }, + { + Name: "Older", + BotkubeVersionStr: "1.7.0", + BotkubeVersionConstraintsStr: ">= 1.0, <= 1.8.0", + ExpectedResult: true, + ExpectedErrMessage: "", + }, + { + Name: "Newer", + BotkubeVersionStr: "1.9.0", + BotkubeVersionConstraintsStr: ">= 1.0, <= 1.8.0", + ExpectedResult: false, + ExpectedErrMessage: "", + }, + { + Name: "Invalid constraint", + BotkubeVersionStr: "1.8.0", + BotkubeVersionConstraintsStr: ">= 1.0, <= dev", + ExpectedResult: false, + ExpectedErrMessage: "unable to parse Botkube semver version constraints: improper constraint: >= 1.0, <= dev", + }, + } + + for _, tc := range testCases { + t.Run(tc.Name, func(t *testing.T) { + result, err := IsCompatible(tc.BotkubeVersionConstraintsStr, tc.BotkubeVersionStr) + if tc.ExpectedErrMessage != "" { + require.Error(t, err) + assert.EqualError(t, err, tc.ExpectedErrMessage) + return + } + + require.NoError(t, err) + assert.Equal(t, tc.ExpectedResult, result) + }) + } +}