@@ -61,7 +61,13 @@ type pipelineDockerProcessGroupKey struct{}
6161
6262var pipelineDockerTLSNames = [3 ]string {"ca.pem" , "cert.pem" , "key.pem" }
6363
64- func resolvePipelineDockerClient (ctx context.Context ) (* pipelineDockerClient , error ) {
64+ func resolvePipelineDockerClient (ctx context.Context ) (_ * pipelineDockerClient , resolveErr error ) {
65+ phase := "docker_resolve_cli"
66+ defer func () {
67+ if resolveErr != nil {
68+ pipelineRecordDiagnosticFromContext (ctx ).fail (phase )
69+ }
70+ }()
6571 // Only discovery receives a snapshot of Docker's transport-selection env.
6672 // All daemon calls use a private empty config, explicit host/TLS flags, and
6773 // a minimal env, avoiding auth helpers, config proxies, and context changes.
@@ -78,10 +84,12 @@ func resolvePipelineDockerClient(ctx context.Context) (*pipelineDockerClient, er
7884 if err != nil {
7985 return nil , fmt .Errorf ("pipeline Docker CLI unavailable" )
8086 }
87+ phase = "docker_resolve_home"
8188 home := snapshot ["HOME" ]
8289 if home == "" {
8390 return nil , fmt .Errorf ("pipeline Docker home unavailable" )
8491 }
92+ phase = "docker_resolve_config"
8593 config := snapshot ["DOCKER_CONFIG" ]
8694 if config == "" {
8795 config = filepath .Join (home , ".docker" )
@@ -97,14 +105,17 @@ func resolvePipelineDockerClient(ctx context.Context) (*pipelineDockerClient, er
97105 discoveryEnv = append (discoveryEnv , key + "=" + value )
98106 }
99107 }
100- out , err := runPipelineDockerCLI (ctx , binary , discoveryEnv , pipelineDockerCallTimeout , "--config" , config , "context" , "inspect" )
108+ phase = "docker_resolve_context"
109+ out , err := runPipelineDockerCLI (pipelineDockerResolutionContext (ctx , "resolve_context" ), binary , discoveryEnv , pipelineDockerCallTimeout , "--config" , config , "context" , "inspect" )
101110 if err != nil {
102111 return nil , fmt .Errorf ("pipeline Docker context resolution failed" )
103112 }
113+ phase = "docker_resolve_context_metadata"
104114 var contexts []pipelineDockerContext
105115 if json .Unmarshal ([]byte (out .Stdout ), & contexts ) != nil || len (contexts ) != 1 {
106116 return nil , fmt .Errorf ("pipeline Docker context metadata invalid" )
107117 }
118+ phase = "docker_resolve_endpoint"
108119 metadata := contexts [0 ]
109120 endpoint , ok := metadata .Endpoints ["docker" ]
110121 if ! ok || metadata .Name == "" {
@@ -113,6 +124,7 @@ func resolvePipelineDockerClient(ctx context.Context) (*pipelineDockerClient, er
113124 if err := validatePipelineDockerEndpoint (endpoint .Host ); err != nil {
114125 return nil , err
115126 }
127+ phase = "docker_resolve_tls"
116128 var material [3 ][]byte
117129 tlsEnabled := false
118130 verifyTLS := false
@@ -153,6 +165,7 @@ func resolvePipelineDockerClient(ctx context.Context) (*pipelineDockerClient, er
153165 if (len (material [1 ]) == 0 ) != (len (material [2 ]) == 0 ) {
154166 return nil , fmt .Errorf ("pipeline Docker TLS client material incomplete" )
155167 }
168+ phase = "docker_resolve_private_config"
156169 dir , err := os .MkdirTemp ("" , "wfctl-pipeline-docker-" )
157170 if err != nil {
158171 return nil , fmt .Errorf ("pipeline Docker private config unavailable" )
@@ -182,7 +195,8 @@ func resolvePipelineDockerClient(ctx context.Context) (*pipelineDockerClient, er
182195 c .args = append (c .args , flag + "=" + path )
183196 }
184197 }
185- serverID , err := c .serverID (ctx )
198+ phase = "docker_resolve_identity_metadata"
199+ serverID , err := c .serverID (pipelineDockerResolutionContext (ctx , "resolve_identity" ))
186200 if err != nil {
187201 return nil , err
188202 }
@@ -426,13 +440,23 @@ func runPipelineDockerCLI(ctx context.Context, binary string, env []string, time
426440 if cmd .ProcessState != nil {
427441 result .ExitCode = cmd .ProcessState .ExitCode ()
428442 }
429- if ctx .Err () != nil {
443+ if contextErr := ctx .Err (); contextErr != nil {
444+ outcome := "command"
445+ switch contextErr {
446+ case context .DeadlineExceeded :
447+ outcome = "deadline"
448+ case context .Canceled :
449+ outcome = "cancelled"
450+ }
451+ observePipelineDockerResolutionFailure (ctx , outcome , result .ExitCode )
430452 return result , fmt .Errorf ("pipeline Docker operation canceled or timed out" )
431453 }
432454 if stdout .overflow || stderr .overflow {
455+ observePipelineDockerResolutionFailure (ctx , "capture" , result .ExitCode )
433456 return result , fmt .Errorf ("pipeline Docker output exceeded capture limit" )
434457 }
435458 if err != nil {
459+ observePipelineDockerResolutionFailure (ctx , "command" , result .ExitCode )
436460 return result , fmt .Errorf ("pipeline Docker operation failed" )
437461 }
438462 return result , nil
0 commit comments