shipit-engine 0.15.0 → 0.16.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 (111) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +34 -1
  3. data/app/assets/javascripts/shipit/page_updater.js.coffee +63 -0
  4. data/app/assets/javascripts/shipit/stacks.js.coffee +9 -21
  5. data/app/assets/stylesheets/_base/_base.scss +2 -2
  6. data/app/assets/stylesheets/_base/_colors.scss +0 -1
  7. data/app/assets/stylesheets/_base/_forms.scss +14 -0
  8. data/app/assets/stylesheets/_pages/_commits.scss +16 -6
  9. data/app/assets/stylesheets/_pages/_settings.scss +8 -0
  10. data/app/assets/stylesheets/_pages/_stacks.scss +1 -1
  11. data/app/controllers/shipit/api/base_controller.rb +7 -3
  12. data/app/controllers/shipit/api/ccmenu_controller.rb +33 -0
  13. data/app/controllers/shipit/api/pull_requests_controller.rb +36 -0
  14. data/app/controllers/shipit/api/stacks_controller.rb +1 -0
  15. data/app/controllers/shipit/ccmenu_url_controller.rb +22 -0
  16. data/app/controllers/shipit/pull_requests_controller.rb +30 -0
  17. data/app/controllers/shipit/stacks_controller.rb +7 -2
  18. data/app/controllers/shipit/webhooks_controller.rb +1 -2
  19. data/app/helpers/shipit/github_url_helper.rb +8 -2
  20. data/app/helpers/shipit/shipit_helper.rb +9 -0
  21. data/app/helpers/shipit/stacks_helper.rb +22 -7
  22. data/app/jobs/shipit/background_job/unique.rb +19 -1
  23. data/app/jobs/shipit/cache_deploy_spec_job.rb +1 -1
  24. data/app/jobs/shipit/merge_pull_requests_job.rb +26 -0
  25. data/app/jobs/shipit/perform_task_job.rb +1 -1
  26. data/app/jobs/shipit/refresh_pull_request_job.rb +8 -0
  27. data/app/models/concerns/shipit/deferred_touch.rb +6 -1
  28. data/app/models/shipit/anonymous_user.rb +4 -0
  29. data/app/models/shipit/application_record.rb +5 -0
  30. data/app/models/shipit/commit.rb +51 -49
  31. data/app/models/shipit/commit_message.rb +32 -0
  32. data/app/models/shipit/deploy.rb +5 -0
  33. data/app/models/shipit/deploy_spec.rb +26 -1
  34. data/app/models/shipit/deploy_spec/file_system.rb +6 -1
  35. data/app/models/shipit/deploy_spec/kubernetes_discovery.rb +10 -13
  36. data/app/models/shipit/deploy_spec/npm_discovery.rb +2 -1
  37. data/app/models/shipit/duration.rb +3 -1
  38. data/app/models/shipit/hook.rb +1 -0
  39. data/app/models/shipit/pull_request.rb +252 -0
  40. data/app/models/shipit/stack.rb +33 -17
  41. data/app/models/shipit/status.rb +1 -16
  42. data/app/models/shipit/status/common.rb +45 -0
  43. data/app/models/shipit/status/group.rb +82 -0
  44. data/app/models/shipit/status/missing.rb +30 -0
  45. data/app/models/shipit/status/unknown.rb +33 -0
  46. data/app/models/shipit/unlimited_api_client.rb +10 -0
  47. data/app/serializers/shipit/commit_serializer.rb +1 -1
  48. data/app/serializers/shipit/pull_request_serializer.rb +20 -0
  49. data/app/serializers/shipit/stack_serializer.rb +6 -2
  50. data/app/views/layouts/shipit.html.erb +41 -39
  51. data/app/views/shipit/ccmenu/project.xml.builder +13 -0
  52. data/app/views/shipit/commits/_commit.html.erb +1 -1
  53. data/app/views/shipit/deploys/_deploy.html.erb +1 -1
  54. data/app/views/shipit/pull_requests/_pull_request.html.erb +29 -0
  55. data/app/views/shipit/pull_requests/index.html.erb +20 -0
  56. data/app/views/shipit/shared/_author.html.erb +7 -0
  57. data/app/views/shipit/stacks/_header.html.erb +5 -0
  58. data/app/views/shipit/stacks/settings.html.erb +13 -0
  59. data/app/views/shipit/stacks/show.html.erb +3 -2
  60. data/app/views/shipit/statuses/_group.html.erb +1 -1
  61. data/app/views/shipit/tasks/_task.html.erb +1 -1
  62. data/config/initializers/inflections.rb +3 -0
  63. data/config/locales/en.yml +1 -3
  64. data/config/routes.rb +8 -0
  65. data/db/migrate/20170130113633_create_shipit_pull_requests.rb +25 -0
  66. data/db/migrate/20170208143657_add_pull_request_number_and_title_to_commits.rb +7 -0
  67. data/db/migrate/20170208154609_backfill_merge_commits.rb +13 -0
  68. data/db/migrate/20170209160355_add_branch_to_pull_requests.rb +5 -0
  69. data/db/migrate/20170215123538_add_merge_queue_enabled_to_stacks.rb +5 -0
  70. data/db/migrate/20170220152410_improve_users_indexing.rb +6 -0
  71. data/db/migrate/20170221102128_improve_tasks_indexing.rb +8 -0
  72. data/db/migrate/20170221130336_add_last_revalidated_at_on_pull_requests.rb +10 -0
  73. data/lib/shipit.rb +2 -0
  74. data/lib/shipit/version.rb +1 -1
  75. data/lib/tasks/cron.rake +1 -0
  76. data/test/controllers/api/ccmenu_controller_test.rb +57 -0
  77. data/test/controllers/api/commits_controller_test.rb +1 -1
  78. data/test/controllers/api/pull_requests_controller_test.rb +59 -0
  79. data/test/controllers/ccmenu_controller_test.rb +33 -0
  80. data/test/controllers/pull_requests_controller_test.rb +31 -0
  81. data/test/controllers/webhooks_controller_test.rb +3 -4
  82. data/test/dummy/config/environments/development.rb +3 -1
  83. data/test/dummy/data/stacks/shopify/junk/production/git/README.md +8 -0
  84. data/test/dummy/data/stacks/shopify/junk/production/git/circle.yml +4 -0
  85. data/test/dummy/data/stacks/shopify/junk/production/git/shipit.yml +4 -0
  86. data/test/dummy/db/development.sqlite3 +0 -0
  87. data/test/dummy/db/schema.rb +45 -11
  88. data/test/dummy/db/seeds.rb +33 -10
  89. data/test/dummy/db/test.sqlite3 +0 -0
  90. data/test/fixtures/shipit/commits.yml +14 -0
  91. data/test/fixtures/shipit/pull_requests.yml +56 -0
  92. data/test/fixtures/shipit/stacks.yml +5 -1
  93. data/test/fixtures/shipit/statuses.yml +8 -0
  94. data/test/helpers/json_helper.rb +16 -14
  95. data/test/jobs/merge_pull_requests_job_test.rb +59 -0
  96. data/test/models/commits_test.rb +104 -49
  97. data/test/{unit → models}/deploy_spec_test.rb +138 -12
  98. data/test/models/deploys_test.rb +10 -4
  99. data/test/models/pull_request_test.rb +197 -0
  100. data/test/models/stacks_test.rb +46 -53
  101. data/test/models/status/group_test.rb +44 -0
  102. data/test/models/status/missing_test.rb +23 -0
  103. data/test/models/status_test.rb +3 -6
  104. data/test/unit/csv_serializer_test.rb +10 -2
  105. metadata +57 -12
  106. data/app/models/shipit/missing_status.rb +0 -21
  107. data/app/models/shipit/status_group.rb +0 -35
  108. data/app/models/shipit/unknown_status.rb +0 -48
  109. data/app/views/shipit/commits/_commit_author.html.erb +0 -7
  110. data/test/models/missing_status_test.rb +0 -23
  111. data/test/models/status_group_test.rb +0 -26
