Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions pkg/version/channels_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
)

func TestGetLatestVersions(t *testing.T) {
four := int64(4)
testCases := []struct {
name string
resp interface{}
Expand All @@ -20,16 +21,18 @@ func TestGetLatestVersions(t *testing.T) {
{
"valid response",
map[string]string{
"foo": "foo-1.2.3",
"stable": "stable-2.1.0",
"edge": "edge-2.1.0",
"foo": "foo-1.2.3",
"fooHotpatch": "foo-1.2.3-4",
"stable": "stable-2.1.0",
"edge": "edge-2.1.0",
},
nil,
Channels{
[]channelVersion{
{"foo", "1.2.3", "foo-1.2.3"},
{"stable", "2.1.0", "stable-2.1.0"},
{"edge", "2.1.0", "edge-2.1.0"},
{"foo", "1.2.3", nil, "foo-1.2.3"},
{"foo", "1.2.3", &four, "foo-1.2.3-4"},
{"stable", "2.1.0", nil, "stable-2.1.0"},
{"edge", "2.1.0", nil, "edge-2.1.0"},
},
},
},
Expand Down Expand Up @@ -99,7 +102,7 @@ func channelsEqual(c1, c2 Channels) bool {
for _, cv1 := range c1.array {
found := false
for _, cv2 := range c2.array {
if cv1.channel == cv2.channel && cv1.version == cv2.version {
if cv1.channel == cv2.channel && cv1.version == cv2.version && cv1.hotpatchEqual(cv2) {
found = true
break
}
Expand All @@ -113,12 +116,13 @@ func channelsEqual(c1, c2 Channels) bool {
}

func TestChannelsMatch(t *testing.T) {
four := int64(4)
channels := Channels{
[]channelVersion{
{"stable", "2.1.0", "stable-2.1.0"},
{"foo", "1.2.3", "foo-1.2.3"},
{"foo", "1.2.3", "foo-1.2.3-4"},
{"version", "3.2.1", "version-3.2.1"},
{"stable", "2.1.0", nil, "stable-2.1.0"},
{"foo", "1.2.3", nil, "foo-1.2.3"},
{"foo", "1.2.3", &four, "foo-1.2.3-4"},
{"version", "3.2.1", nil, "version-3.2.1"},
},
}

Expand All @@ -137,7 +141,8 @@ func TestChannelsMatch(t *testing.T) {
fmt.Errorf("is running version 1.2.2 but the latest foo version is 1.2.3"),
},
{
"foo-1.2.3-3", nil,
"foo-1.2.3-3",
fmt.Errorf("is running version 1.2.3-3 but the latest foo version is 1.2.3-4"),
},
{
"unsupportedChannel-1.2.3",
Expand Down
48 changes: 44 additions & 4 deletions pkg/version/channelversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package version

import (
"fmt"
"strconv"
"strings"
)

Expand All @@ -10,22 +11,53 @@ import (
type channelVersion struct {
channel string
version string
hotpatch *int64
original string
}

// hotpatchSuffix is the suffix applied to channel names to indicate that the
// version string includes a hotpatch number (e.g. dev-0.1.2-3)
const hotpatchSuffix = "Hotpatch"

func (cv channelVersion) String() string {
return cv.original
}

// updateChannel returns the channel name to check for updates, returning the
// channel name.
// updateChannel returns the channel name to check for updates. if there's no
// hotpatch number set, then it returns the channel name itself. otherwise it
// returns the channel name suffixed with "Hotpatch" to indicate that a separate
// update channel should be used.
func (cv channelVersion) updateChannel() string {
if cv.hotpatch != nil {
return cv.channel + hotpatchSuffix
}
return cv.channel
}

// versionWithHotpatch returns the version string, suffixed with the hotpatch
// number if it exists.
func (cv channelVersion) versionWithHotpatch() string {
if cv.hotpatch == nil {
return cv.version
}
return fmt.Sprintf("%s-%d", cv.version, *cv.hotpatch)
}

func (cv channelVersion) hotpatchEqual(other channelVersion) bool {
if cv.hotpatch == nil && other.hotpatch == nil {
return true
}
if cv.hotpatch == nil || other.hotpatch == nil {
return false
}
return *cv.hotpatch == *other.hotpatch
}

// parseChannelVersion parses a build string into a channelVersion struct. it
// expects the channel and version to be separated by a hyphen (e.g. dev-0.1.2).
// if the version is suffixed with any other non-numeric build info strings (e.g. dev-0.1.2-foo),
// the version may additionally include a hotpatch number, which is separated
// from the base version by another hyphen (e.g. dev-0.1.2-3). if the version is
// suffixed with any other non-numeric build info strings (e.g. dev-0.1.2-foo),
// those strings are ignored.
func parseChannelVersion(cv string) (channelVersion, error) {
parts := strings.Split(cv, "-")
Expand All @@ -35,8 +67,16 @@ func parseChannelVersion(cv string) (channelVersion, error) {

channel := parts[0]
version := parts[1]
var hotpatch *int64

for _, part := range parts[2:] {
if i, err := strconv.ParseInt(part, 10, 64); err == nil {
hotpatch = &i
break
}
}

return channelVersion{channel, version, cv}, nil
return channelVersion{channel, version, hotpatch, cv}, nil
}

// IsReleaseChannel returns true if the channel of the version is "edge" or
Expand Down
4 changes: 2 additions & 2 deletions pkg/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ func match(expectedVersion, actualVersion string) error {
actual, expected)
}

if actual.version != expected.version {
if actual.version != expected.version || !actual.hotpatchEqual(expected) {
return fmt.Errorf("is running version %s but the latest %s version is %s",
actual.version, actual.channel, expected.version)
actual.versionWithHotpatch(), actual.channel, expected.versionWithHotpatch())
}

return nil
Expand Down
16 changes: 16 additions & 0 deletions pkg/version/version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ func TestMatch(t *testing.T) {
expected: "dev-0.1.2-bar",
actual: "dev-0.1.2-baz",
},
{
name: "up-to-date with hotpatch",
expected: "dev-0.1.2-3",
actual: "dev-0.1.2-3",
},
{
name: "up-to-date with hotpatch and different build info",
expected: "dev-0.1.2-3-bar",
actual: "dev-0.1.2-3-baz",
},
{
name: "not up-to-date",
expected: "dev-0.1.2",
Expand All @@ -39,6 +49,12 @@ func TestMatch(t *testing.T) {
actual: "dev-0.1.1-bar",
err: errors.New("is running version 0.1.1 but the latest dev version is 0.1.2"),
},
{
name: "not up-to-date with hotpatch",
expected: "dev-0.1.2-3",
actual: "dev-0.1.2-2",
err: errors.New("is running version 0.1.2-2 but the latest dev version is 0.1.2-3"),
},
{
name: "mismatched channels",
expected: "dev-0.1.2",
Expand Down