extractStepOutput extracts the output of a specific step from job logs
(jobLog string, stepNumber int)
| 1064 | |
| 1065 | // extractStepOutput extracts the output of a specific step from job logs |
| 1066 | func extractStepOutput(jobLog string, stepNumber int) (string, error) { |
| 1067 | auditLog.Printf("Extracting output for step %d from job logs (%d bytes)", stepNumber, len(jobLog)) |
| 1068 | lines := strings.Split(jobLog, "\n") |
| 1069 | var stepOutput []string |
| 1070 | inStep := false |
| 1071 | stepPattern := "##[group]Run " // GitHub Actions step marker |
| 1072 | stepEndPattern := "##[endgroup]" |
| 1073 | currentStep := 0 |
| 1074 | |
| 1075 | for _, line := range lines { |
| 1076 | // Detect step boundaries |
| 1077 | if strings.Contains(line, stepPattern) || strings.HasPrefix(line, fmt.Sprintf("##[group]Step %d:", stepNumber)) { |
| 1078 | currentStep++ |
| 1079 | if currentStep == stepNumber { |
| 1080 | inStep = true |
| 1081 | } |
| 1082 | } else if strings.Contains(line, stepEndPattern) { |
| 1083 | if inStep { |
| 1084 | break // End of target step |
| 1085 | } |
| 1086 | } |
| 1087 | |
| 1088 | if inStep { |
| 1089 | stepOutput = append(stepOutput, line) |
| 1090 | } |
| 1091 | } |
| 1092 | |
| 1093 | if len(stepOutput) == 0 { |
| 1094 | auditLog.Printf("Step %d not found in job logs (scanned %d lines)", stepNumber, len(lines)) |
| 1095 | return "", fmt.Errorf("step %d not found in job logs", stepNumber) |
| 1096 | } |
| 1097 | |
| 1098 | auditLog.Printf("Extracted %d lines for step %d", len(stepOutput), stepNumber) |
| 1099 | return strings.Join(stepOutput, "\n"), nil |
| 1100 | } |
| 1101 | |
| 1102 | // findFirstFailingStep finds the first step that failed in the job logs |
| 1103 | func findFirstFailingStep(jobLog string) (int, string) { |