1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-01-19 08:19:15 +08:00

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

fix: 升级逻辑调整
This commit is contained in:
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)
}
// @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
// @Summary Upgrade
// @Description 系统更新

View File

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

View File

@ -1,6 +1,8 @@
package service
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
@ -20,6 +22,7 @@ type UpgradeService struct{}
type IUpgradeService interface {
Upgrade(req dto.Upgrade) error
LoadNotes(req dto.Upgrade) (string, error)
SearchUpgrade() (*dto.UpgradeInfo, error)
}
@ -34,36 +37,45 @@ func (u *UpgradeService) SearchUpgrade() (*dto.UpgradeInfo, error) {
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 {
global.LOG.Infof("load latest version failed, err: %v", err)
return nil, err
}
defer versionRes.Body.Close()
version, err := ioutil.ReadAll(versionRes.Body)
if !common.CompareVersion(string(latestVersion), currentVersion.Value) {
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
}
isNew := common.CompareVersion(string(version), currentVersion.Value)
if !isNew {
return nil, err
if newerVersion == currentVersion.Value {
upgrade.NewVersion = ""
} else {
upgrade.NewVersion = newerVersion
}
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))
}
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 {
return nil, err
return nil, fmt.Errorf("load relase-notes of version %s failed, err: %v", latestVersion, err)
}
defer releaseNotes.Body.Close()
release, err := ioutil.ReadAll(releaseNotes.Body)
if err != nil {
return nil, err
}
upgrade.ReleaseNote = string(release)
upgrade.ReleaseNote = notes
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 {
global.LOG.Info("start to upgrade now...")
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 {
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("/upgrade", baseApi.Upgrade)
settingRouter.POST("/upgrade/notes", baseApi.GetNotesByVersion)
settingRouter.GET("/upgrade", baseApi.GetUpgradeInfo)
settingRouter.GET("/basedir", baseApi.LoadBaseDir)
}

View File

@ -6853,17 +6853,28 @@ const docTemplate = `{
"ApiKeyAuth": []
}
],
"description": "系统更新信息",
"description": "获取版本 release notes",
"consumes": [
"application/json"
],
"tags": [
"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": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/dto.UpgradeInfo"
}
"description": ""
}
}
},
@ -10711,6 +10722,9 @@ const docTemplate = `{
"dto.UpgradeInfo": {
"type": "object",
"properties": {
"latestVersion": {
"type": "string"
},
"newVersion": {
"type": "string"
},

View File

@ -6846,17 +6846,28 @@
"ApiKeyAuth": []
}
],
"description": "系统更新信息",
"description": "获取版本 release notes",
"consumes": [
"application/json"
],
"tags": [
"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": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/dto.UpgradeInfo"
}
"description": ""
}
}
},
@ -10704,6 +10715,9 @@
"dto.UpgradeInfo": {
"type": "object",
"properties": {
"latestVersion": {
"type": "string"
},
"newVersion": {
"type": "string"
},

View File

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

View File

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

View File

@ -139,6 +139,9 @@ export const searchSnapshotPage = (param: SearchWithPage) => {
export const loadUpgradeInfo = () => {
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) => {
return http.post(`/settings/upgrade`, { version: version });
};

View File

@ -1,7 +1,7 @@
<template>
<div>
<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') }}
</el-button>
<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" />
</template>
<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">
<h2 class="inline-block">{{ $t('setting.newVersion') }}</h2>
<el-tag class="inline-block tag">{{ upgradeInfo.newVersion }}</el-tag>
<h2 class="inline-block">{{ $t('app.version') }}</h2>
</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 />
</div>
<template #footer>
@ -27,13 +39,14 @@
</el-drawer>
</template>
<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 i18n from '@/lang';
import 'md-editor-v3/lib/style.css';
import { MsgSuccess } from '@/utils/message';
import { onMounted, ref } from 'vue';
import { GlobalStore } from '@/store';
import { ElMessageBox } from 'element-plus';
const globalStore = GlobalStore();
const version = ref();
@ -42,6 +55,8 @@ const drawerVisiable = ref(false);
const upgradeInfo = ref();
const refresh = ref();
const upgradeVersion = ref();
const search = async () => {
const res = await getSettingInfo();
version.value = res.data.systemVersion;
@ -56,12 +71,12 @@ const onLoadUpgradeInfo = async () => {
await loadUpgradeInfo()
.then((res) => {
loading.value = false;
if (!res.data) {
MsgSuccess(i18n.global.t('setting.noUpgrade'));
return;
}
upgradeInfo.value = res.data;
upgradeVersion.value = upgradeInfo.value.newVersion || upgradeInfo.value.latestVersion;
drawerVisiable.value = true;
})
.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 () => {
ElMessageBox.confirm(i18n.global.t('setting.upgradeHelper', i18n.global.t('setting.upgrade')), {
confirmButtonText: i18n.global.t('commons.button.confirm'),
@ -76,7 +96,7 @@ const onUpgrade = async () => {
type: 'info',
}).then(async () => {
globalStore.isLoading = true;
await upgrade(upgradeInfo.value.newVersion);
await upgrade(upgradeVersion.value);
drawerVisiable.value = false;
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
search();
@ -99,7 +119,6 @@ onMounted(() => {
height: calc(100vh - 330px);
margin-left: 70px;
.tag {
margin-left: 20px;
margin-top: -6px;
vertical-align: middle;
}

View File

@ -854,7 +854,12 @@ const message = {
upgrading: 'Please wait while the upgrade is underway...',
upgradeHelper: 'The upgrade requires a service restart. Do you want to continue?',
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',
upgradeNotes: 'Release note',
upgradeNow: 'Upgrade now',

View File

@ -839,7 +839,11 @@ const message = {
upgrading: '正在升级中请稍候...',
upgradeHelper: '升级操作需要重启服务是否继续',
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: '检查更新',
upgradeNotes: '更新内容',
upgradeNow: '立即更新',