@@ -126,6 +126,38 @@ func diff(command string) ([]string, error) {
126126 return paths , nil
127127}
128128
129+ // filterValidSteps splits steps into valid and invalid
130+ func filterValidSteps (steps []Step ) (valid []Step , invalid []Step ) {
131+ valid = []Step {}
132+ invalid = []Step {}
133+
134+ for _ , step := range steps {
135+ if step .isValid () {
136+ valid = append (valid , step )
137+ } else {
138+ invalid = append (invalid , step )
139+ }
140+ }
141+ return valid , invalid
142+ }
143+
144+ // logInvalidStep logs why a step is invalid
145+ func logInvalidStep (step Step ) {
146+ context := "empty step configuration"
147+
148+ if step .Group != "" {
149+ if len (step .Steps ) == 0 {
150+ context = fmt .Sprintf ("group '%s' has no valid nested steps" , step .Group )
151+ } else {
152+ context = fmt .Sprintf ("group '%s' has invalid nested steps" , step .Group )
153+ }
154+ } else if step .Label != "" {
155+ context = fmt .Sprintf ("step with label '%s' has no command, trigger, or group" , step .Label )
156+ }
157+
158+ log .Warnf ("Skipping invalid step: %s. Steps must have at least one of: command, commands, trigger, or group with nested steps." , context )
159+ }
160+
129161func stepsToTrigger (files []string , watch []WatchConfig ) ([]Step , error ) {
130162 steps := []Step {}
131163 var defaultStep * Step
@@ -192,7 +224,15 @@ func stepsToTrigger(files []string, watch []WatchConfig) ([]Step, error) {
192224 steps = append (steps , * defaultStep )
193225 }
194226
195- return dedupSteps (steps ), nil
227+ deduped := dedupSteps (steps )
228+ valid , invalid := filterValidSteps (deduped )
229+
230+ // Log all invalid steps with helpful context
231+ for _ , step := range invalid {
232+ logInvalidStep (step )
233+ }
234+
235+ return valid , nil
196236}
197237
198238// matchPath checks if the file f matches the path p.
0 commit comments