shipit-engine 0.25.1 → 0.26.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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/shipit/merge_status_controller.rb +1 -1
  3. data/app/controllers/shipit/stacks_controller.rb +2 -1
  4. data/app/controllers/shipit/webhooks_controller.rb +15 -0
  5. data/app/jobs/shipit/cache_deploy_spec_job.rb +1 -0
  6. data/app/jobs/shipit/perform_task_job.rb +4 -2
  7. data/app/jobs/shipit/refresh_check_runs_job.rb +14 -0
  8. data/app/models/shipit/check_run.rb +71 -0
  9. data/app/models/shipit/commit.rb +25 -2
  10. data/app/models/shipit/deploy_spec.rb +1 -1
  11. data/app/models/shipit/pull_request.rb +2 -2
  12. data/app/models/shipit/status.rb +1 -1
  13. data/app/views/shipit/commits/_commit.html.erb +1 -1
  14. data/db/migrate/20181010150947_create_shipit_check_runs.rb +17 -0
  15. data/lib/shipit.rb +1 -0
  16. data/lib/shipit/octokit_check_runs.rb +9 -0
  17. data/lib/shipit/stack_commands.rb +8 -3
  18. data/lib/shipit/task_commands.rb +2 -3
  19. data/lib/shipit/version.rb +1 -1
  20. data/test/controllers/merge_status_controller_test.rb +15 -0
  21. data/test/controllers/stacks_controller_test.rb +12 -2
  22. data/test/controllers/webhooks_controller_test.rb +9 -0
  23. data/test/dummy/db/schema.rb +17 -1
  24. data/test/fixtures/payloads/check_suite_master.json +194 -0
  25. data/test/fixtures/shipit/check_runs.yml +21 -0
  26. data/test/fixtures/shipit/commits.yml +13 -0
  27. data/test/fixtures/shipit/stacks.yml +8 -0
  28. data/test/jobs/perform_task_job_test.rb +10 -1
  29. data/test/models/commits_test.rb +29 -2
  30. data/test/models/deploy_spec_test.rb +40 -0
  31. data/test/models/shipit/check_run_test.rb +51 -0
  32. data/test/models/status/group_test.rb +3 -3
  33. data/test/unit/deploy_commands_test.rb +5 -1
  34. metadata +128 -118