@@ -42,12 +42,11 @@ module Shipit
42
42
  assert_equal status_payload['created_at'], status.created_at.iso8601
43
43
  end
44
44
 
45
- test ":state with a unexisting commit trows ActiveRecord::RecordNotFound" do
45
+ test ":state with a unexisting commit respond with 200 OK" do
46
46
  request.headers['X-Github-Event'] = 'status'
47
47
  params = {'sha' => 'notarealcommit', 'state' => 'pending', 'branches' => [{'name' => 'master'}]}
48
- assert_raises ActiveRecord::RecordNotFound do
49
- post :state, params: {stack_id: @stack.id}.merge(params)
50
- end
48
+ post :state, params: {stack_id: @stack.id}.merge(params)
49
+ assert_response :ok
51
50
  end
52
51
 
53
52
  test ":state in an untracked branche bails out" do
@@ -42,6 +42,8 @@ Rails.application.configure do
42
42
  Shipit::DeferredTouch.enabled = false
43
43
  end
44
44
  config.active_job.queue_adapter = :async
45
-
45
+
46
46
  Pubsubstub.use_persistent_connections = false
47
+
48
+ Shipit.disable_api_authentication = true if ENV['PUBLIC_API']
47
49
  end
@@ -0,0 +1,8 @@
1
+ # junk
2
+ For testing purposes. Feel free to delete if I forgot (byroot).
3
+
4
+ PR 1
5
+ PR 2
6
+ PR 3
7
+ PR 4
8
+ PR 5
@@ -0,0 +1,4 @@
1
+ test:
2
+ override:
3
+ - "true"
4
+ - echo done
@@ -0,0 +1,4 @@
1
+ deploy:
2
+ override:
3
+ - sleep 3
4
+ - echo done
@@ -10,7 +10,7 @@
10
10
  #
