shipit-engine 0.24.0 → 0.25.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 (75) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/shipit/stacks.js.coffee +15 -1
  3. data/app/assets/stylesheets/_base/_icons.scss +18 -0
  4. data/app/assets/stylesheets/_base/_status-items.scss +28 -0
  5. data/app/assets/stylesheets/_pages/_commits.scss +1 -5
  6. data/app/assets/stylesheets/_pages/_deploy.scss +60 -3
  7. data/app/controllers/concerns/shipit/authentication.rb +1 -1
  8. data/app/controllers/shipit/merge_status_controller.rb +2 -0
  9. data/app/controllers/shipit/release_statuses_controller.rb +36 -0
  10. data/app/jobs/shipit/append_delayed_release_status_job.rb +17 -0
  11. data/app/jobs/shipit/cache_deploy_spec_job.rb +2 -0
  12. data/app/jobs/shipit/clear_git_cache_job.rb +1 -1
  13. data/app/jobs/shipit/create_release_statuses_job.rb +11 -0
  14. data/app/jobs/shipit/deferred_touch_job.rb +2 -0
  15. data/app/jobs/shipit/deliver_hook_job.rb +1 -0
  16. data/app/jobs/shipit/merge_pull_requests_job.rb +2 -0
  17. data/app/jobs/shipit/perform_commit_checks_job.rb +2 -0
  18. data/app/jobs/shipit/perform_task_job.rb +2 -4
  19. data/app/jobs/shipit/refresh_pull_request_job.rb +2 -0
  20. data/app/models/shipit/anonymous_user.rb +1 -1
  21. data/app/models/shipit/commit.rb +36 -3
  22. data/app/models/shipit/deploy.rb +43 -0
  23. data/app/models/shipit/deploy_spec.rb +16 -2
  24. data/app/models/shipit/deploy_spec/bundler_discovery.rb +5 -1
  25. data/app/models/shipit/deploy_spec/file_system.rb +4 -0
  26. data/app/models/shipit/deploy_spec/kubernetes_discovery.rb +1 -1
  27. data/app/models/shipit/ephemeral_commit_checks.rb +2 -4
  28. data/app/models/shipit/hook.rb +36 -3
  29. data/app/models/shipit/pull_request.rb +4 -2
  30. data/app/models/shipit/release_status.rb +41 -0
  31. data/app/models/shipit/rollback.rb +9 -0
  32. data/app/models/shipit/stack.rb +4 -9
  33. data/app/models/shipit/status/common.rb +4 -0
  34. data/app/models/shipit/status/group.rb +2 -1
  35. data/app/models/shipit/status/missing.rb +4 -0
  36. data/app/models/shipit/status/unknown.rb +15 -0
  37. data/app/models/shipit/task.rb +4 -0
  38. data/app/models/shipit/user.rb +16 -3
  39. data/app/serializers/shipit/stack_serializer.rb +1 -1
  40. data/app/views/shipit/deploys/_deploy.html.erb +18 -2
  41. data/config/locales/en.yml +3 -0
  42. data/config/routes.rb +2 -0
  43. data/db/migrate/20180802172632_allow_commit_without_author.rb +6 -0
  44. data/db/migrate/20180906083930_create_release_statuses.rb +21 -0
  45. data/lib/shipit.rb +5 -0
  46. data/lib/shipit/command.rb +14 -18
  47. data/lib/shipit/deploy_commands.rb +0 -4
  48. data/lib/shipit/engine.rb +1 -1
  49. data/lib/shipit/first_parent_commits_iterator.rb +1 -1
  50. data/lib/shipit/flock.rb +43 -0
  51. data/lib/shipit/github_app.rb +5 -3
  52. data/lib/shipit/rollback_commands.rb +6 -0
  53. data/lib/shipit/task_commands.rb +1 -5
  54. data/lib/shipit/version.rb +1 -1
  55. data/test/controllers/release_statuses_controller_test.rb +23 -0
  56. data/test/dummy/db/schema.rb +18 -3
  57. data/test/dummy/db/seeds.rb +4 -0
  58. data/test/fixtures/shipit/commits.yml +13 -0
  59. data/test/fixtures/shipit/release_statuses.yml +16 -0
  60. data/test/fixtures/shipit/stacks.yml +4 -0
  61. data/test/jobs/append_delayed_release_status_job_test.rb +25 -0
  62. data/test/jobs/cache_deploy_spec_job_test.rb +1 -2
  63. data/test/jobs/emit_event_job_test.rb +1 -1
  64. data/test/jobs/github_sync_job_test.rb +1 -0
  65. data/test/models/commits_test.rb +54 -1
  66. data/test/models/deploy_spec_test.rb +83 -11
  67. data/test/models/deploys_test.rb +52 -0
  68. data/test/models/hook_test.rb +1 -28
  69. data/test/models/pull_request_test.rb +19 -0
  70. data/test/models/release_statuses_test.rb +28 -0
  71. data/test/models/rollbacks_test.rb +2 -0
  72. data/test/models/stacks_test.rb +1 -1
  73. data/test/test_helper.rb +5 -0
  74. data/test/unit/rollback_commands_test.rb +35 -0
  75. metadata +121 -104
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ef8f9d577b2985bc9e82fd48bcb930c12261aef6
4
- data.tar.gz: 4bf4282862504a06c96b5563750dc8d742e8c7ef
3
+ metadata.gz: 71f403cb4167fb521f7a2c190e2d31504dc0dea8
4
+ data.tar.gz: e1b1a94eefcc449a882ced01fa8036cd9df8e072
5
5
  SHA512:
