diff --git a/pkg/workflow/copilot_participant_steps.go b/pkg/workflow/copilot_participant_steps.go index 96bf8faffa5..c17311c1f63 100644 --- a/pkg/workflow/copilot_participant_steps.go +++ b/pkg/workflow/copilot_participant_steps.go @@ -2,8 +2,12 @@ package workflow import ( "fmt" + + "github.com/githubnext/gh-aw/pkg/logger" ) +var copilotParticipantLog = logger.New("workflow:copilot_participant_steps") + // CopilotParticipantConfig holds configuration for generating Copilot participant steps type CopilotParticipantConfig struct { // Participants is the list of users/bots to assign/review @@ -25,7 +29,10 @@ type CopilotParticipantConfig struct { // buildCopilotParticipantSteps generates steps for adding Copilot participants (assignees or reviewers) // This function extracts the common logic between issue assignees and PR reviewers func buildCopilotParticipantSteps(config CopilotParticipantConfig) []string { + copilotParticipantLog.Printf("Building Copilot participant steps: type=%s, count=%d", config.ParticipantType, len(config.Participants)) + if len(config.Participants) == 0 { + copilotParticipantLog.Print("No participants to add, returning empty steps") return nil } @@ -50,15 +57,19 @@ func buildCopilotParticipantSteps(config CopilotParticipantConfig) []string { // Use Copilot token preference if adding copilot as participant, otherwise use regular token var effectiveToken string if hasCopilotParticipant { + copilotParticipantLog.Print("Using Copilot token preference") effectiveToken = getEffectiveCopilotGitHubToken(config.CustomToken, getEffectiveCopilotGitHubToken(config.SafeOutputsToken, config.WorkflowToken)) } else { + copilotParticipantLog.Print("Using regular GitHub token") effectiveToken = getEffectiveGitHubToken(config.CustomToken, getEffectiveGitHubToken(config.SafeOutputsToken, config.WorkflowToken)) } // Generate participant-specific steps if config.ParticipantType == "assignee" { + copilotParticipantLog.Printf("Generating issue assignee steps for %d participants", len(config.Participants)) steps = append(steps, buildIssueAssigneeSteps(config, effectiveToken)...) } else if config.ParticipantType == "reviewer" { + copilotParticipantLog.Printf("Generating PR reviewer steps for %d participants", len(config.Participants)) steps = append(steps, buildPRReviewerSteps(config, effectiveToken)...) } diff --git a/pkg/workflow/manual_approval.go b/pkg/workflow/manual_approval.go index cc6a315cadc..a6d4bbc975e 100644 --- a/pkg/workflow/manual_approval.go +++ b/pkg/workflow/manual_approval.go @@ -2,12 +2,17 @@ package workflow import ( "fmt" + + "github.com/githubnext/gh-aw/pkg/logger" ) +var manualApprovalLog = logger.New("workflow:manual_approval") + // extractManualApprovalFromOn extracts the manual-approval value from the on: section func (c *Compiler) extractManualApprovalFromOn(frontmatter map[string]any) (string, error) { onSection, exists := frontmatter["on"] if !exists { + manualApprovalLog.Print("No on: section found in frontmatter") return "", nil } @@ -15,15 +20,18 @@ func (c *Compiler) extractManualApprovalFromOn(frontmatter map[string]any) (stri switch on := onSection.(type) { case string: // Simple string format like "on: push" - no manual-approval possible + manualApprovalLog.Printf("on: section is simple string format: %s", on) return "", nil case map[string]any: // Complex object format - look for manual-approval if manualApproval, exists := on["manual-approval"]; exists { if str, ok := manualApproval.(string); ok { + manualApprovalLog.Printf("Found manual-approval configuration: %s", str) return str, nil } return "", fmt.Errorf("manual-approval value must be a string") } + manualApprovalLog.Print("on: section is object format but no manual-approval field found") return "", nil default: return "", fmt.Errorf("invalid on: section format") @@ -32,12 +40,21 @@ func (c *Compiler) extractManualApprovalFromOn(frontmatter map[string]any) (stri // processManualApprovalConfiguration extracts manual-approval configuration from frontmatter func (c *Compiler) processManualApprovalConfiguration(frontmatter map[string]any, workflowData *WorkflowData) error { + manualApprovalLog.Print("Processing manual-approval configuration") + // Extract manual-approval from the on: section manualApproval, err := c.extractManualApprovalFromOn(frontmatter) if err != nil { + manualApprovalLog.Printf("Failed to extract manual-approval: %v", err) return err } workflowData.ManualApproval = manualApproval + if manualApproval != "" { + manualApprovalLog.Printf("Manual approval configured for workflow: %s", manualApproval) + } else { + manualApprovalLog.Print("No manual approval configured for workflow") + } + return nil } diff --git a/pkg/workflow/secret_masking.go b/pkg/workflow/secret_masking.go index abdab038797..557e6406ba8 100644 --- a/pkg/workflow/secret_masking.go +++ b/pkg/workflow/secret_masking.go @@ -7,6 +7,8 @@ import ( // extractSecretMaskingConfig extracts secret-masking configuration from frontmatter func (c *Compiler) extractSecretMaskingConfig(frontmatter map[string]any) *SecretMaskingConfig { + secretMaskingLog.Print("Extracting secret-masking configuration from frontmatter") + if secretMasking, exists := frontmatter["secret-masking"]; exists { if secretMaskingMap, ok := secretMasking.(map[string]any); ok { config := &SecretMaskingConfig{} @@ -21,11 +23,13 @@ func (c *Compiler) extractSecretMaskingConfig(frontmatter map[string]any) *Secre } } config.Steps = stepsConfig + secretMaskingLog.Printf("Extracted %d secret-masking steps from frontmatter", len(stepsConfig)) } } // Return nil if no steps were found if len(config.Steps) == 0 { + secretMaskingLog.Print("No secret-masking steps found in frontmatter") return nil } @@ -33,6 +37,7 @@ func (c *Compiler) extractSecretMaskingConfig(frontmatter map[string]any) *Secre } } + secretMaskingLog.Print("No secret-masking configuration found in frontmatter") return nil } diff --git a/pkg/workflow/time_delta.go b/pkg/workflow/time_delta.go index e3fbee01245..268dbf493f0 100644 --- a/pkg/workflow/time_delta.go +++ b/pkg/workflow/time_delta.go @@ -6,8 +6,12 @@ import ( "strconv" "strings" "time" + + "github.com/githubnext/gh-aw/pkg/logger" ) +var timeDeltaLog = logger.New("workflow:time_delta") + // Pre-compiled regexes for time parsing (performance optimization) var ( timeDeltaPattern = regexp.MustCompile(`(\d+)(mo|w|d|h|m)`) @@ -53,12 +57,15 @@ func parseTimeDeltaForStopAfter(deltaStr string) (*TimeDelta, error) { // parseTimeDeltaWithMinutes parses a relative time delta string with optional minute support func parseTimeDeltaWithMinutes(deltaStr string, allowMinutes bool) (*TimeDelta, error) { + timeDeltaLog.Printf("Parsing time delta: input=%s, allowMinutes=%v", deltaStr, allowMinutes) + if deltaStr == "" { return nil, fmt.Errorf("empty time delta") } // Must start with '+' if !strings.HasPrefix(deltaStr, "+") { + timeDeltaLog.Printf("Time delta validation failed: missing '+' prefix") return nil, fmt.Errorf("time delta must start with '+', got: %s", deltaStr) } @@ -148,6 +155,7 @@ func parseTimeDeltaWithMinutes(deltaStr string, allowMinutes bool) (*TimeDelta, return nil, fmt.Errorf("time delta too large: %d minutes exceeds maximum of 525600 minutes", delta.Minutes) } + timeDeltaLog.Printf("Parsed time delta successfully: %s", delta.String()) return delta, nil } @@ -182,6 +190,8 @@ func isRelativeStopTime(stopTime string) bool { // parseAbsoluteDateTime parses various date-time formats and returns a standardized timestamp func parseAbsoluteDateTime(dateTimeStr string) (string, error) { + timeDeltaLog.Printf("Parsing absolute date-time: %s", dateTimeStr) + // Try multiple date-time formats in order of preference formats := []string{ // Standard formats @@ -236,7 +246,9 @@ func parseAbsoluteDateTime(dateTimeStr string) (string, error) { for _, format := range formats { if parsed, err := time.Parse(format, dateTimeStr); err == nil { // Successfully parsed, convert to UTC and return in standard format - return parsed.UTC().Format("2006-01-02 15:04:05"), nil + result := parsed.UTC().Format("2006-01-02 15:04:05") + timeDeltaLog.Printf("Successfully parsed date-time using format, result: %s", result) + return result, nil } } @@ -247,7 +259,9 @@ func parseAbsoluteDateTime(dateTimeStr string) (string, error) { for _, format := range formats { if parsed, err := time.Parse(format, normalizedStr); err == nil { // Successfully parsed, convert to UTC and return in standard format - return parsed.UTC().Format("2006-01-02 15:04:05"), nil + result := parsed.UTC().Format("2006-01-02 15:04:05") + timeDeltaLog.Printf("Successfully parsed date-time using ordinal normalization, result: %s", result) + return result, nil } } diff --git a/pkg/workflow/xml_comments.go b/pkg/workflow/xml_comments.go index 0cd81394f18..3a1decd6dc8 100644 --- a/pkg/workflow/xml_comments.go +++ b/pkg/workflow/xml_comments.go @@ -1,16 +1,25 @@ package workflow -import "strings" +import ( + "strings" + + "github.com/githubnext/gh-aw/pkg/logger" +) + +var xmlCommentsLog = logger.New("workflow:xml_comments") // removeXMLComments removes XML comments () from markdown content // while preserving comments that appear within code blocks func removeXMLComments(content string) string { + xmlCommentsLog.Printf("Removing XML comments from content: %d lines", len(strings.Split(content, "\n"))) + // Track if we're inside a code block to avoid removing comments in code lines := strings.Split(content, "\n") var result []string inCodeBlock := false var openMarker string inXMLComment := false + removedComments := 0 for _, line := range lines { // If we're in a code block, preserve the line as-is (ignore XML comment processing) @@ -33,6 +42,7 @@ func removeXMLComments(content string) string { // If we're in an XML comment, skip this line entirely (including code block markers) if wasInComment && isInComment { // In the middle of a comment, skip the line completely + removedComments++ continue } @@ -43,6 +53,7 @@ func removeXMLComments(content string) string { // Opening a code block openMarker, _ = extractCodeBlockMarker(trimmedLine) inCodeBlock = true + xmlCommentsLog.Printf("Detected code block opening with marker: %s", openMarker) result = append(result, processedLine) continue } @@ -65,6 +76,7 @@ func removeXMLComments(content string) string { } } + xmlCommentsLog.Printf("XML comment removal completed: removed %d comment lines, output %d lines", removedComments, len(result)) return strings.Join(result, "\n") }