shipit-engine 0.6.4 → 0.7.0
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 +4 -2
- data/app/assets/javascripts/shipit/checklist.js.coffee +2 -2
- data/app/controllers/shipit/api/hooks_controller.rb +2 -2
- data/app/controllers/shipit/shipit_controller.rb +4 -3
- data/app/models/shipit/hook.rb +3 -2
- data/app/models/shipit/stack.rb +18 -2
- data/app/models/shipit/user.rb +2 -0
- data/app/serializers/shipit/hook_serializer.rb +9 -1
- data/app/serializers/shipit/stack_serializer.rb +1 -1
- data/app/views/shipit/deploys/_checklist.html.erb +1 -1
- data/app/views/shipit/deploys/_concurrent_deploy_warning.html.erb +4 -0
- data/app/views/shipit/deploys/new.html.erb +3 -5
- data/app/views/shipit/deploys/rollback.html.erb +3 -5
- data/config/routes.rb +29 -29
- data/db/migrate/20160122165559_rename_hooks_url_in_delivery_url.rb +5 -0
- data/lib/shipit.rb +3 -2
- data/lib/shipit/version.rb +1 -1
- data/test/controllers/api/hooks_controller_test.rb +19 -11
- data/test/controllers/stacks_controller_test.rb +7 -3
- data/test/dummy/config/secrets.example.yml +6 -2
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/schema.rb +2 -4
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/fixtures/shipit/hooks.yml +5 -5
- data/test/helpers/hooks_helper.rb +36 -0
- data/test/helpers/payloads_helper.rb +0 -1
- data/test/jobs/perform_task_job_test.rb +0 -1
- data/test/models/commits_test.rb +27 -16
- data/test/models/deploys_test.rb +12 -12
- data/test/models/hook_test.rb +5 -5
- data/test/models/stacks_test.rb +15 -7
- data/test/test_helper.rb +9 -5
- data/test/unit/shipit_test.rb +16 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 13126d19eca4966f56856152cf632751bf1ba9d1
|
4
|
+
data.tar.gz: 665a8bce4eb15e193e55b0da971a5840b7888bf6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 87cf3290c48593691fec2c278607cc1783206af426ca3dbefcab269b639614d98e5e8632cd1bc4fa27842f70615886f9b7c3914191d99dfc8168d43ab61ffcae
|
7
|
+
data.tar.gz: 12077a22444887bb58eb55faed2b395e257d97f2a762fc64164ef216b61921c6606d8261de6f202192324b17e461e4b3c9f008d4278503c7631a41513a309ce2
|
data/README.md
CHANGED
@@ -316,7 +316,7 @@ development:
|
|
316
316
|
|
317
317
|
The value for `id` is your application's *Client ID*, and the value for `secret` is your application's *Client Secret* — both of these should appear on your application's GitHub page.
|
318
318
|
|
319
|
-
The `
|
319
|
+
The `teams` key is optional, and required only if you want to specify some teams which have access to the stack in Shipit.
|
320
320
|
|
321
321
|
For example:
|
322
322
|
|
@@ -325,7 +325,9 @@ development:
|
|
325
325
|
github_oauth:
|
326
326
|
id: (your application's Client ID)
|
327
327
|
secret: (your application's Client Secret)
|
328
|
-
|
328
|
+
teams:
|
329
|
+
- Shipit/team
|
330
|
+
- Shipit/another_team
|
329
331
|
```
|
330
332
|
<br>
|
331
333
|
|
@@ -1,9 +1,9 @@
|
|
1
1
|
$document = $(document)
|
2
2
|
|
3
3
|
toggleDeployButton = ->
|
4
|
-
$('.trigger-deploy').toggleClass('disabled btn--disabled', !!$(':checkbox
|
4
|
+
$('.trigger-deploy').toggleClass('disabled btn--disabled', !!$(':checkbox.required:not(:checked)').length)
|
5
5
|
|
6
|
-
$document.on('change', ':checkbox
|
6
|
+
$document.on('change', ':checkbox.required', toggleDeployButton)
|
7
7
|
|
8
8
|
jQuery ($) ->
|
9
9
|
toggleDeployButton()
|
@@ -13,7 +13,7 @@ module Shipit
|
|
13
13
|
end
|
14
14
|
|
15
15
|
params do
|
16
|
-
requires :
|
16
|
+
requires :delivery_url, String
|
17
17
|
requires :events, Array[String]
|
18
18
|
accepts :content_type, String
|
19
19
|
end
|
@@ -22,7 +22,7 @@ module Shipit
|
|
22
22
|
end
|
23
23
|
|
24
24
|
params do
|
25
|
-
accepts :
|
25
|
+
accepts :delivery_url, String
|
26
26
|
accepts :events, Array[String]
|
27
27
|
accepts :content_type, String
|
28
28
|
end
|
@@ -32,9 +32,10 @@ module Shipit
|
|
32
32
|
|
33
33
|
def force_github_authentication
|
34
34
|
if current_user.logged_in?
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
teams = Shipit.github_teams
|
36
|
+
unless teams.empty? || current_user.teams.where(id: teams).exists?
|
37
|
+
team_list = teams.map(&:handle).to_sentence(two_words_connector: ' or ', last_word_connector: ', or ')
|
38
|
+
render text: "You must be a member of #{team_list} to access this application.", status: :forbidden
|
38
39
|
end
|
39
40
|
else
|
40
41
|
redirect_to Shipit::Engine.routes.url_helpers.github_authentication_path(origin: request.original_url)
|
data/app/models/shipit/hook.rb
CHANGED
@@ -8,6 +8,7 @@ module Shipit
|
|
8
8
|
}.freeze
|
9
9
|
|
10
10
|
EVENTS = %w(
|
11
|
+
stack
|
11
12
|
task
|
12
13
|
deploy
|
13
14
|
rollback
|
@@ -19,7 +20,7 @@ module Shipit
|
|
19
20
|
belongs_to :stack, required: false
|
20
21
|
has_many :deliveries
|
21
22
|
|
22
|
-
validates :
|
23
|
+
validates :delivery_url, presence: true, url: {no_local: true, allow_blank: true}
|
23
24
|
validates :content_type, presence: true, inclusion: {in: CONTENT_TYPES.keys}
|
24
25
|
validates :events, presence: true, subset: {of: EVENTS}
|
25
26
|
|
@@ -67,7 +68,7 @@ module Shipit
|
|
67
68
|
def deliver!(event, payload)
|
68
69
|
deliveries.create!(
|
69
70
|
event: event,
|
70
|
-
url:
|
71
|
+
url: delivery_url,
|
71
72
|
content_type: CONTENT_TYPES[content_type],
|
72
73
|
payload: serialize_payload(payload),
|
73
74
|
).schedule!
|
data/app/models/shipit/stack.rb
CHANGED
@@ -27,7 +27,10 @@ module Shipit
|
|
27
27
|
|
28
28
|
before_validation :update_defaults
|
29
29
|
before_destroy :clear_local_files
|
30
|
-
after_commit :
|
30
|
+
after_commit :emit_lock_hooks
|
31
|
+
after_commit :emit_added_hooks, on: :create
|
32
|
+
after_commit :emit_updated_hooks, on: :update
|
33
|
+
after_commit :emit_removed_hooks, on: :destroy
|
31
34
|
after_commit :broadcast_update, on: :update
|
32
35
|
after_commit :setup_hooks, :sync_github, on: :create
|
33
36
|
after_touch :clear_cache
|
@@ -296,11 +299,24 @@ module Shipit
|
|
296
299
|
self.branch = 'master' if branch.blank?
|
297
300
|
end
|
298
301
|
|
299
|
-
def
|
302
|
+
def emit_lock_hooks
|
300
303
|
return unless previous_changes.include?('lock_reason')
|
301
304
|
Hook.emit(:lock, self, locked: locked?, stack: self)
|
302
305
|
end
|
303
306
|
|
307
|
+
def emit_added_hooks
|
308
|
+
Hook.emit(:stack, self, action: :added, stack: self)
|
309
|
+
end
|
310
|
+
|
311
|
+
def emit_updated_hooks
|
312
|
+
changed = !(previous_changes.keys - %w(updated_at)).empty?
|
313
|
+
Hook.emit(:stack, self, action: :updated, stack: self) if changed
|
314
|
+
end
|
315
|
+
|
316
|
+
def emit_removed_hooks
|
317
|
+
Hook.emit(:stack, self, action: :removed, stack: self)
|
318
|
+
end
|
319
|
+
|
304
320
|
def ci_enabled_cache_key
|
305
321
|
"stacks:#{id}:ci_enabled"
|
306
322
|
end
|
data/app/models/shipit/user.rb
CHANGED
@@ -2,6 +2,8 @@ module Shipit
|
|
2
2
|
class User < ActiveRecord::Base
|
3
3
|
DEFAULT_AVATAR = URI.parse('https://avatars.githubusercontent.com/u/583231?')
|
4
4
|
|
5
|
+
has_many :teams, through: :memberships
|
6
|
+
has_many :memberships
|
5
7
|
has_many :authored_commits, class_name: :Commit, foreign_key: :author_id, inverse_of: :author
|
6
8
|
has_many :commits, foreign_key: :committer_id, inverse_of: :committer
|
7
9
|
has_many :tasks
|
@@ -3,7 +3,15 @@ module Shipit
|
|
3
3
|
include ConditionalAttributes
|
4
4
|
|
5
5
|
has_one :stack
|
6
|
-
attributes :id, :url, :content_type, :events, :insecure_ssl, :created_at, :updated_at
|
6
|
+
attributes :id, :url, :delivery_url, :content_type, :events, :insecure_ssl, :created_at, :updated_at
|
7
|
+
|
8
|
+
def url
|
9
|
+
if object.scoped?
|
10
|
+
api_stack_hook_url(object.stack, object)
|
11
|
+
else
|
12
|
+
api_hook_url(object)
|
13
|
+
end
|
14
|
+
end
|
7
15
|
|
8
16
|
def include_stack?
|
9
17
|
object.scoped?
|
@@ -3,7 +3,7 @@ module Shipit
|
|
3
3
|
include ConditionalAttributes
|
4
4
|
|
5
5
|
has_one :lock_author
|
6
|
-
attributes :id, :repo_owner, :repo_name, :environment, :html_url, :url, :tasks_url, :deploy_spec,
|
6
|
+
attributes :id, :repo_owner, :repo_name, :environment, :html_url, :url, :tasks_url, :deploy_url, :deploy_spec,
|
7
7
|
:undeployed_commits_count, :is_locked, :lock_reason, :continuous_deployment, :created_at, :updated_at
|
8
8
|
|
9
9
|
def url
|
@@ -6,7 +6,7 @@
|
|
6
6
|
<ul class="deploy-checklist">
|
7
7
|
<%- checklist.each_with_index do |check, index| -%>
|
8
8
|
<li class="deploy-checklist__item">
|
9
|
-
<%= check_box_tag :checklist, nil, false, class: 'deploy-checklist__item__checkbox', id: "checkbox_#{index}" %>
|
9
|
+
<%= check_box_tag :checklist, nil, false, class: 'deploy-checklist__item__checkbox required', id: "checkbox_#{index}" %>
|
10
10
|
<label class="deploy-checklist__item__label" for="checkbox_<%= index %>">
|
11
11
|
<%= sanitize(check, tags: %w(a strong), attributes: %w(href target)) %>
|
12
12
|
</label>
|
@@ -2,5 +2,9 @@
|
|
2
2
|
<h2><%= render_github_user(@stack.active_deploy.author) %> is already deploying!</h2>
|
3
3
|
<ul>
|
4
4
|
<li>Are you sure you want to deploy concurrently?</li>
|
5
|
+
<li>
|
6
|
+
<%= check_box_tag :force, true, false, class: 'required' %>
|
7
|
+
Yes I know what I'm doing.
|
8
|
+
</li>
|
5
9
|
</ul>
|
6
10
|
</section>
|
@@ -1,8 +1,6 @@
|
|
1
1
|
<%= render partial: 'shipit/stacks/header', locals: { stack: @stack } %>
|
2
2
|
|
3
3
|
<div class="wrapper">
|
4
|
-
<%= render 'concurrent_deploy_warning' if @stack.deploying? %>
|
5
|
-
|
6
4
|
<section>
|
7
5
|
<header class="section-header">
|
8
6
|
<h2>Commits included in this deploy (<%= link_to_github_deploy(@deploy) %>)</h2>
|
@@ -45,10 +43,10 @@
|
|
45
43
|
<% end %>
|
46
44
|
</section>
|
47
45
|
<% end %>
|
46
|
+
|
47
|
+
<%= render 'concurrent_deploy_warning' if @stack.deploying? %>
|
48
|
+
|
48
49
|
<section class="submit-section">
|
49
|
-
<% if @stack.deploying? %>
|
50
|
-
<%= hidden_field_tag :force, value: true %>
|
51
|
-
<% end %>
|
52
50
|
<%= f.hidden_field :until_commit_id %>
|
53
51
|
<%= f.submit class: 'btn btn--primary btn--large trigger-deploy' %>
|
54
52
|
</section>
|
@@ -9,8 +9,6 @@
|
|
9
9
|
</ul>
|
10
10
|
</section>
|
11
11
|
|
12
|
-
<%= render 'concurrent_deploy_warning' if @stack.deploying? %>
|
13
|
-
|
14
12
|
<section>
|
15
13
|
<header class="section-header">
|
16
14
|
<h2>Commits included in this rollback</h2>
|
@@ -41,10 +39,10 @@
|
|
41
39
|
<% end %>
|
42
40
|
</section>
|
43
41
|
<% end %>
|
42
|
+
|
43
|
+
<%= render 'concurrent_deploy_warning' if @stack.deploying? %>
|
44
|
+
|
44
45
|
<section class="submit-section">
|
45
|
-
<% if @stack.deploying? %>
|
46
|
-
<%= hidden_field_tag :force, value: true %>
|
47
|
-
<% end %>
|
48
46
|
<%= f.hidden_field :parent_id %>
|
49
47
|
<%= f.submit 'Rollback', :class => ['btn', 'rollback', 'trigger-rollback'], data: {confirm: "Are you really sure it's safe?"} %>
|
50
48
|
</section>
|
data/config/routes.rb
CHANGED
@@ -5,16 +5,9 @@ Shipit::Engine.routes.draw do
|
|
5
5
|
|
6
6
|
mount Pubsubstub::StreamAction.new, at: "/events", as: :events
|
7
7
|
|
8
|
+
# Robots
|
8
9
|
get '/status/version' => 'status#version', as: :version
|
9
10
|
|
10
|
-
scope '/github/auth/github', as: :github_authentication, controller: :github_authentication do
|
11
|
-
get '/', action: :request
|
12
|
-
post :callback
|
13
|
-
get :callback
|
14
|
-
get :logout
|
15
|
-
end
|
16
|
-
|
17
|
-
# Robots
|
18
11
|
resources :stacks, only: %i(new create index) do
|
19
12
|
resource :webhooks, only: [] do
|
20
13
|
post :push, :state
|
@@ -28,7 +21,35 @@ Shipit::Engine.routes.draw do
|
|
28
21
|
end
|
29
22
|
end
|
30
23
|
|
24
|
+
# API
|
25
|
+
namespace :api do
|
26
|
+
root to: 'base#index'
|
27
|
+
resources :stacks, only: :index
|
28
|
+
scope '/stacks/*id', id: stack_id_format, as: :stack do
|
29
|
+
get '/' => 'stacks#show'
|
30
|
+
end
|
31
|
+
|
32
|
+
scope '/stacks/*stack_id', stack_id: stack_id_format, as: :stack do
|
33
|
+
resource :lock, only: %i(create update destroy)
|
34
|
+
resources :tasks, only: %i(index show) do
|
35
|
+
resource :output, only: :show
|
36
|
+
end
|
37
|
+
resources :deploys, only: %i(create)
|
38
|
+
post '/task/:task_name' => 'tasks#trigger', as: :trigger_task
|
39
|
+
resources :hooks, only: %i(index create show update destroy)
|
40
|
+
end
|
41
|
+
|
42
|
+
resources :hooks, only: %i(index create show update destroy)
|
43
|
+
end
|
44
|
+
|
31
45
|
# Humans
|
46
|
+
scope '/github/auth/github', as: :github_authentication, controller: :github_authentication do
|
47
|
+
get '/', action: :request
|
48
|
+
post :callback
|
49
|
+
get :callback
|
50
|
+
get :logout
|
51
|
+
end
|
52
|
+
|
32
53
|
scope '/*id', id: stack_id_format, as: :stack do
|
33
54
|
get '/' => 'stacks#show'
|
34
55
|
patch '/' => 'stacks#update'
|
@@ -64,25 +85,4 @@ Shipit::Engine.routes.draw do
|
|
64
85
|
end
|
65
86
|
end
|
66
87
|
end
|
67
|
-
|
68
|
-
# API
|
69
|
-
namespace :api do
|
70
|
-
root to: 'base#index'
|
71
|
-
resources :stacks, only: :index
|
72
|
-
scope '/stacks/*id', id: stack_id_format, as: :stack do
|
73
|
-
get '/' => 'stacks#show'
|
74
|
-
end
|
75
|
-
|
76
|
-
scope '/stacks/*stack_id', stack_id: stack_id_format, as: :stack do
|
77
|
-
resource :lock, only: %i(create update destroy)
|
78
|
-
resources :tasks, only: %i(index show) do
|
79
|
-
resource :output, only: :show
|
80
|
-
end
|
81
|
-
resources :deploys, only: %i(create)
|
82
|
-
post '/task/:task_name' => 'tasks#trigger', as: :trigger_task
|
83
|
-
resources :hooks, only: %i(index create show update destroy)
|
84
|
-
end
|
85
|
-
|
86
|
-
resources :hooks, only: %i(index create show update destroy)
|
87
|
-
end
|
88
88
|
end
|
data/lib/shipit.rb
CHANGED
@@ -103,8 +103,9 @@ module Shipit
|
|
103
103
|
secrets.host.presence
|
104
104
|
end
|
105
105
|
|
106
|
-
def
|
107
|
-
|
106
|
+
def github_teams
|
107
|
+
teams = (Array(github_oauth_credentials['team']) + Array(github_oauth_credentials['teams'])).sort.uniq
|
108
|
+
@github_teams ||= teams.map { |t| Team.find_or_create_by_handle(t) }
|
108
109
|
end
|
109
110
|
|
110
111
|
def github_oauth_id
|
data/lib/shipit/version.rb
CHANGED
@@ -8,13 +8,17 @@ module Shipit
|
|
8
8
|
@stack = shipit_stacks(:shipit)
|
9
9
|
end
|
10
10
|
|
11
|
+
test "the route has priority over stacks one" do
|
12
|
+
assert_recognizes({controller: 'shipit/api/hooks', action: 'show', id: '42'}, '/api/hooks/42')
|
13
|
+
end
|
14
|
+
|
11
15
|
test "#index without a stack_id returns the list of global hooks" do
|
12
16
|
hook = Hook.global.first
|
13
17
|
|
14
18
|
get :index
|
15
19
|
assert_response :ok
|
16
20
|
assert_json '0.id', hook.id
|
17
|
-
assert_json '0.
|
21
|
+
assert_json '0.delivery_url', hook.delivery_url
|
18
22
|
assert_json '0.content_type', hook.content_type
|
19
23
|
assert_no_json '0.stack'
|
20
24
|
end
|
@@ -25,7 +29,7 @@ module Shipit
|
|
25
29
|
get :index, stack_id: @stack.to_param
|
26
30
|
assert_response :ok
|
27
31
|
assert_json '0.id', hook.id
|
28
|
-
assert_json '0.
|
32
|
+
assert_json '0.delivery_url', hook.delivery_url
|
29
33
|
assert_json '0.content_type', hook.content_type
|
30
34
|
assert_json '0.stack.id', @stack.id
|
31
35
|
end
|
@@ -37,35 +41,39 @@ module Shipit
|
|
37
41
|
assert_response :ok
|
38
42
|
|
39
43
|
assert_json 'id', hook.id
|
40
|
-
assert_json '
|
44
|
+
assert_json 'delivery_url', hook.delivery_url
|
41
45
|
assert_json 'content_type', hook.content_type
|
42
46
|
assert_json 'stack.id', @stack.id
|
43
47
|
end
|
44
48
|
|
45
49
|
test "#create adds a new hook" do
|
46
50
|
assert_difference -> { Hook.count }, 1 do
|
47
|
-
post :create,
|
51
|
+
post :create, delivery_url: 'https://example.com/hook', events: %w(deploy rollback)
|
48
52
|
end
|
49
|
-
|
50
|
-
assert_json '
|
53
|
+
hook = Hook.last
|
54
|
+
assert_json 'delivery_url', 'https://example.com/hook'
|
55
|
+
assert_json 'url', "http://shipit.com/api/hooks/#{hook.id}"
|
56
|
+
assert_json 'id', hook.id
|
51
57
|
end
|
52
58
|
|
53
59
|
test "#create do not allow to set protected attributes" do
|
54
|
-
post :create,
|
60
|
+
post :create, delivery_url: 'https://example.com/hook',
|
61
|
+
events: %w(deploy rollback),
|
62
|
+
created_at: 2.months.ago.to_s(:db)
|
55
63
|
Hook.last.created_at > 2.seconds.ago
|
56
64
|
end
|
57
65
|
|
58
66
|
test "#create returns validation errors" do
|
59
|
-
post :create,
|
67
|
+
post :create, delivery_url: '../etc/passwd', events: %w(deploy)
|
60
68
|
assert_response :unprocessable_entity
|
61
|
-
assert_json 'errors', '
|
69
|
+
assert_json 'errors', 'delivery_url' => ['is not a valid URL']
|
62
70
|
end
|
63
71
|
|
64
72
|
test "#update changes an existing hook" do
|
65
73
|
hook = Hook.global.first
|
66
|
-
patch :update, id: hook.id,
|
74
|
+
patch :update, id: hook.id, delivery_url: 'https://shipit.com/'
|
67
75
|
assert_response :ok
|
68
|
-
assert_json '
|
76
|
+
assert_json 'delivery_url', 'https://shipit.com/'
|
69
77
|
end
|
70
78
|
|
71
79
|
test "#destroy removes an existing hook" do
|
@@ -54,11 +54,15 @@ module Shipit
|
|
54
54
|
assert_redirected_to '/github/auth/github?origin=http%3A%2F%2Ftest.host%2F'
|
55
55
|
end
|
56
56
|
|
57
|
-
test "current_user must be a member of Shipit.
|
58
|
-
|
57
|
+
test "current_user must be a member of at least a Shipit.github_teams" do
|
58
|
+
session[:user_id] = shipit_users(:bob).id
|
59
|
+
Shipit.stubs(:github_teams).returns([shipit_teams(:cyclimse_cooks), shipit_teams(:shopify_developers)])
|
59
60
|
get :index
|
60
61
|
assert_response :forbidden
|
61
|
-
assert_equal
|
62
|
+
assert_equal(
|
63
|
+
'You must be a member of cyclimse/cooks or shopify/developers to access this application.',
|
64
|
+
response.body,
|
65
|
+
)
|
62
66
|
end
|
63
67
|
|
64
68
|
test "#show is success" do
|
@@ -3,7 +3,9 @@ development:
|
|
3
3
|
github_oauth:
|
4
4
|
# id:
|
5
5
|
# secret:
|
6
|
-
#
|
6
|
+
# teams:
|
7
|
+
# -
|
8
|
+
# -
|
7
9
|
github_api:
|
8
10
|
# access_token:
|
9
11
|
# login:
|
@@ -23,5 +25,7 @@ test:
|
|
23
25
|
github_oauth:
|
24
26
|
id: 1d
|
25
27
|
secret: s3cr37
|
26
|
-
#
|
28
|
+
# teams:
|
29
|
+
# -
|
30
|
+
# -
|
27
31
|
redis_url: "redis://127.0.0.1:6379/7"
|
Binary file
|
data/test/dummy/db/schema.rb
CHANGED
@@ -11,7 +11,7 @@
|
|
11
11
|
#
|
12
12
|
# It's strongly recommended that you check this file into your version control system.
|
13
13
|
|
14
|
-
ActiveRecord::Schema.define(version:
|
14
|
+
ActiveRecord::Schema.define(version: 20160122165559) do
|
15
15
|
|
16
16
|
create_table "api_clients", force: :cascade do |t|
|
17
17
|
t.text "permissions", limit: 65535
|
@@ -76,7 +76,7 @@ ActiveRecord::Schema.define(version: 20160104151833) do
|
|
76
76
|
|
77
77
|
create_table "hooks", force: :cascade do |t|
|
78
78
|
t.integer "stack_id", limit: 4
|
79
|
-
t.string "
|
79
|
+
t.string "delivery_url", limit: 4096, null: false
|
80
80
|
t.string "content_type", limit: 4, default: "json", null: false
|
81
81
|
t.string "secret", limit: 255
|
82
82
|
t.string "events", limit: 255, default: "", null: false
|
@@ -161,8 +161,6 @@ ActiveRecord::Schema.define(version: 20160104151833) do
|
|
161
161
|
add_index "tasks", ["rolled_up", "created_at", "status"], name: "index_tasks_on_rolled_up_and_created_at_and_status"
|
162
162
|
add_index "tasks", ["since_commit_id"], name: "index_tasks_on_since_commit_id"
|
163
163
|
add_index "tasks", ["stack_id"], name: "index_tasks_on_stack_id"
|
164
|
-
add_index "tasks", ["type", "stack_id", "parent_id"], name: "index_tasks_by_stack_and_parent"
|
165
|
-
add_index "tasks", ["type", "stack_id", "status"], name: "index_tasks_by_stack_and_status"
|
166
164
|
add_index "tasks", ["until_commit_id"], name: "index_tasks_on_until_commit_id"
|
167
165
|
add_index "tasks", ["user_id"], name: "index_tasks_on_user_id"
|
168
166
|
|
data/test/dummy/db/test.sqlite3
CHANGED
Binary file
|
@@ -1,28 +1,28 @@
|
|
1
1
|
shipit_deploys:
|
2
2
|
stack: shipit
|
3
3
|
events: 'deploy,rollback'
|
4
|
-
|
4
|
+
delivery_url: https://example.com/events/deploy
|
5
5
|
content_type: json
|
6
6
|
|
7
7
|
all_deploys:
|
8
8
|
events: 'deploy,rollback'
|
9
|
-
|
9
|
+
delivery_url: https://example.com/events/deploy
|
10
10
|
content_type: form
|
11
11
|
|
12
12
|
shipit_tasks:
|
13
13
|
stack: shipit
|
14
14
|
events: 'task'
|
15
|
-
|
15
|
+
delivery_url: https://example.com/events/deploy
|
16
16
|
content_type: json
|
17
17
|
|
18
18
|
shipit_commit_status:
|
19
19
|
stack: shipit
|
20
20
|
events: 'commit_status'
|
21
|
-
|
21
|
+
delivery_url: https://example.com/events/commit_status
|
22
22
|
content_type: json
|
23
23
|
|
24
24
|
cyclimse_deploy_status:
|
25
25
|
stack: cyclimse
|
26
26
|
events: 'deploy_status'
|
27
|
-
|
27
|
+
delivery_url: https://example.com/events/deploy_status
|
28
28
|
content_type: json
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module HooksHelper
|
2
|
+
def expect_hook(event, stack = nil, payload = nil)
|
3
|
+
spy_on_hook
|
4
|
+
yield
|
5
|
+
assert_received_with(Shipit::Hook, :emit) do |call|
|
6
|
+
if call.args.first == event && (stack.nil? || call.args.second == stack)
|
7
|
+
if payload.respond_to?(:call)
|
8
|
+
payload.call(call.args.third)
|
9
|
+
elsif payload
|
10
|
+
payload == call.args.third
|
11
|
+
else
|
12
|
+
true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def expect_no_hook(*args)
|
19
|
+
spy_on_hook
|
20
|
+
yield
|
21
|
+
spy = Spy::Subroutine.get(Shipit::Hook, :emit)
|
22
|
+
called = spy.calls.find do |call|
|
23
|
+
args.map.with_index.all? { |value, index| value == call.args[index] }
|
24
|
+
end
|
25
|
+
matcher = args.map(&:inspect).join(', ')
|
26
|
+
got = called && called.args.map(&:inspect).join(', ')
|
27
|
+
refute called, "Expected no hook matching: (#{matcher})\n got: (#{got})"
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def spy_on_hook
|
33
|
+
Spy.on(Shipit::Hook, :emit).and_call_through
|
34
|
+
rescue Spy::AlreadyHookedError
|
35
|
+
end
|
36
|
+
end
|
data/test/models/commits_test.rb
CHANGED
@@ -309,14 +309,14 @@ module Shipit
|
|
309
309
|
assert_equal initial_state, commit.state
|
310
310
|
|
311
311
|
expected_status_attributes = {state: new_state, description: initial_state, context: 'ci/travis'}
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
312
|
+
add_status = -> { commit.add_status(expected_status_attributes.merge(created_at: 1.day.ago.to_s(:db))) }
|
313
|
+
expect_hook_emit(commit, :commit_status, expected_status_attributes) do
|
314
|
+
if should_fire
|
315
|
+
expect_hook_emit(commit, :deployable_status, expected_status_attributes, &add_status)
|
316
|
+
else
|
317
|
+
expect_no_hook(:deployable_status, &add_status)
|
318
|
+
end
|
316
319
|
end
|
317
|
-
expect_hook_emit(commit, :commit_status, expected_status_attributes)
|
318
|
-
|
319
|
-
commit.add_status(expected_status_attributes.merge(created_at: 1.day.ago.to_s(:db)))
|
320
320
|
end
|
321
321
|
end
|
322
322
|
end
|
@@ -324,15 +324,24 @@ module Shipit
|
|
324
324
|
test "#add_status does not fire webhooks for invisible statuses" do
|
325
325
|
commit = shipit_commits(:second)
|
326
326
|
assert commit.stack.hooks.where(events: ['commit_status']).size >= 1
|
327
|
-
|
328
|
-
|
327
|
+
|
328
|
+
expect_no_hook(:deployable_status) do
|
329
|
+
commit.add_status(state: 'failure', description: 'Sad', context: 'ci/hidden', created_at: 1.day.ago.to_s(:db))
|
330
|
+
end
|
329
331
|
end
|
330
332
|
|
331
333
|
test "#add_status does not fire webhooks for non-meaningful statuses" do
|
332
334
|
commit = shipit_commits(:second)
|
333
335
|
assert commit.stack.hooks.where(events: ['commit_status']).size >= 1
|
334
|
-
|
335
|
-
|
336
|
+
|
337
|
+
expect_no_hook(:deployable_status) do
|
338
|
+
commit.add_status(
|
339
|
+
state: 'failure',
|
340
|
+
description: 'Sad',
|
341
|
+
context: 'ci/ok_to_fail',
|
342
|
+
created_at: 1.day.ago.to_s(:db),
|
343
|
+
)
|
344
|
+
end
|
336
345
|
end
|
337
346
|
|
338
347
|
test "#visible_statuses forward the last_statuses to the stack" do
|
@@ -397,11 +406,13 @@ module Shipit
|
|
397
406
|
end
|
398
407
|
end
|
399
408
|
|
400
|
-
def expect_hook_emit(commit, event, status_attributes)
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
409
|
+
def expect_hook_emit(commit, event, status_attributes, &block)
|
410
|
+
matches = lambda do |payload|
|
411
|
+
assert_equal commit, payload[:commit]
|
412
|
+
assert_equal commit.stack, payload[:stack]
|
413
|
+
assert_equal status_attributes[:state], payload[:status]
|
414
|
+
end
|
415
|
+
expect_hook(event, commit.stack, matches, &block)
|
405
416
|
end
|
406
417
|
end
|
407
418
|
end
|
data/test/models/deploys_test.rb
CHANGED
@@ -96,37 +96,41 @@ module Shipit
|
|
96
96
|
test "transitioning to success causes an event to be broadcasted" do
|
97
97
|
deploy = shipit_deploys(:shipit_pending)
|
98
98
|
|
99
|
-
expect_hook(:deploy, deploy.stack, status: 'success', deploy: deploy, stack: deploy.stack)
|
100
99
|
expect_event(deploy)
|
101
100
|
deploy.status = 'running'
|
102
|
-
deploy.
|
101
|
+
expect_hook(:deploy, deploy.stack, status: 'success', deploy: deploy, stack: deploy.stack) do
|
102
|
+
deploy.complete!
|
103
|
+
end
|
103
104
|
end
|
104
105
|
|
105
106
|
test "transitioning to failed causes an event to be broadcasted" do
|
106
107
|
deploy = shipit_deploys(:shipit_pending)
|
107
108
|
|
108
|
-
expect_hook(:deploy, deploy.stack, status: 'failed', deploy: deploy, stack: deploy.stack)
|
109
109
|
expect_event(deploy)
|
110
110
|
deploy.status = 'running'
|
111
|
-
deploy.
|
111
|
+
expect_hook(:deploy, deploy.stack, status: 'failed', deploy: deploy, stack: deploy.stack) do
|
112
|
+
deploy.failure!
|
113
|
+
end
|
112
114
|
end
|
113
115
|
|
114
116
|
test "transitioning to error causes an event to be broadcasted" do
|
115
117
|
deploy = shipit_deploys(:shipit_pending)
|
116
118
|
|
117
|
-
expect_hook(:deploy, deploy.stack, status: 'error', deploy: deploy, stack: deploy.stack)
|
118
119
|
expect_event(deploy)
|
119
120
|
deploy.status = 'running'
|
120
|
-
deploy.error
|
121
|
+
expect_hook(:deploy, deploy.stack, status: 'error', deploy: deploy, stack: deploy.stack) do
|
122
|
+
deploy.error!
|
123
|
+
end
|
121
124
|
end
|
122
125
|
|
123
126
|
test "transitioning to running causes an event to be broadcasted" do
|
124
127
|
deploy = shipit_deploys(:shipit_pending)
|
125
128
|
|
126
|
-
expect_hook(:deploy, deploy.stack, status: 'running', deploy: deploy, stack: deploy.stack)
|
127
129
|
expect_event(deploy)
|
128
130
|
deploy.status = 'pending'
|
129
|
-
deploy.
|
131
|
+
expect_hook(:deploy, deploy.stack, status: 'running', deploy: deploy, stack: deploy.stack) do
|
132
|
+
deploy.run!
|
133
|
+
end
|
130
134
|
end
|
131
135
|
|
132
136
|
test "creating a deploy causes an event to be broadcasted" do
|
@@ -386,9 +390,5 @@ module Shipit
|
|
386
390
|
channel == "stack.#{deploy.stack.id}" && data['url'] == "/#{deploy.stack.to_param}"
|
387
391
|
end
|
388
392
|
end
|
389
|
-
|
390
|
-
def expect_hook(event, stack, payload)
|
391
|
-
Hook.expects(:emit).with(event, stack, payload)
|
392
|
-
end
|
393
393
|
end
|
394
394
|
end
|
data/test/models/hook_test.rb
CHANGED
@@ -8,15 +8,15 @@ module Shipit
|
|
8
8
|
end
|
9
9
|
|
10
10
|
test "#url must be valid" do
|
11
|
-
@hook.
|
11
|
+
@hook.delivery_url = 'file:/ad"fa/adfa'
|
12
12
|
refute @hook.valid?
|
13
|
-
assert_equal ['
|
13
|
+
assert_equal ['Delivery url is not a valid URL'], @hook.errors.full_messages
|
14
14
|
end
|
15
15
|
|
16
16
|
test "#url must not be localhost" do
|
17
|
-
@hook.
|
17
|
+
@hook.delivery_url = 'file:///etc/passwd'
|
18
18
|
refute @hook.valid?
|
19
|
-
assert_equal ['
|
19
|
+
assert_equal ['Delivery url is not a valid URL'], @hook.errors.full_messages
|
20
20
|
end
|
21
21
|
|
22
22
|
test "#events is accessible as an array" do
|
@@ -42,7 +42,7 @@ module Shipit
|
|
42
42
|
|
43
43
|
delivery = Delivery.last
|
44
44
|
|
45
|
-
assert_equal @hook.
|
45
|
+
assert_equal @hook.delivery_url, delivery.url
|
46
46
|
assert_equal 'application/x-www-form-urlencoded', delivery.content_type
|
47
47
|
assert_equal 'foo=42', delivery.payload
|
48
48
|
assert_equal 'scheduled', delivery.status
|
data/test/models/stacks_test.rb
CHANGED
@@ -284,14 +284,16 @@ module Shipit
|
|
284
284
|
end
|
285
285
|
|
286
286
|
test "locking the stack triggers a webhook" do
|
287
|
-
expect_hook(:lock, @stack, locked: true, stack: @stack)
|
288
|
-
|
287
|
+
expect_hook(:lock, @stack, locked: true, stack: @stack) do
|
288
|
+
@stack.update(lock_reason: "Just for fun", lock_author: shipit_users(:walrus))
|
289
|
+
end
|
289
290
|
end
|
290
291
|
|
291
292
|
test "unlocking the stack triggers a webhook" do
|
292
293
|
@stack.update(lock_reason: "Just for fun", lock_author: shipit_users(:walrus))
|
293
|
-
expect_hook(:lock, @stack, locked: false, stack: @stack)
|
294
|
-
|
294
|
+
expect_hook(:lock, @stack, locked: false, stack: @stack) do
|
295
|
+
@stack.update(lock_reason: nil)
|
296
|
+
end
|
295
297
|
end
|
296
298
|
|
297
299
|
test "the git cache lock prevent concurrent access to the git cache" do
|
@@ -347,10 +349,16 @@ module Shipit
|
|
347
349
|
assert_equal [commit1, commit2], stack.filter_meaningful_statuses([soft_fail, commit1, commit2])
|
348
350
|
end
|
349
351
|
|
350
|
-
|
352
|
+
test "updating the stack emit a hook" do
|
353
|
+
expect_hook(:stack, @stack, action: :updated, stack: @stack) do
|
354
|
+
@stack.update(repo_name: 'foo')
|
355
|
+
end
|
356
|
+
end
|
351
357
|
|
352
|
-
|
353
|
-
|
358
|
+
test "updating the stack doesn't emit a hook if only `updated_at` is changed" do
|
359
|
+
expect_no_hook(:stack) do
|
360
|
+
@stack.update(updated_at: Time.zone.now)
|
361
|
+
end
|
354
362
|
end
|
355
363
|
end
|
356
364
|
end
|
data/test/test_helper.rb
CHANGED
@@ -6,11 +6,14 @@ SimpleCov.start 'rails'
|
|
6
6
|
require 'fakeweb'
|
7
7
|
FakeWeb.allow_net_connect = false
|
8
8
|
|
9
|
-
require File.expand_path(
|
10
|
-
ActiveRecord::Migrator.migrations_paths = [
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
require File.expand_path('../../test/dummy/config/environment.rb', __FILE__)
|
10
|
+
ActiveRecord::Migrator.migrations_paths = [
|
11
|
+
File.expand_path('../../test/dummy/db/migrate', __FILE__),
|
12
|
+
File.expand_path('../../db/migrate', __FILE__),
|
13
|
+
]
|
14
|
+
require 'rails/test_help'
|
15
|
+
require 'mocha/mini_test'
|
16
|
+
require 'spy/integration'
|
14
17
|
|
15
18
|
# Load fixtures from the engine
|
16
19
|
if ActiveSupport::TestCase.respond_to?(:fixture_path=)
|
@@ -34,6 +37,7 @@ class ActiveSupport::TestCase
|
|
34
37
|
include JSONHelper
|
35
38
|
include LinksHelper
|
36
39
|
include ApiHelper
|
40
|
+
include HooksHelper
|
37
41
|
include ActiveJob::TestHelper
|
38
42
|
|
39
43
|
setup do
|
data/test/unit/shipit_test.rb
CHANGED
@@ -44,5 +44,21 @@ module Shipit
|
|
44
44
|
refute Shipit.github_enterprise?
|
45
45
|
assert_equal({}, Shipit.github_oauth_options)
|
46
46
|
end
|
47
|
+
|
48
|
+
test ".github_teams returns an empty array if there's no team" do
|
49
|
+
assert_equal([], Shipit.github_teams)
|
50
|
+
end
|
51
|
+
|
52
|
+
test ".github_teams returns the team key as an array" do
|
53
|
+
Rails.application.secrets.stubs(:github_oauth).returns('team' => 'shopify/developers')
|
54
|
+
assert_equal(['shopify/developers'], Shipit.github_teams.map(&:handle))
|
55
|
+
end
|
56
|
+
|
57
|
+
test ".github_teams merges the teams and team keys in a single array" do
|
58
|
+
Rails.application.secrets.stubs(:github_oauth).returns(
|
59
|
+
'team' => 'shopify/developers',
|
60
|
+
'teams' => ['shopify/developers', 'cyclimse/cooks'])
|
61
|
+
assert_equal(['cyclimse/cooks', 'shopify/developers'], Shipit.github_teams.map(&:handle))
|
62
|
+
end
|
47
63
|
end
|
48
64
|
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.
|
4
|
+
version: 0.7.0
|
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-
|
11
|
+
date: 2016-02-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -531,6 +531,7 @@ files:
|
|
531
531
|
- db/migrate/20151113151323_improve_indexes_on_tasks.rb
|
532
532
|
- db/migrate/20160104151742_increase_tasks_type_size_back.rb
|
533
533
|
- db/migrate/20160104151833_convert_sti_columns.rb
|
534
|
+
- db/migrate/20160122165559_rename_hooks_url_in_delivery_url.rb
|
534
535
|
- db/schema.rb
|
535
536
|
- lib/shipit-engine.rb
|
536
537
|
- lib/shipit.rb
|
@@ -632,6 +633,7 @@ files:
|
|
632
633
|
- test/fixtures/shipit/users.yml
|
633
634
|
- test/helpers/api_helper.rb
|
634
635
|
- test/helpers/fixture_aliases_helper.rb
|
636
|
+
- test/helpers/hooks_helper.rb
|
635
637
|
- test/helpers/json_helper.rb
|
636
638
|
- test/helpers/links_helper.rb
|
637
639
|
- test/helpers/payloads_helper.rb
|
@@ -772,6 +774,7 @@ test_files:
|
|
772
774
|
- test/fixtures/shipit/users.yml
|
773
775
|
- test/helpers/api_helper.rb
|
774
776
|
- test/helpers/fixture_aliases_helper.rb
|
777
|
+
- test/helpers/hooks_helper.rb
|
775
778
|
- test/helpers/json_helper.rb
|
776
779
|
- test/helpers/links_helper.rb
|
777
780
|
- test/helpers/payloads_helper.rb
|