2026-03-08 18:05:17 +08:00
|
|
|
package taskdebug
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
2026-03-15 17:03:15 +08:00
|
|
|
"devops/agent/script"
|
|
|
|
|
"devops/agent/tasks"
|
2026-03-08 18:05:17 +08:00
|
|
|
"devops/server/apps/task"
|
2026-03-15 17:03:15 +08:00
|
|
|
"fmt"
|
|
|
|
|
"strings"
|
|
|
|
|
"time"
|
2026-03-08 18:05:17 +08:00
|
|
|
)
|
|
|
|
|
|
2026-03-15 17:03:15 +08:00
|
|
|
const (
|
|
|
|
|
TASK_NAME = "task_debug"
|
|
|
|
|
)
|
2026-03-08 18:05:17 +08:00
|
|
|
|
2026-03-15 17:03:15 +08:00
|
|
|
func init() {
|
|
|
|
|
tasks.RegisterTaskRunner(TASK_NAME, &TaskDebugRunner{})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 实现一个 task_debug 任务
|
2026-03-08 18:05:17 +08:00
|
|
|
type TaskDebugRunner struct{}
|
|
|
|
|
|
|
|
|
|
func (t *TaskDebugRunner) Run(ctx context.Context, spec *task.TaskSpec) (*task.Task, error) {
|
2026-03-15 17:03:15 +08:00
|
|
|
// 直接使用单元测试的上下文, 方便取消
|
|
|
|
|
req := script.NewExecuteScriptRequest("task_debug.sh", []string{})
|
|
|
|
|
req.SetWorkDir(spec.GetWorkDir())
|
|
|
|
|
req.SetTimeout(spec.GetTimeout())
|
|
|
|
|
req.SetDebugScript(true)
|
|
|
|
|
req.SetLogFile("stdout.txt")
|
|
|
|
|
|
|
|
|
|
// 添加输入参数
|
|
|
|
|
for k, v := range spec.InputParams {
|
|
|
|
|
req.SetEnv(k, v)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resp, err := script.ExecuteScript(ctx, req)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 将resp 转化为 TaskStatus
|
|
|
|
|
taskIns := task.NewTask(spec)
|
|
|
|
|
MapExecutionResultToTask(taskIns, resp)
|
2026-03-08 18:05:17 +08:00
|
|
|
// 使用脚本执行
|
2026-03-15 17:03:15 +08:00
|
|
|
return taskIns, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MapExecutionResultToTask updates a Task with execution results
|
|
|
|
|
func MapExecutionResultToTask(task *task.Task, result *script.ExecutionResult) {
|
|
|
|
|
if task == nil || result == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update TaskStatus fields from ExecutionResult
|
|
|
|
|
task.TaskStatus = convertExecutionResultToStatus(result)
|
|
|
|
|
|
|
|
|
|
// Optionally update some TaskSpec fields if needed
|
|
|
|
|
// For example, if you want to store output params in the task spec extras
|
|
|
|
|
if len(result.OutputParams) > 0 && task.TaskSpec.Extras == nil {
|
|
|
|
|
task.TaskSpec.Extras = make(map[string]string)
|
|
|
|
|
}
|
|
|
|
|
for k, v := range result.OutputParams {
|
|
|
|
|
task.TaskSpec.Extras["output_"+k] = v
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// convertExecutionResultToStatus converts ExecutionResult to TaskStatus
|
|
|
|
|
func convertExecutionResultToStatus(result *script.ExecutionResult) *task.TaskStatus {
|
|
|
|
|
status := &task.TaskStatus{
|
|
|
|
|
Status: mapSuccessToStatus(result.Success, result.Skipped),
|
|
|
|
|
Message: getMessage(result),
|
|
|
|
|
Detail: getDetail(result),
|
|
|
|
|
StartAt: &result.StartTime,
|
|
|
|
|
EndAt: getEndTime(result),
|
|
|
|
|
UpdateAt: time.Now(),
|
|
|
|
|
Output: result.OutputParams,
|
|
|
|
|
Extras: make(map[string]string),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add file contents to extras if present
|
|
|
|
|
if len(result.FileContents) > 0 {
|
|
|
|
|
for k, v := range result.FileContents {
|
|
|
|
|
status.Extras["file_"+k] = v
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add command execution details
|
|
|
|
|
if result.Command != "" {
|
|
|
|
|
status.Extras["executed_command"] = result.Command
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if result.ExitCode != 0 {
|
|
|
|
|
status.Extras["exit_code"] = fmt.Sprintf("%d", result.ExitCode)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if result.Duration > 0 {
|
|
|
|
|
status.Extras["duration"] = result.Duration.String()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return status
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// mapSuccessToStatus maps execution result success/skipped to task status
|
|
|
|
|
func mapSuccessToStatus(success bool, skipped bool) task.STATUS {
|
|
|
|
|
if skipped {
|
|
|
|
|
return task.STATUS_SKIP
|
|
|
|
|
}
|
|
|
|
|
if success {
|
|
|
|
|
return task.STATUS_SUCCESS
|
|
|
|
|
}
|
|
|
|
|
return task.STATUS_FAILED
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// getMessage combines error and message from execution result
|
|
|
|
|
func getMessage(result *script.ExecutionResult) string {
|
|
|
|
|
if result.Error != "" {
|
|
|
|
|
return result.Error
|
|
|
|
|
}
|
|
|
|
|
return result.Message
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// getDetail creates a detailed message from execution result
|
|
|
|
|
func getDetail(result *script.ExecutionResult) string {
|
|
|
|
|
var details []string
|
|
|
|
|
|
|
|
|
|
if result.Command != "" {
|
|
|
|
|
details = append(details, fmt.Sprintf("Command: %s", result.Command))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if result.ExitCode != 0 {
|
|
|
|
|
details = append(details, fmt.Sprintf("Exit Code: %d", result.ExitCode))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if result.Duration > 0 {
|
|
|
|
|
details = append(details, fmt.Sprintf("Duration: %v", result.Duration))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if result.Error != "" && result.Error != result.Message {
|
|
|
|
|
details = append(details, fmt.Sprintf("Error: %s", result.Error))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if result.Message != "" && result.Message != result.Error {
|
|
|
|
|
details = append(details, fmt.Sprintf("Message: %s", result.Message))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return strings.Join(details, "\n")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// getEndTime returns the end time or current time if nil
|
|
|
|
|
func getEndTime(result *script.ExecutionResult) time.Time {
|
|
|
|
|
if result.EndTime != nil {
|
|
|
|
|
return *result.EndTime
|
|
|
|
|
}
|
|
|
|
|
return time.Now()
|
2026-03-08 18:05:17 +08:00
|
|
|
}
|