11
11
  # It's strongly recommended that you check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema.define(version: 20161206105318) do
13
+ ActiveRecord::Schema.define(version: 20170221130336) do
14
14
 
15
15
  create_table "api_clients", force: :cascade do |t|
16
16
  t.text "permissions", limit: 65535
@@ -44,18 +44,21 @@ ActiveRecord::Schema.define(version: 20161206105318) do
44
44
  end
45
45
 
46
46
  create_table "commits", force: :cascade do |t|
47
- t.integer "stack_id", limit: 4, null: false
48
- t.integer "author_id", limit: 4, null: false
49
- t.integer "committer_id", limit: 4, null: false
50
- t.string "sha", limit: 40, null: false
51
- t.text "message", limit: 65535, null: false
47
+ t.integer "stack_id", limit: 4, null: false
48
+ t.integer "author_id", limit: 4, null: false
49
+ t.integer "committer_id", limit: 4, null: false
50
+ t.string "sha", limit: 40, null: false
51
+ t.text "message", limit: 65535, null: false
52
52
  t.datetime "created_at"
53
53
  t.datetime "updated_at"
54
- t.boolean "detached", default: false, null: false
55
- t.datetime "authored_at", null: false
56
- t.datetime "committed_at", null: false
57
- t.integer "additions", limit: 4
58
- t.integer "deletions", limit: 4
54
+ t.boolean "detached", default: false, null: false
55
+ t.datetime "authored_at", null: false
56
+ t.datetime "committed_at", null: false
57
+ t.integer "additions", limit: 4
58
+ t.integer "deletions", limit: 4
59
+ t.integer "pull_request_number"
60
+ t.string "pull_request_title", limit: 1024
61
+ t.integer "pull_request_id"
59
62
  t.index ["author_id"], name: "index_commits_on_author_id"
60
63
  t.index ["committer_id"], name: "index_commits_on_committer_id"
61
64
  t.index ["created_at"], name: "index_commits_on_created_at"
@@ -123,6 +126,33 @@ ActiveRecord::Schema.define(version: 20161206105318) do
123
126
  t.index ["task_id"], name: "index_output_chunks_on_task_id"
124
127
  end
125
128
 