6
- metadata.gz: 15cc3525496d566cc27b67cefde82a3833f2bac1801a026b3de73c59a2208dc43c6b563b231da39d61eab6d1cf97c9f959515db5e873f7e16c2dfa5021732703
7
- data.tar.gz: ec850e528fa5625ec20c3ebe81418381876e46ac2016ca55651284e3cabe58a641d29e304532290a096ca1e0237064308d1f8495537fc3ed278cf9e16a49c46a
6
+ metadata.gz: 0a04e776ddb132ab89a89b80ba5f5a78dfb69a53e73e7300b495e38deaa947cf6c69a6fd3b14dd9ca769ed5aa5d18c47d41a6e3a79de6f02ce2655f3cf305293
7
+ data.tar.gz: 5e71eaea76929fb232b98197018bc029e32d1f8b4d7743b775c72a6c549082fc0bdc7d212f930d66d657322f7fc15a2b0d736ee519bab026ecc18c16f0ae756a
@@ -1,4 +1,6 @@
1
- $(document).on 'click', '.commit-lock a', (event) ->
1
+ $document = $(document)
2
+
3
+ $document.on 'click', '.commit-lock a', (event) ->
2
4
  event.preventDefault()
3
5
  $commit = $(event.target).closest('.commit')
4
6
  $link = $(event.target).closest('a')
@@ -8,6 +10,18 @@ $(document).on 'click', '.commit-lock a', (event) ->
8
10
 
9
11
  $.ajax($link.attr('href'), method: 'PATCH', data: {commit: {locked: !locked}})
10
12
 
13
+ $document.on 'click', '.action-set-release-status', (event) ->
14
+ event.preventDefault()
15
+ $link = $(event.target).closest('a')
16
+ $deploy = $link.closest('.deploy')
17
+ newStatus = $link.data('status')
18
+
19
+ return if $deploy.attr('data-release-status') == newStatus
20
+
21
+ $.ajax($link.attr('href'), method: 'POST', data: {status: newStatus}).success((last_status) ->
22
+ $deploy.attr('data-release-status', last_status.state)
23
+ )
24
+
11
25
  jQuery ($) ->
12
26
  displayIgnoreCiMessage = ->
13
27
  ignoreCiMessage = $(".ignoring-ci")
@@ -6,3 +6,21 @@
6
6
  height: 15px;
7
7
  width: 12px;
8
8
  }
9
+
10
+ .icon--validate {
11
+ display: inline-block;
12
+ background-color: #000;
13
+ mask: asset-data-url("success-small.svg") no-repeat 50% 50%;
14
+ // background: asset-data-url("lock.svg") center center no-repeat;
15
+ height: 15px;
16
+ width: 12px;
17
+ }
18
+
19
+ .icon--reject {
20
+ display: inline-block;
21
+ background-color: #000;
22
+ mask: asset-data-url("error-small.svg") no-repeat 50% 50%;
23
+ // background: asset-data-url("lock.svg") center center no-repeat;
24
+ height: 15px;
25
+ width: 12px;
26
+ }
@@ -136,3 +136,31 @@
136
136
  background-image: asset-data-url('failure-small.svg');
