@@ -2,15 +2,18 @@ package exec
2
2
3
3
import (
4
4
"bytes"
5
+ "context"
5
6
"encoding/json"
6
7
"fmt"
7
8
"html/template"
9
+
8
10
"os"
9
11
"os/exec"
10
12
"runtime"
11
13
"strconv"
12
14
"syscall"
13
15
16
+ "github.com/charmbracelet/log"
14
17
"github.com/ctrlplanedev/cli/internal/api"
15
18
"github.com/ctrlplanedev/cli/pkg/jobagent"
16
19
)
@@ -49,7 +52,7 @@ func (r *ExecRunner) Status(job api.Job) (api.JobStatus, string) {
49
52
return api .JobStatusInProgress , fmt .Sprintf ("process running with pid %d" , externalId )
50
53
}
51
54
52
- func (r * ExecRunner ) Start (job api.JobWithTrigger ) (string , error ) {
55
+ func (r * ExecRunner ) Start (client * api. ClientWithResponses , job api.JobWithTrigger ) (string , error ) {
53
56
// Create temp script file
54
57
ext := ".sh"
55
58
if runtime .GOOS == "windows" {
@@ -60,7 +63,6 @@ func (r *ExecRunner) Start(job api.JobWithTrigger) (string, error) {
60
63
if err != nil {
61
64
return "" , fmt .Errorf ("failed to create temp script file: %w" , err )
62
65
}
63
- defer os .Remove (tmpFile .Name ())
64
66
65
67
config := ExecConfig {}
66
68
jsonBytes , err := json .Marshal (job .JobAgentConfig )
@@ -71,33 +73,31 @@ func (r *ExecRunner) Start(job api.JobWithTrigger) (string, error) {
71
73
return "" , fmt .Errorf ("failed to unmarshal job agent config: %w" , err )
72
74
}
73
75
74
- templatedScript , err := template .New ("script" ).Parse (config .Script )
76
+ tmpl , err := template .New ("script" ).Parse (config .Script )
75
77
if err != nil {
76
78
return "" , fmt .Errorf ("failed to parse script template: %w" , err )
77
79
}
78
80
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 {
81
83
return "" , fmt .Errorf ("failed to execute script template: %w" , err )
82
84
}
83
- script := buf .String ()
84
85
85
- // Write script contents
86
- if _ , err := tmpFile .WriteString (script ); err != nil {
86
+ if _ , err := tmpFile .Write (script .Bytes ()); err != nil {
87
87
return "" , fmt .Errorf ("failed to write script file: %w" , err )
88
88
}
89
+
89
90
if err := tmpFile .Close (); err != nil {
90
91
return "" , fmt .Errorf ("failed to close script file: %w" , err )
91
92
}
92
93
93
- // Make executable on Unix systems
94
94
if runtime .GOOS != "windows" {
95
95
if err := os .Chmod (tmpFile .Name (), 0700 ); err != nil {
96
96
return "" , fmt .Errorf ("failed to make script executable: %w" , err )
97
97
}
98
98
}
99
99
100
- cmd := exec .Command ("bash" , "-c" , tmpFile .Name ())
100
+ cmd := exec .Command ("bash" , tmpFile .Name ())
101
101
if runtime .GOOS == "windows" {
102
102
cmd = exec .Command ("powershell" , "-File" , tmpFile .Name ())
103
103
}
@@ -108,14 +108,41 @@ func (r *ExecRunner) Start(job api.JobWithTrigger) (string, error) {
108
108
109
109
// Start the command without waiting for it to complete
110
110
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 )
112
116
}
113
117
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
+ }()
119
146
120
147
return strconv .Itoa (cmd .Process .Pid ), nil
121
148
}
0 commit comments