diff --git a/pkg/release/publish.go b/pkg/release/publish.go index 4b50bd498e1..87fb3f2b6c4 100644 --- a/pkg/release/publish.go +++ b/pkg/release/publish.go @@ -282,7 +282,17 @@ func (p *Publisher) VerifyLatestUpdate( return false, fmt.Errorf("invalid GCS version format %s", gcsVersion) } - if sv.LTE(gcsSemverVersion) { + // The version format that we use is: + // - Stable: "v..-+" + // - Prerelease: "v..-.+" + // blang/semver library considers "-" part as the prerelease part even though + // the version is stable. This is causing issues when we're supposed to bump the version marker + // from rc to stable. + // blang/semver models prerelease as a slice of prereleases, so stable releases + // are going to have one element (the number of commits), and prereleases are going to have three elements + // (alpha/beta/rc, number of prerelease, number of commits). + // We can use this to determine when we're switching from rc to stable and act accordingly. + if sv.LTE(gcsSemverVersion) && len(sv.Pre) >= len(gcsSemverVersion.Pre) { logrus.Infof( "Not updating version, because %s <= %s", version, gcsVersion, ) diff --git a/pkg/release/publish_test.go b/pkg/release/publish_test.go index f76d1709cbd..ed41c0d9580 100644 --- a/pkg/release/publish_test.go +++ b/pkg/release/publish_test.go @@ -325,3 +325,181 @@ func TestPublishReleaseNotesIndex(t *testing.T) { } } } + +func TestVerifyLatestUpdate(t *testing.T) { + // err := errors.New("") + for _, tc := range []struct { + prepare func(*releasefakes.FakePublisherClient, string) + version string + gcsVersion string + needsUpdate bool + shouldError bool + }{ + { // success same version + prepare: func(mock *releasefakes.FakePublisherClient, gcsVersion string) { + mock.NormalizePath("", "") + mock.GSUtilOutputReturns(gcsVersion, nil) + }, + version: "v1.24.0", + gcsVersion: "v1.24.0", + needsUpdate: false, + shouldError: false, + }, + + { // success version > gcsVersion (patch) + prepare: func(mock *releasefakes.FakePublisherClient, gcsVersion string) { + mock.NormalizePath("", "") + mock.GSUtilOutputReturns(gcsVersion, nil) + }, + version: "v1.24.1", + gcsVersion: "v1.24.0", + needsUpdate: true, + shouldError: false, + }, + { // success version < gcsVersion (patch) + prepare: func(mock *releasefakes.FakePublisherClient, gcsVersion string) { + mock.NormalizePath("", "") + mock.GSUtilOutputReturns(gcsVersion, nil) + }, + version: "v1.24.0", + gcsVersion: "v1.24.1", + needsUpdate: false, + shouldError: false, + }, + + { // success version > gcsVersion (minor) + prepare: func(mock *releasefakes.FakePublisherClient, gcsVersion string) { + mock.NormalizePath("", "") + mock.GSUtilOutputReturns(gcsVersion, nil) + }, + version: "v1.25.0", + gcsVersion: "v1.24.0", + needsUpdate: true, + shouldError: false, + }, + { // success version < gcsVersion (minor) + prepare: func(mock *releasefakes.FakePublisherClient, gcsVersion string) { + mock.NormalizePath("", "") + mock.GSUtilOutputReturns(gcsVersion, nil) + }, + version: "v1.23.0", + gcsVersion: "v1.24.0", + needsUpdate: false, + shouldError: false, + }, + + { // success version = gcsVersion (with build version) + prepare: func(mock *releasefakes.FakePublisherClient, gcsVersion string) { + mock.NormalizePath("", "") + mock.GSUtilOutputReturns(gcsVersion, nil) + }, + version: "v1.28.0-7+c4e17abb04728e", + gcsVersion: "v1.28.0-7+c4e17abb04728e", + needsUpdate: false, + shouldError: false, + }, + { // success version > gcsVersion (with build version) + prepare: func(mock *releasefakes.FakePublisherClient, gcsVersion string) { + mock.NormalizePath("", "") + mock.GSUtilOutputReturns(gcsVersion, nil) + }, + version: "v1.28.0-9+aaaaaabb04728e", + gcsVersion: "v1.28.0-7+c4e17abb04728e", + needsUpdate: true, + shouldError: false, + }, + { // success version < gcsVersion (with build version) + prepare: func(mock *releasefakes.FakePublisherClient, gcsVersion string) { + mock.NormalizePath("", "") + mock.GSUtilOutputReturns(gcsVersion, nil) + }, + version: "v1.28.0-7+c4e17abb04728e", + gcsVersion: "v1.28.0-9+aaaaaabb04728e", + needsUpdate: false, + shouldError: false, + }, + { // success version > gcsVersion (with build version) + prepare: func(mock *releasefakes.FakePublisherClient, gcsVersion string) { + mock.NormalizePath("", "") + mock.GSUtilOutputReturns(gcsVersion, nil) + }, + version: "v1.28.1-1+aaaaaabb04728e", + gcsVersion: "v1.28.0-7+c4e17abb04728e", + needsUpdate: true, + shouldError: false, + }, + { // success version = gcsVersion (with build version, prerelease) + prepare: func(mock *releasefakes.FakePublisherClient, gcsVersion string) { + mock.NormalizePath("", "") + mock.GSUtilOutputReturns(gcsVersion, nil) + }, + version: "v1.28.0-rc.1.9+3fb5377b25ec51", + gcsVersion: "v1.28.0-rc.1.9+3fb5377b25ec51", + needsUpdate: false, + shouldError: false, + }, + { // success version > gcsVersion (with build version, prerelease) + prepare: func(mock *releasefakes.FakePublisherClient, gcsVersion string) { + mock.NormalizePath("", "") + mock.GSUtilOutputReturns(gcsVersion, nil) + }, + version: "v1.28.0-rc.1.10+3fb5377b25ec51", + gcsVersion: "v1.28.0-rc.1.9+3fb5377b25ec51", + needsUpdate: true, + shouldError: false, + }, + { // success version < gcsVersion (with build version, prerelease) + prepare: func(mock *releasefakes.FakePublisherClient, gcsVersion string) { + mock.NormalizePath("", "") + mock.GSUtilOutputReturns(gcsVersion, nil) + }, + version: "v1.28.0-rc.1.9+3fb5377b25ec51", + gcsVersion: "v1.28.0-rc.1.10+3fb5377b25ec51", + needsUpdate: false, + shouldError: false, + }, + { // success version < gcsVersion (with build version, prerelease) + prepare: func(mock *releasefakes.FakePublisherClient, gcsVersion string) { + mock.NormalizePath("", "") + mock.GSUtilOutputReturns(gcsVersion, nil) + }, + version: "v1.28.0-beta.1.9+3fb5377b25ec51", + gcsVersion: "v1.28.0-rc.1.9+3fb5377b25ec51", + needsUpdate: false, + shouldError: false, + }, + { // success version > gcsVersion (with build version, prerelease) + prepare: func(mock *releasefakes.FakePublisherClient, gcsVersion string) { + mock.NormalizePath("", "") + mock.GSUtilOutputReturns(gcsVersion, nil) + }, + version: "v1.28.0-rc.1.9+3fb5377b25ec51", + gcsVersion: "v1.28.0-beta.1.9+3fb5377b25ec51", + needsUpdate: true, + shouldError: false, + }, + { // success version > gcsVersion (with build version, stable and prerelease) + prepare: func(mock *releasefakes.FakePublisherClient, gcsVersion string) { + mock.NormalizePath("", "") + mock.GSUtilOutputReturns(gcsVersion, nil) + }, + version: "v1.28.0-7+c4e17abb04728e", + gcsVersion: "v1.28.0-rc.1.9+3fb5377b25ec51", + needsUpdate: true, + shouldError: false, + }, + } { + sut := release.NewPublisher() + clientMock := &releasefakes.FakePublisherClient{} + sut.SetClient(clientMock) + tc.prepare(clientMock, tc.gcsVersion) + + needsUpdate, err := sut.VerifyLatestUpdate("", "", tc.version) + if tc.shouldError { + require.NotNil(t, err) + } else { + require.Nil(t, err) + require.Equal(t, tc.needsUpdate, needsUpdate) + } + } +}