1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
class DeploymentStrategy extends ViewableData { |
4
|
|
|
|
5
|
|
|
const SUCCESS_CODE = 'success'; |
6
|
|
|
|
7
|
|
|
const WARNING_CODE = 'warning'; |
8
|
|
|
|
9
|
|
|
const ERROR_CODE = 'error'; |
10
|
|
|
|
11
|
|
|
/** |
12
|
|
|
* @var DNEnvironment |
13
|
|
|
*/ |
14
|
|
|
protected $environment; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* @var string |
18
|
|
|
*/ |
19
|
|
|
protected $actionTitle = 'Deploy'; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* @var string |
23
|
|
|
*/ |
24
|
|
|
protected $actionCode = 'default'; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* @var int |
28
|
|
|
*/ |
29
|
|
|
protected $estimatedTime = 0; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* @var array |
33
|
|
|
*/ |
34
|
|
|
protected $changes = []; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* @var array |
38
|
|
|
*/ |
39
|
|
|
protected $options; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* Validation code |
43
|
|
|
* |
44
|
|
|
* @var string |
45
|
|
|
*/ |
46
|
|
|
protected $validationCode = DeploymentStrategy::SUCCESS_CODE; |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* @var array |
50
|
|
|
*/ |
51
|
|
|
protected $messages = []; |
52
|
|
|
|
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* @param DNEnvironment $environment |
56
|
|
|
* @param array $options |
57
|
|
|
*/ |
58
|
|
|
public function __construct(DNEnvironment $environment, $options = array()) { |
59
|
|
|
$this->environment = $environment; |
60
|
|
|
$this->options = $options; |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* @param string $title |
65
|
|
|
*/ |
66
|
|
|
public function setActionTitle($title) { |
67
|
|
|
$this->actionTitle = $title; |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* @return string |
72
|
|
|
*/ |
73
|
|
|
public function getActionTitle() { |
74
|
|
|
return $this->actionTitle; |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
*/ |
79
|
|
|
public function setActionCode($code) { |
80
|
|
|
$this->actionCode = $code; |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
/** |
84
|
|
|
* @return string |
85
|
|
|
*/ |
86
|
|
|
public function getActionCode() { |
87
|
|
|
return $this->actionCode; |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
/** |
91
|
|
|
* @param int |
92
|
|
|
*/ |
93
|
|
|
public function setEstimatedTime($seconds) { |
94
|
|
|
$this->estimatedTime = $seconds; |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* @return int Time in minutes |
99
|
|
|
*/ |
100
|
|
|
public function getEstimatedTime() { |
101
|
|
|
return $this->estimatedTime; |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* @param string $title |
106
|
|
|
* @param string $from |
107
|
|
|
* @param string $to |
108
|
|
|
*/ |
109
|
|
|
public function setChange($title, $from, $to) { |
110
|
|
|
// Normalise "empty" values into dashes so comparisons are done properly. |
111
|
|
|
// This means there is no diference between an empty string and a null |
112
|
|
|
// but "0" is considered to be non-empty. |
113
|
|
|
if(empty($from) && !strlen($from)) $from = '-'; |
114
|
|
|
if(empty($to) && !strlen($to)) $to = '-'; |
115
|
|
|
|
116
|
|
|
return $this->changes[$title] = array( |
117
|
|
|
'from' => $from, |
118
|
|
|
'to' => $to |
119
|
|
|
); |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* @param string $title |
124
|
|
|
* @param string $desc |
125
|
|
|
*/ |
126
|
|
|
public function setChangeDescriptionOnly($title, $desc) { |
127
|
|
|
return $this->changes[$title] = array( |
128
|
|
|
'description' => $desc |
129
|
|
|
); |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* Filter the changeset where modification was not required. |
134
|
|
|
* |
135
|
|
|
* @return array |
136
|
|
|
*/ |
137
|
|
|
public function getChangesModificationNeeded() { |
138
|
|
|
$filtered = []; |
139
|
|
|
foreach ($this->changes as $change => $details) { |
140
|
|
|
if (array_key_exists('description', $details)) { |
141
|
|
|
$filtered[$change] = $details; |
142
|
|
|
} else if ( |
143
|
|
|
(array_key_exists('from', $details) || array_key_exists('to', $details)) |
144
|
|
|
&& $details['from'] !== $details['to'] |
145
|
|
|
) { |
146
|
|
|
$filtered[$change] = $details; |
147
|
|
|
} |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
return $filtered; |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
/** |
154
|
|
|
* @return array Associative array of changes, e.g. |
155
|
|
|
* array( |
156
|
|
|
* 'SHA' => array( |
157
|
|
|
* 'from' => 'abc', |
158
|
|
|
* 'to' => 'def' |
159
|
|
|
* ) |
160
|
|
|
* ) |
161
|
|
|
*/ |
162
|
|
|
public function getChanges() { |
163
|
|
|
return $this->changes; |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* Returns a change or a given key. |
168
|
|
|
* |
169
|
|
|
* @return ArrayData|null |
170
|
|
|
*/ |
171
|
|
|
public function getChange($key) { |
172
|
|
|
$changes = $this->getChanges(); |
173
|
|
|
if(array_key_exists($key, $changes)) { |
174
|
|
|
return new ArrayData($changes[$key]); |
175
|
|
|
} |
176
|
|
|
return null; |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
/** |
180
|
|
|
* @param string $option |
181
|
|
|
* @param string $value |
182
|
|
|
*/ |
183
|
|
|
public function setOption($option, $value) { |
184
|
|
|
$this->options[$option] = $value; |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
/** |
188
|
|
|
* @param string $option |
189
|
|
|
* @return string|null |
190
|
|
|
*/ |
191
|
|
|
public function getOption($option) { |
192
|
|
|
if(!empty($this->options[$option])) { |
193
|
|
|
return $this->options[$option]; |
194
|
|
|
} |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
/** |
198
|
|
|
* @return string |
199
|
|
|
*/ |
200
|
|
|
public function getOptions() { |
201
|
|
|
return $this->options; |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
/** |
205
|
|
|
* @param string $code |
206
|
|
|
*/ |
207
|
|
|
public function setValidationCode($code) { |
208
|
|
|
$this->validationCode = $code; |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
/** |
212
|
|
|
* @return string |
213
|
|
|
*/ |
214
|
|
|
public function getValidationCode() { |
215
|
|
|
return $this->validationCode; |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
/** |
219
|
|
|
* @param string $msg |
220
|
|
|
*/ |
221
|
|
|
public function setMessage($msg, $code = self::ERROR_CODE) { |
222
|
|
|
$this->messages[] = [ |
223
|
|
|
'text' => $msg, |
224
|
|
|
'code' => $code |
225
|
|
|
]; |
226
|
|
|
|
227
|
|
|
$current = $this->getValidationCode(); |
228
|
|
|
$map = [ |
229
|
|
|
DeploymentStrategy::SUCCESS_CODE => 0, |
230
|
|
|
DeploymentStrategy::WARNING_CODE => 1, |
231
|
|
|
DeploymentStrategy::ERROR_CODE => 2 |
232
|
|
|
]; |
233
|
|
|
if($map[$current] < $map[$code]) { |
234
|
|
|
$this->setValidationCode($code); |
235
|
|
|
} |
236
|
|
|
} |
237
|
|
|
|
238
|
|
|
/** |
239
|
|
|
* @return array |
240
|
|
|
*/ |
241
|
|
|
public function getMessages() { |
242
|
|
|
return $this->messages; |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
/** |
246
|
|
|
* Transform the deployment strategy to an array. |
247
|
|
|
* |
248
|
|
|
* @return array |
249
|
|
|
*/ |
250
|
|
View Code Duplication |
public function toArray() { |
|
|
|
|
251
|
|
|
$fields = array( |
252
|
|
|
'actionTitle', |
253
|
|
|
'actionCode', |
254
|
|
|
'estimatedTime', |
255
|
|
|
'changes', |
256
|
|
|
'options', |
257
|
|
|
'validationCode', |
258
|
|
|
'messages' |
259
|
|
|
); |
260
|
|
|
|
261
|
|
|
$output = array(); |
262
|
|
|
foreach($fields as $field) { |
263
|
|
|
$output[$field] = $this->$field; |
264
|
|
|
} |
265
|
|
|
return $output; |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
/** |
269
|
|
|
* @return string |
270
|
|
|
*/ |
271
|
|
|
public function toJSON() { |
272
|
|
|
return json_encode($this->toArray(), JSON_PRETTY_PRINT); |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
/** |
276
|
|
|
* Load from JSON associative array. |
277
|
|
|
* Environment must be set by the callee when creating this object. |
278
|
|
|
* |
279
|
|
|
* @param string $json |
280
|
|
|
*/ |
281
|
|
|
public function fromJSON($json) { |
282
|
|
|
$decoded = json_decode($json, true); |
283
|
|
|
return $this->fromArray($decoded); |
284
|
|
|
} |
285
|
|
|
|
286
|
|
|
/** |
287
|
|
|
* Load from array. |
288
|
|
|
* Environment must be set by the callee when creating this object. |
289
|
|
|
* |
290
|
|
|
* @param string $data |
291
|
|
|
*/ |
292
|
|
View Code Duplication |
public function fromArray($data) { |
|
|
|
|
293
|
|
|
$fields = array( |
294
|
|
|
'actionTitle', |
295
|
|
|
'actionCode', |
296
|
|
|
'estimatedTime', |
297
|
|
|
'changes', |
298
|
|
|
'options', |
299
|
|
|
'validationCode', |
300
|
|
|
'messages' |
301
|
|
|
); |
302
|
|
|
|
303
|
|
|
foreach($fields as $field) { |
304
|
|
|
if(!empty($data[$field])) { |
305
|
|
|
$this->$field = $data[$field]; |
306
|
|
|
} |
307
|
|
|
} |
308
|
|
|
} |
309
|
|
|
|
310
|
|
|
/** |
311
|
|
|
* @return DNDeployment |
312
|
|
|
*/ |
313
|
|
|
public function createDeployment() { |
314
|
|
|
$deployment = DNDeployment::create(); |
315
|
|
|
$deployment->EnvironmentID = $this->environment->ID; |
316
|
|
|
// Pull out the SHA from the options so we can make it queryable. |
317
|
|
|
$deployment->SHA = $this->getOption('sha'); |
318
|
|
|
$deployment->Strategy = $this->toJSON(); |
|
|
|
|
319
|
|
|
$deployment->write(); |
320
|
|
|
|
321
|
|
|
return $deployment; |
322
|
|
|
} |
323
|
|
|
|
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.