From 0f057e81e921aa76695e879c75773c53daf1381b Mon Sep 17 00:00:00 2001 From: boojack Date: Sat, 7 Jan 2023 13:58:42 +0800 Subject: [PATCH] fix: version compare (#916) * fix: version compare * chore: update --- go.mod | 3 +- go.sum | 6 ++- server/version/version.go | 47 ++++++++-------- server/version/version_test.go | 62 +++++++++++++++++++++- store/db/db.go | 6 +-- web/package.json | 2 + web/src/components/UpdateVersionBanner.tsx | 3 +- web/yarn.lock | 14 ++++- 8 files changed, 108 insertions(+), 35 deletions(-) diff --git a/go.mod b/go.mod index 674c26c3..21535e12 100644 --- a/go.mod +++ b/go.mod @@ -48,5 +48,6 @@ require ( require ( github.com/pkg/errors v0.9.1 github.com/segmentio/analytics-go v3.1.0+incompatible - golang.org/x/exp v0.0.0-20221217163422-3c43f8badb15 + golang.org/x/exp v0.0.0-20230105202349-8879d0199aa3 + golang.org/x/mod v0.7.0 ) diff --git a/go.sum b/go.sum index c749cff1..0b59a65f 100644 --- a/go.sum +++ b/go.sum @@ -72,8 +72,10 @@ github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c h1:3lbZUMbMiGUW/LMkfsEAB github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c/go.mod h1:UrdRz5enIKZ63MEE3IF9l2/ebyx59GyGgPi+tICQdmM= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/exp v0.0.0-20221217163422-3c43f8badb15 h1:5oN1Pz/eDhCpbMbLstvIPa0b/BEQo6g6nwV3pLjfM6w= -golang.org/x/exp v0.0.0-20221217163422-3c43f8badb15/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230105202349-8879d0199aa3 h1:fJwx88sMf5RXwDwziL0/Mn9Wqs+efMSo/RYcL+37W9c= +golang.org/x/exp v0.0.0-20230105202349-8879d0199aa3/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20220728030405-41545e8bf201 h1:bvOltf3SADAfG05iRml8lAB3qjoEX5RCyN4K6G5v3N0= golang.org/x/net v0.0.0-20220728030405-41545e8bf201/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/server/version/version.go b/server/version/version.go index 49021b4a..df7a572e 100644 --- a/server/version/version.go +++ b/server/version/version.go @@ -1,8 +1,10 @@ package version import ( - "strconv" + "fmt" "strings" + + "golang.org/x/mod/semver" ) // Version is the service current released version. @@ -32,35 +34,28 @@ func GetSchemaVersion(version string) string { return minorVersion + ".0" } -// convSemanticVersionToInt converts version string to int. -func convSemanticVersionToInt(version string) int { - versionList := strings.Split(version, ".") - - if len(versionList) < 3 { - return 0 - } - major, err := strconv.Atoi(versionList[0]) - if err != nil { - return 0 - } - minor, err := strconv.Atoi(versionList[1]) - if err != nil { - return 0 - } - patch, err := strconv.Atoi(versionList[2]) - if err != nil { - return 0 - } - - return major*10000 + minor*100 + patch -} - // IsVersionGreaterThanOrEqualTo returns true if version is greater than or equal to target. func IsVersionGreaterOrEqualThan(version, target string) bool { - return convSemanticVersionToInt(version) >= convSemanticVersionToInt(target) + return semver.Compare(fmt.Sprintf("v%s", version), fmt.Sprintf("v%s", target)) > -1 } // IsVersionGreaterThan returns true if version is greater than target. func IsVersionGreaterThan(version, target string) bool { - return convSemanticVersionToInt(version) > convSemanticVersionToInt(target) + return semver.Compare(fmt.Sprintf("v%s", version), fmt.Sprintf("v%s", target)) > 0 +} + +type SortVersion []string + +func (s SortVersion) Len() int { + return len(s) +} + +func (s SortVersion) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +func (s SortVersion) Less(i, j int) bool { + v1 := fmt.Sprintf("v%s", s[i]) + v2 := fmt.Sprintf("v%s", s[j]) + return semver.Compare(v1, v2) == -1 } diff --git a/server/version/version_test.go b/server/version/version_test.go index 21be7c95..d06d97aa 100644 --- a/server/version/version_test.go +++ b/server/version/version_test.go @@ -1,6 +1,11 @@ package version -import "testing" +import ( + "sort" + "testing" + + "github.com/stretchr/testify/assert" +) func TestIsVersionGreaterOrEqualThan(t *testing.T) { tests := []struct { @@ -31,3 +36,58 @@ func TestIsVersionGreaterOrEqualThan(t *testing.T) { } } } + +func TestIsVersionGreaterThan(t *testing.T) { + tests := []struct { + version string + target string + want bool + }{ + { + version: "0.9.1", + target: "0.9.1", + want: false, + }, + { + version: "0.10.0", + target: "0.8.0", + want: true, + }, + { + version: "0.8.0", + target: "0.10.0", + want: false, + }, + { + version: "0.9.0", + target: "0.9.1", + want: false, + }, + } + for _, test := range tests { + result := IsVersionGreaterThan(test.version, test.target) + if result != test.want { + t.Errorf("got result %v, want %v.", result, test.want) + } + } +} + +func TestSortVersion(t *testing.T) { + tests := []struct { + versionList []string + want []string + }{ + { + versionList: []string{"0.9.1", "0.10.0", "0.8.0"}, + want: []string{"0.8.0", "0.9.1", "0.10.0"}, + }, + { + versionList: []string{"1.9.1", "0.9.1", "0.10.0", "0.8.0"}, + want: []string{"0.8.0", "0.9.1", "0.10.0", "1.9.1"}, + }, + } + for _, test := range tests { + sort.Sort(SortVersion(test.versionList)) + assert.Equal(t, test.versionList, test.want) + } +} diff --git a/store/db/db.go b/store/db/db.go index 2694bcbd..5ef6f4cc 100644 --- a/store/db/db.go +++ b/store/db/db.go @@ -84,8 +84,8 @@ func (db *DB) Open(ctx context.Context) (err error) { for _, migrationHistory := range migrationHistoryList { migrationHistoryVersionList = append(migrationHistoryVersionList, migrationHistory.Version) } - sort.Strings(migrationHistoryVersionList) - latestMigrationHistoryVersion := migrationHistoryVersionList[0] + sort.Sort(version.SortVersion(migrationHistoryVersionList)) + latestMigrationHistoryVersion := migrationHistoryVersionList[len(migrationHistoryVersionList)-1] if version.IsVersionGreaterThan(version.GetSchemaVersion(currentVersion), latestMigrationHistoryVersion) { minorVersionList := getMinorVersionList() @@ -235,7 +235,7 @@ func getMinorVersionList() []string { panic(err) } - sort.Strings(minorVersionList) + sort.Sort(version.SortVersion(minorVersionList)) return minorVersionList } diff --git a/web/package.json b/web/package.json index 56ea375d..2313376d 100644 --- a/web/package.json +++ b/web/package.json @@ -24,6 +24,7 @@ "react-i18next": "^11.18.6", "react-redux": "^8.0.1", "react-router-dom": "^6.4.0", + "semver": "^7.3.8", "tailwindcss": "^3.2.4" }, "devDependencies": { @@ -33,6 +34,7 @@ "@types/qs": "^6.9.7", "@types/react": "^18.0.21", "@types/react-dom": "^18.0.6", + "@types/semver": "^7.3.13", "@typescript-eslint/eslint-plugin": "^5.6.0", "@typescript-eslint/parser": "^5.6.0", "@vitejs/plugin-legacy": "^3.0.1", diff --git a/web/src/components/UpdateVersionBanner.tsx b/web/src/components/UpdateVersionBanner.tsx index 89792a38..ccc00a6f 100644 --- a/web/src/components/UpdateVersionBanner.tsx +++ b/web/src/components/UpdateVersionBanner.tsx @@ -1,4 +1,5 @@ import { useEffect, useState } from "react"; +import { compare } from "semver"; import * as api from "../helpers/api"; import * as storage from "../helpers/storage"; import Icon from "./Icon"; @@ -26,7 +27,7 @@ const UpdateVersionBanner: React.FC = () => { const skipped = skippedVersion ? skippedVersion === latestVersion : false; setState({ latestVersion, - show: !skipped && currentVersion < latestVersion, + show: !skipped && compare(currentVersion, latestVersion) === -1, }); }); }, []); diff --git a/web/yarn.lock b/web/yarn.lock index b665b8e0..a51d9b21 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -1184,6 +1184,11 @@ resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== +"@types/semver@^7.3.13": + version "7.3.13" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" + integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== + "@types/stack-utils@^2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" @@ -3987,6 +3992,13 @@ semver@^6.0.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.3.8: + version "7.3.8" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" + integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== + dependencies: + lru-cache "^6.0.0" + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -4476,4 +4488,4 @@ yargs@^17.3.1: yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== \ No newline at end of file + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==