mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 02:15:48 +02:00
enhance: display downloading progress in upgrader
This commit is contained in:
parent
defd81461e
commit
710325447a
7 changed files with 146 additions and 58 deletions
|
@ -1 +1 @@
|
|||
{"version":"1.7.9","build_id":88,"total_build":158}
|
||||
{"version":"1.7.9","build_id":92,"total_build":162}
|
|
@ -7,6 +7,7 @@ import dayjs from 'dayjs'
|
|||
import {marked} from 'marked'
|
||||
import Template from '@/views/template/Template.vue'
|
||||
import websocket from '@/lib/websocket'
|
||||
import {message} from 'ant-design-vue'
|
||||
|
||||
const {$gettext} = useGettext()
|
||||
|
||||
|
@ -20,15 +21,23 @@ const progressStrokeColor = {
|
|||
}
|
||||
|
||||
const modalVisible = ref(false)
|
||||
const progressPercent = ref(0)
|
||||
const progressPercent: any = ref(0)
|
||||
const progressStatus = ref('active')
|
||||
const modalClosable = ref(false)
|
||||
const get_release_error = ref(false)
|
||||
|
||||
function get_release_list() {
|
||||
const progressPercentComputed = computed(() => {
|
||||
return parseFloat(progressPercent.value.toFixed(1))
|
||||
})
|
||||
|
||||
function get_latest_release() {
|
||||
loading.value = true
|
||||
upgrade.get_latest_release().then(r => {
|
||||
data.value = r
|
||||
last_check.value = dayjs().format('YYYY-MM-DD HH:mm:ss')
|
||||
}).catch(e => {
|
||||
get_release_error.value = e?.message
|
||||
message.error(e?.message ?? $gettext('Server error'))
|
||||
}).finally(() => {
|
||||
setTimeout(() => {
|
||||
loading.value = false
|
||||
|
@ -36,7 +45,7 @@ function get_release_list() {
|
|||
})
|
||||
}
|
||||
|
||||
get_release_list()
|
||||
get_latest_release()
|
||||
|
||||
const is_latest_ver = computed(() => {
|
||||
return data.value.name === `v${version.version}`
|
||||
|
@ -64,14 +73,20 @@ async function perform_upgrade() {
|
|||
|
||||
const ws = websocket('/api/upgrade/perform', false)
|
||||
|
||||
ws.onmessage = m => {
|
||||
const r = JSON.parse(m.data)
|
||||
log(r.message)
|
||||
let last = 0
|
||||
|
||||
ws.onmessage = async m => {
|
||||
const r = JSON.parse(m.data)
|
||||
if (r.message) log(r.message)
|
||||
console.log(r.status)
|
||||
switch (r.status) {
|
||||
case 'info':
|
||||
progressPercent.value += 10
|
||||
break
|
||||
case 'progress':
|
||||
progressPercent.value += (r.progress - last) / 2
|
||||
last = r.progress
|
||||
break
|
||||
case 'error':
|
||||
progressStatus.value = 'exception'
|
||||
modalClosable.value = true
|
||||
|
@ -109,7 +124,7 @@ async function perform_upgrade() {
|
|||
:footer="null" :closable="modalClosable" force-render>
|
||||
<a-progress
|
||||
:stroke-color="progressStrokeColor"
|
||||
:percent="progressPercent"
|
||||
:percent="progressPercentComputed"
|
||||
:status="progressStatus"
|
||||
/>
|
||||
|
||||
|
@ -118,32 +133,41 @@ async function perform_upgrade() {
|
|||
<div class="upgrade-container">
|
||||
<p>{{ $gettext('You can check Nginx UI upgrade at this page.') }}</p>
|
||||
<h3>{{ $gettext('Current Version') }}: v{{ version.version }}</h3>
|
||||
<p>{{ $gettext('OS') }}: {{ data.os }}</p>
|
||||
<p>{{ $gettext('Arch') }}: {{ data.arch }}</p>
|
||||
<p>{{ $gettext('Executable Path') }}: {{ data.ex_path }}</p>
|
||||
<p>{{ $gettext('Last checked at') }}: {{ last_check }}
|
||||
<a-button type="link" @click="get_release_list" :loading="loading">
|
||||
{{ $gettext('Check again') }}
|
||||
</a-button>
|
||||
</p>
|
||||
<a-alert type="success" v-if="is_latest_ver"
|
||||
:message="$gettext('You are using the latest version')"
|
||||
banner
|
||||
/>
|
||||
<a-alert type="info" v-else
|
||||
:message="$gettext('New version released')"
|
||||
banner
|
||||
/>
|
||||
<div class="control-btn">
|
||||
<a-space>
|
||||
<a-button type="primary" @click="perform_upgrade"
|
||||
ghost v-if="is_latest_ver">{{ $gettext('Reinstall') }}
|
||||
<template v-if="get_release_error">
|
||||
<a-alert type="error"
|
||||
:title="$gettext('Get release information error')"
|
||||
:message="get_release_error"
|
||||
banner
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<p>{{ $gettext('OS') }}: {{ data.os }}</p>
|
||||
<p>{{ $gettext('Arch') }}: {{ data.arch }}</p>
|
||||
<p>{{ $gettext('Executable Path') }}: {{ data.ex_path }}</p>
|
||||
<p>{{ $gettext('Last checked at') }}: {{ last_check }}
|
||||
<a-button type="link" @click="get_latest_release" :loading="loading">
|
||||
{{ $gettext('Check again') }}
|
||||
</a-button>
|
||||
<a-button type="primary" @click="perform_upgrade"
|
||||
ghost v-else>{{ $gettext('Upgrade') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</p>
|
||||
<a-alert type="success" v-if="is_latest_ver"
|
||||
:message="$gettext('You are using the latest version')"
|
||||
banner
|
||||
/>
|
||||
<a-alert type="info" v-else
|
||||
:message="$gettext('New version released')"
|
||||
banner
|
||||
/>
|
||||
<div class="control-btn">
|
||||
<a-space>
|
||||
<a-button type="primary" @click="perform_upgrade"
|
||||
ghost v-if="is_latest_ver">{{ $gettext('Reinstall') }}
|
||||
</a-button>
|
||||
<a-button type="primary" @click="perform_upgrade"
|
||||
ghost v-else>{{ $gettext('Upgrade') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="data.body">
|
||||
<h2>{{ $gettext('Release Note') }}</h2>
|
||||
<div v-html="marked.parse(data.body)"></div>
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"version":"1.7.9","build_id":88,"total_build":158}
|
||||
{"version":"1.7.9","build_id":92,"total_build":162}
|
1
go.mod
1
go.mod
|
@ -36,6 +36,7 @@ require (
|
|||
github.com/BurntSushi/toml v1.2.1 // indirect
|
||||
github.com/StackExchange/wmi v1.2.1 // indirect
|
||||
github.com/bytedance/sonic v1.8.7 // indirect
|
||||
github.com/cavaliergopher/grab/v3 v3.0.1 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.2.0 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
|
|
2
go.sum
2
go.sum
|
@ -6,6 +6,8 @@ github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9
|
|||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||
github.com/bytedance/sonic v1.8.7 h1:d3sry5vGgVq/OpgozRUNP6xBsSo0mtNdwliApw+SAMQ=
|
||||
github.com/bytedance/sonic v1.8.7/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||
github.com/cavaliergopher/grab/v3 v3.0.1 h1:4z7TkBfmPjmLAAmkkAZNX/6QJ1nNFdv3SdIHXju0Fr4=
|
||||
github.com/cavaliergopher/grab/v3 v3.0.1/go.mod h1:1U/KNnD+Ft6JJiYoYBAimKH2XrYptb8Kl3DFGmsjpq4=
|
||||
github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
|
||||
github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func GetRelease(c *gin.Context) {
|
||||
|
@ -67,7 +66,16 @@ func PerformCoreUpgrade(c *gin.Context) {
|
|||
"status": "info",
|
||||
"message": "Downloading latest release",
|
||||
})
|
||||
tarName, err := u.DownloadLatestRelease()
|
||||
progressChan := make(chan float64)
|
||||
go func() {
|
||||
for progress := range progressChan {
|
||||
_ = ws.WriteJSON(gin.H{
|
||||
"status": "progress",
|
||||
"progress": progress,
|
||||
})
|
||||
}
|
||||
}()
|
||||
tarName, err := u.DownloadLatestRelease(progressChan)
|
||||
if err != nil {
|
||||
_ = ws.WriteJSON(gin.H{
|
||||
"status": "error",
|
||||
|
@ -86,7 +94,7 @@ func PerformCoreUpgrade(c *gin.Context) {
|
|||
})
|
||||
_ = os.Remove(u.Release.ExPath)
|
||||
// bye, overseer will restart nginx-ui
|
||||
err = u.PerformCoreUpgrade(filepath.Dir(u.Release.ExPath), tarName)
|
||||
err = u.PerformCoreUpgrade(u.Release.ExPath, tarName)
|
||||
if err != nil {
|
||||
_ = ws.WriteJSON(gin.H{
|
||||
"status": "error",
|
||||
|
@ -96,7 +104,7 @@ func PerformCoreUpgrade(c *gin.Context) {
|
|||
"status": "error",
|
||||
"message": err.Error(),
|
||||
})
|
||||
log.Println("[Error] PerformCoreUpgrade PerformCoreUpgrade", err)
|
||||
log.Println("[Error] PerformCoreUpgrade", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,11 +9,13 @@ import (
|
|||
"github.com/0xJacky/Nginx-UI/server/settings"
|
||||
"github.com/pkg/errors"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -72,6 +74,12 @@ func GetRelease() (data TRelease, err error) {
|
|||
err = errors.Wrap(err, "service.GetReleaseList io.ReadAll err")
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != 200 {
|
||||
err = errors.New(string(body))
|
||||
log.Println(string(body))
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(body, &data)
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "service.GetReleaseList json.Unmarshal err")
|
||||
|
@ -118,7 +126,56 @@ func NewUpgrader() (u *Upgrader, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (u *Upgrader) DownloadLatestRelease() (tarName string, err error) {
|
||||
type ProgressWriter struct {
|
||||
io.Writer
|
||||
totalSize int64
|
||||
currentSize int64
|
||||
progressChan chan<- float64
|
||||
}
|
||||
|
||||
func (pw *ProgressWriter) Write(p []byte) (int, error) {
|
||||
n, err := pw.Writer.Write(p)
|
||||
pw.currentSize += int64(n)
|
||||
progress := float64(pw.currentSize) / float64(pw.totalSize) * 100
|
||||
pw.progressChan <- progress
|
||||
return n, err
|
||||
}
|
||||
|
||||
func downloadRelease(url string, dir string, progressChan chan float64) (tarName string, err error) {
|
||||
client := &http.Client{}
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
totalSize, err := strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 64)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
file, err := os.CreateTemp(dir, "nginx-ui-temp-*.tar.gz")
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "service.DownloadLatestRelease CreateTemp error")
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
progressWriter := &ProgressWriter{Writer: file, totalSize: totalSize, progressChan: progressChan}
|
||||
multiWriter := io.MultiWriter(progressWriter)
|
||||
|
||||
_, err = io.Copy(multiWriter, resp.Body)
|
||||
close(progressChan)
|
||||
|
||||
tarName = file.Name()
|
||||
return
|
||||
}
|
||||
|
||||
func (u *Upgrader) DownloadLatestRelease(progressChan chan float64) (tarName string, err error) {
|
||||
bytes, err := _github.DistFS.ReadFile("build/build_info.json")
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "service.DownloadLatestRelease Read build_info.json error")
|
||||
|
@ -156,12 +213,7 @@ func (u *Upgrader) DownloadLatestRelease() (tarName string, err error) {
|
|||
}
|
||||
|
||||
dir := filepath.Dir(u.Release.ExPath)
|
||||
file, err := os.CreateTemp(dir, "nginx-ui-temp-*.tar.gz")
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "service.DownloadLatestRelease CreateTemp error")
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
if settings.ServerSettings.GithubProxy != "" {
|
||||
downloadUrl, err = url.JoinPath(settings.ServerSettings.GithubProxy, downloadUrl)
|
||||
if err != nil {
|
||||
|
@ -169,30 +221,31 @@ func (u *Upgrader) DownloadLatestRelease() (tarName string, err error) {
|
|||
return
|
||||
}
|
||||
}
|
||||
client := &http.Client{}
|
||||
resp, err := client.Get(downloadUrl)
|
||||
tarName, err = downloadRelease(downloadUrl, dir, progressChan)
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "service.DownloadLatestRelease client.Get() error")
|
||||
err = errors.Wrap(err, "service.DownloadLatestRelease downloadFile error")
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
_, err = io.Copy(file, resp.Body)
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "service.DownloadLatestRelease io.Copy error")
|
||||
return
|
||||
}
|
||||
tarName = file.Name()
|
||||
return
|
||||
}
|
||||
|
||||
func (u *Upgrader) PerformCoreUpgrade(dir, tarPath string) (err error) {
|
||||
func (u *Upgrader) PerformCoreUpgrade(exPath string, tarPath string) (err error) {
|
||||
dir := filepath.Dir(exPath)
|
||||
err = helper.UnTar(dir, tarPath)
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "PerformCoreUpgrade unTar error")
|
||||
return
|
||||
}
|
||||
err = os.Rename(filepath.Join(dir, "nginx-ui"), exPath)
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "PerformCoreUpgrade rename error")
|
||||
return
|
||||
}
|
||||
|
||||
_ = os.Remove(tarPath)
|
||||
|
||||
err = os.Remove(tarPath)
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "PerformCoreUpgrade remove tar error")
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue