mirror of https://github.com/openspug/spug
fix issue
parent
3485d36b85
commit
4e900006be
|
@ -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/<int:r_id>/', RequestDetailView.as_view()),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -192,7 +192,7 @@ export default observer(function () {
|
|||
repositories.map(item => (
|
||||
<Select.Option key={item.id} value={item.id} disabled={type === '2' && item.id >= rb_id}>
|
||||
<div style={{display: 'flex', justifyContent: 'space-between'}}>
|
||||
<span>{item.remarks ? `${item.version} (${item.remarks})` : item.version}</span>
|
||||
<span>{item.version}</span>
|
||||
<span style={{color: '#999', fontSize: 12}}>构建于 {moment(item.created_at).fromNow()}</span>
|
||||
</div>
|
||||
</Select.Option>
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
* Copyright (c) OpenSpug Organization. https://github.com/openspug/spug
|
||||
* Copyright (c) <spug.dev@gmail.com>
|
||||
* 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 (
|
||||
<Modal
|
||||
visible
|
||||
width={600}
|
||||
maskClosable={false}
|
||||
title="新建回滚发布申请"
|
||||
onCancel={() => store.rollbackVisible = false}
|
||||
confirmLoading={loading}
|
||||
onOk={handleSubmit}>
|
||||
<Form form={form} initialValues={store.record} labelCol={{span: 5}} wrapperCol={{span: 17}}>
|
||||
<Form.Item required name="name" label="申请标题">
|
||||
<Input placeholder="请输入申请标题"/>
|
||||
</Form.Item>
|
||||
<Form.Item required name="request_id" label="选择版本">
|
||||
<Select
|
||||
showSearch
|
||||
placeholder="请选择回滚至哪个版本"
|
||||
filterOption={(input, option) => includes(option.props.children, input)}>
|
||||
{store.records.filter(x => x.deploy_id === deploy_id && ['3', '-3'].includes(x.status)).map((item, index) => (
|
||||
<Select.Option key={item.id} value={item.id} record={item} disabled={index === 0}>
|
||||
<div style={{display: 'flex', justifyContent: 'space-between'}}>
|
||||
<span>{`${item.name} (${item.version})`}</span>
|
||||
<span style={{color: '#999', fontSize: 12}}>创建于 {moment(item.created_at).fromNow()}</span>
|
||||
</div>
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item required label="目标主机" tooltip="可以通过创建多个发布申请单,选择主机分批发布。">
|
||||
{host_ids.length > 0 && `已选择 ${host_ids.length} 台(可选${app_host_ids.length})`}
|
||||
<Button type="link" onClick={() => setVisible(true)}>选择主机</Button>
|
||||
</Form.Item>
|
||||
<Form.Item name="desc" label="备注信息">
|
||||
<Input placeholder="请输入备注信息"/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
{visible && <HostSelector
|
||||
host_ids={host_ids}
|
||||
app_host_ids={app_host_ids}
|
||||
onCancel={() => setVisible(false)}
|
||||
onOk={ids => setHostIds(ids)}/>}
|
||||
</Modal>
|
||||
)
|
||||
})
|
|
@ -92,18 +92,16 @@ function ComTable() {
|
|||
<Popconfirm title="确认要执行该发布申请?" onConfirm={e => handleDeploy(e, info)}>
|
||||
<Action.Button auth="deploy.request.do">发布</Action.Button>
|
||||
</Popconfirm>
|
||||
<Action.Button
|
||||
auth="deploy.request.do"
|
||||
disabled={info.type === '2'}
|
||||
onClick={() => store.rollback(info)}>回滚</Action.Button>
|
||||
{info.visible_rollback && (
|
||||
<Action.Button auth="deploy.request.do" onClick={() => store.rollback(info)}>回滚</Action.Button>
|
||||
)}
|
||||
</Action>;
|
||||
case '3':
|
||||
return <Action>
|
||||
<Action.Button auth="deploy.request.do" onClick={() => store.readConsole(info)}>查看</Action.Button>
|
||||
<Action.Button
|
||||
auth="deploy.request.do"
|
||||
disabled={info.type === '2'}
|
||||
onClick={() => store.rollback(info)}>回滚</Action.Button>
|
||||
{info.visible_rollback && (
|
||||
<Action.Button auth="deploy.request.do" onClick={() => store.rollback(info)}>回滚</Action.Button>
|
||||
)}
|
||||
</Action>;
|
||||
case '-1':
|
||||
return <Action>
|
||||
|
|
|
@ -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 && <Ext2Form/>}
|
||||
{store.batchVisible && <BatchDelete/>}
|
||||
{store.approveVisible && <Approve/>}
|
||||
{store.rollbackVisible && <Rollback/>}
|
||||
{store.tabs.length > 0 && (
|
||||
<Space className={styles.miniConsole}>
|
||||
{store.tabs.map(item => (
|
||||
|
|
|
@ -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) => {
|
||||
|
|
Loading…
Reference in New Issue