A self-hosted orchestration system crafted for power users. composia.xyz
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990package agent
import ( "bytes" "os/exec" "strings" "sync")
type commandLogWriter struct { mu sync.Mutex uploadLog func(string) error output bytes.Buffer captureOut bool}
func newCommandLogWriter(uploadLog func(string) error, captureOut bool) *commandLogWriter { return &commandLogWriter{uploadLog: uploadLog, captureOut: captureOut}}
func (writer *commandLogWriter) Write(p []byte) (int, error) { if len(p) == 0 { return 0, nil }
writer.mu.Lock() defer writer.mu.Unlock()
if writer.captureOut { if _, err := writer.output.Write(p); err != nil { return 0, err } } if writer.uploadLog != nil { if err := writer.uploadLog(string(p)); err != nil { return 0, err } } return len(p), nil}
func (writer *commandLogWriter) String() string { writer.mu.Lock() defer writer.mu.Unlock() return writer.output.String()}
func prepareCommandForTerminalLog(command *exec.Cmd) { if command == nil { return }
env := command.Environ() env = setCommandEnv(env, "TERM", "xterm-256color") env = setCommandEnv(env, "CLICOLOR_FORCE", "1") env = setCommandEnv(env, "FORCE_COLOR", "1") env = setCommandEnv(env, "COMPOSE_ANSI", "always") env = setCommandEnv(env, "COMPOSE_STATUS_STDOUT", "1") env = setCommandEnv(env, "COMPOSE_PROGRESS", "tty") command.Env = env}
func setCommandEnv(env []string, key, value string) []string { prefix := key + "=" for index, entry := range env { if strings.HasPrefix(entry, prefix) { env[index] = prefix + value return env } } return append(env, prefix+value)}
func runCommandWithLiveLogs(command *exec.Cmd, uploadLog func(string) error) error { writer := newCommandLogWriter(uploadLog, false) prepareCommandForTerminalLog(command) command.Stdout = writer command.Stderr = writer return command.Run()}
func runCommandWithLiveLogsAndCapture(command *exec.Cmd, uploadLog func(string) error) (string, error) { writer := newCommandLogWriter(uploadLog, true) prepareCommandForTerminalLog(command) command.Stdout = writer command.Stderr = writer err := command.Run() return writer.String(), err}