@@ -0,0 +1,194 @@
1
+ {
2
+ "action": "requested",
3
+ "check_suite": {
4
+ "id": 5,
5
+ "head_branch": "master",
6
+ "head_sha": "6d9278037b872fd9a6690523e411ecb3aa181355",
7
+ "status": "completed",
8
+ "conclusion": "neutral",
9
+ "url": "https://api.github.com/repos/Shopify/shipit-engine/check-suites/5",
10
+ "before": "146e867f55c26428e5f9fade55a9bbf5e95a7912",
11
+ "after": "d6fde92930d4715a2b49857d24b940956b26d2d3",
12
+ "pull_requests": [
13
+
14
+ ],
15
+ "app": {
16
+ "id": 2,
17
+ "node_id": "MDExOkludGVncmF0aW9uMQ==",
18
+ "owner": {
19
+ "login": "github",
20
+ "id": 340,
21
+ "node_id": "MDEyOk9yZ2FuaXphdGlvbjE=",
22
+ "avatar_url": "http://alambic.github.com/avatars/u/340?",
23
+ "gravatar_id": "",
24
+ "url": "https://api.github.com/users/github",
25
+ "html_url": "http://github.com/github",
26
+ "followers_url": "https://api.github.com/users/github/followers",
27
+ "following_url": "https://api.github.com/users/github/following{/other_user}",
28
+ "gists_url": "https://api.github.com/users/github/gists{/gist_id}",
29
+ "starred_url": "https://api.github.com/users/github/starred{/owner}{/repo}",
30
+ "subscriptions_url": "https://api.github.com/users/github/subscriptions",
31
+ "organizations_url": "https://api.github.com/users/github/orgs",
32
+ "repos_url": "https://api.github.com/users/github/repos",
33
+ "events_url": "https://api.github.com/users/github/events{/privacy}",
34
+ "received_events_url": "https://api.github.com/users/github/received_events",
35
+ "type": "Organization",
36
+ "site_admin": false
37
+ },
38
+ "name": "Super Duper",
39
+ "description": null,
40
+ "external_url": "http://super-duper.example.com",
41
+ "html_url": "http://github.com/apps/super-duper",
42
+ "created_at": "2018-04-25 20:42:10",
43
+ "updated_at": "2018-04-25 20:42:10"
44
+ },
45
+ "created_at": "2018-05-04T01:14:52Z",
46
+ "updated_at": "2018-05-04T01:14:52Z",
47
+ "latest_check_runs_count": 1,
48
+ "check_runs_url": "https://api.github.com/repos/Shopify/shipit-engine/check-suites/5/check-runs",
49
+ "head_commit": {
50
+ "id": "d6fde92930d4715a2b49857d24b940956b26d2d3",
51
+ "tree_id": "41a846c7d878d279f11355e23b348e1bb63b89a8",
52
+ "message": "Say hello (again) to everybody",
53
+ "timestamp": "2018-05-04T01:14:46Z",
54
+ "author": {
55
+ "name": "octocat",
56
+ "email": "octocat@github.com"
57
+ },
58
+ "committer": {
59
+ "name": "octocat",
60
+ "email": "octocat@github.com"
61
+ }
62
+ }
63
+ },
64
+ "repository": {
65
+ "id": 526,
66
+ "node_id": "MDEwOlJlcG9zaXRvcnkxMzU0OTMyMzM=",
67
+ "name": "shipit-engine",
68
+ "full_name": "Shopify/shipit-engine",
69
+ "owner": {
70
+ "login": "github",
71
+ "id": 340,
72
+ "node_id": "MDQ6VXNlcjIxMDMxMDY3",
73
+ "avatar_url": "http://alambic.github.com/avatars/u/340?",
74
+ "gravatar_id": "",
75
+ "url": "https://api.github.com/users/github",
76
+ "html_url": "http://github.com/github",
77
+ "followers_url": "https://api.github.com/users/github/followers",
78
+ "following_url": "https://api.github.com/users/github/following{/other_user}",
79
+ "gists_url": "https://api.github.com/users/github/gists{/gist_id}",
80
+ "starred_url": "https://api.github.com/users/github/starred{/owner}{/repo}",
81
+ "subscriptions_url": "https://api.github.com/users/github/subscriptions",
82
+ "organizations_url": "https://api.github.com/users/github/orgs",
83
+ "repos_url": "https://api.github.com/users/github/repos",
84
+ "events_url": "https://api.github.com/users/github/events{/privacy}",
85
+ "received_events_url": "https://api.github.com/users/github/received_events",
86
+ "type": "Organization",
87
+ "site_admin": false
88
+ },
89
+ "private": false,
90
+ "html_url": "http://github.com/Shopify/shipit-engine",
91
+ "description": null,
92
+ "fork": false,
93
+ "url": "https://api.github.com/repos/Shopify/shipit-engine",
94
+ "forks_url": "https://api.github.com/repos/Shopify/shipit-engine/forks",
95
+ "keys_url": "https://api.github.com/repos/Shopify/shipit-engine/keys{/key_id}",
96
+ "collaborators_url": "https://api.github.com/repos/Shopify/shipit-engine/collaborators{/collaborator}",
97
+ "teams_url": "https://api.github.com/repos/Shopify/shipit-engine/teams",
98
+ "hooks_url": "https://api.github.com/repos/Shopify/shipit-engine/hooks",
99
+ "issue_events_url": "https://api.github.com/repos/Shopify/shipit-engine/issues/events{/number}",
100
+ "events_url": "https://api.github.com/repos/Shopify/shipit-engine/events",
101
+ "assignees_url": "https://api.github.com/repos/Shopify/shipit-engine/assignees{/user}",
102
+ "branches_url": "https://api.github.com/repos/Shopify/shipit-engine/branches{/branch}",
103
+ "tags_url": "https://api.github.com/repos/Shopify/shipit-engine/tags",
104
+ "blobs_url": "https://api.github.com/repos/Shopify/shipit-engine/git/blobs{/sha}",
105
+ "git_tags_url": "https://api.github.com/repos/Shopify/shipit-engine/git/tags{/sha}",
106
+ "git_refs_url": "https://api.github.com/repos/Shopify/shipit-engine/git/refs{/sha}",
107
+ "trees_url": "https://api.github.com/repos/Shopify/shipit-engine/git/trees{/sha}",
108
+ "statuses_url": "https://api.github.com/repos/Shopify/shipit-engine/statuses/{sha}",
109
+ "languages_url": "https://api.github.com/repos/Shopify/shipit-engine/languages",
110
+ "stargazers_url": "https://api.github.com/repos/Shopify/shipit-engine/stargazers",
111
+ "contributors_url": "https://api.github.com/repos/Shopify/shipit-engine/contributors",
112
+ "subscribers_url": "https://api.github.com/repos/Shopify/shipit-engine/subscribers",
113
+ "subscription_url": "https://api.github.com/repos/Shopify/shipit-engine/subscription",
114
+ "commits_url": "https://api.github.com/repos/Shopify/shipit-engine/commits{/sha}",
115
+ "git_commits_url": "https://api.github.com/repos/Shopify/shipit-engine/git/commits{/sha}",
116
+ "comments_url": "https://api.github.com/repos/Shopify/shipit-engine/comments{/number}",
117
+ "issue_comment_url": "https://api.github.com/repos/Shopify/shipit-engine/issues/comments{/number}",
118
+ "contents_url": "https://api.github.com/repos/Shopify/shipit-engine/contents/{+path}",
119
+ "compare_url": "https://api.github.com/repos/Shopify/shipit-engine/compare/{base}...{head}",
120
+ "merges_url": "https://api.github.com/repos/Shopify/shipit-engine/merges",
121
+ "archive_url": "https://api.github.com/repos/Shopify/shipit-engine/{archive_format}{/ref}",
122
+ "downloads_url": "https://api.github.com/repos/Shopify/shipit-engine/downloads",
123
+ "issues_url": "https://api.github.com/repos/Shopify/shipit-engine/issues{/number}",
124
+ "pulls_url": "https://api.github.com/repos/Shopify/shipit-engine/pulls{/number}",
125
+ "milestones_url": "https://api.github.com/repos/Shopify/shipit-engine/milestones{/number}",
126
+ "notifications_url": "https://api.github.com/repos/Shopify/shipit-engine/notifications{?since,all,participating}",
127
+ "labels_url": "https://api.github.com/repos/Shopify/shipit-engine/labels{/name}",
128
+ "releases_url": "https://api.github.com/repos/Shopify/shipit-engine/releases{/id}",
129
+ "deployments_url": "https://api.github.com/repos/Shopify/shipit-engine/deployments",
130
+ "created_at": "2018-04-25T20:42:10Z",
131
+ "updated_at": "2018-04-25T20:43:34Z",
132
+ "pushed_at": "2018-05-04T01:14:47Z",
133
+ "git_url": "git://github.com/Shopify/shipit-engine.git",
134
+ "ssh_url": "ssh://git@localhost:3035/Shopify/shipit-engine.git",
135
+ "clone_url": "http://github.com/Shopify/shipit-engine.git",
136
+ "svn_url": "http://github.com/Shopify/shipit-engine",
137
+ "homepage": null,
138
+ "size": 0,
139
+ "stargazers_count": 0,
140
+ "watchers_count": 0,
141
+ "language": null,
142
+ "has_issues": true,
143
+ "has_projects": true,
144
+ "has_downloads": true,
145
+ "has_wiki": true,
146
+ "has_pages": false,
147
+ "forks_count": 0,
148
+ "mirror_url": null,
149
+ "archived": false,
150
+ "open_issues_count": 3,
151
+ "license": null,
152
+ "forks": 0,
153
+ "open_issues": 3,
154
+ "watchers": 0,
155
+ "default_branch": "master"
156
+ },
157
+ "organization": {
158
+ "login": "github",
159
+ "id": 340,
160
+ "node_id": "MDEyOk9yZ2FuaXphdGlvbjM4MzAyODk5",
161
+ "url": "https://api.github.com/orgs/github",
162
+ "repos_url": "https://api.github.com/orgs/github/repos",
163
+ "events_url": "https://api.github.com/orgs/github/events",
164
+ "hooks_url": "https://api.github.com/orgs/github/hooks",
165
+ "issues_url": "https://api.github.com/orgs/github/issues",
166
+ "members_url": "https://api.github.com/orgs/github/members{/member}",
167
+ "public_members_url": "https://api.github.com/orgs/github/public_members{/member}",
168
+ "avatar_url": "http://alambic.github.com/avatars/u/340?",
169
+ "description": "How people build software."
170
+ },
171
+ "sender": {
172
+ "login": "octocat",
173
+ "id": 5346,
174
+ "node_id": "MDQ6VXNlcjIxMDMxMDY3",
175
+ "avatar_url": "http://alambic.github.com/avatars/u/5346?",
176
+ "gravatar_id": "",
177
+ "url": "https://api.github.com/users/octocat",
178
+ "html_url": "http://github.com/octocat",
179
+ "followers_url": "https://api.github.com/users/octocat/followers",
180
+ "following_url": "https://api.github.com/users/octocat/following{/other_user}",
181
+ "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
182
+ "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
183
+ "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
184
+ "organizations_url": "https://api.github.com/users/octocat/orgs",
185
+ "repos_url": "https://api.github.com/users/octocat/repos",
186
+ "events_url": "https://api.github.com/users/octocat/events{/privacy}",
187
+ "received_events_url": "https://api.github.com/users/octocat/received_events",
188
+ "type": "User",
189
+ "site_admin": false
190
+ },
191
+ "installation": {
192
+ "id": 1
193
+ }
194
+ }
@@ -0,0 +1,21 @@
1
+ second_pending_travis:
2
+ stack: shipit
3
+ commit_id: 2 # second
4
+ github_id: 424242
5
+ name: Travis CI
6
+ title: Tests ran successfully
7
+ conclusion: success
8
+ html_url: "http://www.example.com/run/424242"
9
+ details_url: "http://www.example.com/build/424242"
10
+ created_at: <%= 10.days.ago.to_s(:db) %>
11
+
12
+ check_runs_first_success_coveralls:
13
+ stack: check_runs
14
+ commit_id: 201 # check_runs_first
15
+ github_id: 434343
16
+ title: lets go
17
+ name: Coverage metrics
18
+ created_at: <%= 9.days.ago.to_s(:db) %>
19
+ conclusion: success
20
+ html_url: "http://www.example.com/run/434343"
21
+ details_url: "http://www.example.com/build/434343"
@@ -168,3 +168,16 @@ soc_third:
168
168
  additions: 12
