From 6ebb396947f2d4b835149b0c0ebc73c6932b3a3a Mon Sep 17 00:00:00 2001 From: asyu17 Date: Tue, 8 Jun 2021 14:49:49 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20playbook?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/playbook/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/playbook/.keep diff --git a/apps/playbook/.keep b/apps/playbook/.keep new file mode 100644 index 0000000..e69de29 -- Gitee From 8ca68e98b4b866fd327139dea1a2ec604b1db9dc Mon Sep 17 00:00:00 2001 From: asyu17 Date: Tue, 8 Jun 2021 15:43:11 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E8=B0=83=E7=94=A8=E5=89=A7=E6=9C=ACapp=20?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=86=85=E5=AE=B9=EF=BC=9A=E5=8F=AF=E5=9C=A8?= =?UTF-8?q?=E4=B8=80=E5=89=A7=E6=9C=AC=E5=86=85=E5=AF=B9=E5=8F=A6=E4=B8=80?= =?UTF-8?q?=E5=89=A7=E6=9C=AC=E5=86=85=E7=9A=84=E5=A4=9Aapp=E3=80=81?= =?UTF-8?q?=E5=A4=9A=E5=8F=82=E6=95=B0=E8=BF=9B=E8=A1=8C=E8=B5=8B=E5=80=BC?= =?UTF-8?q?=EF=BC=8C=E5=B9=B6=E6=9C=80=E7=BB=88=E8=8E=B7=E5=8F=96=E8=BF=99?= =?UTF-8?q?=E4=BA=9Bapp=E7=9A=84=E8=BF=94=E5=9B=9E=E7=BB=93=E6=9E=9C?= =?UTF-8?q?=E3=80=82=20=E5=8F=82=E6=95=B0=E8=AF=B4=E6=98=8E=EF=BC=9A=20uui?= =?UTF-8?q?d=EF=BC=9A=E7=9B=AE=E6=A0=87=E5=89=A7=E6=9C=ACuuid=EF=BC=8C?= =?UTF-8?q?=E7=A4=BA=E4=BE=8B=EF=BC=9A59c88704-c694-11eb-8ebe-0242ac110003?= =?UTF-8?q?=20app=5Fuuids=EF=BC=9A=E7=9B=AE=E6=A0=87=E5=89=A7=E6=9C=AC?= =?UTF-8?q?=E5=86=85=E7=9A=84app=5Fuuid=E9=9B=86=E5=90=88=EF=BC=8C?= =?UTF-8?q?=E7=A4=BA=E4=BE=8B=EF=BC=9A[61eaa840-c694-11eb-b241-23cb919a2e2?= =?UTF-8?q?9,eff61240-c695-11eb-b241-23cb919a2e29]=20func=5Fnum=EF=BC=9A?= =?UTF-8?q?=E7=9B=AE=E6=A0=87app=E5=86=85=E7=BD=AE=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E7=9A=84=E9=A1=BA=E5=BA=8F=E5=8F=B7=EF=BC=8C=E7=A4=BA=E4=BE=8B?= =?UTF-8?q?=EF=BC=9A[0,0]=20datas=EF=BC=9A=E4=B8=BA=E7=9B=AE=E6=A0=87?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E8=B5=8B=E5=80=BC=EF=BC=8C=E7=A4=BA=E4=BE=8B?= =?UTF-8?q?=EF=BC=9A[[12312345],[123123]]=20overtime=EF=BC=9A=E7=9B=AE?= =?UTF-8?q?=E6=A0=87=E5=89=A7=E6=9C=AC=E8=BF=90=E8=A1=8C=E8=B6=85=E6=97=B6?= =?UTF-8?q?=E6=97=B6=E9=97=B4=EF=BC=8C=E5=8D=95=E4=BD=8D=E7=A7=92=EF=BC=8C?= =?UTF-8?q?=E7=A4=BA=E4=BE=8B=EF=BC=9A20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 注:对目标剧本app参数的修改,会保留在目标剧本中。 若是仅想获取某一app返回结果,则只填app_uuids,而不填datas --- apps/playbook/app.json | 43 +++++++++ apps/playbook/icon.png | Bin 0 -> 28458 bytes apps/playbook/linux/__init__.py | 6 ++ apps/playbook/linux/run.py | 144 ++++++++++++++++++++++++++++++ apps/playbook/mac/__init__.py | 6 ++ apps/playbook/mac/run.py | 144 ++++++++++++++++++++++++++++++ apps/playbook/readme.md | 25 ++++++ apps/playbook/windows/__init__.py | 6 ++ apps/playbook/windows/run.py | 144 ++++++++++++++++++++++++++++++ 9 files changed, 518 insertions(+) create mode 100644 apps/playbook/app.json create mode 100644 apps/playbook/icon.png create mode 100644 apps/playbook/linux/__init__.py create mode 100644 apps/playbook/linux/run.py create mode 100644 apps/playbook/mac/__init__.py create mode 100644 apps/playbook/mac/run.py create mode 100644 apps/playbook/readme.md create mode 100644 apps/playbook/windows/__init__.py create mode 100644 apps/playbook/windows/run.py diff --git a/apps/playbook/app.json b/apps/playbook/app.json new file mode 100644 index 0000000..65c60cf --- /dev/null +++ b/apps/playbook/app.json @@ -0,0 +1,43 @@ +{ + "identification": "w5soar", + "is_public": true, + "name": "调用剧本", + "version": "0.1", + "description": "调用剧本", + "type": "调用剧本", + "action": [ + { + "name": "执行剧本", + "func": "exec_play_book" + } + ], + "args": { + "exec_play_book": [ + { + "key": "uuid", + "type": "text", + "required": true + }, + { + "key": "app_uuids", + "type": "text", + "required": false + }, + { + "key": "func_num", + "type": "number", + "required": false + }, + { + "key": "datas", + "type": "text", + "required": false + }, + { + "key": "overtime", + "type": "text", + "required": false + } + ] + } +} \ No newline at end of file diff --git a/apps/playbook/icon.png b/apps/playbook/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..8540c7d56e6c5a8ef750ceb82a19a6a24cf7a429 GIT binary patch literal 28458 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 literal 0 HcmV?d00001 diff --git a/apps/playbook/linux/__init__.py b/apps/playbook/linux/__init__.py new file mode 100644 index 0000000..a505ad1 --- /dev/null +++ b/apps/playbook/linux/__init__.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python +# _*_ coding: utf-8 _*_ +# @Time : 2021/6/3 11:58 +# @Author : asyu17 +# @File : __init__.py.py +# @Version : 1.0 \ No newline at end of file diff --git a/apps/playbook/linux/run.py b/apps/playbook/linux/run.py new file mode 100644 index 0000000..839209d --- /dev/null +++ b/apps/playbook/linux/run.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python +# _*_ coding: utf-8 _*_ +# @Time : 2021/6/3 11:58 +# @Author : asyu17 +# @File : run.py +# @Version : 1.0 + + +import platform +import os +import sys +import json +import threading +import asyncio + +from loguru import logger + + +def my_auto_execute(uuid, Auto): + def thread_exec(): + async def run(): + await asyncio.gather(Auto.run(uuid=uuid)) + + try: + asyncio.run(run()) + except RuntimeError: + asyncio.gather(Auto.run(uuid=uuid)) + + t = threading.Thread(target=thread_exec) + t.setDaemon(True) + t.start() + + +async def exec_play_book(uuid, app_uuids='', func_num='', datas='', overtime='10'): + # app_uuids 格式:[app1,app2] + # func_num 是指目标函数为目标app的第几个函数,从0开始计算 + # datas 格式:[[data1]],[data2]] + # overtime 是设置目标剧本执行的超时时间 + + logger.info("[Exec-Play-Book] APP执行参数为: {uuid} ", uuid=uuid) + try: + app_uuids = app_uuids.strip(',[]').split(',') + func_num = func_num.strip(',[]').split(',') + datas = datas[1:-1].strip(',').split(',') + overtime = int(overtime) * 2 + for i in range(len(datas)): + datas[i] = datas[i].strip(',[]').split(',') + if app_uuids[0] == '': + app_uuids = [] + if func_num == '': + func_num = [0] * len(app_uuids) + for i in range(len(func_num)): + func_num[i] = int(func_num[i]) + if datas[0] == '': + datas = [[]] + if len(func_num) != len(app_uuids): + logger.error("[Exec-Play-Book] 函数序号无法与app_uuids匹配!") + return {"status": 1, "result": "函数序号无法与app_uuids匹配!"} + except Exception as e: + logger.error("[Exec-Play-Book] 传入参数格式有误:{e}", e=e) + return {"status": 2, "result": "传入参数格式有误!"} + current_path = sys.path[0] + path = current_path + for i in range(3): + path = os.path.dirname(path) + sys.path[0] = path + # —————————————————————— 导入依赖core模块 —————————————————————— + os.chdir(path) + try: + if platform.system() == 'Windows': + from core.auto.windows.core import Auto + elif platform.system() == 'Linux': + from core.auto.linux.core import Auto + elif platform.system() == "Darwin": + from core.auto.mac.core import Auto + from core.model import Workflow, Logs + from core.utils.times import Time + flow_data = Workflow.select( + 'flow_data', + ).where( + "uuid", uuid + ).first().flow_data + except Exception as e: + logger.error("[Exec-Play-Book] 导入依赖模块失败:{e}", e=e) + return {"status": 2, "result": "导入依赖模块失败!"} + + # —————————————————————— 修改目标剧本执行过程中的参数 —————————————————————— + flow_data = json.loads(flow_data) + for i in range(len(app_uuids)): + args = list(flow_data[app_uuids[i]]["args"].values())[func_num[i]] + for arg in args: + key = arg["key"] + if len(datas) == len(app_uuids): + for data in datas[i]: + flow_data[app_uuids[i]]["data"][key] = data + Workflow.where('uuid', uuid).update({ + 'flow_data': json.dumps(flow_data), + 'update_time': Time.get_date_time() + }) + try: + # —————————————————————— 调用目标剧本 —————————————————————— + auto = Auto() + my_auto_execute(uuid, auto) + except Exception as e: + logger.error("[Exec-Play-Book] 调用 {uuid} 剧本失败:{e}", uuid=uuid, e=e) + return {"status": 2, "result": "调用剧本失败!"} + + try: + # —————————————————————— 判断与解析剧本执行状况 —————————————————————— + only_id = auto.only_id + log = None + + for i in range(overtime): + await asyncio.sleep(0.5) # 要等待auto_execute用线程执行完 + log = Logs.select( + 'app_uuid', + 'app_name', + 'result' + + ).where( + "only_id", only_id + ).where('app_name', '结束').get().to_json()[1:-1] + log = json.loads(log) + + if None != log and '剧本执行结束' == log['result'] and '结束' == log['app_name']: + break + if None == log: + logger.error("[Exec-Play-Book] 调用 {uuid} 剧本超时!", uuid=uuid) + return {"status": 1, "result": "调用剧本超时!"} + dict_log = {} + for app_uuid in app_uuids: + log = Logs.select( + 'result' + ).where( + "only_id", only_id + ).where("app_uuid", app_uuid).get().to_json()[1:-1] + dict_log.update({app_uuid: json.loads(log)}) + result = dict_log + os.chdir(current_path) + logger.info("[Exec-Play-Book] {uuid} 剧本执行结果:{result}", uuid=uuid, result=result) + return {"status": 0, "result": result} + except Exception as e: + logger.error("[Exec-Play-Book] 解析 {uuid} 剧本结果失败:{e}", uuid=uuid, e=e) + return {"status": 2, "result": "解析剧本结果失败!"} diff --git a/apps/playbook/mac/__init__.py b/apps/playbook/mac/__init__.py new file mode 100644 index 0000000..a505ad1 --- /dev/null +++ b/apps/playbook/mac/__init__.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python +# _*_ coding: utf-8 _*_ +# @Time : 2021/6/3 11:58 +# @Author : asyu17 +# @File : __init__.py.py +# @Version : 1.0 \ No newline at end of file diff --git a/apps/playbook/mac/run.py b/apps/playbook/mac/run.py new file mode 100644 index 0000000..839209d --- /dev/null +++ b/apps/playbook/mac/run.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python +# _*_ coding: utf-8 _*_ +# @Time : 2021/6/3 11:58 +# @Author : asyu17 +# @File : run.py +# @Version : 1.0 + + +import platform +import os +import sys +import json +import threading +import asyncio + +from loguru import logger + + +def my_auto_execute(uuid, Auto): + def thread_exec(): + async def run(): + await asyncio.gather(Auto.run(uuid=uuid)) + + try: + asyncio.run(run()) + except RuntimeError: + asyncio.gather(Auto.run(uuid=uuid)) + + t = threading.Thread(target=thread_exec) + t.setDaemon(True) + t.start() + + +async def exec_play_book(uuid, app_uuids='', func_num='', datas='', overtime='10'): + # app_uuids 格式:[app1,app2] + # func_num 是指目标函数为目标app的第几个函数,从0开始计算 + # datas 格式:[[data1]],[data2]] + # overtime 是设置目标剧本执行的超时时间 + + logger.info("[Exec-Play-Book] APP执行参数为: {uuid} ", uuid=uuid) + try: + app_uuids = app_uuids.strip(',[]').split(',') + func_num = func_num.strip(',[]').split(',') + datas = datas[1:-1].strip(',').split(',') + overtime = int(overtime) * 2 + for i in range(len(datas)): + datas[i] = datas[i].strip(',[]').split(',') + if app_uuids[0] == '': + app_uuids = [] + if func_num == '': + func_num = [0] * len(app_uuids) + for i in range(len(func_num)): + func_num[i] = int(func_num[i]) + if datas[0] == '': + datas = [[]] + if len(func_num) != len(app_uuids): + logger.error("[Exec-Play-Book] 函数序号无法与app_uuids匹配!") + return {"status": 1, "result": "函数序号无法与app_uuids匹配!"} + except Exception as e: + logger.error("[Exec-Play-Book] 传入参数格式有误:{e}", e=e) + return {"status": 2, "result": "传入参数格式有误!"} + current_path = sys.path[0] + path = current_path + for i in range(3): + path = os.path.dirname(path) + sys.path[0] = path + # —————————————————————— 导入依赖core模块 —————————————————————— + os.chdir(path) + try: + if platform.system() == 'Windows': + from core.auto.windows.core import Auto + elif platform.system() == 'Linux': + from core.auto.linux.core import Auto + elif platform.system() == "Darwin": + from core.auto.mac.core import Auto + from core.model import Workflow, Logs + from core.utils.times import Time + flow_data = Workflow.select( + 'flow_data', + ).where( + "uuid", uuid + ).first().flow_data + except Exception as e: + logger.error("[Exec-Play-Book] 导入依赖模块失败:{e}", e=e) + return {"status": 2, "result": "导入依赖模块失败!"} + + # —————————————————————— 修改目标剧本执行过程中的参数 —————————————————————— + flow_data = json.loads(flow_data) + for i in range(len(app_uuids)): + args = list(flow_data[app_uuids[i]]["args"].values())[func_num[i]] + for arg in args: + key = arg["key"] + if len(datas) == len(app_uuids): + for data in datas[i]: + flow_data[app_uuids[i]]["data"][key] = data + Workflow.where('uuid', uuid).update({ + 'flow_data': json.dumps(flow_data), + 'update_time': Time.get_date_time() + }) + try: + # —————————————————————— 调用目标剧本 —————————————————————— + auto = Auto() + my_auto_execute(uuid, auto) + except Exception as e: + logger.error("[Exec-Play-Book] 调用 {uuid} 剧本失败:{e}", uuid=uuid, e=e) + return {"status": 2, "result": "调用剧本失败!"} + + try: + # —————————————————————— 判断与解析剧本执行状况 —————————————————————— + only_id = auto.only_id + log = None + + for i in range(overtime): + await asyncio.sleep(0.5) # 要等待auto_execute用线程执行完 + log = Logs.select( + 'app_uuid', + 'app_name', + 'result' + + ).where( + "only_id", only_id + ).where('app_name', '结束').get().to_json()[1:-1] + log = json.loads(log) + + if None != log and '剧本执行结束' == log['result'] and '结束' == log['app_name']: + break + if None == log: + logger.error("[Exec-Play-Book] 调用 {uuid} 剧本超时!", uuid=uuid) + return {"status": 1, "result": "调用剧本超时!"} + dict_log = {} + for app_uuid in app_uuids: + log = Logs.select( + 'result' + ).where( + "only_id", only_id + ).where("app_uuid", app_uuid).get().to_json()[1:-1] + dict_log.update({app_uuid: json.loads(log)}) + result = dict_log + os.chdir(current_path) + logger.info("[Exec-Play-Book] {uuid} 剧本执行结果:{result}", uuid=uuid, result=result) + return {"status": 0, "result": result} + except Exception as e: + logger.error("[Exec-Play-Book] 解析 {uuid} 剧本结果失败:{e}", uuid=uuid, e=e) + return {"status": 2, "result": "解析剧本结果失败!"} diff --git a/apps/playbook/readme.md b/apps/playbook/readme.md new file mode 100644 index 0000000..6638d62 --- /dev/null +++ b/apps/playbook/readme.md @@ -0,0 +1,25 @@ +## APP 说明 + +> 剧本调用 + +## 动作列表 + +### 查询信息 + +**参数:** + +| 参数 | 类型 | 必填 | 备注 | +| ---- | ---- | ---- | ---- | +| **uuid** | text | `是` | 要操作的剧本,示例:59c88704-c694-11eb-8ebe-0242ac110003 | +| **app_uuids** | text | `否` | 要操作的应用,示例:[61eaa840-c694-11eb-b241-23cb919a2e29,eff61240-c695-11eb-b241-23cb919a2e29] | +| **func_num** | text | `否` | 要操作的函数序号,示例:[0,0] | +| **datas** | text | `否` | 要操作应用的参数,示例:[[12312345],[123123]] | +| **overtime** | text | `否` | 要操作应用的参数,示例:20 | + +**返回值:** + +``` +{'status': 0, 'result': {'61eaa840-c694-11eb-b241-23cb919a2e29': {'result': '{}'}, 'eff6 +1240-c695-11eb-b241-23cb919a2e29': {'result': ''}}} +``` + diff --git a/apps/playbook/windows/__init__.py b/apps/playbook/windows/__init__.py new file mode 100644 index 0000000..a505ad1 --- /dev/null +++ b/apps/playbook/windows/__init__.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python +# _*_ coding: utf-8 _*_ +# @Time : 2021/6/3 11:58 +# @Author : asyu17 +# @File : __init__.py.py +# @Version : 1.0 \ No newline at end of file diff --git a/apps/playbook/windows/run.py b/apps/playbook/windows/run.py new file mode 100644 index 0000000..839209d --- /dev/null +++ b/apps/playbook/windows/run.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python +# _*_ coding: utf-8 _*_ +# @Time : 2021/6/3 11:58 +# @Author : asyu17 +# @File : run.py +# @Version : 1.0 + + +import platform +import os +import sys +import json +import threading +import asyncio + +from loguru import logger + + +def my_auto_execute(uuid, Auto): + def thread_exec(): + async def run(): + await asyncio.gather(Auto.run(uuid=uuid)) + + try: + asyncio.run(run()) + except RuntimeError: + asyncio.gather(Auto.run(uuid=uuid)) + + t = threading.Thread(target=thread_exec) + t.setDaemon(True) + t.start() + + +async def exec_play_book(uuid, app_uuids='', func_num='', datas='', overtime='10'): + # app_uuids 格式:[app1,app2] + # func_num 是指目标函数为目标app的第几个函数,从0开始计算 + # datas 格式:[[data1]],[data2]] + # overtime 是设置目标剧本执行的超时时间 + + logger.info("[Exec-Play-Book] APP执行参数为: {uuid} ", uuid=uuid) + try: + app_uuids = app_uuids.strip(',[]').split(',') + func_num = func_num.strip(',[]').split(',') + datas = datas[1:-1].strip(',').split(',') + overtime = int(overtime) * 2 + for i in range(len(datas)): + datas[i] = datas[i].strip(',[]').split(',') + if app_uuids[0] == '': + app_uuids = [] + if func_num == '': + func_num = [0] * len(app_uuids) + for i in range(len(func_num)): + func_num[i] = int(func_num[i]) + if datas[0] == '': + datas = [[]] + if len(func_num) != len(app_uuids): + logger.error("[Exec-Play-Book] 函数序号无法与app_uuids匹配!") + return {"status": 1, "result": "函数序号无法与app_uuids匹配!"} + except Exception as e: + logger.error("[Exec-Play-Book] 传入参数格式有误:{e}", e=e) + return {"status": 2, "result": "传入参数格式有误!"} + current_path = sys.path[0] + path = current_path + for i in range(3): + path = os.path.dirname(path) + sys.path[0] = path + # —————————————————————— 导入依赖core模块 —————————————————————— + os.chdir(path) + try: + if platform.system() == 'Windows': + from core.auto.windows.core import Auto + elif platform.system() == 'Linux': + from core.auto.linux.core import Auto + elif platform.system() == "Darwin": + from core.auto.mac.core import Auto + from core.model import Workflow, Logs + from core.utils.times import Time + flow_data = Workflow.select( + 'flow_data', + ).where( + "uuid", uuid + ).first().flow_data + except Exception as e: + logger.error("[Exec-Play-Book] 导入依赖模块失败:{e}", e=e) + return {"status": 2, "result": "导入依赖模块失败!"} + + # —————————————————————— 修改目标剧本执行过程中的参数 —————————————————————— + flow_data = json.loads(flow_data) + for i in range(len(app_uuids)): + args = list(flow_data[app_uuids[i]]["args"].values())[func_num[i]] + for arg in args: + key = arg["key"] + if len(datas) == len(app_uuids): + for data in datas[i]: + flow_data[app_uuids[i]]["data"][key] = data + Workflow.where('uuid', uuid).update({ + 'flow_data': json.dumps(flow_data), + 'update_time': Time.get_date_time() + }) + try: + # —————————————————————— 调用目标剧本 —————————————————————— + auto = Auto() + my_auto_execute(uuid, auto) + except Exception as e: + logger.error("[Exec-Play-Book] 调用 {uuid} 剧本失败:{e}", uuid=uuid, e=e) + return {"status": 2, "result": "调用剧本失败!"} + + try: + # —————————————————————— 判断与解析剧本执行状况 —————————————————————— + only_id = auto.only_id + log = None + + for i in range(overtime): + await asyncio.sleep(0.5) # 要等待auto_execute用线程执行完 + log = Logs.select( + 'app_uuid', + 'app_name', + 'result' + + ).where( + "only_id", only_id + ).where('app_name', '结束').get().to_json()[1:-1] + log = json.loads(log) + + if None != log and '剧本执行结束' == log['result'] and '结束' == log['app_name']: + break + if None == log: + logger.error("[Exec-Play-Book] 调用 {uuid} 剧本超时!", uuid=uuid) + return {"status": 1, "result": "调用剧本超时!"} + dict_log = {} + for app_uuid in app_uuids: + log = Logs.select( + 'result' + ).where( + "only_id", only_id + ).where("app_uuid", app_uuid).get().to_json()[1:-1] + dict_log.update({app_uuid: json.loads(log)}) + result = dict_log + os.chdir(current_path) + logger.info("[Exec-Play-Book] {uuid} 剧本执行结果:{result}", uuid=uuid, result=result) + return {"status": 0, "result": result} + except Exception as e: + logger.error("[Exec-Play-Book] 解析 {uuid} 剧本结果失败:{e}", uuid=uuid, e=e) + return {"status": 2, "result": "解析剧本结果失败!"} -- Gitee From c184c3e8e06d8ce3c7efb7f844817445e2bc4368 Mon Sep 17 00:00:00 2001 From: asyu17 Date: Tue, 8 Jun 2021 15:43:22 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20apps?= =?UTF-8?q?/playbook/.keep?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/playbook/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/playbook/.keep diff --git a/apps/playbook/.keep b/apps/playbook/.keep deleted file mode 100644 index e69de29..0000000 -- Gitee