Skip to content

Commit a1fddee

Browse files
committed
Create validation functions
1 parent f76e49f commit a1fddee

2 files changed

Lines changed: 72 additions & 1 deletion

File tree

pipeline.go

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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+
129161
func 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.

plugin.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,37 @@ type Step struct {
9999
Steps []Step `yaml:"steps,omitempty"`
100100
}
101101

102+
// isValid checks if a step has required fields (command, trigger, or group with steps)
103+
func (s Step) isValid() bool {
104+
if s.Group != "" {
105+
return s.hasValidNesting()
106+
}
107+
return s.hasAction()
108+
}
109+
110+
// hasAction checks if a step has a command or trigger
111+
func (s Step) hasAction() bool {
112+
return s.Command != nil || s.Commands != nil || s.Trigger != ""
113+
}
114+
115+
// hasValidNesting validates group step nesting
116+
func (s Step) hasValidNesting() bool {
117+
if s.hasAction() {
118+
return true
119+
}
120+
121+
if len(s.Steps) > 0 {
122+
for _, nestedStep := range s.Steps {
123+
if !nestedStep.isValid() {
124+
return false
125+
}
126+
}
127+
return true
128+
}
129+
130+
return false
131+
}
132+
102133
// UnmarshalJSON handles both "artifacts" and "artifact_paths" field names for backward compatibility
103134
// Both fields are supported by the Buildkite API; "artifact_paths" is preferred per documentation
104135
func (step *Step) UnmarshalJSON(data []byte) error {

0 commit comments

Comments
 (0)