Skip to content

Commit fa59cc3

Browse files
committed
fix exec runner
1 parent 45fd9a4 commit fa59cc3

File tree

4 files changed

+72
-26
lines changed

4 files changed

+72
-26
lines changed

cmd/ctrlc/root/run/exec/exec.go

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package exec
22

33
import (
44
"fmt"
5+
"sync"
6+
"time"
57

68
"github.com/charmbracelet/log"
79
"github.com/ctrlplanedev/cli/internal/api"
@@ -33,12 +35,30 @@ func NewRunExecCmd() *cobra.Command {
3335
if err != nil {
3436
return fmt.Errorf("failed to create job agent: %w", err)
3537
}
36-
if err := ja.RunQueuedJobs(); err != nil {
37-
log.Error("failed to run queued jobs", "error", err)
38-
}
39-
if err := ja.UpdateRunningJobs(); err != nil {
40-
log.Error("failed to check for jobs", "error", err)
41-
}
38+
var wg sync.WaitGroup
39+
wg.Add(2)
40+
41+
go func() {
42+
defer wg.Done()
43+
for {
44+
if err := ja.RunQueuedJobs(); err != nil {
45+
log.Error("failed to run queued jobs", "error", err)
46+
}
47+
time.Sleep(1 * time.Second)
48+
}
49+
}()
50+
51+
go func() {
52+
defer wg.Done()
53+
for {
54+
if err := ja.UpdateRunningJobs(); err != nil {
55+
log.Error("failed to check for jobs", "error", err)
56+
}
57+
time.Sleep(1 * time.Second)
58+
}
59+
}()
60+
61+
wg.Wait()
4262
return nil
4363
},
4464
}

cmd/ctrlc/root/run/exec/runner.go

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@ package exec
22

33
import (
44
"bytes"
5+
"context"
56
"encoding/json"
67
"fmt"
78
"html/template"
9+
810
"os"
911
"os/exec"
1012
"runtime"
1113
"strconv"
1214
"syscall"
1315

16+
"github.com/charmbracelet/log"
1417
"github.com/ctrlplanedev/cli/internal/api"
1518
"github.com/ctrlplanedev/cli/pkg/jobagent"
1619
)
@@ -49,7 +52,7 @@ func (r *ExecRunner) Status(job api.Job) (api.JobStatus, string) {
4952
return api.JobStatusInProgress, fmt.Sprintf("process running with pid %d", externalId)
5053
}
5154

