-
Notifications
You must be signed in to change notification settings - Fork 0
/
stage.go
148 lines (127 loc) · 5.28 KB
/
stage.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
package manifest
import (
"fmt"
yaml "gopkg.in/yaml.v2"
)
// EstafetteStage represents a stage of a build pipeline or release
type EstafetteStage struct {
Name string `yaml:"-" json:",omitempty"`
ContainerImage string `yaml:"image,omitempty" json:",omitempty"`
Shell string `yaml:"shell,omitempty" json:",omitempty"`
WorkingDirectory string `yaml:"workDir,omitempty" json:",omitempty"`
Commands []string `yaml:"commands,omitempty" json:",omitempty"`
RunCommandsInForeground bool `yaml:"runCommandsInForeground,omitempty" json:",omitempty"`
When string `yaml:"when,omitempty" json:",omitempty"`
EnvVars map[string]string `yaml:"env,omitempty" json:",omitempty"`
AutoInjected bool `yaml:"autoInjected,omitempty" json:",omitempty"`
ParallelStages []*EstafetteStage `yaml:"parallelStages,omitempty" json:",omitempty"`
Services []*EstafetteService `yaml:"services,omitempty" json:",omitempty"`
CustomProperties map[string]interface{} `yaml:",inline" json:",omitempty"`
}
// UnmarshalYAML customizes unmarshalling an EstafetteStage
func (stage *EstafetteStage) UnmarshalYAML(unmarshal func(interface{}) error) (err error) {
var aux struct {
Name string `yaml:"name,omitempty"`
ContainerImage string `yaml:"image,omitempty"`
Shell string `yaml:"shell,omitempty"`
WorkingDirectory string `yaml:"workDir,omitempty"`
Commands []string `yaml:"commands,omitempty"`
RunCommandsInForeground bool `yaml:"runCommandsInForeground,omitempty"`
When string `yaml:"when,omitempty"`
EnvVars map[string]string `yaml:"env,omitempty"`
AutoInjected bool `yaml:"autoInjected,omitempty"`
ParallelStages yaml.MapSlice `yaml:"parallelStages"`
Services []*EstafetteService `yaml:"services,omitempty"`
CustomProperties map[string]interface{} `yaml:",inline"`
}
// unmarshal to auxiliary type
if err := unmarshal(&aux); err != nil {
return err
}
// map auxiliary properties
stage.Name = aux.Name
stage.ContainerImage = aux.ContainerImage
stage.Shell = aux.Shell
stage.WorkingDirectory = aux.WorkingDirectory
stage.Commands = aux.Commands
stage.RunCommandsInForeground = aux.RunCommandsInForeground
stage.When = aux.When
stage.EnvVars = aux.EnvVars
stage.AutoInjected = aux.AutoInjected
stage.Services = aux.Services
for _, mi := range aux.ParallelStages {
bytes, err := yaml.Marshal(mi.Value)
if err != nil {
return err
}
var innerStage *EstafetteStage
if err := yaml.Unmarshal(bytes, &innerStage); err != nil {
return err
}
if innerStage == nil {
innerStage = &EstafetteStage{}
}
if innerStage.Name == "" {
innerStage.Name = mi.Key.(string)
}
stage.ParallelStages = append(stage.ParallelStages, innerStage)
}
// fix for map[interface{}]interface breaking json.marshal - see https://github.com/go-yaml/yaml/issues/139
stage.CustomProperties = cleanUpStringMap(aux.CustomProperties)
return nil
}
// SetDefaults sets default values for properties of EstafetteStage if not defined
func (stage *EstafetteStage) SetDefaults(builder EstafetteBuilder) {
// set default for Shell if not set
if len(stage.ParallelStages) == 0 && stage.Shell == "" {
if builder.OperatingSystem == "windows" {
stage.Shell = "powershell"
} else {
stage.Shell = "/bin/sh"
}
}
// set default for WorkingDirectory if not set
if len(stage.ParallelStages) == 0 && stage.WorkingDirectory == "" {
if builder.OperatingSystem == "windows" {
stage.WorkingDirectory = "C:/estafette-work"
} else {
stage.WorkingDirectory = "/estafette-work"
}
}
// set default for When if not set
if stage.When == "" {
stage.When = "status == 'succeeded'"
}
// set defaults for inner stages
for _, s := range stage.ParallelStages {
s.SetDefaults(builder)
}
for _, svc := range stage.Services {
svc.SetDefaults(builder, *stage)
}
}
// Validate checks whether the stage has valid parameters
func (stage *EstafetteStage) Validate() (err error) {
if len(stage.ParallelStages) > 0 {
if stage.ContainerImage != "" {
return fmt.Errorf("Stage %v cannot use parameters parallelStages and image at the same time", stage.Name)
}
if stage.Shell != "" {
return fmt.Errorf("Stage %v cannot use parameters parallelStages and shell at the same time", stage.Name)
}
if stage.WorkingDirectory != "" {
return fmt.Errorf("Stage %v cannot use parameters parallelStages and workDir at the same time", stage.Name)
}
if len(stage.Commands) > 0 {
return fmt.Errorf("Stage %v cannot use parameters parallelStages and commands at the same time", stage.Name)
}
if len(stage.EnvVars) > 0 {
return fmt.Errorf("Stage %v cannot use parameters parallelStages and env at the same time", stage.Name)
}
} else {
if stage.ContainerImage == "" && len(stage.Services) == 0 {
return fmt.Errorf("Stage %v has no image set", stage.Name)
}
}
return nil
}