Windows ARM64 使用场景极少,windows-11-arm runner 上 MSYS2 CLANGARM64 交叉编译不稳定,CGO 编译问题难以排查,维护成本 远超收益。移除 arm64 的 CI 矩阵条目、Makefile Windows 变量、 versionctl 资产白名单、README 文档和规范中的相关需求。 Linux 和 macOS arm64 不受影响。
266 lines
9.3 KiB
Go
266 lines
9.3 KiB
Go
package projectversion
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestParse(t *testing.T) {
|
|
t.Run("valid", func(t *testing.T) {
|
|
version, err := Parse("1.2.3")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, Version{Major: 1, Minor: 2, Patch: 3}, version)
|
|
assert.Equal(t, "1.2.3", version.String())
|
|
})
|
|
|
|
t.Run("invalid", func(t *testing.T) {
|
|
invalidValues := []string{"", "1.2", "1.2.3.4", "v1.2.3", "01.2.3", "1.02.3"}
|
|
for _, tc := range invalidValues {
|
|
_, err := Parse(tc)
|
|
assert.Error(t, err, "%q 应校验失败", tc)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestUpdatePackageJSONVersion(t *testing.T) {
|
|
content := "{\n \"name\": \"frontend\",\n \"version\": \"0.0.0\"\n}\n"
|
|
updated, err := UpdatePackageJSONVersion(content, "1.2.3")
|
|
require.NoError(t, err)
|
|
assert.Contains(t, updated, `"version": "1.2.3"`)
|
|
|
|
version, err := ReadPackageJSONVersion(updated)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "1.2.3", version)
|
|
}
|
|
|
|
func TestUpsertEnvVar(t *testing.T) {
|
|
updated := UpsertEnvVar("VITE_API_BASE=/api\n", "VITE_APP_VERSION", "1.2.3")
|
|
assert.Contains(t, updated, "VITE_API_BASE=/api\n")
|
|
assert.Contains(t, updated, "VITE_APP_VERSION=1.2.3\n")
|
|
|
|
updated = UpsertEnvVar(updated, "VITE_APP_VERSION", "2.0.0")
|
|
value, ok := ReadEnvVar(updated, "VITE_APP_VERSION")
|
|
assert.True(t, ok)
|
|
assert.Equal(t, "2.0.0", value)
|
|
assert.Equal(t, 1, strings.Count(updated, "VITE_APP_VERSION="))
|
|
}
|
|
|
|
func TestSyncAndCheck(t *testing.T) {
|
|
root := t.TempDir()
|
|
require.NoError(t, os.WriteFile(filepath.Join(root, "VERSION"), []byte("1.2.3\n"), 0o600))
|
|
require.NoError(t, os.MkdirAll(filepath.Join(root, "frontend"), 0o755))
|
|
require.NoError(t, os.WriteFile(filepath.Join(root, "frontend", "package.json"), []byte("{\n \"name\": \"frontend\",\n \"version\": \"0.0.0\"\n}\n"), 0o600))
|
|
require.NoError(t, os.WriteFile(filepath.Join(root, "frontend", ".env.production"), []byte("VITE_API_BASE=/api\n"), 0o600))
|
|
require.NoError(t, os.WriteFile(filepath.Join(root, "frontend", ".env.development"), []byte("VITE_API_BASE=\n"), 0o600))
|
|
require.NoError(t, os.WriteFile(filepath.Join(root, "frontend", ".env.desktop"), []byte("VITE_API_BASE=\n"), 0o600))
|
|
|
|
require.NoError(t, Sync(root))
|
|
require.NoError(t, Check(root))
|
|
|
|
packageJSONContent, err := os.ReadFile(filepath.Join(root, "frontend", "package.json"))
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(packageJSONContent), `"version": "1.2.3"`)
|
|
|
|
for _, relPath := range frontendVersionFiles {
|
|
content, readErr := os.ReadFile(filepath.Join(root, relPath))
|
|
require.NoError(t, readErr)
|
|
assert.Contains(t, string(content), "VITE_APP_VERSION=1.2.3\n")
|
|
}
|
|
}
|
|
|
|
func TestVerifyTag(t *testing.T) {
|
|
root := t.TempDir()
|
|
require.NoError(t, os.WriteFile(filepath.Join(root, "VERSION"), []byte("1.2.3\n"), 0o600))
|
|
|
|
require.NoError(t, VerifyTag(root, "v1.2.3"))
|
|
assert.Error(t, VerifyTag(root, "1.2.3"))
|
|
assert.Error(t, VerifyTag(root, "v1.2.4"))
|
|
}
|
|
|
|
func TestAssetNames(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
component string
|
|
platform string
|
|
arch string
|
|
format string
|
|
want string
|
|
}{
|
|
{"server linux amd64", "server", "linux", "amd64", "tar.gz", "nex-server_1.2.3_linux_amd64.tar.gz"},
|
|
{"server linux arm64", "server", "linux", "arm64", "tar.gz", "nex-server_1.2.3_linux_arm64.tar.gz"},
|
|
{"server macos amd64", "server", "macos", "amd64", "tar.gz", "nex-server_1.2.3_macos_amd64.tar.gz"},
|
|
{"server macos arm64", "server", "macos", "arm64", "tar.gz", "nex-server_1.2.3_macos_arm64.tar.gz"},
|
|
{"server macos universal", "server", "macos", "universal", "tar.gz", "nex-server_1.2.3_macos_universal.tar.gz"},
|
|
{"server windows amd64", "server", "windows", "amd64", "zip", "nex-server_1.2.3_windows_amd64.zip"},
|
|
{"web", "web", "", "", "tar.gz", "nex-web_1.2.3.tar.gz"},
|
|
{"desktop linux amd64 tar", "desktop", "linux", "amd64", "tar.gz", "nex-desktop_1.2.3_linux_amd64.tar.gz"},
|
|
{"desktop linux amd64 appimage", "desktop", "linux", "amd64", "AppImage", "nex-desktop_1.2.3_linux_amd64.AppImage"},
|
|
{"desktop linux amd64 deb", "desktop", "linux", "amd64", "deb", "nex-desktop_1.2.3_linux_amd64.deb"},
|
|
{"desktop linux amd64 rpm", "desktop", "linux", "amd64", "rpm", "nex-desktop_1.2.3_linux_amd64.rpm"},
|
|
{"desktop linux arm64 tar", "desktop", "linux", "arm64", "tar.gz", "nex-desktop_1.2.3_linux_arm64.tar.gz"},
|
|
{"desktop linux arm64 appimage", "desktop", "linux", "arm64", "AppImage", "nex-desktop_1.2.3_linux_arm64.AppImage"},
|
|
{"desktop linux arm64 deb", "desktop", "linux", "arm64", "deb", "nex-desktop_1.2.3_linux_arm64.deb"},
|
|
{"desktop linux arm64 rpm", "desktop", "linux", "arm64", "rpm", "nex-desktop_1.2.3_linux_arm64.rpm"},
|
|
{"desktop macos zip", "desktop", "macos", "universal", "zip", "nex-desktop_1.2.3_macos_universal.zip"},
|
|
{"desktop macos dmg", "desktop", "macos", "universal", "dmg", "nex-desktop_1.2.3_macos_universal.dmg"},
|
|
{"desktop windows amd64", "desktop", "windows", "amd64", "zip", "nex-desktop_1.2.3_windows_amd64.zip"},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
got, err := ReleaseAssetName("1.2.3", tc.component, tc.platform, tc.arch, tc.format)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, tc.want, got)
|
|
})
|
|
}
|
|
|
|
invalidCases := []struct {
|
|
name string
|
|
component string
|
|
platform string
|
|
arch string
|
|
format string
|
|
}{
|
|
{"invalid version", "server", "linux", "amd64", "tar.gz"},
|
|
{"invalid component", "mobile", "linux", "amd64", "tar.gz"},
|
|
{"darwin platform", "server", "darwin", "arm64", "tar.gz"},
|
|
{"server unsupported format", "server", "linux", "amd64", "zip"},
|
|
{"server unsupported arch", "server", "windows", "universal", "zip"},
|
|
{"web with platform", "web", "linux", "amd64", "tar.gz"},
|
|
{"web unsupported format", "web", "", "", "zip"},
|
|
{"desktop unsupported platform", "desktop", "ios", "arm64", "zip"},
|
|
{"desktop unsupported format", "desktop", "macos", "universal", "tar.gz"},
|
|
}
|
|
|
|
for _, tc := range invalidCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
version := "1.2.3"
|
|
if tc.name == "invalid version" {
|
|
version = "1.2"
|
|
}
|
|
_, err := ReleaseAssetName(version, tc.component, tc.platform, tc.arch, tc.format)
|
|
assert.Error(t, err)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDesktopInfoPlist(t *testing.T) {
|
|
plist, err := DesktopInfoPlist("1.2.3", "13.0")
|
|
require.NoError(t, err)
|
|
assert.Contains(t, plist, "<key>CFBundleShortVersionString</key>\n <string>1.2.3</string>")
|
|
assert.Contains(t, plist, "<key>CFBundleVersion</key>\n <string>1.2.3</string>")
|
|
assert.Contains(t, plist, "<key>LSMinimumSystemVersion</key>\n <string>13.0</string>")
|
|
|
|
_, err = DesktopInfoPlist("1.2", "13.0")
|
|
assert.Error(t, err)
|
|
_, err = DesktopInfoPlist("1.2.3", "")
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
func TestLess(t *testing.T) {
|
|
assert.True(t, Version{1, 0, 0}.Less(Version{2, 0, 0}))
|
|
assert.True(t, Version{1, 1, 0}.Less(Version{1, 2, 0}))
|
|
assert.True(t, Version{1, 0, 1}.Less(Version{1, 0, 2}))
|
|
assert.False(t, Version{2, 0, 0}.Less(Version{1, 0, 0}))
|
|
assert.False(t, Version{1, 0, 0}.Less(Version{1, 0, 0}))
|
|
}
|
|
|
|
func TestBump(t *testing.T) {
|
|
setupRoot := func(t *testing.T) string {
|
|
t.Helper()
|
|
root := t.TempDir()
|
|
require.NoError(t, os.WriteFile(filepath.Join(root, "VERSION"), []byte("0.1.0\n"), 0o600))
|
|
return root
|
|
}
|
|
|
|
t.Run("major", func(t *testing.T) {
|
|
root := setupRoot(t)
|
|
v, err := Bump(root, "major")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, Version{1, 0, 0}, v)
|
|
|
|
read, readErr := ReadString(root)
|
|
require.NoError(t, readErr)
|
|
assert.Equal(t, "1.0.0", read)
|
|
})
|
|
|
|
t.Run("minor", func(t *testing.T) {
|
|
root := setupRoot(t)
|
|
v, err := Bump(root, "minor")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, Version{0, 2, 0}, v)
|
|
|
|
read, readErr := ReadString(root)
|
|
require.NoError(t, readErr)
|
|
assert.Equal(t, "0.2.0", read)
|
|
})
|
|
|
|
t.Run("patch", func(t *testing.T) {
|
|
root := setupRoot(t)
|
|
v, err := Bump(root, "patch")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, Version{0, 1, 1}, v)
|
|
|
|
read, readErr := ReadString(root)
|
|
require.NoError(t, readErr)
|
|
assert.Equal(t, "0.1.1", read)
|
|
})
|
|
|
|
t.Run("specific version", func(t *testing.T) {
|
|
root := setupRoot(t)
|
|
v, err := Bump(root, "1.0.0")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, Version{1, 0, 0}, v)
|
|
})
|
|
|
|
t.Run("same version as current", func(t *testing.T) {
|
|
root := setupRoot(t)
|
|
v, err := Bump(root, "0.1.0")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, Version{0, 1, 0}, v)
|
|
})
|
|
|
|
t.Run("invalid argument", func(t *testing.T) {
|
|
root := setupRoot(t)
|
|
_, err := Bump(root, "invalid")
|
|
assert.Error(t, err)
|
|
})
|
|
}
|
|
|
|
func TestCheckNoRegression(t *testing.T) {
|
|
t.Run("greater than existing tag", func(t *testing.T) {
|
|
err := CheckNoRegression(Version{0, 2, 0}, []string{"v0.1.0"})
|
|
assert.NoError(t, err)
|
|
})
|
|
|
|
t.Run("equal to existing tag", func(t *testing.T) {
|
|
err := CheckNoRegression(Version{0, 1, 0}, []string{"v0.1.0"})
|
|
assert.Error(t, err)
|
|
})
|
|
|
|
t.Run("less than existing tag", func(t *testing.T) {
|
|
err := CheckNoRegression(Version{0, 1, 5}, []string{"v0.2.0"})
|
|
assert.Error(t, err)
|
|
})
|
|
|
|
t.Run("no tags", func(t *testing.T) {
|
|
err := CheckNoRegression(Version{0, 1, 0}, nil)
|
|
assert.NoError(t, err)
|
|
})
|
|
|
|
t.Run("skips non-semver tags", func(t *testing.T) {
|
|
err := CheckNoRegression(Version{0, 2, 0}, []string{"v0.1.0", "some-other-tag"})
|
|
assert.NoError(t, err)
|
|
})
|
|
|
|
t.Run("picks max tag", func(t *testing.T) {
|
|
err := CheckNoRegression(Version{0, 1, 5}, []string{"v0.1.0", "v0.2.0", "v0.0.5"})
|
|
assert.Error(t, err)
|
|
})
|
|
}
|