129
+ create_table "pull_requests", force: :cascade do |t|
130
+ t.integer "stack_id", null: false
131
+ t.integer "number", null: false
132
+ t.string "title", limit: 256
133
+ t.integer "github_id", limit: 8
134
+ t.string "api_url", limit: 1024
135
+ t.string "state"
136
+ t.integer "head_id"
137
+ t.boolean "mergeable"
138
+ t.integer "additions", default: 0, null: false
139
+ t.integer "deletions", default: 0, null: false
140
+ t.string "merge_status", limit: 30, null: false
141
+ t.string "rejection_reason"
142
+ t.datetime "merge_requested_at", null: false
143
+ t.integer "merge_requested_by_id"
144
+ t.datetime "created_at", null: false
145
+ t.datetime "updated_at", null: false
146
+ t.string "branch"
147
+ t.datetime "revalidated_at"
148
+ t.index ["head_id"], name: "index_pull_requests_on_head_id"
149
+ t.index ["merge_requested_by_id"], name: "index_pull_requests_on_merge_requested_by_id"
150
+ t.index ["stack_id", "github_id"], name: "index_pull_requests_on_stack_id_and_github_id", unique: true
151
+ t.index ["stack_id", "merge_status"], name: "index_pull_requests_on_stack_id_and_merge_status"
152
+ t.index ["stack_id", "number"], name: "index_pull_requests_on_stack_id_and_number", unique: true
153
+ t.index ["stack_id"], name: "index_pull_requests_on_stack_id"
154
+ end
155
+
126
156
  create_table "stacks", force: :cascade do |t|
127
157
  t.string "repo_name", limit: 100, null: false
128
158
  t.string "repo_owner", limit: 39, null: false
@@ -142,6 +172,7 @@ ActiveRecord::Schema.define(version: 20161206105318) do
142
172
  t.integer "estimated_deploy_duration", default: 1, null: false
143
173
  t.datetime "continuous_delivery_delayed_since"
144
174
  t.datetime "locked_since"
175
+ t.boolean "merge_queue_enabled", default: false, null: false
145
176
  t.index ["repo_owner", "repo_name", "environment"], name: "stack_unicity", unique: true
146
177
  end
147
178
 
@@ -181,6 +212,7 @@ ActiveRecord::Schema.define(version: 20161206105318) do
181
212
  t.index ["rolled_up", "created_at", "status"], name: "index_tasks_on_rolled_up_and_created_at_and_status"
182
213
  t.index ["since_commit_id"], name: "index_tasks_on_since_commit_id"
183
214
  t.index ["stack_id", "allow_concurrency", "status"], name: "index_active_tasks"
215
+ t.index ["stack_id", "allow_concurrency"], name: "index_tasks_on_stack_id_and_allow_concurrency"
184
216
  t.index ["type", "stack_id", "parent_id"], name: "index_tasks_by_stack_and_parent"
185
217
  t.index ["type", "stack_id", "status"], name: "index_tasks_by_stack_and_status"
186
218
  t.index ["until_commit_id"], name: "index_tasks_on_until_commit_id"
@@ -209,7 +241,9 @@ ActiveRecord::Schema.define(version: 20161206105318) do
209
241
  t.string "avatar_url", limit: 255
210
242
  t.string "encrypted_github_access_token"
211
243
  t.string "encrypted_github_access_token_iv"
244
+ t.index ["github_id"], name: "index_users_on_github_id"
212
245
  t.index ["login"], name: "index_users_on_login"
246
+ t.index ["updated_at"], name: "index_users_on_updated_at"
213
247
  end
214
248
 
215
249
  end
@@ -26,6 +26,11 @@ module Shipit
26
26
  deploy_url: "https://#{Faker::Internet.domain_name.parameterize}.#{Faker::Internet.domain_suffix}/",
