99 "github.com/OctopusDeploy/cli/pkg/cmd"
1010 "github.com/OctopusDeploy/cli/pkg/constants"
1111 "github.com/OctopusDeploy/cli/pkg/factory"
12+ "github.com/OctopusDeploy/cli/pkg/output"
1213 "github.com/OctopusDeploy/cli/pkg/util"
1314 "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client"
1415 "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/tasks"
@@ -34,12 +35,23 @@ type WaitOptions struct {
3435 PollInterval int
3536 CancelOnTimeout bool
3637 ShowProgress bool
38+ Command * cobra.Command
3739}
3840
3941type ServerTasksCallback func ([]string ) ([]* tasks.Task , error )
4042type TaskDetailsCallback func (string ) (* tasks.TaskDetailsResource , error )
4143
42- func NewWaitOps (dependencies * cmd.Dependencies , taskIDs []string , timeout int , pollInterval int , cancelOnTimeout bool , showProgress bool ) * WaitOptions {
44+ type TaskAsJson struct {
45+ Id string `json:"Id"`
46+ Description string `json:"Description"`
47+ State string `json:"State"`
48+ StartTime * time.Time `json:"StartTime"`
49+ CompletedTime * time.Time `json:"CompletedTime"`
50+ Duration string `json:"Duration"`
51+ FinishedSuccessfully * bool `json:"FinishedSuccessfully"`
52+ }
53+
54+ func NewWaitOps (dependencies * cmd.Dependencies , taskIDs []string , timeout int , pollInterval int , cancelOnTimeout bool , showProgress bool , cmd * cobra.Command ) * WaitOptions {
4355 return & WaitOptions {
4456 Dependencies : dependencies ,
4557 TaskIDs : taskIDs ,
@@ -50,6 +62,7 @@ func NewWaitOps(dependencies *cmd.Dependencies, taskIDs []string, timeout int, p
5062 PollInterval : pollInterval ,
5163 CancelOnTimeout : cancelOnTimeout ,
5264 ShowProgress : showProgress ,
65+ Command : cmd ,
5366 }
5467}
5568
@@ -70,7 +83,7 @@ func NewCmdWait(f factory.Factory) *cobra.Command {
7083
7184 taskIDs = append (taskIDs , util .ReadValuesFromPipe ()... )
7285 dependencies := cmd .NewDependencies (f , c )
73- opts := NewWaitOps (dependencies , taskIDs , timeout , pollInterval , cancelOnTimeout , showProgress )
86+ opts := NewWaitOps (dependencies , taskIDs , timeout , pollInterval , cancelOnTimeout , showProgress , c )
7487
7588 return WaitRun (opts )
7689 },
@@ -106,6 +119,7 @@ func WaitRun(opts *WaitOptions) error {
106119 pendingTaskIDs := make ([]string , 0 )
107120 failedTaskIDs := make ([]string , 0 )
108121 formatter := NewTaskOutputFormatter (opts .Out )
122+ tableHeaderPrinted := false
109123
110124 for _ , t := range serverTasks {
111125 if t .IsCompleted == nil || ! * t .IsCompleted {
@@ -115,7 +129,11 @@ func WaitRun(opts *WaitOptions) error {
115129 failedTaskIDs = append (failedTaskIDs , t .ID )
116130 }
117131
118- formatter .PrintTaskInfo (t )
132+ if shouldUseCustomOutputFormat (opts , t ) {
133+ printTaskWithCustomFormat (opts , t , & tableHeaderPrinted )
134+ } else {
135+ formatter .PrintTaskInfo (t )
136+ }
119137 }
120138
121139 if len (pendingTaskIDs ) == 0 {
@@ -156,7 +174,13 @@ func WaitRun(opts *WaitOptions) error {
156174 if t .FinishedSuccessfully != nil && ! * t .FinishedSuccessfully {
157175 failedTaskIDs = append (failedTaskIDs , t .ID )
158176 }
159- formatter .PrintTaskInfo (t )
177+
178+ if shouldUseCustomOutputFormat (opts , t ) {
179+ printTaskWithCustomFormat (opts , t , & tableHeaderPrinted )
180+ } else {
181+ formatter .PrintTaskInfo (t )
182+ }
183+
160184 pendingTaskIDs = removeTaskID (pendingTaskIDs , t .ID )
161185 }
162186 }
@@ -235,3 +259,79 @@ func removeTaskID(taskIDs []string, taskID string) []string {
235259 }
236260 return taskIDs
237261}
262+
263+ func getTaskMappers () output.Mappers [* tasks.Task ] {
264+ return output.Mappers [* tasks.Task ]{
265+ Json : func (task * tasks.Task ) any {
266+ var duration string
267+ if task .StartTime != nil && task .CompletedTime != nil {
268+ duration = task .CompletedTime .Sub (* task .StartTime ).Round (time .Second ).String ()
269+ }
270+ return TaskAsJson {
271+ Id : task .ID ,
272+ Description : task .Description ,
273+ State : task .State ,
274+ StartTime : task .StartTime ,
275+ CompletedTime : task .CompletedTime ,
276+ Duration : duration ,
277+ FinishedSuccessfully : task .FinishedSuccessfully ,
278+ }
279+ },
280+ Table : output.TableDefinition [* tasks.Task ]{
281+ Header : []string {"ID" , "DESCRIPTION" , "STATE" , "STARTED" , "COMPLETED" , "DURATION" },
282+ Row : func (task * tasks.Task ) []string {
283+ var startTime , completedTime , duration string
284+ if task .StartTime != nil {
285+ startTime = task .StartTime .Format ("02-01-2006 15:04:05" )
286+ }
287+ if task .CompletedTime != nil {
288+ completedTime = task .CompletedTime .Format ("02-01-2006 15:04:05" )
289+ }
290+ if task .StartTime != nil && task .CompletedTime != nil {
291+ duration = task .CompletedTime .Sub (* task .StartTime ).Round (time .Second ).String ()
292+ }
293+
294+ state := task .State
295+ switch task .State {
296+ case "Failed" , "TimedOut" :
297+ state = output .Red (task .State )
298+ case "Success" :
299+ state = output .Green (task .State )
300+ case "Queued" , "Executing" , "Cancelling" , "Canceled" :
301+ state = output .Yellow (task .State )
302+ }
303+
304+ return []string {task .ID , task .Description , state , startTime , completedTime , duration }
305+ },
306+ },
307+ Basic : nil , // Not used - we use the existing formatter for basic output
308+ }
309+ }
310+
311+ func shouldUseCustomOutputFormat (opts * WaitOptions , t * tasks.Task ) bool {
312+ if opts .Command == nil {
313+ return false
314+ }
315+
316+ outputFormat , _ := opts .Command .Flags ().GetString (constants .FlagOutputFormat )
317+ isFormatSpecified := opts .Command .Flags ().Changed (constants .FlagOutputFormat )
318+ isJsonOrTable := outputFormat == constants .OutputFormatJson || outputFormat == constants .OutputFormatTable
319+ isTaskReady := ! opts .ShowProgress || (t .IsCompleted != nil && * t .IsCompleted )
320+
321+ return isFormatSpecified && isJsonOrTable && isTaskReady
322+ }
323+
324+ func printTaskWithCustomFormat (opts * WaitOptions , t * tasks.Task , tableHeaderPrinted * bool ) {
325+ outputFormat , _ := opts .Command .Flags ().GetString (constants .FlagOutputFormat )
326+
327+ if outputFormat == constants .OutputFormatJson {
328+ _ = output .PrintResource (t , opts .Command , getTaskMappers ())
329+ } else if outputFormat == constants .OutputFormatTable {
330+ mappers := getTaskMappers ()
331+ if * tableHeaderPrinted {
332+ mappers .Table .Header = nil // Don't print header for subsequent updates
333+ }
334+ _ = output .PrintResource (t , opts .Command , mappers )
335+ * tableHeaderPrinted = true
336+ }
337+ }
0 commit comments