fix: 升级逻辑调整 (#341)

fix: 升级逻辑调整
pull/342/head
ssongliu 2023-03-21 15:16:28 +08:00 committed by GitHub
parent 72237596f3
commit 68a457ae89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 201 additions and 51 deletions

View File

@ -22,6 +22,28 @@ func (b *BaseApi) GetUpgradeInfo(c *gin.Context) {
helper.SuccessWithData(c, info) helper.SuccessWithData(c, info)
} }
// @Tags System Setting
// @Summary Load release notes by version
// @Description 获取版本 release notes
// @Accept json
// @Param request body dto.Upgrade true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /settings/upgrade [get]
func (b *BaseApi) GetNotesByVersion(c *gin.Context) {
var req dto.Upgrade
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
notes, err := upgradeService.LoadNotes(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, notes)
}
// @Tags System Setting // @Tags System Setting
// @Summary Upgrade // @Summary Upgrade
// @Description 系统更新 // @Description 系统更新

View File

@ -82,9 +82,11 @@ type SnapshotInfo struct {
} }
type UpgradeInfo struct { type UpgradeInfo struct {
NewVersion string `json:"newVersion"` NewVersion string `json:"newVersion"`
ReleaseNote string `json:"releaseNote"` LatestVersion string `json:"latestVersion"`
ReleaseNote string `json:"releaseNote"`
} }
type Upgrade struct { type Upgrade struct {
Version string `json:"version"` Version string `json:"version"`
} }

View File

@ -1,6 +1,8 @@
package service package service
import ( import (
"encoding/json"
"errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
@ -20,6 +22,7 @@ type UpgradeService struct{}
type IUpgradeService interface { type IUpgradeService interface {
Upgrade(req dto.Upgrade) error Upgrade(req dto.Upgrade) error
LoadNotes(req dto.Upgrade) (string, error)
SearchUpgrade() (*dto.UpgradeInfo, error) SearchUpgrade() (*dto.UpgradeInfo, error)
} }
@ -34,36 +37,45 @@ func (u *UpgradeService) SearchUpgrade() (*dto.UpgradeInfo, error) {
return nil, err return nil, err
} }
versionRes, err := http.Get(fmt.Sprintf("%s/%s/latest", global.CONF.System.RepoUrl, global.CONF.System.Mode)) latestVersion, err := u.loadVersion(true, currentVersion.Value)
if err != nil { if err != nil {
global.LOG.Infof("load latest version failed, err: %v", err)
return nil, err return nil, err
} }
defer versionRes.Body.Close() if !common.CompareVersion(string(latestVersion), currentVersion.Value) {
version, err := ioutil.ReadAll(versionRes.Body) return nil, err
}
upgrade.LatestVersion = latestVersion
if latestVersion[0:4] == currentVersion.Value[0:4] {
upgrade.NewVersion = ""
} else {
newerVersion, err := u.loadVersion(false, currentVersion.Value)
if err != nil {
global.LOG.Infof("load newer version failed, err: %v", err)
return nil, err
}
if newerVersion == currentVersion.Value {
upgrade.NewVersion = ""
} else {
upgrade.NewVersion = newerVersion
}
}
notes, err := u.loadReleaseNotes(fmt.Sprintf("%s/%s/%s/release/1panel-%s-release-notes", global.CONF.System.RepoUrl, global.CONF.System.Mode, upgrade.LatestVersion, upgrade.LatestVersion))
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("load relase-notes of version %s failed, err: %v", latestVersion, err)
} }
isNew := common.CompareVersion(string(version), currentVersion.Value) upgrade.ReleaseNote = notes
if !isNew {
return nil, err
}
upgrade.NewVersion = string(version)
releaseNotes, err := http.Get(fmt.Sprintf("%s/%s/%s/release/1panel-%s-release-notes", global.CONF.System.RepoUrl, global.CONF.System.Mode, upgrade.NewVersion, upgrade.NewVersion))
if err != nil {
return nil, err
}
defer releaseNotes.Body.Close()
release, err := ioutil.ReadAll(releaseNotes.Body)
if err != nil {
return nil, err
}
upgrade.ReleaseNote = string(release)
return &upgrade, nil return &upgrade, nil
} }
func (u *UpgradeService) LoadNotes(req dto.Upgrade) (string, error) {
notes, err := u.loadReleaseNotes(fmt.Sprintf("%s/%s/%s/release/1panel-%s-release-notes", global.CONF.System.RepoUrl, global.CONF.System.Mode, req.Version, req.Version))
if err != nil {
return "", fmt.Errorf("load relase-notes of version %s failed, err: %v", req.Version, err)
}
return notes, nil
}
func (u *UpgradeService) Upgrade(req dto.Upgrade) error { func (u *UpgradeService) Upgrade(req dto.Upgrade) error {
global.LOG.Info("start to upgrade now...") global.LOG.Info("start to upgrade now...")
fileOp := files.NewFileOp() fileOp := files.NewFileOp()
@ -174,5 +186,49 @@ func (u *UpgradeService) handleRollback(fileOp files.FileOp, originalDir string,
if err := cpBinary(originalDir+"/1panel.service", "/etc/systemd/system/1panel.service"); err != nil { if err := cpBinary(originalDir+"/1panel.service", "/etc/systemd/system/1panel.service"); err != nil {
global.LOG.Errorf("rollback 1panel failed, err: %v", err) global.LOG.Errorf("rollback 1panel failed, err: %v", err)
} }
}
func (u *UpgradeService) loadVersion(isLatest bool, currentVersion string) (string, error) {
path := fmt.Sprintf("%s/%s/latest", global.CONF.System.RepoUrl, global.CONF.System.Mode)
if !isLatest {
path = fmt.Sprintf("%s/%s/latest.current", global.CONF.System.RepoUrl, global.CONF.System.Mode)
}
latestVersionRes, err := http.Get(path)
if err != nil {
return "", err
}
defer latestVersionRes.Body.Close()
version, err := ioutil.ReadAll(latestVersionRes.Body)
if err != nil {
return "", err
}
if isLatest {
return string(version), nil
}
versionMap := make(map[string]string)
if err := json.Unmarshal(version, &versionMap); err != nil {
return "", fmt.Errorf("load version map failed, err: %v", err)
}
if len(currentVersion) < 4 {
return "", fmt.Errorf("current version is error format: %s", currentVersion)
}
if version, ok := versionMap[currentVersion[0:4]]; ok {
return version, nil
}
return "", errors.New("load version failed in latest.current")
}
func (u *UpgradeService) loadReleaseNotes(path string) (string, error) {
releaseNotes, err := http.Get(path)
if err != nil {
return "", err
}
defer releaseNotes.Body.Close()
release, err := ioutil.ReadAll(releaseNotes.Body)
if err != nil {
return "", err
}
return string(release), nil
} }

View File

@ -51,6 +51,7 @@ func (s *SettingRouter) InitSettingRouter(Router *gin.RouterGroup) {
settingRouter.POST("/backup/record/del", baseApi.DeleteBackupRecord) settingRouter.POST("/backup/record/del", baseApi.DeleteBackupRecord)
settingRouter.POST("/upgrade", baseApi.Upgrade) settingRouter.POST("/upgrade", baseApi.Upgrade)
settingRouter.POST("/upgrade/notes", baseApi.GetNotesByVersion)
settingRouter.GET("/upgrade", baseApi.GetUpgradeInfo) settingRouter.GET("/upgrade", baseApi.GetUpgradeInfo)
settingRouter.GET("/basedir", baseApi.LoadBaseDir) settingRouter.GET("/basedir", baseApi.LoadBaseDir)
} }

