Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version v1.0.2-alpha.0 should be greater than v1.0.1 but version.NewConstraint(...).Check returns false #130

Open
sebastian-sommerfeld-io opened this issue Aug 3, 2023 · 1 comment

Comments

@sebastian-sommerfeld-io
Copy link

sebastian-sommerfeld-io commented Aug 3, 2023

Hey guys ... I stumbled upon this issue while implementing a tool to validate versions when I release one of my github projects. I want to make sure, that the version for my next release is greater than the latest version.

When checking for pre-release versions (alpha / beta) I stumbled upon a bug (from my point of view):

  • Given my latest version is v1.0.1 which is a stable release
  • When I check if v1.0.2 is greater than v1.0.1 then everything works fine
  • When I check if v1.0.2-alpha.0 is greater than v1.0.1 then the result is false ... my expectation is that this check would pass, because I increased the minor version and marked it as unstable.
  • When I check if v1.0.2-alpha.1 is greater than v1.0.2-alpha.0 then everything works fine again.

I wrote a short testcase in Go to validate

issue.go:

package services

import (
	"fmt"

	"github.com/hashicorp/go-version"
)

// The next version should be greater that the current version
func IsGreater(current string, next string) bool {
	parsedCurrent, err := version.NewVersion(current)
	if err != nil {
		fmt.Print(err)
		return false
	}

	parsedNext, err := version.NewVersion(next)
	if err != nil {
		fmt.Print(err)
		return false
	}

	// should be greater that current version
	constraint, err := version.NewConstraint("> " + parsedCurrent.Original())
	if err != nil {
		fmt.Print(err)
		return false
	}

	if !constraint.Check(parsedNext) {
		fmt.Print("next version " + parsedNext.Original() + " is not greater that current version " + parsedCurrent.Original())
	}
	return constraint.Check(parsedNext)
}

issue_test.go:

package services

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

func Test_ShouldBeGreater(t *testing.T) {
	testCases := []struct {
		currentVersion string
		nextVersion    string
		shouldBeValid  bool
	}{
		{"v1.0.1", "v1.0.2", true},
		{"v1.0.1", "v1.1.0", true},
		{"v1.0.1", "v2.0.0", true},
		{"v1.0.1", "v1.0.2-alpha.0", true}, // fails but should be true
		{"v1.0.1", "v1.0.2-beta.0", true},  // fails but should be true
		{"v1.0.2-alpha.0", "v1.0.2-alpha.1", true},
		{"v1.0.2-alpha.0", "v1.0.2-beta.0", true},
		{"v1.0.2-beta.1", "v1.0.2-beta.2", true},
		{"v1.0.2-alpha.0", "v1.0.2", true},
		{"v1.0.2-beta.0", "v1.0.2", true},
		{"v1.0.2", "v1.0.2", false},
		{"v1.0.2", "v1.0.1", false},
		{"v1.0.2-beta.0", "v1.0.2-alpha.0", false},
		{"v1.0.2-beta.2", "v1.0.2-beta.1", false},
		{"v2.0.0", "v2.0.0", false},
	}
	for _, tc := range testCases {
		assert := assert.New(t)
		got := IsGreater(tc.currentVersion, tc.nextVersion)

		assert.NotNil(got)
		assert.Equal(tc.shouldBeValid, got, "Result did not meet expectation - next version = "+tc.nextVersion+", current version = "+tc.currentVersion)
	}
}

Could you take a look into this please? Feel free to reach out to me for information if you feel the need. Best regards.

@sebastian-sommerfeld-io sebastian-sommerfeld-io changed the title Version v1.0.2-alpha.0 should be greater than v1.0.1 but constraint.Check returns false Version v1.0.2-alpha.0 should be greater than v1.0.1 but version.NewConstraint(...).Check returns false Aug 3, 2023
@kke
Copy link

kke commented Sep 11, 2023

I don't know if it is mentioned in the docs, but the implementation and code comments are here: https://github.com/hashicorp/go-version/blob/main/constraint.go#L197-L215

	case cPre && vPre:
		// A constraint with a pre-release can only match a pre-release version
		// with the same base segments.
		return reflect.DeepEqual(c.Segments64(), v.Segments64())

	case !cPre && vPre:
		// A constraint without a pre-release can only match a version without a
		// pre-release.
		return false

So, it's intentional.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants