mirror of https://github.com/1Panel-dev/1Panel
parent
72237596f3
commit
68a457ae89
|
@ -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 系统更新
|
||||
|
|
|
@ -82,9 +82,11 @@ type SnapshotInfo struct {
|
|||
}
|
||||
|
||||
type UpgradeInfo struct {
|
||||
NewVersion string `json:"newVersion"`
|
||||
ReleaseNote string `json:"releaseNote"`
|
||||
NewVersion string `json:"newVersion"`
|
||||
LatestVersion string `json:"latestVersion"`
|
||||
ReleaseNote string `json:"releaseNote"`
|
||||
}
|
||||
|
||||
type Upgrade struct {
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
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 {
|
||||
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)
|
||||
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)
|
||||
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
},
|
||||
|
|
|
@ -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"
|
||||
},
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -82,6 +82,7 @@ export namespace Setting {
|
|||
}
|
||||
export interface UpgradeInfo {
|
||||
newVersion: string;
|
||||
latestVersion: string;
|
||||
releaseNote: string;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 });
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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: '立即更新',
|
||||
|
|
Loading…
Reference in New Issue