/
validate.go
147 lines (119 loc) · 4.01 KB
/
validate.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// SPDX-License-Identifier: Apache-2.0
package native
import (
"fmt"
"github.com/hashicorp/go-multierror"
"github.com/go-vela/types/yaml"
)
// Validate verifies the yaml configuration is valid.
func (c *client) Validate(p *yaml.Build) error {
var result error
// check a version is provided
if len(p.Version) == 0 {
result = multierror.Append(result, fmt.Errorf("no \"version:\" YAML property provided"))
}
// check that stages or steps are provided
if len(p.Stages) == 0 && len(p.Steps) == 0 && (!p.Metadata.RenderInline && len(p.Templates) == 0) {
result = multierror.Append(result, fmt.Errorf("no stages, steps or templates provided"))
}
// check that stages and steps aren't provided
if len(p.Stages) > 0 && len(p.Steps) > 0 {
result = multierror.Append(result, fmt.Errorf("stages and steps provided"))
}
if p.Metadata.RenderInline {
for _, step := range p.Steps {
if step.Template.Name != "" {
result = multierror.Append(result, fmt.Errorf("step %s: cannot combine render_inline and a step that references a template", step.Name))
}
}
for _, stage := range p.Stages {
for _, step := range stage.Steps {
if step.Template.Name != "" {
result = multierror.Append(result, fmt.Errorf("step %s.%s: cannot combine render_inline and a step that references a template", stage.Name, step.Name))
}
}
}
}
// validate the services block provided
err := validateServices(p.Services)
if err != nil {
result = multierror.Append(result, err)
}
// validate the stages block provided
err = validateStages(p.Stages)
if err != nil {
result = multierror.Append(result, err)
}
// validate the steps block provided
err = validateSteps(p.Steps)
if err != nil {
result = multierror.Append(result, err)
}
return result
}
// validateServices is a helper function that verifies the
// services block in the yaml configuration is valid.
func validateServices(s yaml.ServiceSlice) error {
for _, service := range s {
if len(service.Name) == 0 {
return fmt.Errorf("no name provided for service")
}
if len(service.Image) == 0 {
return fmt.Errorf("no image provided for service %s", service.Name)
}
}
return nil
}
// validateStages is a helper function that verifies the
// stages block in the yaml configuration is valid.
func validateStages(s yaml.StageSlice) error {
for _, stage := range s {
if len(stage.Name) == 0 {
return fmt.Errorf("no name provided for stage")
}
// validate that a stage is not referencing itself in needs
for _, need := range stage.Needs {
if stage.Name == need {
return fmt.Errorf("stage %s references itself in 'needs' declaration", stage.Name)
}
}
for _, step := range stage.Steps {
if len(step.Name) == 0 {
return fmt.Errorf("no name provided for step for stage %s", stage.Name)
}
if len(step.Image) == 0 {
return fmt.Errorf("no image provided for step %s for stage %s", step.Name, stage.Name)
}
if step.Name == "clone" || step.Name == "init" {
continue
}
if len(step.Commands) == 0 && len(step.Environment) == 0 &&
len(step.Parameters) == 0 && len(step.Secrets) == 0 &&
len(step.Template.Name) == 0 && !step.Detach {
return fmt.Errorf("no commands, environment, parameters, secrets or template provided for step %s for stage %s", step.Name, stage.Name)
}
}
}
return nil
}
// validateSteps is a helper function that verifies the
// steps block in the yaml configuration is valid.
func validateSteps(s yaml.StepSlice) error {
for _, step := range s {
if len(step.Name) == 0 {
return fmt.Errorf("no name provided for step")
}
if len(step.Image) == 0 {
return fmt.Errorf("no image provided for step %s", step.Name)
}
if step.Name == "clone" || step.Name == "init" {
continue
}
if len(step.Commands) == 0 && len(step.Environment) == 0 &&
len(step.Parameters) == 0 && len(step.Secrets) == 0 &&
len(step.Template.Name) == 0 && !step.Detach {
return fmt.Errorf("no commands, environment, parameters, secrets or template provided for step %s", step.Name)
}
}
return nil
}