169
169
  deletions: 64
170
170
  updated_at: <%= 8.days.ago.to_s(:db) %>
171
+
172
+ check_runs_first:
173
+ id: 201
174
+ sha: 234328037b872fd9a6690523e411ecb3aa181355
175
+ message: "lets go"
176
+ stack: check_runs
177
+ author: walrus
178
+ committer: walrus
179
+ authored_at: <%= 10.days.ago.to_s(:db) %>
180
+ committed_at: <%= 9.days.ago.to_s(:db) %>
181
+ additions: 42
182
+ deletions: 24
183
+ updated_at: <%= 8.days.ago.to_s(:db) %>
@@ -162,3 +162,11 @@ soc:
162
162
  }
163
163
  }
164
164
  updated_at: <%= 8.days.ago.to_s(:db) %>
165
+
166
+ check_runs:
167
+ repo_owner: shopify
168
+ repo_name: check_runs
169
+ environment: production
170
+ branch: master
171
+ tasks_count: 0
172
+ undeployed_commits_count: 1
@@ -2,6 +2,15 @@ require 'test_helper'
2
2
 
3
3
  module Shipit
4
4
  class PerformTaskJobTest < ActiveSupport::TestCase
5
+ class FakeSuccessfulCommand
6
+ def run
7
+ end
8
+
9
+ def success?
10
+ true
11
+ end
12
+ end
13
+
5
14
  setup do
