mirror of https://github.com/openspug/spug
A 发布配置路径和过滤规则支持使用全局变量
parent
348de8c36b
commit
95952f9348
|
@ -1,9 +1,7 @@
|
||||||
# Copyright: (c) OpenSpug Organization. https://github.com/openspug/spug
|
# Copyright: (c) OpenSpug Organization. https://github.com/openspug/spug
|
||||||
# Copyright: (c) <spug.dev@gmail.com>
|
# Copyright: (c) <spug.dev@gmail.com>
|
||||||
# Released under the AGPL-3.0 License.
|
# Released under the AGPL-3.0 License.
|
||||||
from django_redis import get_redis_connection
|
from libs.utils import human_datetime, render_str
|
||||||
from django.conf import settings
|
|
||||||
from libs.utils import human_datetime
|
|
||||||
from libs.spug import Notification
|
from libs.spug import Notification
|
||||||
from apps.host.models import Host
|
from apps.host.models import Host
|
||||||
import subprocess
|
import subprocess
|
||||||
|
@ -208,13 +206,13 @@ class Helper:
|
||||||
def add_callback(self, func):
|
def add_callback(self, func):
|
||||||
self.callback.append(func)
|
self.callback.append(func)
|
||||||
|
|
||||||
def parse_filter_rule(self, data: str, sep='\n'):
|
def parse_filter_rule(self, data: str, sep='\n', env=None):
|
||||||
data, files = data.strip(), []
|
data, files = data.strip(), []
|
||||||
if data:
|
if data:
|
||||||
for line in data.split(sep):
|
for line in data.split(sep):
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
if line and not line.startswith('#'):
|
if line and not line.startswith('#'):
|
||||||
files.append(line)
|
files.append(render_str(line, env))
|
||||||
return files
|
return files
|
||||||
|
|
||||||
def _send(self, message):
|
def _send(self, message):
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
from django_redis import get_redis_connection
|
from django_redis import get_redis_connection
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import close_old_connections
|
from django.db import close_old_connections
|
||||||
from libs.utils import AttrDict, human_time
|
from libs.utils import AttrDict, human_time, render_str
|
||||||
from apps.host.models import Host
|
from apps.host.models import Host
|
||||||
from apps.config.utils import compose_configs
|
from apps.config.utils import compose_configs
|
||||||
from apps.repository.models import Repository
|
from apps.repository.models import Repository
|
||||||
|
@ -74,8 +74,6 @@ def _ext1_deploy(req, helper, env):
|
||||||
)
|
)
|
||||||
build_repository(rep, helper)
|
build_repository(rep, helper)
|
||||||
req.repository = rep
|
req.repository = rep
|
||||||
extend = req.deploy.extend_obj
|
|
||||||
env.update(SPUG_DST_DIR=extend.dst_dir)
|
|
||||||
extras = json.loads(req.extra)
|
extras = json.loads(req.extra)
|
||||||
if extras[0] == 'repository':
|
if extras[0] == 'repository':
|
||||||
extras = extras[1:]
|
extras = extras[1:]
|
||||||
|
@ -127,22 +125,25 @@ def _ext2_deploy(req, helper, env):
|
||||||
helper.send_step('local', step, f'{human_time()} {action["title"]}...\r\n')
|
helper.send_step('local', step, f'{human_time()} {action["title"]}...\r\n')
|
||||||
helper.local(f'cd /tmp && {action["data"]}', env)
|
helper.local(f'cd /tmp && {action["data"]}', env)
|
||||||
step += 1
|
step += 1
|
||||||
helper.send_step('local', 100, '')
|
|
||||||
|
|
||||||
for action in host_actions:
|
for action in host_actions:
|
||||||
if action.get('type') == 'transfer':
|
if action.get('type') == 'transfer':
|
||||||
|
action['src'] = render_str(action['src'].strip().rstrip('/'), env)
|
||||||
|
action['dst'] = render_str(action['dst'].strip().rstrip('/'), env)
|
||||||
if action.get('src_mode') == '1':
|
if action.get('src_mode') == '1':
|
||||||
break
|
break
|
||||||
helper.send_info('local', f'{human_time()} 检测到来源为本地路径的数据传输动作,执行打包... \r\n')
|
helper.send_step('local', step, f'{human_time()} 检测到来源为本地路径的数据传输动作,执行打包... \r\n')
|
||||||
action['src'] = action['src'].rstrip('/ ')
|
action['src'] = action['src'].rstrip('/ ')
|
||||||
action['dst'] = action['dst'].rstrip('/ ')
|
action['dst'] = action['dst'].rstrip('/ ')
|
||||||
if not action['src'] or not action['dst']:
|
if not action['src'] or not action['dst']:
|
||||||
helper.send_error('local', f'invalid path for transfer, src: {action["src"]} dst: {action["dst"]}')
|
helper.send_error('local', f'Invalid path for transfer, src: {action["src"]} dst: {action["dst"]}')
|
||||||
|
if not os.path.exists(action['src']):
|
||||||
|
helper.send_error('local', f'No such file or directory: {action["src"]}')
|
||||||
is_dir, exclude = os.path.isdir(action['src']), ''
|
is_dir, exclude = os.path.isdir(action['src']), ''
|
||||||
sp_dir, sd_dst = os.path.split(action['src'])
|
sp_dir, sd_dst = os.path.split(action['src'])
|
||||||
contain = sd_dst
|
contain = sd_dst
|
||||||
if action['mode'] != '0' and is_dir:
|
if action['mode'] != '0' and is_dir:
|
||||||
files = helper.parse_filter_rule(action['rule'], ',')
|
files = helper.parse_filter_rule(action['rule'], ',', env)
|
||||||
if files:
|
if files:
|
||||||
if action['mode'] == '1':
|
if action['mode'] == '1':
|
||||||
contain = ' '.join(f'{sd_dst}/{x}' for x in files)
|
contain = ' '.join(f'{sd_dst}/{x}' for x in files)
|
||||||
|
@ -159,6 +160,8 @@ def _ext2_deploy(req, helper, env):
|
||||||
helper.send_info('local', f'{human_time()} \033[32m完成√\033[0m\r\n')
|
helper.send_info('local', f'{human_time()} \033[32m完成√\033[0m\r\n')
|
||||||
helper.add_callback(partial(os.remove, os.path.join(sp_dir, tar_gz_file)))
|
helper.add_callback(partial(os.remove, os.path.join(sp_dir, tar_gz_file)))
|
||||||
break
|
break
|
||||||
|
helper.send_step('local', 100, '')
|
||||||
|
|
||||||
if host_actions:
|
if host_actions:
|
||||||
if req.deploy.is_parallel:
|
if req.deploy.is_parallel:
|
||||||
threads, latest_exception = [], None
|
threads, latest_exception = [], None
|
||||||
|
@ -194,12 +197,15 @@ def _ext2_deploy(req, helper, env):
|
||||||
|
|
||||||
|
|
||||||
def _deploy_ext1_host(req, helper, h_id, env):
|
def _deploy_ext1_host(req, helper, h_id, env):
|
||||||
extend = req.deploy.extend_obj
|
|
||||||
helper.send_step(h_id, 1, f'\033[32m就绪√\033[0m\r\n{human_time()} 数据准备... ')
|
helper.send_step(h_id, 1, f'\033[32m就绪√\033[0m\r\n{human_time()} 数据准备... ')
|
||||||
host = Host.objects.filter(pk=h_id).first()
|
host = Host.objects.filter(pk=h_id).first()
|
||||||
if not host:
|
if not host:
|
||||||
helper.send_error(h_id, 'no such host')
|
helper.send_error(h_id, 'no such host')
|
||||||
env.update({'SPUG_HOST_ID': h_id, 'SPUG_HOST_NAME': host.hostname})
|
env.update({'SPUG_HOST_ID': h_id, 'SPUG_HOST_NAME': host.hostname})
|
||||||
|
extend = req.deploy.extend_obj
|
||||||
|
extend.dst_dir = render_str(extend.dst_dir, env)
|
||||||
|
extend.dst_repo = render_str(extend.dst_repo, env)
|
||||||
|
env.update(SPUG_DST_DIR=extend.dst_dir)
|
||||||
with host.get_ssh(default_env=env) as ssh:
|
with host.get_ssh(default_env=env) as ssh:
|
||||||
base_dst_dir = os.path.dirname(extend.dst_dir)
|
base_dst_dir = os.path.dirname(extend.dst_dir)
|
||||||
code, _ = ssh.exec_command_raw(
|
code, _ = ssh.exec_command_raw(
|
||||||
|
|
|
@ -159,9 +159,11 @@ class RequestDetailView(View):
|
||||||
outputs['local'] = {'id': 'local', 'step': 0, 'data': f'{human_time()} 建立连接... '}
|
outputs['local'] = {'id': 'local', 'step': 0, 'data': f'{human_time()} 建立连接... '}
|
||||||
if req.deploy.extend == '2':
|
if req.deploy.extend == '2':
|
||||||
outputs['local'] = {'id': 'local', 'step': 0, 'data': f'{human_time()} 建立连接... '}
|
outputs['local'] = {'id': 'local', 'step': 0, 'data': f'{human_time()} 建立连接... '}
|
||||||
if req.deploy.extend == '2':
|
|
||||||
s_actions = json.loads(req.deploy.extend_obj.server_actions)
|
s_actions = json.loads(req.deploy.extend_obj.server_actions)
|
||||||
h_actions = json.loads(req.deploy.extend_obj.host_actions)
|
h_actions = json.loads(req.deploy.extend_obj.host_actions)
|
||||||
|
for item in h_actions:
|
||||||
|
if item.get('type') == 'transfer' and item.get('src_mode') == '0':
|
||||||
|
s_actions.append({'title': '执行打包'})
|
||||||
if not h_actions:
|
if not h_actions:
|
||||||
outputs = {'local': outputs['local']}
|
outputs = {'local': outputs['local']}
|
||||||
return json_response({'s_actions': s_actions, 'h_actions': h_actions, 'outputs': outputs})
|
return json_response({'s_actions': s_actions, 'h_actions': h_actions, 'outputs': outputs})
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
from django_redis import get_redis_connection
|
from django_redis import get_redis_connection
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import close_old_connections
|
from django.db import close_old_connections
|
||||||
from libs.utils import AttrDict, human_time
|
from libs.utils import AttrDict, human_time, render_str
|
||||||
from apps.repository.models import Repository
|
from apps.repository.models import Repository
|
||||||
from apps.app.utils import fetch_repo
|
from apps.app.utils import fetch_repo
|
||||||
from apps.config.utils import compose_configs
|
from apps.config.utils import compose_configs
|
||||||
|
@ -68,13 +68,13 @@ def _build(rep: Repository, helper, env):
|
||||||
git_dir = os.path.join(REPOS_DIR, str(rep.deploy_id))
|
git_dir = os.path.join(REPOS_DIR, str(rep.deploy_id))
|
||||||
build_dir = os.path.join(REPOS_DIR, rep.spug_version)
|
build_dir = os.path.join(REPOS_DIR, rep.spug_version)
|
||||||
tar_file = os.path.join(BUILD_DIR, f'{rep.spug_version}.tar.gz')
|
tar_file = os.path.join(BUILD_DIR, f'{rep.spug_version}.tar.gz')
|
||||||
env.update(SPUG_DST_DIR=extend.dst_dir)
|
|
||||||
if extras[0] == 'branch':
|
if extras[0] == 'branch':
|
||||||
tree_ish = extras[2]
|
tree_ish = extras[2]
|
||||||
env.update(SPUG_GIT_BRANCH=extras[1], SPUG_GIT_COMMIT_ID=extras[2])
|
env.update(SPUG_GIT_BRANCH=extras[1], SPUG_GIT_COMMIT_ID=extras[2])
|
||||||
else:
|
else:
|
||||||
tree_ish = extras[1]
|
tree_ish = extras[1]
|
||||||
env.update(SPUG_GIT_TAG=extras[1])
|
env.update(SPUG_GIT_TAG=extras[1])
|
||||||
|
env.update(SPUG_DST_DIR=render_str(extend.dst_dir, env))
|
||||||
fetch_repo(rep.deploy_id, extend.git_repo)
|
fetch_repo(rep.deploy_id, extend.git_repo)
|
||||||
helper.send_info('local', '\033[32m完成√\033[0m\r\n')
|
helper.send_info('local', '\033[32m完成√\033[0m\r\n')
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ def _build(rep: Repository, helper, env):
|
||||||
|
|
||||||
helper.send_step('local', 4, f'\r\n{human_time()} 执行打包... ')
|
helper.send_step('local', 4, f'\r\n{human_time()} 执行打包... ')
|
||||||
filter_rule, exclude, contain = json.loads(extend.filter_rule), '', rep.spug_version
|
filter_rule, exclude, contain = json.loads(extend.filter_rule), '', rep.spug_version
|
||||||
files = helper.parse_filter_rule(filter_rule['data'])
|
files = helper.parse_filter_rule(filter_rule['data'], env=env)
|
||||||
if files:
|
if files:
|
||||||
if filter_rule['type'] == 'exclude':
|
if filter_rule['type'] == 'exclude':
|
||||||
excludes = []
|
excludes = []
|
||||||
|
|
|
@ -5,6 +5,7 @@ from django.http.response import HttpResponse
|
||||||
from django.db.models import QuerySet
|
from django.db.models import QuerySet
|
||||||
from datetime import datetime, date as datetime_date
|
from datetime import datetime, date as datetime_date
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
from string import Template
|
||||||
import string
|
import string
|
||||||
import random
|
import random
|
||||||
import json
|
import json
|
||||||
|
@ -62,6 +63,11 @@ def human_diff_time(time1, time2):
|
||||||
return '%d天%s' % (delta.days, text) if delta.days else text
|
return '%d天%s' % (delta.days, text) if delta.days else text
|
||||||
|
|
||||||
|
|
||||||
|
# 字符串模版渲染
|
||||||
|
def render_str(template, datasheet):
|
||||||
|
return Template(template).safe_substitute(datasheet)
|
||||||
|
|
||||||
|
|
||||||
def json_response(data='', error=''):
|
def json_response(data='', error=''):
|
||||||
content = AttrDict(data=data, error=error)
|
content = AttrDict(data=data, error=error)
|
||||||
if error:
|
if error:
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -90,12 +91,6 @@
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
color: #1890ff;
|
color: #1890ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon {
|
|
||||||
font-size: 22px;
|
|
||||||
font-weight: 300;
|
|
||||||
color: #1890ff;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue