detectWorkflowScheduleInfo extracts the schedule expression and classifies its frequency from workflow content. Returns a scheduleDetection struct. Workflows whose "on:" field is a simple string schedule, or a map containing a "schedule" key, are considered updatable. For multi-trigger workflows (w
(content string)
| 48 | // schedule/workflow_dispatch), IsMultiTrigger is set so the caller knows to update the |
| 49 | // "schedule" sub-field rather than the entire "on:" field. |
| 50 | func detectWorkflowScheduleInfo(content string) scheduleDetection { |
| 51 | result, err := parser.ExtractFrontmatterFromContent(content) |
| 52 | if err != nil || result.Frontmatter == nil { |
| 53 | return scheduleDetection{} |
| 54 | } |
| 55 | |
| 56 | onValue, exists := result.Frontmatter["on"] |
| 57 | if !exists { |
| 58 | return scheduleDetection{} |
| 59 | } |
| 60 | |
| 61 | // Case 1: on is a simple string (e.g., "on: daily" or "on: 0 * * * *") |
| 62 | if onStr, ok := onValue.(string); ok { |
| 63 | _, _, parseErr := parser.ParseSchedule(onStr) |
| 64 | if parseErr == nil { |
| 65 | return scheduleDetection{ |
| 66 | RawExpr: onStr, |
| 67 | Frequency: classifyScheduleFrequency(onStr), |
| 68 | IsUpdatable: true, |
| 69 | IsOnMap: false, |
| 70 | } |
| 71 | } |
| 72 | return scheduleDetection{} |
| 73 | } |
| 74 | |
| 75 | // Case 2: on is a map — extract schedule value if present |
| 76 | if onMap, ok := onValue.(map[string]any); ok { |
| 77 | schedValue, hasSchedule := onMap["schedule"] |
| 78 | if !hasSchedule { |
| 79 | return scheduleDetection{} |
| 80 | } |
| 81 | |
| 82 | // Determine if on: has triggers beyond schedule / workflow_dispatch |
| 83 | isMultiTrigger := false |
| 84 | for key := range onMap { |
| 85 | if key != "schedule" && key != "workflow_dispatch" { |
| 86 | isMultiTrigger = true |
| 87 | scheduleWizardLog.Printf("Multi-trigger on: map detected (trigger '%s')", key) |
| 88 | break |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | // Schedule as string shorthand (e.g., "schedule: daily") |
| 93 | if schedStr, ok := schedValue.(string); ok { |
| 94 | return scheduleDetection{ |
| 95 | RawExpr: schedStr, |
| 96 | Frequency: classifyScheduleFrequency(schedStr), |
| 97 | IsUpdatable: true, |
| 98 | IsMultiTrigger: isMultiTrigger, |
| 99 | IsOnMap: true, |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | // Schedule as array (e.g., "schedule:\n - cron: daily") |
| 104 | if schedArray, ok := schedValue.([]any); ok && len(schedArray) > 0 { |
| 105 | // Workflows with multiple cron entries cannot be safely rewritten to a single |
| 106 | // frequency, so mark them as not updatable. |
| 107 | if len(schedArray) > 1 { |