6
15
  @job = PerformTaskJob.new
7
16
  @deploy = shipit_deploys(:shipit_pending)
@@ -14,7 +23,7 @@ module Shipit
14
23
  @commands = stub(:commands)
15
24
  Commands.expects(:for).with(@deploy).returns(@commands)
16
25
 
17
- @commands.expects(:fetch).once
26
+ @commands.expects(:fetched?).once.returns(FakeSuccessfulCommand.new)
18
27
  @commands.expects(:clone).returns([]).once
19
28
  @commands.expects(:checkout).with(@deploy.until_commit).once
20
29
  @commands.expects(:install_dependencies).returns([]).once
@@ -222,6 +222,29 @@ module Shipit
222
222
  assert_equal 'success', @commit.statuses.first.state
223
223
  end
224
224
 
225
+ test "refresh_check_runs! pull state from github" do
226
+ check_run = mock(
227
+ id: 34_234_234_234_432,
228
+ name: 'Test suite',
229
+ conclusion: 'neutral',
230
+ details_url: 'https://example.com/details',
231
+ html_url: 'https://example.com/run',
232
+ output: mock(
233
+ title: 'Tests build ran successfully',
234
+ ),
235
+ )
236
+ response = mock(
237
+ check_runs: [check_run],
238
+ )
239
+ Shipit.github.api.expects(:check_runs).with(@stack.github_repo_name, @commit.sha).returns(response)
240
+
241
+ assert_difference -> { @commit.check_runs.count }, 1 do
242
+ @commit.refresh_check_runs!
243
+ end
244
+
245
+ assert_equal 'success', @commit.check_runs.first.state
246
+ end
247
+
225
248
  test "#creating a commit update the undeployed_commits_count" do
