shipit-engine 0.8.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +92 -2
- data/app/assets/stylesheets/_pages/_commits.scss +3 -0
- data/app/assets/stylesheets/_pages/_deploy.scss +9 -0
- data/app/assets/stylesheets/_structure/_layout.scss +9 -0
- data/app/jobs/shipit/perform_task_job.rb +1 -1
- data/app/models/shipit/commit.rb +3 -7
- data/app/models/shipit/commit_deployment.rb +1 -0
- data/app/models/shipit/deploy.rb +1 -1
- data/app/models/shipit/deploy_spec.rb +28 -5
- data/app/models/shipit/deploy_spec/file_system.rb +15 -6
- data/app/models/shipit/hook.rb +2 -0
- data/app/models/shipit/stack.rb +22 -3
- data/app/models/shipit/status.rb +10 -0
- data/app/models/shipit/task.rb +0 -4
- data/app/models/shipit/unknown_status.rb +1 -0
- data/app/views/layouts/shipit.html.erb +1 -0
- data/app/views/shipit/stacks/new.html.erb +1 -1
- data/app/views/shipit/statuses/_group.html.erb +1 -1
- data/app/views/shipit/tasks/_task_output.html.erb +20 -17
- data/lib/shipit.rb +1 -0
- data/lib/shipit/task_commands.rb +4 -0
- data/lib/shipit/version.rb +1 -1
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/jobs/perform_task_job_test.rb +2 -2
- data/test/models/commit_deployment_test.rb +1 -0
- data/test/models/stacks_test.rb +45 -0
- data/test/models/status_test.rb +9 -0
- data/test/unit/deploy_commands_test.rb +12 -0
- data/test/unit/deploy_spec_test.rb +40 -7
- metadata +2 -4
- data/test/dummy/README.rdoc +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 044a58eabe4689b586de4daf11cca00b72cf7d37
|
4
|
+
data.tar.gz: 39509907d1d0ae00f7573f699b6c2c9e63cf9999
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eef3d23d0c0b3cb858e7986332fda01cbfcfdc02a48cb7b3ea486d304e818366ea9365db89b1657354f3e90bb3ccb49818a0ea667c141eb6e39207d95ea2ab89
|
7
|
+
data.tar.gz: 1f96ec3403295af649196bcdc38a13bdbe6212931022ccb1b7882e638f3d4a80f8f820dc3fdb7b39ee7b4e45ff450c59d79626799a0fb5f2f212d415d818e46a
|
data/README.md
CHANGED
@@ -118,7 +118,7 @@ The settings in the `shipit.yml` file relate to the different things you can do
|
|
118
118
|
|
119
119
|
* [Installing dependencies](#installing-dependencies) (`dependencies`)
|
120
120
|
* [Deployment](#deployment) (`deploy`, `rollback`, `fetch`)
|
121
|
-
* [Environment](#environment) (`machine.environment`)
|
121
|
+
* [Environment](#environment) (`machine.environment`, `machine.directory`, `machine.cleanup`)
|
122
122
|
* [CI](#ci) (`ci.require`, `ci.hide`, `ci.allow_failures`)
|
123
123
|
* [Custom tasks](#custom-tasks) (`restart`, `unlock`)
|
124
124
|
* [Review Process](#review-process) (`monitor`, `checklist`, `checks`)
|
@@ -172,9 +172,33 @@ dependencies:
|
|
172
172
|
- npm install
|
173
173
|
```
|
174
174
|
|
175
|
+
**<code>dependencies.pre</code>** If you wish to execute commands before Shipit install the dependencies you can specify them here:
|
176
|
+
|
177
|
+
For example:
|
178
|
+
|
179
|
+
```yml
|
180
|
+
depedencies:
|
181
|
+
pre:
|
182
|
+
- mkdir tmp/
|
183
|
+
- cp -R /var/cache/ tmp/cache
|
184
|
+
```
|
185
|
+
<br>
|
186
|
+
|
187
|
+
**<code>dependencies.post</code>** If you wish to execute commands after Shipit installed the dependencies you can specify them here:
|
188
|
+
|
189
|
+
For example:
|
190
|
+
|
191
|
+
```yml
|
192
|
+
depedencies:
|
193
|
+
post:
|
194
|
+
- cp -R tmp/cache /var/cache/
|
195
|
+
```
|
196
|
+
<br>
|
197
|
+
|
198
|
+
|
175
199
|
<h3 id="deployment">Deployment</h3>
|
176
200
|
|
177
|
-
The `
|
201
|
+
The `deploy` and `rollback` sections are the core of Shipit:
|
178
202
|
|
179
203
|
**<code>deploy.override</code>** contains an array of the shell commands required to deploy the application. Shipit will try to infer it from the repository structure, but you can change the default inference.
|
180
204
|
|
@@ -187,6 +211,29 @@ deploy:
|
|
187
211
|
```
|
188
212
|
<br>
|
189
213
|
|
214
|
+
**<code>deploy.pre</code>** If you wish to execute commands before Shipit execute your deploy script you can specify them here:
|
215
|
+
|
216
|
+
For example:
|
217
|
+
|
218
|
+
```yml
|
219
|
+
deploy:
|
220
|
+
pre:
|
221
|
+
- ./script/notify_deploy_start
|
222
|
+
```
|
223
|
+
<br>
|
224
|
+
|
225
|
+
**<code>deploy.post</code>** If you wish to execute commands after Shipit executed your deploy script you can specify them here:
|
226
|
+
|
227
|
+
For example:
|
228
|
+
|
229
|
+
```yml
|
230
|
+
deploy:
|
231
|
+
post:
|
232
|
+
- ./script/notify_deploy_end
|
233
|
+
```
|
234
|
+
<br>
|
235
|
+
|
236
|
+
|
190
237
|
You can also accept custom environment variables defined by the user that trigger the deploy:
|
191
238
|
|
192
239
|
**<code>deploy.variables</code>** contains an array of variable definitions.
|
@@ -214,6 +261,29 @@ rollback:
|
|
214
261
|
```
|
215
262
|
<br>
|
216
263
|
|
264
|
+
**<code>rollback.pre</code>** If you wish to execute commands before Shipit execute your rollback script you can specify them here:
|
265
|
+
|
266
|
+
For example:
|
267
|
+
|
268
|
+
```yml
|
269
|
+
rollback:
|
270
|
+
pre:
|
271
|
+
- ./script/notify_rollback_start
|
272
|
+
```
|
273
|
+
<br>
|
274
|
+
|
275
|
+
**<code>rollback.post</code>** If you wish to execute commands after Shipit executed your rollback script you can specify them here:
|
276
|
+
|
277
|
+
For example:
|
278
|
+
|
279
|
+
```yml
|
280
|
+
rollback:
|
281
|
+
post:
|
282
|
+
- ./script/notify_rollback_end
|
283
|
+
```
|
284
|
+
<br>
|
285
|
+
|
286
|
+
|
217
287
|
**<code>fetch</code>** contains an array of the shell commands that Shipit executes to check the revision of the currently-deployed version. This key defaults to disabled.
|
218
288
|
|
219
289
|
For example:
|
@@ -232,6 +302,26 @@ machine:
|
|
232
302
|
key: val # things added as environment variables
|
233
303
|
```
|
234
304
|
|
305
|
+
<h3 id="directory">Directory</h3>
|
306
|
+
|
307
|
+
**<code>machine.directory</code>** specify a subfolder in which to execute all tasks. Useful for repositories containing multiple applications or if you don't want your deploy scripts to be located at the root.
|
308
|
+
|
309
|
+
For example:
|
310
|
+
```yml
|
311
|
+
machine:
|
312
|
+
directory: scripts/deploy/
|
313
|
+
```
|
314
|
+
|
315
|
+
<h3 id="cleanup">Cleanup</h3>
|
316
|
+
|
317
|
+
**<code>machine.cleanup</code>** specify wether or not the deploy working directory should cleaned up once the deploy completed. Defaults to `true`, but can be useful to disable temporarily to investigate bugs.
|
318
|
+
|
319
|
+
For example:
|
320
|
+
```yml
|
321
|
+
machine:
|
322
|
+
cleanup: false
|
323
|
+
```
|
324
|
+
|
235
325
|
<h3 id="ci">CI</h3>
|
236
326
|
**<code>ci.require</code>** contains an array of the [statuses context](https://developer.github.com/v3/repos/statuses/) you want Shipit to disallow deploys if any of them is missing.
|
237
327
|
|
@@ -63,9 +63,14 @@
|
|
63
63
|
flex-wrap: wrap;
|
64
64
|
|
65
65
|
.deploy-banner-section {
|
66
|
+
display: inline-block;
|
66
67
|
padding: .95rem 1.5rem 1.125rem;
|
67
68
|
}
|
68
69
|
|
70
|
+
.stack-link {
|
71
|
+
display: none;
|
72
|
+
}
|
73
|
+
|
69
74
|
.action-buttons {
|
70
75
|
flex: none;
|
71
76
|
}
|
@@ -75,6 +80,10 @@
|
|
75
80
|
top: 0;
|
76
81
|
left: 0;
|
77
82
|
right: 0;
|
83
|
+
|
84
|
+
.stack-link {
|
85
|
+
display: inline-block;
|
86
|
+
}
|
78
87
|
}
|
79
88
|
|
80
89
|
&[data-status="running"]:before,
|
@@ -38,6 +38,15 @@
|
|
38
38
|
margin: .4em .5em .4em 0;
|
39
39
|
}
|
40
40
|
|
41
|
+
.powered-by {
|
42
|
+
float: right;
|
43
|
+
position: relative;
|
44
|
+
top: .5rem;
|
45
|
+
right: 1rem;
|
46
|
+
font-size: 12px;
|
47
|
+
color: #999;
|
48
|
+
}
|
49
|
+
|
41
50
|
|
42
51
|
// LOGO
|
43
52
|
// -----------------------------------------------------------------------------
|
data/app/models/shipit/commit.rb
CHANGED
@@ -9,7 +9,7 @@ module Shipit
|
|
9
9
|
after_commit { broadcast_update }
|
10
10
|
after_create { stack.update_undeployed_commits_count }
|
11
11
|
|
12
|
-
after_commit :schedule_refresh_statuses!, :schedule_fetch_stats!, on: :create
|
12
|
+
after_commit :schedule_refresh_statuses!, :schedule_fetch_stats!, :schedule_continuous_delivery, on: :create
|
13
13
|
|
14
14
|
after_touch :touch_stack
|
15
15
|
|
@@ -92,7 +92,7 @@ module Shipit
|
|
92
92
|
|
93
93
|
payload = {commit: self, stack: stack, status: new_status.state}
|
94
94
|
Hook.emit(:commit_status, stack, payload.merge(commit_status: new_status)) if previous_status != new_status
|
95
|
-
if simple_state
|
95
|
+
if previous_status.simple_state != new_status.simple_state && !new_status.pending?
|
96
96
|
Hook.emit(:deployable_status, stack, payload.merge(deployable_status: new_status))
|
97
97
|
end
|
98
98
|
new_status
|
@@ -141,7 +141,7 @@ module Shipit
|
|
141
141
|
end
|
142
142
|
|
143
143
|
def schedule_continuous_delivery
|
144
|
-
return unless
|
144
|
+
return unless deployable? && stack.continuous_deployment? && stack.deployable?
|
145
145
|
ContinuousDeliveryJob.perform_later(stack)
|
146
146
|
end
|
147
147
|
|
@@ -199,9 +199,5 @@ module Shipit
|
|
199
199
|
def touch_stack
|
200
200
|
stack.touch
|
201
201
|
end
|
202
|
-
|
203
|
-
def simple_state(status)
|
204
|
-
status.state == 'error' ? 'failure' : status.state
|
205
|
-
end
|
206
202
|
end
|
207
203
|
end
|
data/app/models/shipit/deploy.rb
CHANGED
@@ -14,7 +14,7 @@ module Shipit
|
|
14
14
|
has_many :commit_deployments, inverse_of: :task, foreign_key: :task_id do
|
15
15
|
GITHUB_STATUSES = {
|
16
16
|
'pending' => 'pending',
|
17
|
-
'failed' => '
|
17
|
+
'failed' => 'failure',
|
18
18
|
'success' => 'success',
|
19
19
|
'error' => 'error',
|
20
20
|
'aborted' => 'error',
|
@@ -29,8 +29,15 @@ module Shipit
|
|
29
29
|
self
|
30
30
|
end
|
31
31
|
|
32
|
-
def config(*keys)
|
33
|
-
|
32
|
+
def config(*keys, &default)
|
33
|
+
default ||= -> { nil }
|
34
|
+
keys.flatten.reduce(@config) do |hash, key|
|
35
|
+
if hash.is_a?(Hash)
|
36
|
+
hash.fetch(key) { return default.call }
|
37
|
+
else
|
38
|
+
return default.call
|
39
|
+
end
|
40
|
+
end
|
34
41
|
end
|
35
42
|
|
36
43
|
def supports_fetch_deployed_revision?
|
@@ -50,12 +57,16 @@ module Shipit
|
|
50
57
|
end
|
51
58
|
|
52
59
|
def dependencies_steps
|
53
|
-
|
60
|
+
around_steps('dependencies') do
|
61
|
+
config('dependencies', 'override') { discover_dependencies_steps || [] }
|
62
|
+
end
|
54
63
|
end
|
55
64
|
alias_method :dependencies_steps!, :dependencies_steps
|
56
65
|
|
57
66
|
def deploy_steps
|
58
|
-
|
67
|
+
around_steps('deploy') do
|
68
|
+
config('deploy', 'override') { discover_deploy_steps }
|
69
|
+
end
|
59
70
|
end
|
60
71
|
|
61
72
|
def deploy_steps!
|
@@ -67,7 +78,9 @@ module Shipit
|
|
67
78
|
end
|
68
79
|
|
69
80
|
def rollback_steps
|
70
|
-
|
81
|
+
around_steps('rollback') do
|
82
|
+
config('rollback', 'override') { discover_rollback_steps }
|
83
|
+
end
|
71
84
|
end
|
72
85
|
|
73
86
|
def rollback_steps!
|
@@ -126,8 +139,18 @@ module Shipit
|
|
126
139
|
config('plugins') || {}
|
127
140
|
end
|
128
141
|
|
142
|
+
def clear_working_directory?
|
143
|
+
config('machine', 'cleanup') { true }
|
144
|
+
end
|
145
|
+
|
129
146
|
private
|
130
147
|
|
148
|
+
def around_steps(section)
|
149
|
+
steps = yield
|
150
|
+
return unless steps
|
151
|
+
config(section, 'pre') { [] } + steps + config(section, 'post') { [] }
|
152
|
+
end
|
153
|
+
|
131
154
|
def coerce_task_definition(config)
|
132
155
|
config
|
133
156
|
end
|
@@ -15,6 +15,14 @@ module Shipit
|
|
15
15
|
DeploySpec.new(cacheable_config)
|
16
16
|
end
|
17
17
|
|
18
|
+
def file(path, root: false)
|
19
|
+
if root || directory.blank?
|
20
|
+
@app_dir.join(path)
|
21
|
+
else
|
22
|
+
Pathname.new(File.join(@app_dir, directory, path))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
18
26
|
private
|
19
27
|
|
20
28
|
def cacheable_config
|
@@ -24,7 +32,11 @@ module Shipit
|
|
24
32
|
'allow_failures' => soft_failing_statuses,
|
25
33
|
'require' => required_statuses,
|
26
34
|
},
|
27
|
-
'machine' => {
|
35
|
+
'machine' => {
|
36
|
+
'environment' => machine_env,
|
37
|
+
'directory' => directory,
|
38
|
+
'cleanup' => true,
|
39
|
+
},
|
28
40
|
'review' => {
|
29
41
|
'checklist' => review_checklist,
|
30
42
|
'monitoring' => review_monitoring,
|
@@ -49,16 +61,13 @@ module Shipit
|
|
49
61
|
end
|
50
62
|
|
51
63
|
def load_config
|
52
|
-
read_config(file("shipit.#{@env}.yml")) ||
|
64
|
+
read_config(file("shipit.#{@env}.yml", root: true)) ||
|
65
|
+
read_config(file('shipit.yml', root: true))
|
53
66
|
end
|
54
67
|
|
55
68
|
def read_config(path)
|
56
69
|
SafeYAML.load(path.read) if path.exist?
|
57
70
|
end
|
58
|
-
|
59
|
-
def file(path)
|
60
|
-
@app_dir.join(path)
|
61
|
-
end
|
62
71
|
end
|
63
72
|
end
|
64
73
|
end
|
data/app/models/shipit/hook.rb
CHANGED
@@ -15,6 +15,7 @@ module Shipit
|
|
15
15
|
lock
|
16
16
|
commit_status
|
17
17
|
deployable_status
|
18
|
+
merge_status
|
18
19
|
).freeze
|
19
20
|
|
20
21
|
belongs_to :stack, required: false
|
@@ -32,6 +33,7 @@ module Shipit
|
|
32
33
|
|
33
34
|
class << self
|
34
35
|
def emit(event, stack, payload)
|
36
|
+
raise "#{event} is not declared in Shipit::Hook::EVENTS" unless EVENTS.include?(event.to_s)
|
35
37
|
Shipit::EmitEventJob.perform_later(
|
36
38
|
event: event.to_s,
|
37
39
|
stack_id: stack.try!(:id),
|
data/app/models/shipit/stack.rb
CHANGED
@@ -32,6 +32,7 @@ module Shipit
|
|
32
32
|
after_commit :emit_updated_hooks, on: :update
|
33
33
|
after_commit :emit_removed_hooks, on: :destroy
|
34
34
|
after_commit :broadcast_update, on: :update
|
35
|
+
after_commit :emit_merge_status_hooks, on: :update
|
35
36
|
after_commit :setup_hooks, :sync_github, on: :create
|
36
37
|
after_touch :clear_cache
|
37
38
|
|
@@ -116,11 +117,25 @@ module Shipit
|
|
116
117
|
commits.reachable.first.try!(:sha)
|
117
118
|
end
|
118
119
|
|
120
|
+
def merge_status
|
121
|
+
if locked?
|
122
|
+
'locked'
|
123
|
+
else
|
124
|
+
significant_statuses = undeployed_commits.map(&:significant_status)
|
125
|
+
last_finalized_status = significant_statuses.reject { |s| %w(pending unknown).include?(s.state) }.first
|
126
|
+
last_finalized_status.try!(:simple_state) || 'pending'
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
119
130
|
def status
|
120
131
|
return :deploying if active_task?
|
121
132
|
:default
|
122
133
|
end
|
123
134
|
|
135
|
+
def undeployed_commits
|
136
|
+
commits.reachable.newer_than(last_deployed_commit).order(id: :desc)
|
137
|
+
end
|
138
|
+
|
124
139
|
def last_successful_deploy
|
125
140
|
deploys_and_rollbacks.success.order(created_at: :desc).first
|
126
141
|
end
|
@@ -150,11 +165,11 @@ module Shipit
|
|
150
165
|
end
|
151
166
|
|
152
167
|
def repo_name=(name)
|
153
|
-
super(name.try(:downcase))
|
168
|
+
super(name.try!(:downcase))
|
154
169
|
end
|
155
170
|
|
156
171
|
def repo_owner=(name)
|
157
|
-
super(name.try(:downcase))
|
172
|
+
super(name.try!(:downcase))
|
158
173
|
end
|
159
174
|
|
160
175
|
def repo_http_url
|
@@ -250,7 +265,7 @@ module Shipit
|
|
250
265
|
|
251
266
|
def update_undeployed_commits_count(after_commit = nil)
|
252
267
|
after_commit ||= last_deployed_commit
|
253
|
-
undeployed_commits = commits.reachable.select('count(*) as count')
|
268
|
+
undeployed_commits = commits.reachable.newer_than(after_commit).select('count(*) as count')
|
254
269
|
self.class.where(id: id).update_all("undeployed_commits_count = (#{undeployed_commits.to_sql})")
|
255
270
|
end
|
256
271
|
|
@@ -335,6 +350,10 @@ module Shipit
|
|
335
350
|
Hook.emit(:stack, self, action: :removed, stack: self)
|
336
351
|
end
|
337
352
|
|
353
|
+
def emit_merge_status_hooks
|
354
|
+
Hook.emit(:merge_status, self, merge_status: merge_status, stack: self)
|
355
|
+
end
|
356
|
+
|
338
357
|
def ci_enabled_cache_key
|
339
358
|
"stacks:#{id}:ci_enabled"
|
340
359
|
end
|
data/app/models/shipit/status.rb
CHANGED
@@ -23,10 +23,20 @@ module Shipit
|
|
23
23
|
)
|
24
24
|
end
|
25
25
|
|
26
|
+
delegate :stack, to: :commit
|
27
|
+
|
28
|
+
def ignored?
|
29
|
+
stack.soft_failing_statuses.include?(context)
|
30
|
+
end
|
31
|
+
|
26
32
|
def group?
|
27
33
|
false
|
28
34
|
end
|
29
35
|
|
36
|
+
def simple_state
|
37
|
+
state == 'error' ? 'failure' : state
|
38
|
+
end
|
39
|
+
|
30
40
|
private
|
31
41
|
|
32
42
|
def enable_ci_on_stack
|
data/app/models/shipit/task.rb
CHANGED
@@ -11,7 +11,7 @@
|
|
11
11
|
<%= Shipit.github_url %>
|
12
12
|
<%= f.text_field :repo_owner, placeholder: 'e.g. Shopify', required: true, class: "repo" %>
|
13
13
|
/
|
14
|
-
<%= f.text_field :repo_name, required: true, pattern: "^[a-
|
14
|
+
<%= f.text_field :repo_name, required: true, pattern: "^[a-zA-Z0-9\-_\.]+$", class: "repo" %>
|
15
15
|
</p>
|
16
16
|
<p>
|
17
17
|
<%= f.label :branch %>
|
@@ -7,7 +7,7 @@
|
|
7
7
|
<strong class="status-item__service"><%= group.description %></strong>
|
8
8
|
</div>
|
9
9
|
<% group.statuses.each do |status| %>
|
10
|
-
<div class="status-item status-item--<%= status.state %>">
|
10
|
+
<div class="status-item status-item--<%= status.state %> <%= :ignored if status.ignored? %>">
|
11
11
|
<i class="status-item__icon"></i>
|
12
12
|
<a href="<%= status.target_url %>" target="_blank">
|
13
13
|
<strong class="status-item__service"><%= status.context %></strong>
|
@@ -9,26 +9,29 @@
|
|
9
9
|
<div class="deploy-main" data-task="<%= {repo: @stack.github_repo_name, description: task_description(task)}.to_json %>">
|
10
10
|
<span class="deploy-tasks"></span>
|
11
11
|
<div class="deploy-banner" data-status="<%= task.status %>">
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
<div class="deploy-banner-section stack-link">
|
13
|
+
<%= link_to "Return to #{@stack.repo_name}/#{@stack.environment}", stack_path(@stack) %>
|
14
|
+
</div>
|
15
|
+
<div class="deploy-banner-section">
|
16
|
+
<a href="#" class="user main-user disabled"><%= task.author.name %></a>
|
17
|
+
<span class="deploy-status">
|
18
|
+
<%= content_for :task_title %>
|
19
|
+
</span>
|
20
|
+
</div>
|
18
21
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
<div class="deploy-banner-section action-buttons">
|
23
|
+
<%= link_to abort_stack_task_path(@stack, task), class: "btn btn--alert action-button", data: { action: "abort", status: task.status } do %>
|
24
|
+
<span class="caption--ready">Abort</span>
|
25
|
+
<span class="caption--pending">Aborting...</span>
|
26
|
+
<% end %>
|
24
27
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
<% end %>
|
28
|
+
<% if task.supports_rollback? %>
|
29
|
+
<%= link_to abort_stack_task_path(@stack, task, rollback: true), class: "btn btn--delete action-button", data: { action: "abort", rollback: true, status: task.status } do %>
|
30
|
+
<span class="caption--ready">Abort and Rollback</span>
|
31
|
+
<span class="caption--pending">Aborting with Rollback...</span>
|
30
32
|
<% end %>
|
31
|
-
|
33
|
+
<% end %>
|
34
|
+
</div>
|
32
35
|
</div>
|
33
36
|
|
34
37
|
<pre class="nowrap" data-status="<%= task.status %>"><code data-next-chunks-url="<%= next_chunks_url(task) %>"><%= task.chunk_output %></code></pre>
|
data/lib/shipit.rb
CHANGED
data/lib/shipit/task_commands.rb
CHANGED
data/lib/shipit/version.rb
CHANGED
Binary file
|
data/test/dummy/db/test.sqlite3
CHANGED
Binary file
|
@@ -19,7 +19,7 @@ module Shipit
|
|
19
19
|
@commands.expects(:install_dependencies).returns([]).once
|
20
20
|
@commands.expects(:perform).returns([]).once
|
21
21
|
|
22
|
-
@
|
22
|
+
@commands.expects(:clear_working_directory)
|
23
23
|
|
24
24
|
@job.perform(@deploy)
|
25
25
|
end
|
@@ -83,7 +83,7 @@ module Shipit
|
|
83
83
|
@commands.stubs(:install_dependencies).returns([])
|
84
84
|
@commands.stubs(:perform).returns([])
|
85
85
|
DeployCommands.expects(:new).with(@deploy).returns(@commands)
|
86
|
-
@
|
86
|
+
@commands.stubs(:clear_working_directory)
|
87
87
|
|
88
88
|
@stack.update!(cached_deploy_spec: DeploySpec.new({}))
|
89
89
|
|
data/test/models/stacks_test.rb
CHANGED
@@ -19,6 +19,22 @@ module Shipit
|
|
19
19
|
refute_predicate @stack, :valid?
|
20
20
|
end
|
21
21
|
|
22
|
+
test "repo_owner and repo_name are case insensitive" do
|
23
|
+
assert_no_difference -> { Stack.count } do
|
24
|
+
error = assert_raises ActiveRecord::RecordInvalid do
|
25
|
+
Stack.create!(
|
26
|
+
repo_owner: @stack.repo_owner.upcase,
|
27
|
+
repo_name: @stack.repo_name.upcase,
|
28
|
+
environment: @stack.environment,
|
29
|
+
)
|
30
|
+
end
|
31
|
+
assert_equal 'Validation failed: Repo name has already been taken', error.message
|
32
|
+
end
|
33
|
+
|
34
|
+
new_stack = Stack.create!(repo_owner: 'FOO', repo_name: 'BAR')
|
35
|
+
assert_equal new_stack, Stack.find_by(repo_owner: 'foo', repo_name: 'bar')
|
36
|
+
end
|
37
|
+
|
22
38
|
test "repo_owner is automatically downcased" do
|
23
39
|
@stack.repo_owner = 'George'
|
24
40
|
assert_equal 'george', @stack.repo_owner
|
@@ -360,5 +376,34 @@ module Shipit
|
|
360
376
|
@stack.update(updated_at: Time.zone.now)
|
361
377
|
end
|
362
378
|
end
|
379
|
+
|
380
|
+
test "#merge_status returns locked if stack is locked" do
|
381
|
+
@stack.update!(lock_reason: 'Maintenance operation')
|
382
|
+
assert_equal 'locked', @stack.merge_status
|
383
|
+
end
|
384
|
+
|
385
|
+
test "#merge_status returns state of last finalized undeployed commit" do
|
386
|
+
@stack.deploys_and_rollbacks.destroy_all
|
387
|
+
shipit_commits(:fifth).statuses.destroy_all
|
388
|
+
shipit_commits(:fourth).statuses.update_all(state: 'pending')
|
389
|
+
shipit_commits(:third).statuses.update_all(state: 'success')
|
390
|
+
shipit_commits(:second).statuses.update_all(state: 'failure')
|
391
|
+
|
392
|
+
assert_equal 'success', @stack.merge_status
|
393
|
+
end
|
394
|
+
|
395
|
+
test "#merge_status returns pending if all undeployed commits are in pending or unknown state" do
|
396
|
+
shipit_commits(:fifth).statuses.destroy_all
|
397
|
+
shipit_commits(:fourth).statuses.update_all(state: 'pending')
|
398
|
+
@stack.expects(:last_deployed_commit).returns(shipit_commits(:third))
|
399
|
+
|
400
|
+
assert_equal 'pending', @stack.merge_status
|
401
|
+
end
|
402
|
+
|
403
|
+
test "#merge_status returns pending if there are no undeployed commits" do
|
404
|
+
@stack.expects(:last_deployed_commit).returns(shipit_commits(:fifth))
|
405
|
+
|
406
|
+
assert_equal 'pending', @stack.merge_status
|
407
|
+
end
|
363
408
|
end
|
364
409
|
end
|
data/test/models/status_test.rb
CHANGED
@@ -32,6 +32,15 @@ module Shipit
|
|
32
32
|
assert_not_equal stack_last_updated_at, @stack.reload.updated_at
|
33
33
|
end
|
34
34
|
|
35
|
+
test ".simple_state returns failure when status is error" do
|
36
|
+
assert_equal 'failure', Status.new(state: 'error').simple_state
|
37
|
+
end
|
38
|
+
|
39
|
+
test ".simple_state returns status when status is not error" do
|
40
|
+
assert_equal 'success', Status.new(state: 'success').simple_state
|
41
|
+
assert_equal 'failure', Status.new(state: 'failure').simple_state
|
42
|
+
end
|
43
|
+
|
35
44
|
private
|
36
45
|
|
37
46
|
def github_status
|
@@ -12,6 +12,7 @@ module Shipit
|
|
12
12
|
rollback_steps!: ['bundle exec cap $ENVIRONMENT deploy:rollback'],
|
13
13
|
machine_env: {'GLOBAL' => '1'},
|
14
14
|
directory: nil,
|
15
|
+
clear_working_directory?: true,
|
15
16
|
)
|
16
17
|
@commands.stubs(:deploy_spec).returns(@deploy_spec)
|
17
18
|
|
@@ -179,5 +180,16 @@ module Shipit
|
|
179
180
|
command = @commands.install_dependencies.first
|
180
181
|
assert_equal 'BAR', command.env['FOO']
|
181
182
|
end
|
183
|
+
|
184
|
+
test "#clear_working_directory rm -rf the working directory" do
|
185
|
+
FileUtils.expects(:rm_rf).with(@deploy.working_directory)
|
186
|
+
@commands.clear_working_directory
|
187
|
+
end
|
188
|
+
|
189
|
+
test "#clear_working_directory is a noop if the deploy spec disabled cleanup" do
|
190
|
+
@deploy_spec.expects(:clear_working_directory?).returns(false)
|
191
|
+
FileUtils.expects(:rm_rf).never
|
192
|
+
@commands.clear_working_directory
|
193
|
+
end
|
182
194
|
end
|
183
195
|
end
|
@@ -3,7 +3,8 @@ require 'test_helper'
|
|
3
3
|
module Shipit
|
4
4
|
class DeploySpecTest < ActiveSupport::TestCase
|
5
5
|
setup do
|
6
|
-
@
|
6
|
+
@app_dir = '/tmp/'
|
7
|
+
@spec = DeploySpec::FileSystem.new(@app_dir, 'env')
|
7
8
|
@spec.stubs(:load_config).returns({})
|
8
9
|
end
|
9
10
|
|
@@ -37,8 +38,15 @@ module Shipit
|
|
37
38
|
|
38
39
|
test '#dependencies_steps returns `bundle install` if a `Gemfile` is present' do
|
39
40
|
@spec.expects(:bundler?).returns(true)
|
40
|
-
@spec.expects(:bundle_install).returns(
|
41
|
-
assert_equal
|
41
|
+
@spec.expects(:bundle_install).returns(['bundle install'])
|
42
|
+
assert_equal ['bundle install'], @spec.dependencies_steps
|
43
|
+
end
|
44
|
+
|
45
|
+
test "#dependencies_steps prepend and append pre and post steps" do
|
46
|
+
@spec.stubs(:load_config).returns('dependencies' => {'pre' => ['before'], 'post' => ['after']})
|
47
|
+
@spec.expects(:bundler?).returns(true)
|
48
|
+
@spec.expects(:bundle_install).returns(['bundle install'])
|
49
|
+
assert_equal ['before', 'bundle install', 'after'], @spec.dependencies_steps
|
42
50
|
end
|
43
51
|
|
44
52
|
test '#fetch_deployed_revision_steps! is unknown by default' do
|
@@ -108,6 +116,13 @@ module Shipit
|
|
108
116
|
assert_equal ['bundle exec cap $ENVIRONMENT deploy'], @spec.deploy_steps
|
109
117
|
end
|
110
118
|
|
119
|
+
test "#deploy_steps prepend and append pre and post steps" do
|
120
|
+
@spec.stubs(:load_config).returns('deploy' => {'pre' => ['before'], 'post' => ['after']})
|
121
|
+
@spec.expects(:bundler?).returns(true)
|
122
|
+
@spec.expects(:capistrano?).returns(true)
|
123
|
+
assert_equal ['before', 'bundle exec cap $ENVIRONMENT deploy', 'after'], @spec.deploy_steps
|
124
|
+
end
|
125
|
+
|
111
126
|
test '#deploy_steps raise a DeploySpec::Error! if it dont know how to deploy the app' do
|
112
127
|
@spec.expects(:capistrano?).returns(false)
|
113
128
|
assert_raise DeploySpec::Error do
|
@@ -126,6 +141,13 @@ module Shipit
|
|
126
141
|
assert_equal ['bundle exec cap $ENVIRONMENT deploy:rollback'], @spec.rollback_steps
|
127
142
|
end
|
128
143
|
|
144
|
+
test "#rollback_steps prepend and append pre and post steps" do
|
145
|
+
@spec.stubs(:load_config).returns('rollback' => {'pre' => ['before'], 'post' => ['after']})
|
146
|
+
@spec.expects(:bundler?).returns(true)
|
147
|
+
@spec.expects(:capistrano?).returns(true)
|
148
|
+
assert_equal ['before', 'bundle exec cap $ENVIRONMENT deploy:rollback', 'after'], @spec.rollback_steps
|
149
|
+
end
|
150
|
+
|
129
151
|
test '#machine_env return an environment hash' do
|
130
152
|
@spec.stubs(:load_config).returns('machine' => {'environment' => {'GLOBAL' => '1'}})
|
131
153
|
assert_equal({'GLOBAL' => '1'}, @spec.machine_env)
|
@@ -136,7 +158,7 @@ module Shipit
|
|
136
158
|
config.expects(:exist?).returns(true)
|
137
159
|
config.expects(:read).returns({'dependencies' => {'override' => %w(foo bar baz)}}.to_yaml)
|
138
160
|
spec = DeploySpec::FileSystem.new('.', 'staging')
|
139
|
-
spec.expects(:file).with('shipit.staging.yml').returns(config)
|
161
|
+
spec.expects(:file).with('shipit.staging.yml', root: true).returns(config)
|
140
162
|
assert_equal %w(foo bar baz), spec.dependencies_steps
|
141
163
|
end
|
142
164
|
|
@@ -149,8 +171,8 @@ module Shipit
|
|
149
171
|
config.expects(:read).returns({'dependencies' => {'override' => %w(foo bar baz)}}.to_yaml)
|
150
172
|
|
151
173
|
spec = DeploySpec::FileSystem.new('.', 'staging')
|
152
|
-
spec.expects(:file).with('shipit.staging.yml').returns(not_config)
|
153
|
-
spec.expects(:file).with('shipit.yml').returns(config)
|
174
|
+
spec.expects(:file).with('shipit.staging.yml', root: true).returns(not_config)
|
175
|
+
spec.expects(:file).with('shipit.yml', root: true).returns(config)
|
154
176
|
assert_equal %w(foo bar baz), spec.dependencies_steps
|
155
177
|
end
|
156
178
|
|
@@ -204,7 +226,7 @@ module Shipit
|
|
204
226
|
assert_instance_of DeploySpec, @spec.cacheable
|
205
227
|
config = {
|
206
228
|
'ci' => {'hide' => [], 'allow_failures' => [], 'require' => []},
|
207
|
-
'machine' => {'environment' => {}, 'directory' => nil},
|
229
|
+
'machine' => {'environment' => {}, 'directory' => nil, 'cleanup' => true},
|
208
230
|
'review' => {'checklist' => [], 'monitoring' => [], 'checks' => []},
|
209
231
|
'dependencies' => {'override' => []},
|
210
232
|
'plugins' => {},
|
@@ -315,5 +337,16 @@ module Shipit
|
|
315
337
|
@spec.expects(:load_config).returns('ci' => {'hide' => %w(ci/circleci ci/jenkins)})
|
316
338
|
assert_equal %w(ci/circleci ci/jenkins), @spec.hidden_statuses
|
317
339
|
end
|
340
|
+
|
341
|
+
test "#file is impacted by `machine.directory`" do
|
342
|
+
subdir = '/foo/bar'
|
343
|
+
@spec.stubs(:load_config).returns('machine' => {'directory' => subdir})
|
344
|
+
assert_instance_of Pathname, @spec.file('baz')
|
345
|
+
assert_equal File.join(@app_dir, subdir, 'baz'), @spec.file('baz').to_s
|
346
|
+
end
|
347
|
+
|
348
|
+
test "#clear_working_directory? returns true by default" do
|
349
|
+
assert_predicate @spec, :clear_working_directory?
|
350
|
+
end
|
318
351
|
end
|
319
352
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shipit-engine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jean Boussier
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-03-
|
11
|
+
date: 2016-03-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -599,7 +599,6 @@ files:
|
|
599
599
|
- test/controllers/status_controller_test.rb
|
600
600
|
- test/controllers/tasks_controller_test.rb
|
601
601
|
- test/controllers/webhooks_controller_test.rb
|
602
|
-
- test/dummy/README.rdoc
|
603
602
|
- test/dummy/Rakefile
|
604
603
|
- test/dummy/app/assets/javascripts/application.js
|
605
604
|
- test/dummy/app/assets/stylesheets/application.css
|
@@ -807,7 +806,6 @@ test_files:
|
|
807
806
|
- test/dummy/public/500.html
|
808
807
|
- test/dummy/public/favicon.ico
|
809
808
|
- test/dummy/Rakefile
|
810
|
-
- test/dummy/README.rdoc
|
811
809
|
- test/fixtures/payloads/push_master.json
|
812
810
|
- test/fixtures/payloads/push_not_master.json
|
813
811
|
- test/fixtures/payloads/status_master.json
|
data/test/dummy/README.rdoc
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
== README
|
2
|
-
|
3
|
-
This README would normally document whatever steps are necessary to get the
|
4
|
-
application up and running.
|
5
|
-
|
6
|
-
Things you may want to cover:
|
7
|
-
|
8
|
-
* Ruby version
|
9
|
-
|
10
|
-
* System dependencies
|
11
|
-
|
12
|
-
* Configuration
|
13
|
-
|
14
|
-
* Database creation
|
15
|
-
|
16
|
-
* Database initialization
|
17
|
-
|
18
|
-
* How to run the test suite
|
19
|
-
|
20
|
-
* Services (job queues, cache servers, search engines, etc.)
|
21
|
-
|
22
|
-
* Deployment instructions
|
23
|
-
|
24
|
-
* ...
|
25
|
-
|
26
|
-
|
27
|
-
Please feel free to use a different markup language if you do not plan to run
|
28
|
-
<tt>rake doc:app</tt>.
|