-
Notifications
You must be signed in to change notification settings - Fork 18
/
validate.go
119 lines (100 loc) · 3.56 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
package validate
import (
"errors"
"fmt"
"github.com/cirruslabs/cirrus-cli/internal/commands/helpers"
"github.com/cirruslabs/cirrus-cli/internal/evaluator"
eenvironment "github.com/cirruslabs/cirrus-cli/internal/executor/environment"
"github.com/cirruslabs/cirrus-cli/pkg/executorservice"
"github.com/cirruslabs/cirrus-cli/pkg/larker/fs/local"
"github.com/cirruslabs/cirrus-cli/pkg/parser"
"github.com/cirruslabs/cirrus-cli/pkg/parser/parsererror"
"github.com/spf13/cobra"
"io"
"strings"
)
var ErrValidate = errors.New("validate failed")
// General flags.
var validateFile string
var environment []string
var shouldPrint bool
func additionalInstancesOption(stderr io.Writer) parser.Option {
// Try to retrieve additional instances from the Cirrus Cloud
additionalInstances, err := executorservice.New().SupportedInstances()
if err != nil {
_, _ = fmt.Fprintln(stderr, "failed to retrieve additional instances supported by the Cirrus Cloud,"+
"their validation will not be performed")
return parser.WithMissingInstancesAllowed()
}
transformedInstances, err := evaluator.TransformAdditionalInstances(additionalInstances)
if err != nil {
_, _ = fmt.Fprintln(stderr, "failed to parse additional instances from the Cirrus Cloud,"+
"their validation will not be performed")
return parser.WithMissingInstancesAllowed()
}
return parser.WithAdditionalInstances(transformedInstances)
}
func validate(cmd *cobra.Command, args []string) error {
// https://github.com/spf13/cobra/issues/340#issuecomment-374617413
cmd.SilenceUsage = true
// Craft the environment
baseEnvironment := eenvironment.Merge(
eenvironment.Static(),
eenvironment.BuildID(),
eenvironment.ProjectSpecific("."),
)
userSpecifiedEnvironment := helpers.EnvArgsToMap(environment)
resultingEnvironment := eenvironment.Merge(baseEnvironment, userSpecifiedEnvironment)
// Retrieve a combined YAML configuration or a specific one if asked to
var configuration string
var err error
switch {
case validateFile == "":
configuration, err = helpers.ReadCombinedConfig(cmd.Context(), resultingEnvironment)
if err != nil {
return err
}
case strings.HasSuffix(validateFile, ".yml") || strings.HasSuffix(validateFile, ".yaml"):
configuration, err = helpers.ReadYAMLConfig(validateFile)
if err != nil {
return err
}
case strings.HasSuffix(validateFile, ".star"):
configuration, err = helpers.EvaluateStarlarkConfig(cmd.Context(), validateFile, resultingEnvironment)
if err != nil {
return err
}
default:
return ErrValidate
}
if shouldPrint {
fmt.Fprint(cmd.OutOrStdout(), configuration)
}
// Parse
p := parser.New(parser.WithEnvironment(userSpecifiedEnvironment),
additionalInstancesOption(cmd.ErrOrStderr()),
parser.WithFileSystem(local.New(".")))
_, err = p.Parse(cmd.Context(), configuration)
if err != nil {
if re, ok := err.(*parsererror.Rich); ok {
fmt.Print(re.ContextLines())
}
return err
}
return nil
}
func NewValidateCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "validate",
Short: "Validate Cirrus CI configuration file",
RunE: validate,
}
// General flags
cmd.PersistentFlags().StringArrayVarP(&environment, "environment", "e", []string{},
"set (-e A=B) or pass-through (-e A) an environment variable to the Starlark interpreter")
cmd.PersistentFlags().StringVarP(&validateFile, "file", "f", "",
"use file as the configuration file (the path should end with either .yml or ..star)")
cmd.PersistentFlags().BoolVarP(&shouldPrint, "print", "p", false,
"print the configuration as YAML (useful for debugging Starlark files)")
return cmd
}