52-
func (r *ExecRunner) Start(job api.JobWithTrigger) (string, error) {
55+
func (r *ExecRunner) Start(client *api.ClientWithResponses, job api.JobWithTrigger) (string, error) {
5356
// Create temp script file
5457
ext := ".sh"
5558
if runtime.GOOS == "windows" {
@@ -60,7 +63,6 @@ func (r *ExecRunner) Start(job api.JobWithTrigger) (string, error) {
6063
if err != nil {
6164
return "", fmt.Errorf("failed to create temp script file: %w", err)
6265
}
63-
defer os.Remove(tmpFile.Name())
6466

6567
config := ExecConfig{}
6668
jsonBytes, err := json.Marshal(job.JobAgentConfig)
@@ -71,33 +73,31 @@ func (r *ExecRunner) Start(job api.JobWithTrigger) (string, error) {
7173
return "", fmt.Errorf("failed to unmarshal job agent config: %w", err)
7274
}
7375

74-
templatedScript, err := template.New("script").Parse(config.Script)
76+
tmpl, err := template.New("script").Parse(config.Script)
7577
if err != nil {
7678
return "", fmt.Errorf("failed to parse script template: %w", err)
7779
}
7880

79-
buf := new(bytes.Buffer)
80-
if err := templatedScript.Execute(buf, job); err != nil {
81+
var script bytes.Buffer
82+
if err := tmpl.Execute(&script, job); err != nil {
8183
return "", fmt.Errorf("failed to execute script template: %w", err)
8284
}
83-
script := buf.String()
8485

85-
// Write script contents
86-
if _, err := tmpFile.WriteString(script); err != nil {
86+
if _, err := tmpFile.Write(script.Bytes()); err != nil {
8787
return "", fmt.Errorf("failed to write script file: %w", err)
8888
}
89+
8990
if err := tmpFile.Close(); err != nil {
9091
return "", fmt.Errorf("failed to close script file: %w", err)
9192
}
9293

93-
// Make executable on Unix systems
9494
if runtime.GOOS != "windows" {
9595
if err := os.Chmod(tmpFile.Name(), 0700); err != nil {
9696
return "", fmt.Errorf("failed to make script executable: %w", err)
9797
}
9898
}
9999

100-
cmd := exec.Command("bash", "-c", tmpFile.Name())
100+
cmd := exec.Command("bash", tmpFile.Name())
101101
if runtime.GOOS == "windows" {
102102
cmd = exec.Command("powershell", "-File", tmpFile.Name())
103103
}
@@ -108,14 +108,41 @@ func (r *ExecRunner) Start(job api.JobWithTrigger) (string, error) {
108108

109109
// Start the command without waiting for it to complete
110110
if err := cmd.Start(); err != nil {
111-
return "", fmt.Errorf("failed to start script: %w", err)
111+
log.Error("Failed to start script", "error", err)
112+
if cmd.Process == nil {
113+
return "", fmt.Errorf("failed to start script: %w", err)
114+
}
115+
return strconv.Itoa(cmd.Process.Pid), fmt.Errorf("failed to start script: %w", err)
112116
}
113117

114-
// Detach from the process group to prevent child processes from being
115-
// killed
116-
if runtime.GOOS != "windows" {
117-
cmd.Process.Release()
118-
}
118+
// Start a goroutine to monitor the process
119+
go func() {
120+
defer os.Remove(tmpFile.Name())
121+
122+
// Wait for the process to complete
123+
err := cmd.Wait()
124+
125+
status := api.JobStatusSuccessful
126+
message := "Process completed successfully"
127+
if err != nil {
128+
status = api.JobStatusFailure
129+
message = fmt.Sprintf("Process failed: %v", err)
130+
}
131+
132+
_, err = client.UpdateJobWithResponse(
133+
context.Background(),
134+
job.Id.String(),
135+
api.UpdateJobJSONRequestBody{
136+
Status: &status,
137+
Message: &message,
138+
},
139+
)
140+
if err != nil {
141+
log.Info("Failed to update job status", "error", err)
142+
}
143+
144+
log.Info("Job completed", "jobId", job.Id, "status", status, "message", message)
145+
}()
119146

120147
return strconv.Itoa(cmd.Process.Pid), nil
121148
}

cmd/ctrlc/root/run/run.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package run
22

33
import (
44
"github.com/ctrlplanedev/cli/cmd/ctrlc/root/run/exec"
5-
"github.com/ctrlplanedev/cli/internal/cliutil"
65
"github.com/spf13/cobra"
76
)
87

@@ -15,7 +14,7 @@ func NewRunCmd() *cobra.Command {
1514
},
1615
}
1716

18-
cmd.AddCommand(cliutil.AddIntervalSupport(exec.NewRunExecCmd(), ""))
17+
cmd.AddCommand(exec.NewRunExecCmd())
1918

2019
return cmd
2120
}

pkg/jobagent/runner.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
)
1111

1212
type Runner interface {
13-
Start(job api.JobWithTrigger) (string, error)
13+
Start(client *api.ClientWithResponses, job api.JobWithTrigger) (string, error)
1414
Status(job api.Job) (api.JobStatus, string)
1515
}
1616

@@ -90,7 +90,7 @@ func (a *JobAgent) RunQueuedJobs() error {
9090
}
9191

9292
data := resolvedJob.JSON200
93-
externalId, err := a.runner.Start(*data)
93+
externalId, err := a.runner.Start(a.client, *data)
9494
if err != nil {
9595
status := api.JobStatusFailure
9696
message := fmt.Sprintf("Failed to start job: %s", err.Error())

0 commit comments

Comments
 (0)