shipit-engine 0.8.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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>.
|