diff --git a/spug_api/apps/deploy/urls.py b/spug_api/apps/deploy/urls.py index c93cd7e..1fdb7be 100644 --- a/spug_api/apps/deploy/urls.py +++ b/spug_api/apps/deploy/urls.py @@ -8,6 +8,7 @@ from .views import * urlpatterns = [ path('request/', RequestView.as_view()), path('request/ext1/', post_request_ext1), + path('request/ext1/rollback/', post_request_ext1_rollback), path('request/ext2/', post_request_ext2), path('request/upload/', do_upload), path('request//', RequestDetailView.as_view()), diff --git a/spug_api/apps/deploy/views.py b/spug_api/apps/deploy/views.py index 8d8c9f2..7bef9ec 100644 --- a/spug_api/apps/deploy/views.py +++ b/spug_api/apps/deploy/views.py @@ -22,7 +22,7 @@ import os class RequestView(View): def get(self, request): - data, query = [], {} + data, query, counter = [], {}, {} if not request.user.is_supper: perms = request.user.deploy_perms query['deploy__app_id__in'] = perms['apps'] @@ -48,6 +48,9 @@ class RequestView(View): tmp['app_host_ids'] = json.loads(item.app_host_ids) tmp['status_alias'] = item.get_status_display() tmp['created_by_user'] = item.created_by_user + if item.app_extend == '1': + tmp['visible_rollback'] = item.deploy_id not in counter + counter[item.deploy_id] = True data.append(tmp) return json_response(data) @@ -261,6 +264,37 @@ def post_request_ext1(request): return json_response(error=error) +def post_request_ext1_rollback(request): + form, error = JsonParser( + Argument('request_id', type=int, help='参数错误'), + Argument('name', help='请输入申请标题'), + Argument('host_ids', type=list, filter=lambda x: len(x), help='请选择要部署的主机'), + Argument('desc', required=False), + ).parse(request.body) + if error is None: + req = DeployRequest.objects.get(pk=form.pop('request_id')) + requests = DeployRequest.objects.filter(deploy=req.deploy, status__in=('3', '-3')) + versions = list({x.spug_version: 1 for x in requests}.keys()) + if req.spug_version not in versions[:req.deploy.extend_obj.versions + 1]: + return json_response(error='选择的版本超出了发布配置中设置的版本数量,无法快速回滚,可通过新建发布申请选择构建仓库里的该版本再次发布。') + + form.status = '0' if req.deploy.is_audit else '1' + form.host_ids = json.dumps(sorted(form.host_ids)) + new_req = DeployRequest.objects.create( + deploy_id=req.deploy_id, + repository_id=req.repository_id, + type='2', + extra=req.extra, + version=req.version, + spug_version=req.spug_version, + created_by=request.user, + **form + ) + if req.deploy.is_audit: + Thread(target=Helper.send_deploy_notify, args=(new_req, 'approve_req')).start() + return json_response(error=error) + + def post_request_ext2(request): form, error = JsonParser( Argument('id', type=int, required=False), diff --git a/spug_web/src/pages/deploy/request/Ext1Form.js b/spug_web/src/pages/deploy/request/Ext1Form.js index 740ab10..f28c990 100644 --- a/spug_web/src/pages/deploy/request/Ext1Form.js +++ b/spug_web/src/pages/deploy/request/Ext1Form.js @@ -192,7 +192,7 @@ export default observer(function () { repositories.map(item => ( = rb_id}>
- {item.remarks ? `${item.version} (${item.remarks})` : item.version} + {item.version} 构建于 {moment(item.created_at).fromNow()}
diff --git a/spug_web/src/pages/deploy/request/Rollback.js b/spug_web/src/pages/deploy/request/Rollback.js new file mode 100644 index 0000000..bf2d8fd --- /dev/null +++ b/spug_web/src/pages/deploy/request/Rollback.js @@ -0,0 +1,88 @@ +/** + * Copyright (c) OpenSpug Organization. https://github.com/openspug/spug + * Copyright (c) + * Released under the AGPL-3.0 License. + */ +import React, { useState, useEffect } from 'react'; +import { observer } from 'mobx-react'; +import { Modal, Form, Input, Select, Button, message } from 'antd'; +import HostSelector from './HostSelector'; +import hostStore from 'pages/host/store'; +import { http, includes } from 'libs'; +import store from './store'; +import lds from 'lodash'; +import moment from 'moment'; + +export default observer(function () { + const [form] = Form.useForm(); + const [visible, setVisible] = useState(false); + const [loading, setLoading] = useState(false); + const [host_ids, setHostIds] = useState([]); + + useEffect(() => { + const {app_host_ids, host_ids} = store.record; + setHostIds(lds.clone(host_ids || app_host_ids)); + if (!hostStore.records || hostStore.records.length === 0) hostStore.fetchRecords() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + function handleSubmit() { + if (host_ids.length === 0) { + return message.error('请至少选择一个要发布的主机') + } + setLoading(true); + const formData = form.getFieldsValue(); + formData['host_ids'] = host_ids; + http.post('/api/deploy/request/ext1/rollback/', formData) + .then(res => { + message.success('操作成功'); + store.rollbackVisible = false; + store.fetchRecords() + }, () => setLoading(false)) + } + + const {app_host_ids, deploy_id} = store.record; + return ( + store.rollbackVisible = false} + confirmLoading={loading} + onOk={handleSubmit}> +
+ + + + + + + + {host_ids.length > 0 && `已选择 ${host_ids.length} 台(可选${app_host_ids.length})`} + + + + + +
+ {visible && setVisible(false)} + onOk={ids => setHostIds(ids)}/>} +
+ ) +}) \ No newline at end of file diff --git a/spug_web/src/pages/deploy/request/Table.js b/spug_web/src/pages/deploy/request/Table.js index 1b6d1c5..10c7fe6 100644 --- a/spug_web/src/pages/deploy/request/Table.js +++ b/spug_web/src/pages/deploy/request/Table.js @@ -92,18 +92,16 @@ function ComTable() { handleDeploy(e, info)}> 发布 - store.rollback(info)}>回滚 + {info.visible_rollback && ( + store.rollback(info)}>回滚 + )} ; case '3': return store.readConsole(info)}>查看 - store.rollback(info)}>回滚 + {info.visible_rollback && ( + store.rollback(info)}>回滚 + )} ; case '-1': return diff --git a/spug_web/src/pages/deploy/request/index.js b/spug_web/src/pages/deploy/request/index.js index 0298f01..4428e11 100644 --- a/spug_web/src/pages/deploy/request/index.js +++ b/spug_web/src/pages/deploy/request/index.js @@ -15,6 +15,7 @@ import ComTable from './Table'; import Ext1Console from './Ext1Console'; import Ext2Console from './Ext2Console'; import BatchDelete from './BatchDelete'; +import Rollback from './Rollback'; import { includes } from 'libs'; import envStore from 'pages/config/environment/store'; import appStore from 'pages/config/app/store'; @@ -86,6 +87,7 @@ function Index() { {store.ext2Visible && } {store.batchVisible && } {store.approveVisible && } + {store.rollbackVisible && } {store.tabs.length > 0 && ( {store.tabs.map(item => ( diff --git a/spug_web/src/pages/deploy/request/store.js b/spug_web/src/pages/deploy/request/store.js index 4a1b27f..d25f712 100644 --- a/spug_web/src/pages/deploy/request/store.js +++ b/spug_web/src/pages/deploy/request/store.js @@ -21,6 +21,7 @@ class Store { @observable ext2Visible = false; @observable batchVisible = false; @observable approveVisible = false; + @observable rollbackVisible = false; @observable f_status = 'all'; @observable f_app_id; @@ -96,15 +97,10 @@ class Store { }; rollback = (info) => { - this.record = lds.pick(info, ['deploy_id', 'app_host_ids', 'host_ids']); - this.record.type = '2'; - this.record.rb_id = info.repository_id; + this.record = lds.pick(info, ['deploy_id', 'host_ids']); + this.record.app_host_ids = info.host_ids; this.record.name = `${info.name} - 回滚`; - if (info.app_extend === '1') { - this.ext1Visible = true - } else { - this.ext2Visible = true - } + this.rollbackVisible = true } showForm = (info) => {