137
137
  }
138
138
  }
139
+
140
+ // DEPLOY STATUS ICON
141
+ // -----------------------------------------------------------------------------
142
+
143
+ .deploy-status__icon {
144
+ width: 12px;
145
+ height: 12px;
146
+ display: inline-block;
147
+ background: transparent no-repeat center center;
148
+ vertical-align: -2px;
149
+
150
+ .deploy[data-release-status=success] & {
151
+ background-image: asset-data-url('success-small.svg');
152
+ }
153
+
154
+ .deploy[data-release-status=pending] &,
155
+ .deploy[data-release-status=unknown] & {
156
+ background-image: asset-data-url('pending-small.svg');
157
+ }
158
+
159
+ .deploy[data-release-status=error] & {
160
+ background-image: asset-data-url('error-small.svg');
161
+ }
162
+
163
+ .deploy[data-release-status=failure] & {
164
+ background-image: asset-data-url('failure-small.svg');
165
+ }
166
+ }
@@ -136,10 +136,6 @@
136
136
  color: $grey;
137
137
  margin: 0;
138
138
 
139
- @include media(desktop) {
140
- @include truncate;
141
- }
142
-
143
139
  .warning {
144
140
  color: $orange;
145
141
  }
@@ -166,7 +162,7 @@
166
162
 
