Skip to content

Commit

Permalink
2.2.3 workflow repl fix
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaobaidadada committed Jan 24, 2025
1 parent f95927f commit beb7dc6
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 97 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "filecat",
"version": "2.2.2",
"version": "2.2.3",
"description": "filecat 文件管理器",
"author": "xiaobaidadada",
"scripts": {
Expand Down
9 changes: 5 additions & 4 deletions src/common/req/file.req.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ export class WorkflowReq {
export const workflow_dir_name = ".filecat_work_flows";

export enum running_type {
not,
running,
success,
fail
not = 0,
running= 1,
success= 2,
fail= 3
}
export interface step_item {
run: string; // 运行命令
Expand All @@ -66,6 +66,7 @@ export interface job_item {
name: string;
need_job: string | undefined;
steps: step_item[];
repl?:boolean;

// 额外字段
fail_message?: string;
Expand Down
2 changes: 1 addition & 1 deletion src/main/domain/file/workflow/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
build-job1:
cwd: E:\test # 需要一个实际的执行目录 默认是当前的yml所在目录 目录内的文件清理需要自己使用命令操作 必须是绝对路径
name: 第一阶段执行
repl: false # 交互式运行 当上一个step 运行没有结束 有输出的时候 就执行下一个 step 默认是 false 未充分测试
repl: false # 交互式运行 当上一个step 运行没有结束 有输出的时候 就执行下一个 step 默认是 false 必须要自己设置好流程 避免出现一直等待 那么只能手动关闭了
# need_job: build-job2 # 需要别的job先完成 只能是本文件内的
steps: # 这些脚本会按顺序执行
- use-yml: test2 # 使用其它 yml 文件中的 name
Expand Down
197 changes: 110 additions & 87 deletions src/main/domain/file/workflow/workflow.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {SysPojo} from "../../../../common/req/sys.pojo";
import {data_common_key, data_dir_tem_name} from "../../data/data_type";
import {SysEnum, UserAuth} from "../../../../common/req/user.req";
import {get_best_cmd} from "../../../../common/path_util";
import {getSys, SYS_PATH} from "../../shell/shell.service";
import {getSys, sysType} from "../../shell/shell.service";
import {Base_data_util} from "../../data/basedata/base_data_util";
import {removeTrailingPath} from "../../../../common/StringUtil";
import {tree_list, workflow_realtime_tree_list} from "../../../../common/req/common.pojo";
Expand Down Expand Up @@ -47,7 +47,6 @@ class work_children {
import_files_map: Map<string,import_files_item> = new Map<string, import_files_item>(); // 导入的其它文件 key 是对应文件的 name 值是 读到的数据
name: string;
"run-name": string;
repl = false;
jobs_map: Map<string,job_item> = new Map();


Expand Down Expand Up @@ -137,7 +136,7 @@ class work_children {
const yaml_data = param?.yaml_data ?? await readYamlFile(this.yaml_path);
this.env = yaml_data.env;
// 获取用户 id
let user_id = yaml_data.user_id;
let user_id = `${yaml_data.user_id??""}`;
if (!user_id) {
user_id = userService.get_user_id(`${yaml_data.username}`);
}
Expand Down Expand Up @@ -193,12 +192,9 @@ class work_children {
}
}
}
if(yaml_data.repl !== undefined) {
this.repl = yaml_data.repl;
}
yaml_data['run-name'] = Mustache.render(yaml_data['run-name'], this.env);
this["run-name"] = yaml_data['run-name'];
this.name = yaml_data.name;
this["run-name"] = `${yaml_data['run-name']??""}`;
yaml_data['run-name'] = Mustache.render(this["run-name"], this.env??"");
this.name = `${yaml_data.name}`;
if (param?.env) {
for (const key of Object.keys(param.env)) {
this.env[key] = param.env[key];
Expand All @@ -220,6 +216,9 @@ class work_children {

}).catch(e=>{
console.error(e);
job.running_type = running_type.fail;
job.fail_message = JSON.stringify(e);
job.code = 1;
resolve(-1);
});
}
Expand Down Expand Up @@ -262,6 +261,7 @@ class work_children {
// 完成job 以失败的方式
private done_fail_job_handle(job: job_item,fail_message:string) {
job.running_type = running_type.fail;
job.code = 1;
this.send_all_wss();
job.fail_message = fail_message;
this.close();
Expand Down Expand Up @@ -308,35 +308,29 @@ class work_children {
const run_exec_resolve = (code,message?:string)=>{
now_step.code = code;
if(code===0) {
if(!this.repl) {
now_step.success_message = message ?? out_context;
}
if(job.code === undefined) {
// 没有失败过就设置为成功
job.code = 0;
}
now_step.success_message = message ?? out_context;
job.code = 0;
} else {
job.code = code; // 任务整体也失败
if(!this.repl) {
now_step.fail_message = message ?? out_context;
}
now_step.fail_message = message ?? out_context;
}
if(!this.repl) {
if(job.repl) {
out_context = "";
}
if(exec_resolve)
{
exec_resolve(code);
exec_resolve = undefined;
}
exec_resolve = undefined;
}
let out_context = "";
job.cwd = Mustache.render(job.cwd, this.env);
job.cwd = Mustache.render(job.cwd??"", this.env??{});
userService.check_user_path_by_user_id(this.user_id, job.cwd);
const PATH = process.env.PATH +(sysType === "win" ? ";" : ":") + settingService.get_env_list();
const ptyshell = new PtyShell({
cwd: job.cwd,
node_pty: pty,
env: {SYS_PATH},
env: {PATH},
node_pty_shell_list: settingService.get_pty_cmd(),
check_exe_cmd: (exe_cmd, params) => {
// 命令和路径检查
Expand Down Expand Up @@ -369,85 +363,114 @@ class work_children {
if(!this.not_log) {
ptyshell.set_on_call((cmdData)=>{
out_context+=cmdData;
if(this.repl) {
if(exec_resolve)
{
exec_resolve(0);
}
exec_resolve = undefined;
}
})
}
ptyshell.on_child_kill((code)=>{
// 任何命令结束都有的
run_exec_resolve(code);
})
const start_time = Date.now();
// 开始多个命令执行 有前后顺序的
for (const step of job.steps) {
step.running_type = running_type.running;
const step_satrt_time = Date.now();
if (step["use-yml"]) {
// 执行另一个文件
const yaml = this.import_files_map.get(step["use-yml"]);
if(yaml) {
const worker = new work_children(undefined, this.workflow_dir_path);
await worker.init({env:step['with-env'],yaml_data:yaml.yaml_data,yaml_path:yaml.yaml_path});
this.worker_children_use_yml_map.set(step["use-yml"],worker);
let success_list,fail_list;
try {
const v = await worker.run_jobs(true); // 只需要记录整个执行结果 日志不记录了
success_list = v.success_list;
fail_list = v.fail_list;
} catch(e){
step.running_type = running_type.fail;
this.worker_children_use_yml_map.delete(step["use-yml"]);
throw e;
}
this.worker_children_use_yml_map.delete(step["use-yml"]);
step.use_job_children_list = [...success_list,...fail_list]
step.duration = `${((Date.now() - step_satrt_time) / 1000).toFixed(2)} s`;
this.send_all_wss();
if(fail_list.length !== 0){
job.code = -1;
step.code = -1;
step.running_type = running_type.fail;
this.done_fail_job_handle(job,"fail");
break;

if(job.repl) {
try {
job.code = await new Promise(resolve => {
exec_resolve = resolve;
if(job.steps) {
now_step = job.steps[0]; // 交互式的给第一个
for (let i=0;i<job.steps.length;i++) {
const step = job.steps[i];
step.running_type = running_type.running;
step.run = Mustache.render(`${step.run??""}`, this.env??{});
ptyshell.write(`${step.run}\r`);
}
} else {
exec_resolve(1);
}

})
for (const step of job.steps??[]) { // 都完成
step.running_type = running_type.success;
step.code = 0;
continue;
}
step.running_type = running_type.fail;
this.send_all_wss();
step.code = -1;
step.fail_message = `not have yaml use name ${step['use-yml']}`;
job.code = -1;
step.duration = `${((Date.now() - step_satrt_time) / 1000).toFixed(2)} s`;
this.done_fail_job_handle(job,"fail");
break; // 剩下的也不需要执行了
} catch (error) {
for (const step of job.steps??[]) { // 都完成
step.running_type = running_type.fail;
step.code = 1;
}
}
// 普通的执行
now_step = step;
// 等待执行完执行下一条
const code = await new Promise(resolve => {
exec_resolve = resolve;
step.run = Mustache.render(step.run, this.env);
ptyshell.write(`${step.run}\r`);
})
step.duration = `${((Date.now() - step_satrt_time) / 1000).toFixed(2)} s`;
step.code = code as number;
step.running_type = running_type.success;
this.send_all_wss();
if(code !==0 ) {
step.running_type = running_type.fail;
// 终止后面的行为
break;

} else {
// 开始多个命令执行 有前后顺序的
for (const step of job.steps) {
// @ts-ignore
if(job.running_type === running_type.fail) {
break;
}
step.running_type = running_type.running;
const step_satrt_time = Date.now();
if (step["use-yml"]) {
// 执行另一个文件
const yaml = this.import_files_map.get(step["use-yml"]);
if(yaml) {
const worker = new work_children(undefined, this.workflow_dir_path);
await worker.init({env:step['with-env'],yaml_data:yaml.yaml_data,yaml_path:yaml.yaml_path});
this.worker_children_use_yml_map.set(step["use-yml"],worker);
let success_list,fail_list;
try {
const v = await worker.run_jobs(true); // 只需要记录整个执行结果 日志不记录了
success_list = v.success_list;
fail_list = v.fail_list;
} catch(e){
step.running_type = running_type.fail;
this.worker_children_use_yml_map.delete(step["use-yml"]);
throw e;
}
this.worker_children_use_yml_map.delete(step["use-yml"]);
step.use_job_children_list = [...success_list,...fail_list]
step.duration = `${((Date.now() - step_satrt_time) / 1000).toFixed(2)} s`;
this.send_all_wss();
if(fail_list.length !== 0){
job.code = -1;
step.code = -1;
step.running_type = running_type.fail;
this.done_fail_job_handle(job,"fail");
break;
}
step.running_type = running_type.success;
step.code = 0;
continue;
}
step.running_type = running_type.fail;
this.send_all_wss();
step.code = -1;
step.fail_message = `not have yaml use name ${step['use-yml']}`;
job.code = -1;
step.duration = `${((Date.now() - step_satrt_time) / 1000).toFixed(2)} s`;
this.done_fail_job_handle(job,"fail");
break; // 剩下的也不需要执行了
}
// 普通的执行
now_step = step;
// 等待执行完执行下一条
const code = await new Promise(resolve => {
exec_resolve = resolve;
step.run = Mustache.render(`${step.run??""}`, this.env??{});
ptyshell.write(`${step.run}\r`);
})
step.duration = `${((Date.now() - step_satrt_time) / 1000).toFixed(2)} s`;
step.code = code as number;
step.running_type = running_type.success;
this.send_all_wss();
if(code !==0 ) {
step.running_type = running_type.fail;
// 终止后面的行为
break;
}
}

}
this.pty_shell_set.delete(ptyshell);
if(this.repl) {
if(job.repl) {
if(job.code === 0) {
job.success_message = out_context;
} else {
Expand Down
3 changes: 1 addition & 2 deletions src/main/domain/shell/shell.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ const reset = '\x1b[0m'; // 重置颜色

let word_detection = new word_detection_js();
// let word_detection_map = new Map<string, string>(); // 暂时不需要完整的路径
export let SYS_PATH = "";
const s_f = (sysType === "win" ? ";" : ":");
let PATH_file_total = 0; // win我的电脑 也就三千多个没必要上 c++版的了
const exec_map = {// windwos文件命令执行优先级
Expand All @@ -94,7 +93,7 @@ export class ShellService {
word_detection.clear();
word_detection = new word_detection_js();
PATH_file_total = 0;
SYS_PATH = process.env.PATH +s_f + settingService.get_env_list();
const SYS_PATH = process.env.PATH +s_f + settingService.get_env_list();
for (const item of SYS_PATH.split(s_f)) {
try {
if (fs.existsSync(item)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ export function WorkFlow(props) {
const new_list = [
<p>{item.name}</p>,
<div><StatusCircle success={item.code === undefined?undefined:item.code === 0} />{item.code ===0?t("成功"):t('失败')}</div>,
<p>{item.cwd}</p>,
<TextTip>{item.cwd}</TextTip>,
<span>{item.duration}</span>,
<div>
<ActionButton icon={"details"} title={t("详情")} onClick={() => {job_click(item)}}/>
Expand Down
2 changes: 1 addition & 1 deletion src/web/project/component/prompts/FileNew.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
build-job1:
cwd: E:\\test # 需要一个实际的执行目录 默认是当前的yml所在目录 目录内的文件清理需要自己使用命令操作 必须是绝对路径
name: 第一阶段执行
repl: false # 交互式运行 当上一个step 运行没有结束 有输出的时候 就执行下一个 step 默认是 false 未充分测试
repl: false # 交互式运行 当上一个step 运行没有结束 有输出的时候 就执行下一个 step 默认是 false 必须要自己设置好流程 避免出现一直等待 那么只能手动关闭了
# need_job: build-job2 # 需要别的job先完成 只能是本文件内的
steps: # 这些脚本会按顺序执行
- use-yml: test2 # 使用其它 yml 文件中的 name
Expand Down

0 comments on commit beb7dc6

Please sign in to comment.