@@ -3,7 +3,9 @@ package client
3
3
import (
4
4
"context"
5
5
"fmt"
6
+ "log/slog"
6
7
"strconv"
8
+ "strings"
7
9
8
10
"github.com/harness/harness-mcp/client/dto"
9
11
)
@@ -147,18 +149,37 @@ func (p *PipelineService) ListExecutions(
147
149
return response , nil
148
150
}
149
151
150
- // GetExecution retrieves details of a specific pipeline execution
151
- func (p * PipelineService ) GetExecution (
152
+ // PipelineExecutionResult contains the pipeline execution details and log keys
153
+ type PipelineExecutionResult struct {
154
+ Execution dto.PipelineExecution `json:"execution,omitempty"`
155
+ LogKeys dto.FinalLogKeys `json:"logKeys,omitempty"`
156
+ }
157
+
158
+ // GetExecutionWithLogKeys retrieves details of a specific pipeline execution along with log keys
159
+ func (p * PipelineService ) GetExecutionWithLogKeys (
152
160
ctx context.Context ,
153
161
scope dto.Scope ,
154
162
planExecutionID string ,
155
- ) (* dto.Entity [dto.PipelineExecution ], error ) {
163
+ stageNodeID string ,
164
+ childStageNodeID string ,
165
+ ) (* dto.Entity [PipelineExecutionResult ], error ) {
156
166
path := fmt .Sprintf (pipelineExecutionGetPath , planExecutionID )
157
167
158
168
// Prepare query parameters
159
169
params := make (map [string ]string )
160
170
addScope (scope , params )
161
171
172
+ // Add stageNodeId if provided
173
+ if stageNodeID != "" {
174
+ params ["stageNodeId" ] = stageNodeID
175
+ }
176
+
177
+ // Add childStageNodeId if provided
178
+ if childStageNodeID != "" {
179
+ params ["childStageNodeId" ] = childStageNodeID
180
+ }
181
+
182
+ slog .Info ("Fetching execution details with log keys" , "planExecutionID" , planExecutionID , "stageNodeID" , stageNodeID , "childStageNodeID" , childStageNodeID )
162
183
// Initialize the response object with the new structure that matches the API response
163
184
response := & dto.Entity [dto.PipelineExecutionResponse ]{}
164
185
@@ -167,16 +188,64 @@ func (p *PipelineService) GetExecution(
167
188
if err != nil {
168
189
return nil , fmt .Errorf ("failed to get execution details: %w" , err )
169
190
}
191
+ // Extract log keys from the execution graph
192
+ logKeys := extractLogKeys (response .Data )
170
193
171
- // Extract the execution details from the nested structure
172
- result := & dto.Entity [dto. PipelineExecution ]{
194
+ // Create the result with both execution details and log keys
195
+ result := & dto.Entity [PipelineExecutionResult ]{
173
196
Status : response .Status ,
174
- Data : response .Data .PipelineExecutionSummary ,
197
+ Data : PipelineExecutionResult {
198
+ Execution : response .Data .PipelineExecutionSummary ,
199
+ LogKeys : logKeys ,
200
+ },
175
201
}
176
-
202
+ slog . Info ( "Returning execution result with child graph" , "childGraphExists" , response . Data . ChildGraph . ExecutionGraph . NodeMap != nil , "childPipelineId" , response . Data . ChildGraph . PipelineExecutionSummary . PipelineIdentifier )
177
203
return result , nil
178
204
}
179
205
206
+ // extractLogKeys extracts log keys from the execution graph
207
+ func extractLogKeys (executionResponse dto.PipelineExecutionResponse ) dto.FinalLogKeys {
208
+ logKeys := dto.FinalLogKeys {
209
+ StepLogBaseKeys : []string {},
210
+ }
211
+
212
+ // Process the main execution graph
213
+ if executionResponse .ExecutionGraph .NodeMap != nil {
214
+ processExecutionGraph (executionResponse .ExecutionGraph , & logKeys )
215
+ }
216
+
217
+ // Process child graphs if they exist
218
+ if executionResponse .ChildGraph .ExecutionGraph .NodeMap != nil {
219
+ processExecutionGraph (executionResponse .ChildGraph .ExecutionGraph , & logKeys )
220
+ }
221
+
222
+ return logKeys
223
+ }
224
+
225
+ // processExecutionGraph processes an execution graph to extract log keys
226
+ func processExecutionGraph (graph dto.ExecutionGraph , logKeys * dto.FinalLogKeys ) {
227
+ // Extract all log base keys for steps
228
+ stepLogBaseKeys := extractLogBaseKeysForSteps (graph .NodeMap )
229
+
230
+ // Store the step log base keys in the result
231
+ logKeys .StepLogBaseKeys = append (logKeys .StepLogBaseKeys , stepLogBaseKeys ... )
232
+ }
233
+
234
+ // extractLogBaseKeysForSteps extracts an array of logbasekeys where node.BaseFqn contains "steps"
235
+ func extractLogBaseKeysForSteps (nodes map [string ]dto.ExecutionNode ) []string {
236
+ var logBaseKeys []string
237
+
238
+ // Iterate through all nodes and find those containing "steps" in BaseFqn
239
+ for _ , node := range nodes {
240
+ // Check if the BaseFqn contains "steps"
241
+ if strings .Contains (node .BaseFqn , ".steps." ) && node .LogBaseKey != "" {
242
+ logBaseKeys = append (logBaseKeys , node .LogBaseKey )
243
+ }
244
+ }
245
+
246
+ return logBaseKeys
247
+ }
248
+
180
249
func (p * PipelineService ) FetchExecutionURL (
181
250
ctx context.Context ,
182
251
scope dto.Scope ,
@@ -187,6 +256,7 @@ func (p *PipelineService) FetchExecutionURL(
187
256
// Prepare query parameters
188
257
params := make (map [string ]string )
189
258
addScope (scope , params )
259
+
190
260
params ["pipelineIdentifier" ] = pipelineID
191
261
params ["planExecutionId" ] = planExecutionID
192
262
@@ -256,6 +326,7 @@ func (p *PipelineService) GetInputSet(
256
326
// Prepare query parameters
257
327
params := make (map [string ]string )
258
328
addScope (scope , params )
329
+
259
330
params ["pipelineIdentifier" ] = pipelineIdentifier
260
331
261
332
// Initialize the response object
0 commit comments