27
27
  cached_deploy_spec: DeploySpec.load(%(
28
28
  {
29
+ "ci": {
30
+ "hide": ["ci/hidden"],
31
+ "require": ["ci/travis"],
32
+ "allow_failures": ["ci/not-important"]
33
+ },
29
34
  "dependencies": {
30
35
  "bundler": {
31
36
  "without": [
@@ -103,16 +108,18 @@ module Shipit
103
108
  deletions: Faker::Number.number(3),
104
109
  )
105
110
 
106
- Status.create!(
107
- state: %w(pending success error failure).sample,
108
- context: 'ci/travis',
109
- description: "Your tests ran on travis-ci",
110
- target_url: "https://example.com",
111
- commit_id: commit.id,
112
- stack_id: commit.stack_id,
113
- created_at: Time.now,
114
- updated_at: Time.now,
115
- )
111
+ if (i % 4) != 0
112
+ Status.create!(
113
+ state: %w(pending success error failure).sample,
114
+ context: 'ci/travis',
115
+ description: "Your tests ran on travis-ci",
116
+ target_url: "https://example.com",
117
+ commit_id: commit.id,
118
+ stack_id: commit.stack_id,
119
+ created_at: Time.now,
120
+ updated_at: Time.now,
121
+ )
122
+ end
116
123
 
117
124
  if (i % 5) == 0
118
125
  Status.create!(
@@ -127,6 +134,22 @@ module Shipit
127
134
  )
128
135
  end
129
136
  end
137
+
138
+ stack.pull_requests.create!(
139
+ number: Faker::Number.number(3),
140
+ title: Faker::Company.catch_phrase,
141
+ merge_status: 'pending',
142
+ merge_requested_at: 5.minute.ago,
143
+ merge_requested_by: users.sample,
144
+ github_id: Faker::Number.number(8),
145
+ api_url: 'https://api.github.com/repos/shopify/shipit-engine/pulls/62',
146
+ state: 'open',
147
+ branch: "feature-#{Faker::Number.number(3)}",
148
+ head_id: nil,
149
+ mergeable: true,
150
+ additions: Faker::Number.number(3),
151
+ deletions: Faker::Number.number(3),
152
+ )
130
153
  end
131
154
 
132
155
  def create_chunks
Binary file
@@ -88,3 +88,17 @@ undeployed_stack_first:
88
88
  additions: 1
89
89
  deletions: 24
90
90
  updated_at: <%= 8.days.ago.to_s(:db) %>
91
+
92
+ shipit_pending_pr_head:
93
+ id: 8
94
+ sha: 424278037b872fd9a6690523e411ecb3aa181355
95
+ message: "Super feature"
96
+ stack: shipit
97
+ author: walrus
98
+ committer: walrus
99
+ authored_at: <%= 10.days.ago.to_s(:db) %>
100
+ committed_at: <%= 9.days.ago.to_s(:db) %>
101
+ additions: 42
102
+ deletions: 24
103
+ updated_at: <%= 8.days.ago.to_s(:db) %>
104
+ detached: true
@@ -0,0 +1,56 @@
1
+ shipit_fetching:
2
+ stack: shipit
3
+ number: 63
4
+ merge_status: fetching
5
+ merge_requested_at: <%= 1.minute.ago.to_s(:db) %>
6
+ merge_requested_by: walrus
7
+
8
+ shipit_pending:
9
+ stack: shipit
10
+ number: 62
11
+ title: Super duper nice feature
12
+ merge_status: pending
13
+ merge_requested_at: <%= 5.minute.ago.to_s(:db) %>
14
+ revalidated_at: <%= 5.minute.ago.to_s(:db) %>
15
+ merge_requested_by: walrus
16
+ github_id: 42424424242424
17
+ api_url: https://api.github.com/repos/shopify/shipit-engine/pulls/62
18
+ state: open
19
+ branch: feature-62
20
+ head_id: 8
21
+ mergeable: true
22
+ additions: 23
23
+ deletions: 43
24
+
25
+ shipit_pending_unmergeable:
26
+ stack: shipit
27
+ number: 61
28
+ title: Other cool feature
29
+ merge_status: pending
30
+ merge_requested_at: <%= 4.minute.ago.to_s(:db) %>
31
+ revalidated_at: <%= 4.minute.ago.to_s(:db) %>
32
+ merge_requested_by: walrus
33
+ github_id: 43434434343434
34
+ api_url: https://api.github.com/repos/shopify/shipit-engine/pulls/61
35
+ state: open
36
+ branch: feature-61
37
+ head_id: 8
38
+ mergeable: false
39
+ additions: 23
40
+ deletions: 43
41
+
42
+ shipit_pending_not_mergeable_yet:
43
+ stack: shipit
44
+ number: 64
45
+ merge_status: pending
46
+ merge_requested_by: walrus
47
+ merge_requested_at: <%= 3.minute.ago.to_s(:db) %>
48
+ revalidated_at: <%= 3.minute.ago.to_s(:db) %>
49
+ github_id: 45454454545454
50
+ api_url: https://api.github.com/repos/shopify/shipit-engine/pulls/64
51
+ state: open
52
+ branch: feature-64
53
+ head_id: 8
54
+ mergeable: null
55
+ additions: 23
56
+ deletions: 43
@@ -4,6 +4,7 @@ shipit:
4
4
  environment: "production"
5
5
  branch: master
6
6
  ignore_ci: false
7
+ merge_queue_enabled: true
7
8
  tasks_count: 3
8
9
  undeployed_commits_count: 1
9
10
  cached_deploy_spec: >
@@ -16,7 +17,7 @@ shipit:
16
17
  ]
17
18
  },
18
19
  "dependencies": {"override": []},
19
- "deploy": {"override": null, "interval": 60, "variables": [{"name": "SAFETY_DISABLED", "title": "Set to 1 to do dangerous things", "default": 0}]},
20
+ "deploy": {"override": null, "interval": 60, "max_commits": 3, "variables": [{"name": "SAFETY_DISABLED", "title": "Set to 1 to do dangerous things", "default": 0}]},
20
21
  "rollback": {"override": ["echo 'Rollback!'"]},
21
22
  "fetch": ["echo '42'"],
22
23
  "tasks": {
@@ -40,6 +41,9 @@ shipit:
40
41
  "allow_concurrency": true
41
42
  }
42
43
  },
44
+ "merge": {
45
+ "revalidate_after": 900
46
+ },
43
47
  "ci": {
44
48
  "hide": ["ci/hidden"],
45
49
  "allow_failures": ["ci/ok_to_fail"]
@@ -90,3 +90,11 @@ cyclimse_success_travis:
90
90
  state: success
91
91
  target_url: "http://www.example.com"
92
92
 
93
+ shipit_pending_pr_success_travis:
94
+ stack: shipit
95
+ commit_id: 8 # shipit_pending_pr_head
96
+ description: Super feature
97
+ context: ci/travis
98
+ created_at: <%= 9.days.ago.to_s(:db) %>
99
+ state: success
100
+ target_url: "http://www.example.com"
@@ -1,19 +1,24 @@
1
1
  module JSONHelper
2
- def assert_json(path = nil, *args)
3
- value = follow_path(path.to_s.split('.'))
2
+ UNDEFINED = Object.new.freeze
3
+ private_constant :UNDEFINED
4
+
5
+ def assert_json(path = nil, expected_value = UNDEFINED, document: response.body)
6
+ value = follow_path(path.to_s.split('.'), document: document)
4
7
  if block_given?
5
8
  yield value
6
- elsif args.size == 1
7
- assert_equal args.first, value
8
- else
9
+ elsif expected_value == UNDEFINED
9
10
  raise ArgumentError, "Missing either expected_value or a block"
11
+ elsif expected_value.nil?
12
+ assert_nil value
13
+ else
14
+ assert_equal expected_value, value
10
15
  end
11
16
  end
12
17
 
13
- def assert_json_keys(path, keys = nil)
18
+ def assert_json_keys(path, keys = nil, document: response.body)
14
19
  keys, path = path, nil if keys.nil?
15
20
 
16
- value = follow_path(path.to_s.split('.'))
21
+ value = follow_path(path.to_s.split('.'), document: document)
17
22
  case value
18
23
  when Hash
19
24
  assert_equal keys.sort, value.keys.sort
@@ -22,10 +27,10 @@ module JSONHelper
22
27
  end
23
28
  end
24
29
 
25
- def assert_no_json(path)
30
+ def assert_no_json(path, document: response.body)
26
31
  segments = path.to_s.split('.')
27
32
  last_segment = segments.pop
28
- leaf = follow_path(segments)
33
+ leaf = follow_path(segments, document: document)
29
34
  case leaf
30
35
  when Hash
31
36
  refute leaf.key?(last_segment), "Expected #{leaf.inspect} not to include #{last_segment.inspect}"
@@ -38,7 +43,8 @@ module JSONHelper
38
43
 
39
44
  private
40
45
 
41
- def follow_path(segments)
46
+ def follow_path(segments, document:)
47
+ parsed_json = ActiveSupport::JSON.decode(document)
42
48
  segments.inject(parsed_json) do |object, key|
43
49
  case object
44
50
  when Hash
@@ -52,8 +58,4 @@ module JSONHelper
52
58
  end
53
59
  end
54
60
  end
55
-
56
- def parsed_json
57
- @parsed_json ||= ActiveSupport::JSON.decode(response.body)
58
- end
59
61
  end
@@ -0,0 +1,59 @@
1
+ require 'test_helper'
2
+
3
+ module Shipit
4
+ class MergePullRequestsJobTest < ActiveSupport::TestCase
5
+ setup do
6
+ @stack = shipit_stacks(:shipit)
7
+ @job = MergePullRequestsJob.new
8
+
9
+ @pending_pr = shipit_pull_requests(:shipit_pending)
10
+ @unmergeable_pr = shipit_pull_requests(:shipit_pending_unmergeable)
11
+ @not_ready_pr = shipit_pull_requests(:shipit_pending_not_mergeable_yet)
12
+ end
13
+
14
+ test "#perform rejects unmergeable PRs and merge the others" do
15
+ PullRequest.any_instance.stubs(:refresh!)
16
+ FakeWeb.register_uri(:put, "#{@pending_pr.api_url}/merge", status: %w(200 OK), body: {
17
+ sha: "6dcb09b5b57875f334f61aebed695e2e4193db5e",
18
+ merged: true,
19
+ message: "Pull Request successfully merged",
20
+ }.to_json)
21
+ branch_url = "https://api.github.com/repos/shopify/shipit-engine/git/refs/heads/feature-62"
22
+ FakeWeb.register_uri(:delete, branch_url, status: %w(204 No content))
23
+
24
+ @job.perform(@stack)
25
+
26
+ assert_predicate @pending_pr.reload, :merged?
27
+ assert_predicate @unmergeable_pr.reload, :rejected?
28
+ end
29
+
30
+ test "#perform rejects PRs if the merge attempt fails" do
31
+ PullRequest.any_instance.stubs(:refresh!)
32
+ FakeWeb.register_uri(:put, "#{@pending_pr.api_url}/merge", status: %w(405 Method not allowed), body: {
33
+ message: "Pull Request is not mergeable",
34
+ documentation_url: "https://developer.github.com/v3/pulls/#merge-a-pull-request-merge-button",
35
+ }.to_json)
36
+
37
+ @job.perform(@stack)
38
+
39
+ assert_predicate @pending_pr.reload, :rejected?
40
+ end
41
+
42
+ test "#perform rejects PRs but do not attempt to merge any if the stack doesn't allow merges" do
43
+ PullRequest.any_instance.stubs(:refresh!)
44
+ @stack.update!(lock_reason: 'Maintenance')
45
+ @job.perform(@stack)
46
+ assert_predicate @pending_pr.reload, :pending?
47
+ end
48
+
49
+ test "#perform schedules a new job if the first PR in the queue is not mergeable yet" do
50
+ PullRequest.any_instance.stubs(:refresh!)
51
+
52
+ @pending_pr.update!(mergeable: nil)
53
+ assert_enqueued_with(job: MergePullRequestsJob) do
54
+ @job.perform(@stack)
55
+ end
56
+ assert_predicate @pending_pr.reload, :pending?
57
+ end
58
+ end
59
+ end