shipit-engine 0.15.0 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
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