View File

@ -6853,17 +6853,28 @@ const docTemplate = `{
"ApiKeyAuth": [] "ApiKeyAuth": []
} }
], ],
"description": "系统更新信息", "description": "获取版本 release notes",
"consumes": [
"application/json"
],
"tags": [ "tags": [
"System Setting" "System Setting"
], ],
"summary": "Load upgrade info", "summary": "Load release notes by version",
"parameters": [
{
"description": "request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.Upgrade"
}
}
],
"responses": { "responses": {
"200": { "200": {
"description": "OK", "description": ""
"schema": {
"$ref": "#/definitions/dto.UpgradeInfo"
}
} }
} }
}, },
@ -10711,6 +10722,9 @@ const docTemplate = `{
"dto.UpgradeInfo": { "dto.UpgradeInfo": {
"type": "object", "type": "object",
"properties": { "properties": {
"latestVersion": {
"type": "string"
},
"newVersion": { "newVersion": {
"type": "string" "type": "string"
}, },

View File

@ -6846,17 +6846,28 @@
"ApiKeyAuth": [] "ApiKeyAuth": []
} }
], ],
"description": "系统更新信息", "description": "获取版本 release notes",
"consumes": [
"application/json"
],
"tags": [ "tags": [
"System Setting" "System Setting"
], ],
"summary": "Load upgrade info", "summary": "Load release notes by version",
"parameters": [
{
"description": "request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.Upgrade"
}
}
],
"responses": { "responses": {
"200": { "200": {
"description": "OK", "description": ""
"schema": {
"$ref": "#/definitions/dto.UpgradeInfo"
}
} }
} }
}, },
@ -10704,6 +10715,9 @@
"dto.UpgradeInfo": { "dto.UpgradeInfo": {
"type": "object", "type": "object",
"properties": { "properties": {
"latestVersion": {
"type": "string"
},
"newVersion": { "newVersion": {
"type": "string" "type": "string"
}, },

View File

@ -1401,6 +1401,8 @@ definitions:
type: object type: object
dto.UpgradeInfo: dto.UpgradeInfo:
properties: properties:
latestVersion:
type: string
newVersion: newVersion:
type: string type: string
releaseNote: releaseNote:
@ -6983,15 +6985,22 @@ paths:
paramKeys: [] paramKeys: []
/settings/upgrade: /settings/upgrade:
get: get:
description: 系统更新信息 consumes:
- application/json
description: 获取版本 release notes
parameters:
- description: request
in: body
name: request
required: true
schema:
$ref: '#/definitions/dto.Upgrade'
responses: responses:
"200": "200":
description: OK description: ""
schema:
$ref: '#/definitions/dto.UpgradeInfo'
security: security:
- ApiKeyAuth: [] - ApiKeyAuth: []
summary: Load upgrade info summary: Load release notes by version
tags: tags:
- System Setting - System Setting
post: post:

View File

@ -82,6 +82,7 @@ export namespace Setting {
} }
export interface UpgradeInfo { export interface UpgradeInfo {
newVersion: string; newVersion: string;
latestVersion: string;
releaseNote: string; releaseNote: string;
} }
} }

View File

@ -139,6 +139,9 @@ export const searchSnapshotPage = (param: SearchWithPage) => {
export const loadUpgradeInfo = () => { export const loadUpgradeInfo = () => {
return http.get<Setting.UpgradeInfo>(`/settings/upgrade`); return http.get<Setting.UpgradeInfo>(`/settings/upgrade`);
}; };
export const loadReleaseNotes = (version: string) => {
return http.post<string>(`/settings/upgrade/notes`, { version: version });
};
export const upgrade = (version: string) => { export const upgrade = (version: string) => {
return http.post(`/settings/upgrade`, { version: version }); return http.post(`/settings/upgrade`, { version: version });
}; };

View File

@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<span class="version">{{ version }}</span> <span class="version">{{ version }}</span>
<el-button v-if="version !== 'Waiting'" type="primary" link @click="onLoadUpgradeInfo"> <el-button v-if="version !== 'Waiting'" style="margin-top: -2px" type="primary" link @click="onLoadUpgradeInfo">
{{ $t('setting.upgradeCheck') }} {{ $t('setting.upgradeCheck') }}
</el-button> </el-button>
<el-tag v-else round style="margin-left: 10px">{{ $t('setting.upgrading') }}</el-tag> <el-tag v-else round style="margin-left: 10px">{{ $t('setting.upgrading') }}</el-tag>
@ -12,10 +12,22 @@
<DrawerHeader :header="$t('setting.upgrade')" :back="handleClose" /> <DrawerHeader :header="$t('setting.upgrade')" :back="handleClose" />
</template> </template>
<div class="panel-MdEditor"> <div class="panel-MdEditor">
<el-alert :closable="false">
{{ $t('setting.versionHelper') }}
<li>{{ $t('setting.versionHelper1') }}</li>
<li>{{ $t('setting.versionHelper2') }}</li>
</el-alert>
<div class="default-theme"> <div class="default-theme">
<h2 class="inline-block">{{ $t('setting.newVersion') }}</h2> <h2 class="inline-block">{{ $t('app.version') }}</h2>
<el-tag class="inline-block tag">{{ upgradeInfo.newVersion }}</el-tag>
</div> </div>
<el-radio-group class="inline-block tag" v-model="upgradeVersion" @change="changeOption">
<el-radio v-if="upgradeInfo.newVersion" :label="upgradeInfo.newVersion">
{{ upgradeInfo.newVersion }} {{ $t('setting.newVersion') }}
</el-radio>
<el-radio :label="upgradeInfo.latestVersion">
{{ upgradeInfo.latestVersion }} {{ $t('setting.latestVersion') }}
</el-radio>
</el-radio-group>
<MdEditor v-model="upgradeInfo.releaseNote" previewOnly /> <MdEditor v-model="upgradeInfo.releaseNote" previewOnly />
</div> </div>
<template #footer> <template #footer>
@ -27,13 +39,14 @@
</el-drawer> </el-drawer>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { getSettingInfo, loadUpgradeInfo, upgrade } from '@/api/modules/setting'; import { getSettingInfo, loadReleaseNotes, loadUpgradeInfo, upgrade } from '@/api/modules/setting';
import MdEditor from 'md-editor-v3'; import MdEditor from 'md-editor-v3';
import i18n from '@/lang'; import i18n from '@/lang';
import 'md-editor-v3/lib/style.css'; import 'md-editor-v3/lib/style.css';
import { MsgSuccess } from '@/utils/message'; import { MsgSuccess } from '@/utils/message';
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
import { GlobalStore } from '@/store'; import { GlobalStore } from '@/store';
import { ElMessageBox } from 'element-plus';
const globalStore = GlobalStore(); const globalStore = GlobalStore();
const version = ref(); const version = ref();
@ -42,6 +55,8 @@ const drawerVisiable = ref(false);
const upgradeInfo = ref(); const upgradeInfo = ref();
const refresh = ref(); const refresh = ref();
const upgradeVersion = ref();
const search = async () => { const search = async () => {
const res = await getSettingInfo(); const res = await getSettingInfo();
version.value = res.data.systemVersion; version.value = res.data.systemVersion;
@ -56,12 +71,12 @@ const onLoadUpgradeInfo = async () => {
await loadUpgradeInfo() await loadUpgradeInfo()
.then((res) => { .then((res) => {
loading.value = false; loading.value = false;
if (!res.data) { if (!res.data) {
MsgSuccess(i18n.global.t('setting.noUpgrade')); MsgSuccess(i18n.global.t('setting.noUpgrade'));
return; return;
} }
upgradeInfo.value = res.data; upgradeInfo.value = res.data;
upgradeVersion.value = upgradeInfo.value.newVersion || upgradeInfo.value.latestVersion;
drawerVisiable.value = true; drawerVisiable.value = true;
}) })
.catch(() => { .catch(() => {
@ -69,6 +84,11 @@ const onLoadUpgradeInfo = async () => {
}); });
}; };
const changeOption = async () => {
const res = await loadReleaseNotes(upgradeVersion.value);
upgradeInfo.value.releaseNote = res.data;
};
const onUpgrade = async () => { const onUpgrade = async () => {
ElMessageBox.confirm(i18n.global.t('setting.upgradeHelper', i18n.global.t('setting.upgrade')), { ElMessageBox.confirm(i18n.global.t('setting.upgradeHelper', i18n.global.t('setting.upgrade')), {
confirmButtonText: i18n.global.t('commons.button.confirm'), confirmButtonText: i18n.global.t('commons.button.confirm'),
@ -76,7 +96,7 @@ const onUpgrade = async () => {
type: 'info', type: 'info',
}).then(async () => { }).then(async () => {
globalStore.isLoading = true; globalStore.isLoading = true;
await upgrade(upgradeInfo.value.newVersion); await upgrade(upgradeVersion.value);
drawerVisiable.value = false; drawerVisiable.value = false;
MsgSuccess(i18n.global.t('commons.msg.operationSuccess')); MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
search(); search();
@ -99,7 +119,6 @@ onMounted(() => {
height: calc(100vh - 330px); height: calc(100vh - 330px);
margin-left: 70px; margin-left: 70px;
.tag { .tag {
margin-left: 20px;
margin-top: -6px; margin-top: -6px;
vertical-align: middle; vertical-align: middle;
} }

View File

@ -854,7 +854,12 @@ const message = {
upgrading: 'Please wait while the upgrade is underway...', upgrading: 'Please wait while the upgrade is underway...',
upgradeHelper: 'The upgrade requires a service restart. Do you want to continue?', upgradeHelper: 'The upgrade requires a service restart. Do you want to continue?',
noUpgrade: 'It is currently the latest version', noUpgrade: 'It is currently the latest version',
newVersion: 'Latest version', versionHelper:
'Name rules: [major version].[functional version].[Bug fix version], as shown in the following example:',
versionHelper1: 'v1.0.1 is a Bug fix after v1.0.0',
versionHelper2: 'v1.1.0 is a feature release after v1.0.0',
newVersion: '(Bug fix version)',
latestVersion: '(Functional version)',
upgradeCheck: 'Check for updates', upgradeCheck: 'Check for updates',
upgradeNotes: 'Release note', upgradeNotes: 'Release note',
upgradeNow: 'Upgrade now', upgradeNow: 'Upgrade now',

View File

@ -839,7 +839,11 @@ const message = {
upgrading: '...', upgrading: '...',
upgradeHelper: '', upgradeHelper: '',
noUpgrade: '', noUpgrade: '',
newVersion: '', versionHelper: '1Panel [].[].[Bug ]',
versionHelper1: 'v1.0.1 v1.0.0 Bug ',
versionHelper2: 'v1.1.0 v1.0.0 ',
newVersion: '(Bug fix version)',
latestVersion: '()',
upgradeCheck: '', upgradeCheck: '',
upgradeNotes: '', upgradeNotes: '',
upgradeNow: '', upgradeNow: '',