mirror of
https://github.com/gowvp/gb28181.git
synced 2026-04-22 23:17:19 +08:00
Implement OTA functionality for version checking
This commit is contained in:
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/gin-contrib/gzip"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gowvp/owl/internal/core/sms"
|
||||
"github.com/gowvp/owl/pkg/ota"
|
||||
"github.com/gowvp/owl/plugin/stat"
|
||||
"github.com/gowvp/owl/plugin/stat/statapi"
|
||||
"github.com/ixugo/goddd/domain/version/versionapi"
|
||||
@@ -94,6 +95,8 @@ func setupRouter(r *gin.Engine, uc *Usecase) {
|
||||
auth := web.AuthMiddleware(uc.Conf.Server.HTTP.JwtSecret)
|
||||
r.GET("/health", web.WrapH(uc.getHealth))
|
||||
r.GET("/app/metrics/api", web.WrapH(uc.getMetricsAPI))
|
||||
r.GET("/app/version/check", web.WrapH(uc.checkVersion))
|
||||
r.POST("/app/upgrade", auth, uc.upgradeApp)
|
||||
|
||||
versionapi.Register(r, uc.Version, auth)
|
||||
statapi.Register(r)
|
||||
@@ -202,6 +205,109 @@ func sortExpvarMap(data *expvar.Map, top int) []KV {
|
||||
return kvs[:idx]
|
||||
}
|
||||
|
||||
const repoName = "gowvp/owl"
|
||||
|
||||
type checkVersionOutput struct {
|
||||
HasNewVersion bool `json:"has_new_version"`
|
||||
CurrentVersion string `json:"current_version"`
|
||||
NewVersion string `json:"new_version"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// checkVersion 检查是否有新版本
|
||||
// 通过 GitHub API 获取最新 release 信息,与当前版本比较
|
||||
func (uc *Usecase) checkVersion(_ *gin.Context, _ *struct{}) (checkVersionOutput, error) {
|
||||
currentVersion := uc.Conf.BuildVersion
|
||||
newVersion, body, err := ota.GetLastVersion(repoName)
|
||||
if err != nil {
|
||||
return checkVersionOutput{}, err
|
||||
}
|
||||
|
||||
hasNew := compareVersion(currentVersion, newVersion) < 0
|
||||
|
||||
return checkVersionOutput{
|
||||
HasNewVersion: hasNew,
|
||||
CurrentVersion: currentVersion,
|
||||
NewVersion: newVersion,
|
||||
Description: body,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// compareVersion 比较两个版本号
|
||||
// 返回值: -1 表示 v1 < v2, 0 表示相等, 1 表示 v1 > v2
|
||||
func compareVersion(v1, v2 string) int {
|
||||
v1 = strings.TrimPrefix(v1, "v")
|
||||
v2 = strings.TrimPrefix(v2, "v")
|
||||
|
||||
parts1 := strings.Split(v1, ".")
|
||||
parts2 := strings.Split(v2, ".")
|
||||
|
||||
maxLen := len(parts1)
|
||||
if len(parts2) > maxLen {
|
||||
maxLen = len(parts2)
|
||||
}
|
||||
|
||||
for i := 0; i < maxLen; i++ {
|
||||
var n1, n2 int
|
||||
if i < len(parts1) {
|
||||
fmt.Sscanf(parts1[i], "%d", &n1)
|
||||
}
|
||||
if i < len(parts2) {
|
||||
fmt.Sscanf(parts2[i], "%d", &n2)
|
||||
}
|
||||
if n1 < n2 {
|
||||
return -1
|
||||
}
|
||||
if n1 > n2 {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// upgradeApp 执行应用升级
|
||||
// 通过 SSE 返回下载进度,下载完成后由回调决定如何升级
|
||||
func (uc *Usecase) upgradeApp(c *gin.Context) {
|
||||
c.Header("Content-Type", "text/event-stream")
|
||||
c.Header("Cache-Control", "no-cache")
|
||||
c.Header("Connection", "keep-alive")
|
||||
c.Header("Access-Control-Allow-Origin", "*")
|
||||
|
||||
flusher, ok := c.Writer.(http.Flusher)
|
||||
if !ok {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"msg": "不支持 SSE"})
|
||||
return
|
||||
}
|
||||
|
||||
sendEvent := func(event, data string) {
|
||||
fmt.Fprintf(c.Writer, "event: %s\ndata: %s\n\n", event, data)
|
||||
flusher.Flush()
|
||||
}
|
||||
|
||||
sendEvent("start", `{"msg":"开始下载升级包"}`)
|
||||
|
||||
filename := "linux_amd64"
|
||||
if runtime.GOARCH == "arm64" {
|
||||
filename = "linux_arm64"
|
||||
}
|
||||
|
||||
o := ota.NewOTA(repoName, filename)
|
||||
o.SetProgressCallback(func(current, total int64) {
|
||||
percent := 0
|
||||
if total > 0 {
|
||||
percent = int(current * 100 / total)
|
||||
}
|
||||
sendEvent("progress", fmt.Sprintf(`{"current":%d,"total":%d,"percent":%d}`, current, total, percent))
|
||||
})
|
||||
|
||||
if err := o.Download().Error(); err != nil {
|
||||
sendEvent("error", fmt.Sprintf(`{"msg":"%s"}`, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
sendEvent("complete", `{"msg":"下载完成,请手动重启服务"}`)
|
||||
}
|
||||
|
||||
func (uc *Usecase) proxySMS(c *gin.Context) {
|
||||
defer func() {
|
||||
_ = recover()
|
||||
|
||||
Reference in New Issue
Block a user