feat: 拆分任务类型并支持脚本语言联动
- 任务类型改为「执行脚本 / 发起 HTTP 请求 / 运行二进制程序」,脚本类型下新增语言选择(Python / Shell / Node / Lua) - 语言联动表单:Python 才显示虚拟环境、解释器和 uv 状态;Shell/Node/Lua 隐藏这些字段并切换脚本标签、占位符和调用预览 - 切换语言时自动设置解释器与默认脚本,Shell 通过 cmd.exe /C 执行批处理,Node/Lua 使用对应解释器 - TaskAction 新增可选 language,旧任务按解释器推断;补 Shell 执行测试、语言切换单测与 Playwright 用例
This commit is contained in:
+53
-1
@@ -1,4 +1,4 @@
|
||||
use std::time::Duration;
|
||||
use std::{fs, time::Duration};
|
||||
|
||||
use axum::{
|
||||
Json, Router,
|
||||
@@ -201,6 +201,58 @@ async fn wait_for_run(router: &Router, run_id: i64) -> Value {
|
||||
panic!("run {run_id} did not reach a terminal state");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn shell_language_runs_batch_file_with_cmd_c() {
|
||||
let app = test_app().await;
|
||||
let working_dir = app._temp_dir.path().to_string_lossy().into_owned();
|
||||
fs::write(
|
||||
app._temp_dir.path().join("hello.bat"),
|
||||
"@echo off\r\necho shell-language-ok\r\n",
|
||||
)
|
||||
.expect("batch file should be written");
|
||||
|
||||
let mut task = script_task(
|
||||
"shell_task",
|
||||
&working_dir,
|
||||
"cmd.exe",
|
||||
"hello.bat",
|
||||
vec![],
|
||||
"0 0 2 * * *",
|
||||
10,
|
||||
);
|
||||
task["action"]["language"] = json!("shell");
|
||||
let create_response = send_json(&app.router, Method::POST, "/api/v1/tasks", Some(task)).await;
|
||||
assert_eq!(create_response.status(), StatusCode::CREATED);
|
||||
|
||||
let run_response = send_json(
|
||||
&app.router,
|
||||
Method::POST,
|
||||
"/api/v1/tasks/shell_task/run",
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
assert_eq!(run_response.status(), StatusCode::ACCEPTED);
|
||||
let run = response_json(run_response).await;
|
||||
let run_id = run["id"].as_i64().expect("run id should be an integer");
|
||||
|
||||
let completed = wait_for_run(&app.router, run_id).await;
|
||||
assert_eq!(completed["status"], "succeeded");
|
||||
let log_response = send_json(
|
||||
&app.router,
|
||||
Method::GET,
|
||||
&format!("/api/v1/runs/{run_id}/logs"),
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
let log = response_json(log_response).await;
|
||||
assert!(
|
||||
log["content"]
|
||||
.as_str()
|
||||
.expect("log content should be a string")
|
||||
.contains("shell-language-ok")
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn manual_script_run_captures_exit_code_and_logs() {
|
||||
let app = test_app().await;
|
||||
|
||||
@@ -124,6 +124,7 @@ async fn empty_interpreter_defaults_to_python() {
|
||||
assert_eq!(response.status(), StatusCode::CREATED);
|
||||
let created = response_json(response).await;
|
||||
assert_eq!(created["action"]["interpreter"], "python.exe");
|
||||
assert_eq!(created["action"]["language"], "python");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
Reference in New Issue
Block a user