-
Notifications
You must be signed in to change notification settings - Fork 785
/
step_syntax_validate_pipeline.go
149 lines (126 loc) · 4 KB
/
step_syntax_validate_pipeline.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
148
149
package syntax
import (
"context"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"github.com/jenkins-x/jx/v2/pkg/cmd/opts/step"
"github.com/jenkins-x/jx/v2/pkg/cmd/helper"
"github.com/jenkins-x/jx/v2/pkg/cmd/opts"
"github.com/jenkins-x/jx/v2/pkg/cmd/templates"
"github.com/jenkins-x/jx/v2/pkg/config"
"github.com/jenkins-x/jx/v2/pkg/log"
"github.com/jenkins-x/jx/v2/pkg/util"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"sigs.k8s.io/yaml"
)
var (
validatePipeline = templates.Examples(`
# validates the jenkins-x.yml in the current directory
jx step syntax validate pipeline
# validates the jenkins-x-bdd.yml file in the current directory
jx step syntax validate pipeline --context bdd
`)
)
// StepSyntaxValidatePipelineOptions contains the command line flags
type StepSyntaxValidatePipelineOptions struct {
step.StepOptions
Context string
Dir string
}
// NewCmdStepSyntaxValidatePipeline Creates a new Command object
func NewCmdStepSyntaxValidatePipeline(commonOpts *opts.CommonOptions) *cobra.Command {
options := &StepSyntaxValidatePipelineOptions{
StepOptions: step.StepOptions{
CommonOptions: commonOpts,
},
}
cmd := &cobra.Command{
Use: "pipeline",
Short: "Validates a pipeline YAML file",
Long: "Validates the pipeline YAML file in the current directory for the given context, or jenkins-x.yml by default",
Example: validatePipeline,
Run: func(cmd *cobra.Command, args []string) {
options.Cmd = cmd
options.Args = args
err := options.Run()
helper.CheckErr(err)
},
}
cmd.Flags().StringVarP(&options.Context, "context", "c", "", "The context for the pipeline YAML to validate instead of the default.")
cmd.Flags().StringVarP(&options.Dir, "dir", "d", "", "The directory to query to find the pipeline YAML file")
return cmd
}
// Run implements this command
func (o *StepSyntaxValidatePipelineOptions) Run() error {
var err error
dir := o.Dir
if dir == "" {
dir, err = os.Getwd()
if err != nil {
return err
}
}
dirExists, err := util.DirExists(dir)
if err != nil {
return errors.Wrapf(err, "error reading directory %s", dir)
}
if !dirExists {
return fmt.Errorf("directory %s does not exist or is not a directory", dir)
}
pipelineFileName := "jenkins-x.yml"
if o.Context != "" {
pipelineFileName = fmt.Sprintf("jenkins-x-%s.yml", o.Context)
}
pipelineFile := filepath.Join(dir, pipelineFileName)
fileExists, err := util.FileExists(pipelineFile)
if err != nil {
return errors.Wrapf(err, "error reading pipeline file %s", pipelineFile)
}
if !fileExists {
return fmt.Errorf("pipeline file %s does not exist or is not a file", pipelineFile)
}
data, err := ioutil.ReadFile(pipelineFile)
if err != nil {
return errors.Wrapf(err, "Failed to load file %s", pipelineFile)
}
validationErrors, err := util.ValidateYaml(&config.ProjectConfig{}, data)
if err != nil {
return errors.Wrapf(err, "failed to perform schema validation of pipeline YAML file %s", pipelineFile)
}
if len(validationErrors) > 0 {
log.Logger().Errorf("One or more schema validation errors for %s:", pipelineFile)
for _, e := range validationErrors {
log.Logger().Errorf("\t%s", e)
}
return errors.New("FAILURE")
}
projectConfig := &config.ProjectConfig{}
err = yaml.Unmarshal(data, projectConfig)
if err != nil {
return errors.Wrapf(err, "error loading pipeline YAML file %s", pipelineFile)
}
hasErrors := false
if projectConfig.PipelineConfig != nil {
if &projectConfig.PipelineConfig.Pipelines != nil {
for name, lifecycle := range projectConfig.PipelineConfig.Pipelines.AllMap() {
if lifecycle.Pipeline != nil {
validateErr := lifecycle.Pipeline.Validate(context.Background())
if validateErr != nil {
hasErrors = true
log.Logger().Errorf("Validation errors in lifecycle %s:\n\t%s", name, validateErr)
}
}
}
} else {
log.Logger().Infof("No lifecycles defined in %s", pipelineFile)
}
}
if hasErrors {
return errors.New("FAILURE")
}
log.Logger().Infof("Successfully validated %s", pipelineFile)
return nil
}