167
163
  @include media(desktop) {
168
164
  margin-left: 1rem;
169
- min-width: 10rem;
165
+ min-width: 12rem;
170
166
 
171
167
  .btn {
172
168
  float: right;
@@ -35,7 +35,11 @@
35
35
  margin: 0 0.5rem;
36
36
 
37
37
  display: none;
38
- &[data-status="running"], &[data-status="aborting"] { display: inline-block; }
38
+ &[data-status="running"],
39
+ &[data-status="aborting"],
40
+ &[data-status="pending"] {
41
+ display: inline-block;
42
+ }
39
43
 
40
44
  .caption--pending {
41
45
  display: none;
@@ -114,6 +118,7 @@
114
118
  width: 100%;
115
119
  }
116
120
 
121
+ &[data-status="pending"] .deploy-banner-status,
117
122
  &[data-status="running"] .deploy-banner-status {
118
123
  background-color: $blue;
119
124
  width: 0%;
@@ -202,7 +207,7 @@
202
207
  border-color: $bright-red;
203
208
  }
204
209
 
205
- &[data-status="scheduled"],
210
+ &[data-status="pending"],
206
211
  &[data-status="running"] {
207
212
  border-color: $dark-yellow;
208
213
  }
@@ -217,4 +222,56 @@
217
222
 
218
223
  .ignored-safeties {
219
224
  color: $orange;
220
- }
225
+ }
226
+
227
+ .deploy-actions {
228
+ flex-shrink: 0;
229
+
230
+ @include media(desktop) {
231
+ margin-left: 1rem;
232
+ min-width: 12rem;
233
+
234
+ .btn {
235
+ float: right;
236
+ }
237
+ }
238
+ }
239
+
240
+ .release-validation {
241
+ display: inline-block;
242
+ .icon {
243
+ background-color: #ddd;
244
+ }
245
+
246
+ &:hover .icon {
247
+ background-color: darken(#ddd, 20%);
248
+ }
249
+ }
250
+
251
+ .deploy[data-release-status="success"] .release-validation .action-validate-release,
252
+ .deploy[data-release-status="failure"] .release-validation .action-reject-release {
253
+ &:before, &:after {
254
+ display: none; // Hide tooltips
255
+ }
256
+ .icon {
257
+ background-color: #ddd;
258
+ }
259
+ }
260
+
261
+ .deploy .commit-lock {
262
+ .icon {
263
+ background-color: $bright-red;
264
+ }
265
+
266
+ &:hover .icon {
267
+ background-color: darken($bright-red, 20%);
268
+ }
269
+
270
+ .action-lock-commit {
271
+ display: none;
272
+ }
273
+
274
+ .action-unlock-commit {
275
+ display: inline-block;
276
+ }
277
+ }
@@ -16,7 +16,7 @@ module Shipit
16
16
  private
17
17
 
18
18
  def force_github_authentication
19
- if current_user.logged_in?
19
+ if Shipit.authentication_disabled? || current_user.logged_in?
20
20
  unless current_user.authorized?
21
21
  team_handles = Shipit.github_teams.map(&:handle)
22
22
  team_list = team_handles.to_sentence(two_words_connector: ' or ', last_word_connector: ', or ')
@@ -17,6 +17,8 @@ module Shipit
17
17
  else
18
18
  render html: ''
19
19
  end
20
+ rescue ArgumentError
21
+ render html: ''
20
22
  end
21
23
 
22
24
  def enqueue
@@ -0,0 +1,36 @@
1
+ module Shipit
2
+ class ReleaseStatusesController < ShipitController
3
+ before_action :load_stack
4
+ before_action :load_deploy
5
+
6
+ def create
7
+ case params[:status]
8
+ when 'success'
9
+ @deploy.append_release_status(
10
+ 'success',
11
+ "@#{current_user.login} signaled this release as healthy.",
12
+ user: current_user,
13
+ )
14
+ when 'failure'
15
+ @deploy.append_release_status(
16
+ 'failure',
17
+ "@#{current_user.login} signaled this release as faulty.",
18
+ user: current_user,
19
+ )
20
+ else
21
+ render status: :unprocessable_entity, json: {message: "Invalid `status` parameter"}
22
+ end
23
+ render status: :created, json: @deploy.last_release_status
24
+ end
25
+
26
+ private
27
+
28
+ def load_deploy
29
+ @deploy = @stack.deploys_and_rollbacks.find(params[:deploy_id])
30
+ end
31
+
32
+ def load_stack
33
+ @stack ||= Stack.from_param!(params[:stack_id])
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,17 @@
1
+ module Shipit
2
+ class AppendDelayedReleaseStatusJob < BackgroundJob
3
+ include BackgroundJob::Unique
4
+
5
+ queue_as :default
6
+
7
+ def lock_key(deploy, *)
8
+ super(deploy)
9
+ end
10
+
11
+ def perform(deploy, cursor:, status:, description:)
12
+ return unless cursor == deploy.until_commit.release_statuses.last
13
+
14
+ deploy.append_release_status(status, description)
15
+ end
16
+ end
17
+ end
@@ -2,6 +2,8 @@ module Shipit
2
2
  class CacheDeploySpecJob < BackgroundJob
3
3
  include BackgroundJob::Unique
4
4
 
5
+ queue_as :deploys
6
+
5
7
  def perform(stack)
6
8
  return if stack.inaccessible?
7
9
 
@@ -1,6 +1,6 @@
1
1
  module Shipit
2
2
  class ClearGitCacheJob < BackgroundJob
3
- queue_as :default
3
+ queue_as :deploys
4
4
 
5
5
  def perform(stack)
6
6
  stack.clear_git_cache!
@@ -0,0 +1,11 @@
1
+ module Shipit
2
+ class CreateReleaseStatusesJob < BackgroundJob
3
+ include BackgroundJob::Unique
4
+
5
+ queue_as :default
6
+
7
+ def perform(commit)
8
+ commit.release_statuses.to_be_created.each(&:create_status_on_github!)
9
+ end
10
+ end
11
+ end
@@ -2,6 +2,8 @@ module Shipit
2
2
  class DeferredTouchJob < BackgroundJob
3
3
  include BackgroundJob::Unique
4
4
 
5
+ queue_as :default
6
+
5
7
  def perform
6
8
  DeferredTouch.touch_now!
7
9
  end
@@ -3,6 +3,7 @@ module Shipit
3
3
  queue_as :hooks
4
4
 
5
5
  def perform(delivery)
6
+ delivery = Hook::DeliverySpec.new(delivery) if delivery.is_a?(Hash)
6
7
  delivery.send!
7
8
  end
8
9
  end
@@ -3,6 +3,8 @@ module Shipit
3
3
  include BackgroundJob::Unique
4
4
  on_duplicate :drop
5
5
 
6
+ queue_as :default
7
+
6
8
  def perform(stack)
7
9
  pull_requests = stack.pull_requests.to_be_merged.to_a
8
10
  pull_requests.each do |pull_request|
@@ -2,6 +2,8 @@ module Shipit
2
2
  class PerformCommitChecksJob < BackgroundJob
3
3
  include BackgroundJob::Unique
4
4
 
5
+ queue_as :deploys
6
+
5
7
  def perform(commit:)
6
8
  commit.checks.run
7
9
  end
@@ -55,10 +55,8 @@ module Shipit
55
55
  end
56
56
 
57
57
  def perform_task
58
- Bundler.with_clean_env do
59
- capture_all! @commands.install_dependencies
60
- capture_all! @commands.perform
61
- end
58
+ capture_all! @commands.install_dependencies
59
+ capture_all! @commands.perform
62
60
  end
63
61
 
64
62
  def checkout_repository
@@ -1,5 +1,7 @@
1
1
  module Shipit
2
2
  class RefreshPullRequestJob < BackgroundJob
3
+ queue_as :default
4
+
3
5
  def perform(pull_request)
4
6
  pull_request.refresh!
5
7
  MergePullRequestsJob.perform_later(pull_request.stack)
@@ -31,7 +31,7 @@ module Shipit
31
31
  end
32
32
 
33
33
  def authorized?
34
- false
34
+ Shipit.authentication_disabled?
35
35
  end
36
36
 
37
37
  def stacks_contributed_to
@@ -8,6 +8,7 @@ module Shipit
8
8
  has_many :deploys
9
9
  has_many :statuses, -> { order(created_at: :desc) }, dependent: :destroy, inverse_of: :commit
10
10
  has_many :commit_deployments, dependent: :destroy
11
+ has_many :release_statuses, dependent: :destroy
11
12
  belongs_to :pull_request, inverse_of: :merge_commit, optional: true
12
13
 
13
14
  deferred_touch stack: :updated_at
@@ -21,6 +22,14 @@ module Shipit
21
22
  belongs_to :author, class_name: 'User', inverse_of: :authored_commits
22
23
  belongs_to :committer, class_name: 'User', inverse_of: :commits
23
24
 
25
+ def author
26
+ super || AnonymousUser.new
27
+ end
28
+
29
+ def committer
30
+ super || AnonymousUser.new
31
+ end
32
+
24
33
  scope :reachable, -> { where(detached: false) }
25
34
 
26
35
  delegate :broadcast_update, :github_repo_name, :hidden_statuses, :required_statuses, :blocking_statuses,
@@ -64,11 +73,16 @@ module Shipit
64
73
  end
65
74
 
66
75
  def self.from_github(commit)
76
+ author = User.find_or_create_author_from_github_commit(commit)
77
+ author ||= Anonymous.new
78
+ committer = User.find_or_create_committer_from_github_commit(commit)
79
+ committer ||= Anonymous.new
80
+
67
81
  new(
68
82
  sha: commit.sha,
69
83
  message: commit.commit.message,
70
- author: User.find_or_create_from_github(commit.author || commit.commit.author),
71
- committer: User.find_or_create_from_github(commit.committer || commit.commit.committer),
84
+ author: author,
85
+ committer: committer,
72
86
  committed_at: commit.commit.committer.date,
73
87
  authored_at: commit.commit.author.date,
74
88
  additions: commit.stats&.additions,
@@ -104,6 +118,23 @@ module Shipit
104
118
  end
105
119
  end
106
120
 
121
+ def last_release_status
122
+ @last_release_status ||= release_statuses.last || Status::Unknown.new(self)
123
+ end
124
+
125
+ def create_release_status!(state, user: nil, target_url: nil, description: nil)
126
+ return unless stack.release_status?
127
+
128
+ @last_release_status = nil
129
+ release_statuses.create!(
130
+ stack: stack,
131
+ user: user,
132
+ state: state,
133
+ target_url: target_url,
134
+ description: description,
135
+ )
136
+ end
137
+
107
138
  def checks
108
139
  @checks ||= CommitChecks.new(self)
109
140
  end
@@ -233,7 +264,9 @@ module Shipit
233
264
 
234
265
  unless already_deployed
235
266
  payload = {commit: self, stack: stack, status: new_status.state}
236
- Hook.emit(:commit_status, stack, payload.merge(commit_status: new_status)) if previous_status != new_status
267
+ if previous_status != new_status
268
+ Hook.emit(:commit_status, stack, payload.merge(commit_status: new_status))
269
+ end
237
270
  end
238
271
 
239
272
  if previous_status.simple_state != new_status.simple_state