226
249
  walrus = shipit_users(:walrus)
227
250
  assert_equal 1, @stack.undeployed_commits_count
@@ -321,14 +344,18 @@ module Shipit
321
344
  test "#status returns an unknown if the commit has no statuses" do
322
345
  commit = shipit_commits(:second)
323
346
  commit.statuses = []
347
+ commit.check_runs = []
324
348
  assert_predicate commit.status, :unknown?
325
349
  end
326
350
 
327
351
  test "#status rejects the statuses that are specified in the deploy spec's `ci.hide`" do
328
352
  commit = shipit_commits(:second)
329
353
  assert_predicate commit.status, :group?
330
- assert_equal 2, commit.status.size
331
- commit.stack.update!(cached_deploy_spec: DeploySpec.new('ci' => {'hide' => 'metrics/coveralls'}))
354
+ assert_equal 3, commit.status.size
355
+ commit.stack.update!(cached_deploy_spec: DeploySpec.new('ci' => {'hide' => [
356
+ 'Travis CI',
357
+ 'metrics/coveralls',
358
+ ]}))
332
359
  commit.reload
333
360
  refute_predicate commit.status, :group?
334
361
  end
@@ -214,6 +214,46 @@ module Shipit
214
214
  assert_equal ["kubernetes-deploy --max-watch-seconds 900 foo bar"], @spec.rollback_steps
215
215
  end
216
216
 
217
+ test "#discover_task_definitions include a kubernetes restart command if `kubernetes` is present" do
218
+ @spec.stubs(:load_config).returns(
219
+ 'kubernetes' => {
220
+ 'namespace' => 'foo',
221
+ 'context' => 'bar',
222
+ },
223
+ )
224
+ tasks = {
225
+ 'restart' => {
226
+ 'action' => 'Restart application',
227
+ 'description' => 'Simulates a rollout of Kubernetes deployments by using kubernetes-restart utility',
228
+ 'steps' => ['kubernetes-restart foo bar --max-watch-seconds 900'],
229
+ },
230
+ }
231
+ assert_equal tasks, @spec.discover_task_definitions
232
+ end
233
+
234
+ test "#discover_task_definitions include the user defined restart command even if `kubernetes` is present" do
235
+ tasks = {
236
+ 'restart' => {
237
+ 'action' => 'Restart application',
238
+ 'description' => 'Simulates a rollout of Kubernetes deployments by using kubernetes-restart utility',
239
+ 'steps' => ['kubernetes-restart something custom'],
240
+ },
241
+ 'some-other-tasj' => {
242
+ 'action' => 'Do something else',
243
+ 'description' => 'Eat some chips!',
244
+ 'steps' => ['echo chips'],
245
+ },
246
+ }
247
+ @spec.stubs(:load_config).returns(
248
+ 'kubernetes' => {
249
+ 'namespace' => 'foo',
250
+ 'context' => 'bar',
251
+ },
252
+ 'tasks' => tasks,
253
+ )
254
+ assert_equal tasks, @spec.discover_task_definitions
255
+ end
256
+
217
257
  test '#machine_env returns an environment hash' do
