1
All checks were successful
Build Multi-Platform Binaries / build-frontend (push) Successful in 38s
Build Multi-Platform Binaries / build-binaries (amd64, darwin, server, false) (push) Successful in 2m41s
Build Multi-Platform Binaries / build-binaries (amd64, linux, client, true) (push) Successful in 1m15s
Build Multi-Platform Binaries / build-binaries (amd64, linux, server, true) (push) Successful in 3m15s
Build Multi-Platform Binaries / build-binaries (amd64, windows, client, true) (push) Successful in 1m48s
Build Multi-Platform Binaries / build-binaries (amd64, windows, server, true) (push) Successful in 3m35s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, client, true) (push) Successful in 1m9s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, server, true) (push) Successful in 3m15s
Build Multi-Platform Binaries / build-binaries (arm64, darwin, server, false) (push) Successful in 2m58s
Build Multi-Platform Binaries / build-binaries (arm64, linux, client, true) (push) Successful in 1m28s
Build Multi-Platform Binaries / build-binaries (arm64, linux, server, true) (push) Successful in 3m43s
Build Multi-Platform Binaries / build-binaries (arm64, windows, server, false) (push) Successful in 2m53s
All checks were successful
Build Multi-Platform Binaries / build-frontend (push) Successful in 38s
Build Multi-Platform Binaries / build-binaries (amd64, darwin, server, false) (push) Successful in 2m41s
Build Multi-Platform Binaries / build-binaries (amd64, linux, client, true) (push) Successful in 1m15s
Build Multi-Platform Binaries / build-binaries (amd64, linux, server, true) (push) Successful in 3m15s
Build Multi-Platform Binaries / build-binaries (amd64, windows, client, true) (push) Successful in 1m48s
Build Multi-Platform Binaries / build-binaries (amd64, windows, server, true) (push) Successful in 3m35s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, client, true) (push) Successful in 1m9s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, server, true) (push) Successful in 3m15s
Build Multi-Platform Binaries / build-binaries (arm64, darwin, server, false) (push) Successful in 2m58s
Build Multi-Platform Binaries / build-binaries (arm64, linux, client, true) (push) Successful in 1m28s
Build Multi-Platform Binaries / build-binaries (arm64, linux, server, true) (push) Successful in 3m43s
Build Multi-Platform Binaries / build-binaries (arm64, windows, server, false) (push) Successful in 2m53s
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gotunnel/pkg/version"
|
"github.com/gotunnel/pkg/version"
|
||||||
@@ -36,16 +37,14 @@ func checkUpdateForComponent(component string) (*UpdateInfo, error) {
|
|||||||
available := version.CompareVersions(currentVersion, latestVersion) < 0
|
available := version.CompareVersions(currentVersion, latestVersion) < 0
|
||||||
|
|
||||||
// 查找对应平台的资产
|
// 查找对应平台的资产
|
||||||
assetName := getAssetNameForPlatform(component, runtime.GOOS, runtime.GOARCH)
|
|
||||||
var downloadURL string
|
var downloadURL string
|
||||||
|
var assetName string
|
||||||
var assetSize int64
|
var assetSize int64
|
||||||
|
|
||||||
for _, asset := range release.Assets {
|
if asset := findAssetForPlatform(release.Assets, component, runtime.GOOS, runtime.GOARCH); asset != nil {
|
||||||
if asset.Name == assetName {
|
|
||||||
downloadURL = asset.BrowserDownloadURL
|
downloadURL = asset.BrowserDownloadURL
|
||||||
|
assetName = asset.Name
|
||||||
assetSize = asset.Size
|
assetSize = asset.Size
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &UpdateInfo{
|
return &UpdateInfo{
|
||||||
@@ -76,16 +75,14 @@ func checkClientUpdateForPlatform(osName, arch string) (*UpdateInfo, error) {
|
|||||||
latestVersion := release.TagName
|
latestVersion := release.TagName
|
||||||
|
|
||||||
// 查找对应平台的资产
|
// 查找对应平台的资产
|
||||||
assetName := getAssetNameForPlatform("client", osName, arch)
|
|
||||||
var downloadURL string
|
var downloadURL string
|
||||||
|
var assetName string
|
||||||
var assetSize int64
|
var assetSize int64
|
||||||
|
|
||||||
for _, asset := range release.Assets {
|
if asset := findAssetForPlatform(release.Assets, "client", osName, arch); asset != nil {
|
||||||
if asset.Name == assetName {
|
|
||||||
downloadURL = asset.BrowserDownloadURL
|
downloadURL = asset.BrowserDownloadURL
|
||||||
|
assetName = asset.Name
|
||||||
assetSize = asset.Size
|
assetSize = asset.Size
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &UpdateInfo{
|
return &UpdateInfo{
|
||||||
@@ -99,13 +96,21 @@ func checkClientUpdateForPlatform(osName, arch string) (*UpdateInfo, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getAssetNameForPlatform 获取指定平台的资产名称
|
// findAssetForPlatform 在 Release 资产中查找匹配的文件
|
||||||
func getAssetNameForPlatform(component, osName, arch string) string {
|
// CI 格式: gotunnel-server-v1.0.0-linux-amd64.tar.gz
|
||||||
ext := ""
|
// 或者: gotunnel-client-v1.0.0-windows-amd64.zip
|
||||||
if osName == "windows" {
|
func findAssetForPlatform(assets []version.ReleaseAsset, component, osName, arch string) *version.ReleaseAsset {
|
||||||
ext = ".exe"
|
prefix := fmt.Sprintf("gotunnel-%s-", component)
|
||||||
|
suffix := fmt.Sprintf("-%s-%s", osName, arch)
|
||||||
|
|
||||||
|
for i := range assets {
|
||||||
|
name := assets[i].Name
|
||||||
|
// 检查是否匹配 gotunnel-{component}-{version}-{os}-{arch}.{ext}
|
||||||
|
if strings.HasPrefix(name, prefix) && strings.Contains(name, suffix) {
|
||||||
|
return &assets[i]
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s_%s_%s%s", component, osName, arch, ext)
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// performSelfUpdate 执行自更新
|
// performSelfUpdate 执行自更新
|
||||||
|
|||||||
@@ -1,256 +0,0 @@
|
|||||||
package router
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gotunnel/pkg/version"
|
|
||||||
)
|
|
||||||
|
|
||||||
// UpdateInfo 更新信息
|
|
||||||
type UpdateInfo struct {
|
|
||||||
Available bool `json:"available"`
|
|
||||||
Current string `json:"current"`
|
|
||||||
Latest string `json:"latest"`
|
|
||||||
ReleaseNote string `json:"release_note"`
|
|
||||||
DownloadURL string `json:"download_url"`
|
|
||||||
AssetName string `json:"asset_name"`
|
|
||||||
AssetSize int64 `json:"asset_size"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// checkUpdateForComponent 检查组件更新
|
|
||||||
func checkUpdateForComponent(component string) (*UpdateInfo, error) {
|
|
||||||
release, err := version.GetLatestRelease()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("get latest release: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
latestVersion := release.TagName
|
|
||||||
currentVersion := version.Version
|
|
||||||
available := version.CompareVersions(currentVersion, latestVersion) < 0
|
|
||||||
|
|
||||||
// 查找对应平台的资产
|
|
||||||
assetName := getAssetNameForPlatform(component, runtime.GOOS, runtime.GOARCH)
|
|
||||||
var downloadURL string
|
|
||||||
var assetSize int64
|
|
||||||
|
|
||||||
for _, asset := range release.Assets {
|
|
||||||
if asset.Name == assetName {
|
|
||||||
downloadURL = asset.BrowserDownloadURL
|
|
||||||
assetSize = asset.Size
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &UpdateInfo{
|
|
||||||
Available: available,
|
|
||||||
Current: currentVersion,
|
|
||||||
Latest: latestVersion,
|
|
||||||
ReleaseNote: release.Body,
|
|
||||||
DownloadURL: downloadURL,
|
|
||||||
AssetName: assetName,
|
|
||||||
AssetSize: assetSize,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// checkClientUpdateForPlatform 检查指定平台的客户端更新
|
|
||||||
func checkClientUpdateForPlatform(osName, arch string) (*UpdateInfo, error) {
|
|
||||||
if osName == "" {
|
|
||||||
osName = runtime.GOOS
|
|
||||||
}
|
|
||||||
if arch == "" {
|
|
||||||
arch = runtime.GOARCH
|
|
||||||
}
|
|
||||||
|
|
||||||
release, err := version.GetLatestRelease()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("get latest release: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
latestVersion := release.TagName
|
|
||||||
|
|
||||||
// 查找对应平台的资产
|
|
||||||
assetName := getAssetNameForPlatform("client", osName, arch)
|
|
||||||
var downloadURL string
|
|
||||||
var assetSize int64
|
|
||||||
|
|
||||||
for _, asset := range release.Assets {
|
|
||||||
if asset.Name == assetName {
|
|
||||||
downloadURL = asset.BrowserDownloadURL
|
|
||||||
assetSize = asset.Size
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &UpdateInfo{
|
|
||||||
Available: true, // 客户端版本由服务端判断
|
|
||||||
Current: "", // 客户端版本需要单独获取
|
|
||||||
Latest: latestVersion,
|
|
||||||
ReleaseNote: release.Body,
|
|
||||||
DownloadURL: downloadURL,
|
|
||||||
AssetName: assetName,
|
|
||||||
AssetSize: assetSize,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// getAssetNameForPlatform 获取指定平台的资产名称
|
|
||||||
func getAssetNameForPlatform(component, osName, arch string) string {
|
|
||||||
ext := ""
|
|
||||||
if osName == "windows" {
|
|
||||||
ext = ".exe"
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%s_%s_%s%s", component, osName, arch, ext)
|
|
||||||
}
|
|
||||||
|
|
||||||
// performSelfUpdate 执行自更新
|
|
||||||
func performSelfUpdate(downloadURL string, restart bool) error {
|
|
||||||
// 下载新版本
|
|
||||||
tempDir := os.TempDir()
|
|
||||||
tempFile := filepath.Join(tempDir, "gotunnel_update_"+time.Now().Format("20060102150405"))
|
|
||||||
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
tempFile += ".exe"
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := downloadFile(downloadURL, tempFile); err != nil {
|
|
||||||
return fmt.Errorf("download update: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置执行权限
|
|
||||||
if runtime.GOOS != "windows" {
|
|
||||||
if err := os.Chmod(tempFile, 0755); err != nil {
|
|
||||||
os.Remove(tempFile)
|
|
||||||
return fmt.Errorf("chmod: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取当前可执行文件路径
|
|
||||||
currentPath, err := os.Executable()
|
|
||||||
if err != nil {
|
|
||||||
os.Remove(tempFile)
|
|
||||||
return fmt.Errorf("get executable: %w", err)
|
|
||||||
}
|
|
||||||
currentPath, _ = filepath.EvalSymlinks(currentPath)
|
|
||||||
|
|
||||||
// Windows 需要特殊处理(运行中的文件无法直接替换)
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
return performWindowsUpdate(tempFile, currentPath, restart)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Linux/Mac: 直接替换
|
|
||||||
backupPath := currentPath + ".bak"
|
|
||||||
|
|
||||||
// 备份当前文件
|
|
||||||
if err := os.Rename(currentPath, backupPath); err != nil {
|
|
||||||
os.Remove(tempFile)
|
|
||||||
return fmt.Errorf("backup current: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 移动新文件
|
|
||||||
if err := os.Rename(tempFile, currentPath); err != nil {
|
|
||||||
os.Rename(backupPath, currentPath)
|
|
||||||
return fmt.Errorf("replace binary: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除备份
|
|
||||||
os.Remove(backupPath)
|
|
||||||
|
|
||||||
if restart {
|
|
||||||
// 重启进程
|
|
||||||
restartProcess(currentPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// performWindowsUpdate Windows 平台更新
|
|
||||||
func performWindowsUpdate(newFile, currentPath string, restart bool) error {
|
|
||||||
// 创建批处理脚本来替换文件并重启
|
|
||||||
batchScript := fmt.Sprintf(`@echo off
|
|
||||||
ping 127.0.0.1 -n 2 > nul
|
|
||||||
del "%s"
|
|
||||||
move "%s" "%s"
|
|
||||||
`, currentPath, newFile, currentPath)
|
|
||||||
|
|
||||||
if restart {
|
|
||||||
batchScript += fmt.Sprintf(`start "" "%s"
|
|
||||||
`, currentPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
batchScript += "del \"%~f0\"\n"
|
|
||||||
|
|
||||||
batchPath := filepath.Join(os.TempDir(), "gotunnel_update.bat")
|
|
||||||
if err := os.WriteFile(batchPath, []byte(batchScript), 0755); err != nil {
|
|
||||||
return fmt.Errorf("write batch: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd := exec.Command("cmd", "/C", "start", "/MIN", batchPath)
|
|
||||||
if err := cmd.Start(); err != nil {
|
|
||||||
return fmt.Errorf("start batch: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 退出当前进程
|
|
||||||
os.Exit(0)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// restartProcess 重启进程
|
|
||||||
func restartProcess(path string) {
|
|
||||||
cmd := exec.Command(path, os.Args[1:]...)
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
cmd.Start()
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// downloadFile 下载文件
|
|
||||||
func downloadFile(url, dest string) error {
|
|
||||||
client := &http.Client{Timeout: 10 * time.Minute}
|
|
||||||
resp, err := client.Get(url)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
return fmt.Errorf("download failed: %s", resp.Status)
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err := os.Create(dest)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer out.Close()
|
|
||||||
|
|
||||||
_, err = io.Copy(out, resp.Body)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// VersionInfo 版本信息
|
|
||||||
type VersionInfo struct {
|
|
||||||
Version string `json:"version"`
|
|
||||||
GitCommit string `json:"git_commit"`
|
|
||||||
BuildTime string `json:"build_time"`
|
|
||||||
GoVersion string `json:"go_version"`
|
|
||||||
OS string `json:"os"`
|
|
||||||
Arch string `json:"arch"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// getVersionInfo 获取版本信息
|
|
||||||
func getVersionInfo() VersionInfo {
|
|
||||||
info := version.GetInfo()
|
|
||||||
return VersionInfo{
|
|
||||||
Version: info.Version,
|
|
||||||
GitCommit: info.GitCommit,
|
|
||||||
BuildTime: info.BuildTime,
|
|
||||||
GoVersion: info.GoVersion,
|
|
||||||
OS: info.OS,
|
|
||||||
Arch: info.Arch,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -70,13 +70,32 @@ type UpdateInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetLatestRelease 获取最新 Release
|
// GetLatestRelease 获取最新 Release
|
||||||
|
// Gitea 兼容:先尝试 /releases/latest,失败则尝试 /releases 取第一个
|
||||||
func GetLatestRelease() (*ReleaseInfo, error) {
|
func GetLatestRelease() (*ReleaseInfo, error) {
|
||||||
url := fmt.Sprintf("%s/repos/%s/%s/releases/latest", APIBaseURL, RepoOwner, RepoName)
|
|
||||||
|
|
||||||
client := &http.Client{Timeout: 30 * time.Second}
|
client := &http.Client{Timeout: 30 * time.Second}
|
||||||
resp, err := client.Get(url)
|
|
||||||
|
// 首先尝试 /releases/latest 端点(GitHub 兼容)
|
||||||
|
latestURL := fmt.Sprintf("%s/repos/%s/%s/releases/latest", APIBaseURL, RepoOwner, RepoName)
|
||||||
|
resp, err := client.Get(latestURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("request failed: %w", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode == http.StatusOK {
|
||||||
|
var release ReleaseInfo
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&release); err != nil {
|
||||||
|
return nil, fmt.Errorf("decode response: %w", err)
|
||||||
|
}
|
||||||
|
return &release, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果 /releases/latest 不可用,尝试 /releases 并取第一个
|
||||||
|
resp.Body.Close()
|
||||||
|
listURL := fmt.Sprintf("%s/repos/%s/%s/releases?limit=1", APIBaseURL, RepoOwner, RepoName)
|
||||||
|
resp, err = client.Get(listURL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("request failed: %w", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
@@ -85,12 +104,16 @@ func GetLatestRelease() (*ReleaseInfo, error) {
|
|||||||
return nil, fmt.Errorf("API error: %s - %s", resp.Status, string(body))
|
return nil, fmt.Errorf("API error: %s - %s", resp.Status, string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
var release ReleaseInfo
|
var releases []ReleaseInfo
|
||||||
if err := json.NewDecoder(resp.Body).Decode(&release); err != nil {
|
if err := json.NewDecoder(resp.Body).Decode(&releases); err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("decode response: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &release, nil
|
if len(releases) == 0 {
|
||||||
|
return nil, fmt.Errorf("no releases found in repository")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &releases[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckUpdate 检查更新(返回最新版本信息)
|
// CheckUpdate 检查更新(返回最新版本信息)
|
||||||
@@ -101,16 +124,14 @@ func CheckUpdate(component string) (*UpdateInfo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 查找对应平台的资产
|
// 查找对应平台的资产
|
||||||
assetName := getAssetName(component)
|
|
||||||
var downloadURL string
|
var downloadURL string
|
||||||
|
var assetName string
|
||||||
var assetSize int64
|
var assetSize int64
|
||||||
|
|
||||||
for _, asset := range release.Assets {
|
if asset := findAssetForPlatform(release.Assets, component, runtime.GOOS, runtime.GOARCH); asset != nil {
|
||||||
if asset.Name == assetName {
|
|
||||||
downloadURL = asset.BrowserDownloadURL
|
downloadURL = asset.BrowserDownloadURL
|
||||||
|
assetName = asset.Name
|
||||||
assetSize = asset.Size
|
assetSize = asset.Size
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &UpdateInfo{
|
return &UpdateInfo{
|
||||||
@@ -130,16 +151,14 @@ func CheckUpdateForPlatform(component, osName, arch string) (*UpdateInfo, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 查找对应平台的资产
|
// 查找对应平台的资产
|
||||||
assetName := getAssetNameForPlatform(component, osName, arch)
|
|
||||||
var downloadURL string
|
var downloadURL string
|
||||||
|
var assetName string
|
||||||
var assetSize int64
|
var assetSize int64
|
||||||
|
|
||||||
for _, asset := range release.Assets {
|
if asset := findAssetForPlatform(release.Assets, component, osName, arch); asset != nil {
|
||||||
if asset.Name == assetName {
|
|
||||||
downloadURL = asset.BrowserDownloadURL
|
downloadURL = asset.BrowserDownloadURL
|
||||||
|
assetName = asset.Name
|
||||||
assetSize = asset.Size
|
assetSize = asset.Size
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &UpdateInfo{
|
return &UpdateInfo{
|
||||||
@@ -151,18 +170,22 @@ func CheckUpdateForPlatform(component, osName, arch string) (*UpdateInfo, error)
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getAssetName 获取当前平台的资产文件名
|
// findAssetForPlatform 在 Release 资产中查找匹配的文件
|
||||||
func getAssetName(component string) string {
|
func findAssetForPlatform(assets []ReleaseAsset, component, osName, arch string) *ReleaseAsset {
|
||||||
return getAssetNameForPlatform(component, runtime.GOOS, runtime.GOARCH)
|
// 构建匹配模式
|
||||||
}
|
// CI 格式: gotunnel-server-v1.0.0-linux-amd64.tar.gz
|
||||||
|
// 或者: gotunnel-client-v1.0.0-windows-amd64.zip
|
||||||
|
prefix := fmt.Sprintf("gotunnel-%s-", component)
|
||||||
|
suffix := fmt.Sprintf("-%s-%s", osName, arch)
|
||||||
|
|
||||||
// getAssetNameForPlatform 获取指定平台的资产文件名
|
for i := range assets {
|
||||||
func getAssetNameForPlatform(component, osName, arch string) string {
|
name := assets[i].Name
|
||||||
ext := ""
|
// 检查是否匹配 gotunnel-{component}-{version}-{os}-{arch}.{ext}
|
||||||
if osName == "windows" {
|
if strings.HasPrefix(name, prefix) && strings.Contains(name, suffix) {
|
||||||
ext = ".exe"
|
return &assets[i]
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s_%s_%s%s", component, osName, arch, ext)
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompareVersions 比较版本号
|
// CompareVersions 比较版本号
|
||||||
|
|||||||
Reference in New Issue
Block a user