218
258
  @spec.stubs(:load_config).returns('machine' => {'environment' => {'GLOBAL' => '1'}})
219
259
  assert_equal({'GLOBAL' => '1'}, @spec.machine_env)
@@ -0,0 +1,51 @@
1
+ require 'test_helper'
2
+
3
+ module Shipit
4
+ class CheckRunTest < ActiveSupport::TestCase
5
+ setup do
6
+ @commit = shipit_commits(:first)
7
+ @stack = @commit.stack
8
+ @check_run = shipit_check_runs(:second_pending_travis)
9
+ end
10
+
11
+ test ".create_or_update_from_github! is idempotent" do
12
+ assert_difference -> { @commit.check_runs.count }, +1 do
13
+ @commit.check_runs.create_or_update_from_github!(@stack.id, github_check_run)
14
+ end
15
+
16
+ assert_no_difference -> { @commit.check_runs.count } do
17
+ @commit.check_runs.create_or_update_from_github!(@stack.id, github_check_run)
18
+ end
19
+ end
20
+
21
+ {
22
+ nil => 'pending',
23
+ 'success' => 'success',
24
+ 'failure' => 'failure',
25
+ 'neutral' => 'success',
26
+ 'cancelled' => 'failure',
27
+ 'timed_out' => 'error',
28
+ 'action_required' => 'pending',
29
+ }.each do |conclusion, expected_status|
30
+ test "#state is #{expected_status.inspect} when conclusion is #{conclusion.inspect}" do
31
+ @check_run.update!(conclusion: conclusion)
32
+ assert_equal expected_status, @check_run.state
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def github_check_run
39
+ @github_check_run ||= OpenStruct.new(
40
+ id: 424_242,
41
+ conclusion: 'success',
42
+ output: OpenStruct.new(
43
+ description: 'This is a description',
44
+ ),
45
+ name: 'Test Suite',
46
+ html_url: 'http://example.com/run',
47
+ details_url: 'http://example.com/details',
48
+ )
49
+ end
50
+ end
51
+ end
@@ -4,11 +4,11 @@ module Shipit
4
4
  class StatusGroupTest < ActiveSupport::TestCase
5
5
  setup do
6
6
  @commit = shipit_commits(:second)
7
- @group = Status::Group.new(@commit, @commit.statuses)
7
+ @group = Status::Group.new(@commit, @commit.statuses_and_check_runs)
8
8
  end
9
9
 
10
10
  test "#description is a summary of the statuses" do
11
- assert_equal '1 / 2 checks OK', @group.description
11
+ assert_equal '2 / 3 checks OK', @group.description
12
12
  end
13
13
 
14
14
  test "#group? returns true" do
@@ -20,7 +20,7 @@ module Shipit
20
20
  end
21
21
 
22
22
  test "#state is significant's status state" do
23
- assert_equal %w(success failure), @group.statuses.map(&:state)
23
+ assert_equal %w(success success failure), @group.statuses.map(&:state)
24
24
  assert_equal 'failure', @group.state
25
25
  end
26
26
 
@@ -61,7 +61,11 @@ module Shipit
61
61
  test "#clone clones the repository cache into the working directory" do
62
62
  commands = @commands.clone
63
63
  assert_equal 2, commands.size
64
- clone_args = ['git', 'clone', '--local', '--origin', 'cache', @stack.git_path, @deploy.working_directory]
64
+ clone_args = [
65
+ 'git', 'clone', '--local',
66
+ '--origin', 'cache',
67
+ @stack.git_path, @deploy.working_directory
68
+ ]
65
69
  assert_equal clone_args, commands.first.args
66
70
  assert_equal ['git', 'remote', 'add', 'origin', @stack.repo_git_url], commands.second.args
67
71
  end