shipit-engine 0.19.0 → 0.20.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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/_pages/_deploy.scss +4 -0
  3. data/app/controllers/shipit/api/tasks_controller.rb +4 -0
  4. data/app/jobs/shipit/github_sync_job.rb +3 -9
  5. data/app/jobs/shipit/purge_old_deliveries_job.rb +11 -0
  6. data/app/models/shipit/delivery.rb +6 -2
  7. data/app/models/shipit/deploy.rb +2 -1
  8. data/app/models/shipit/deploy_spec/bundler_discovery.rb +10 -1
  9. data/app/models/shipit/deploy_spec/file_system.rb +1 -1
  10. data/app/models/shipit/hook.rb +8 -0
  11. data/app/models/shipit/rollback.rb +8 -0
  12. data/app/models/shipit/stack.rb +27 -6
  13. data/app/serializers/shipit/task_serializer.rb +1 -0
  14. data/app/views/shipit/deploys/_deploy.html.erb +1 -0
  15. data/app/views/shipit/stacks/_header.html.erb +1 -1
  16. data/app/views/shipit/tasks/_task.html.erb +2 -0
  17. data/db/migrate/20170629141736_add_ignored_safeties_on_tasks.rb +5 -0
  18. data/lib/shipit.rb +12 -0
  19. data/lib/shipit/stack_commands.rb +3 -3
  20. data/lib/shipit/task_commands.rb +1 -0
  21. data/lib/shipit/version.rb +1 -1
  22. data/lib/tasks/cron.rake +1 -6
  23. data/test/controllers/api/tasks_controller_test.rb +8 -0
  24. data/test/dummy/db/development.sqlite3 +0 -0
  25. data/test/dummy/db/schema.rb +2 -1
  26. data/test/dummy/db/test.sqlite3 +0 -0
  27. data/test/dummy/db/test.sqlite3-journal +0 -0
  28. data/test/fixtures/shipit/deliveries.yml +1 -0
  29. data/test/jobs/purge_old_deliveries_job_test.rb +15 -0
  30. data/test/models/deploy_spec_test.rb +29 -2
  31. data/test/models/deploys_test.rb +15 -0
  32. data/test/models/hook_test.rb +8 -0
  33. data/test/models/rollbacks_test.rb +34 -0
  34. data/test/models/stacks_test.rb +24 -1
  35. data/test/unit/deploy_commands_test.rb +6 -0
  36. metadata +10 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fd2a6119dc0214d91ad2bfddf344a9cc898d94f1
4
- data.tar.gz: a96e8b153d800ce1cea2a1d22e4f5f51671206d7
3
+ metadata.gz: 32c15d6ba8aee487f4738a05b978cb87ce525c51
4
+ data.tar.gz: 4652419bd067b12dc0e8689f1bc76befdfa96657
5
5
  SHA512:
6
- metadata.gz: 4f69396b6035b1bf6a84371b882c091de91b70f0c1ed24881028f2836f1230abd64f7bac6406aeaaa71eb110ade52206dacd3953d799db18a8d1da427fef10e0
7
- data.tar.gz: 6aa40d715e8aa4e52a16c60c9ad12b15978d88758c188370436806b458f716dbc13ec4d53276df4a727b0a97bd5b84eef3c8e5550bab77fc579beb390a0d137c
6
+ metadata.gz: 3d815536be09f672e39a8eaa61347321765a884707720f22d88985908b6eb0065426c0252d6906e8a9485fd2e178aa5aa64401eb1f92c054e57a5a93e58cb048
7
+ data.tar.gz: c4ab143452da7c46d36374cc4b778bed710d1fe8144a043d22af140dda730e37610350c18787e20a635eb91e1f6d2421de754facc1fccbf61caf4ac0931d1381
@@ -212,3 +212,7 @@
212
212
  border: none;
213
213
  }
214
214
  }
215
+
216
+ .ignored-safeties {
217
+ color: $orange;
218
+ }
@@ -17,6 +17,10 @@ module Shipit
17
17
  end
18
18
  def trigger
19
19
  render_resource stack.trigger_task(params[:task_name], current_user, env: params.env), status: :accepted
20
+ rescue Shipit::Task::ConcurrentTaskRunning
21
+ render status: :conflict, json: {
22
+ message: 'A task is already running.',
23
+ }
20
24
  end
21
25
  end
22
26
  end
@@ -16,23 +16,17 @@ module Shipit
16
16
 
17
17
  @stack.transaction do
18
18
  shared_parent.try!(:detach_children!)
19
- new_commits.each do |gh_commit|
19
+ appended_commits = new_commits.map do |gh_commit|
20
20
  append_commit(gh_commit)
21
21
  end
22
+ @stack.lock_reverted_commits! if appended_commits.any?(&:revert?)
22
23
  end
23
24
  end
24
25
  CacheDeploySpecJob.perform_later(@stack)
25
26
  end
26
27
 
27
28
  def append_commit(gh_commit)
28
- appended_commit = @stack.commits.create_from_github!(gh_commit)
29
- if appended_commit.revert?
30
- impacted_commits = @stack.undeployed_commits.reverse.drop_while { |c| !appended_commit.revert_of?(c) }
31
- impacted_commits.pop # appended_commit
32
- impacted_commits.each do |impacted_commit|
33
- impacted_commit.update!(locked: true)
34
- end
35
- end
29
+ @stack.commits.create_from_github!(gh_commit)
36
30
  end
37
31
 
38
32
  def fetch_missing_commits(&block)
@@ -0,0 +1,11 @@
1
+ module Shipit
2
+ class PurgeOldDeliveriesJob < BackgroundJob
3
+ include BackgroundJob::Unique
4
+
5
+ queue_as :low
6
+
7
+ def perform(hook)
8
+ hook.purge_old_deliveries!
9
+ end
10
+ end
11
+ end
@@ -5,13 +5,13 @@ module Shipit
5
5
 
6
6
  belongs_to :hook
7
7
 
8
- scope :due_for_deletion, -> { where('created_at < ?', 1.month.ago) }
9
-
10
8
  validates :url, presence: true, url: {no_local: true, allow_blank: true}
11
9
  validates :content_type, presence: true
12
10
 
13
11
  serialize :response_headers, JSON
14
12
 
13
+ after_commit :purge_old_deliveries, on: :create
14
+
15
15
  def schedule!
16
16
  DeliverHookJob.perform_later(self)
17
17
  scheduled!
@@ -29,6 +29,10 @@ module Shipit
29
29
 
30
30
  private
31
31
 
32
+ def purge_old_deliveries
33
+ PurgeOldDeliveriesJob.perform_later(hook)
34
+ end
35
+
32
36
  def http
33
37
  Faraday::Connection.new do |connection|
34
38
  connection.headers = headers
@@ -46,6 +46,7 @@ module Shipit
46
46
  until_commit: until_commit,
47
47
  env: env.try!(:to_h) || {},
48
48
  allow_concurrency: force,
49
+ ignored_safeties: force,
49
50
  )
50
51
  end
51
52
 
@@ -117,7 +118,7 @@ module Shipit
117
118
  end
118
119
 
119
120
  def reject!
120
- return if failed?
121
+ return if failed? || aborted?
121
122
  transaction do
122
123
  flap! unless flapping?
123
124
  update!(confirmations: [confirmations - 1, -1].min)
@@ -54,7 +54,16 @@ module Shipit
54
54
  end
55
55
 
56
56
  def coerce_task_definition(config)
57
- config.merge('steps' => Array(config['steps']).map(&method(:bundle_exec)))
57
+ coerced_steps = Array(config['steps']).map do |command|
58
+ should_prepend_bundle_exec?(command) ? bundle_exec(command) : command
59
+ end
60
+ config.merge('steps' => coerced_steps)
61
+ end
62
+
63
+ private
64
+
65
+ def should_prepend_bundle_exec?(command)
66
+ Shipit.automatically_prepend_bundle_exec && !command.start_with?('bundle exec')
58
67
  end
59
68
  end
60
69
  end
@@ -64,7 +64,7 @@ module Shipit
64
64
  end
65
65
 
66
66
  def cacheable_tasks
67
- (config('tasks') || {}).map { |k, c| [k, coerce_task_definition(c)] }.to_h
67
+ discover_task_definitions.map { |k, c| [k, coerce_task_definition(c)] }.to_h
68
68
  end
69
69
 
70
70
  def config(*)
@@ -2,6 +2,8 @@ module Shipit
2
2
  class Hook < ActiveRecord::Base
3
3
  default_scope { order :id }
4
4
 
5
+ DELIVERIES_LOG_SIZE = 500
6
+
5
7
  CONTENT_TYPES = {
6
8
  'json' => 'application/json',
7
9
  'form' => 'application/x-www-form-urlencoded',
@@ -77,6 +79,12 @@ module Shipit
77
79
  ).schedule!
78
80
  end
79
81
 
82
+ def purge_old_deliveries!(keep: DELIVERIES_LOG_SIZE)
83
+ if cut_off_time = deliveries.order(created_at: :desc).limit(1).offset(keep).pluck(:created_at).first
84
+ deliveries.where('created_at > ?', cut_off_time).delete_all
85
+ end
86
+ end
87
+
80
88
  private
81
89
 
82
90
  def serialize_payload(payload)
@@ -2,6 +2,10 @@ module Shipit
2
2
  class Rollback < Deploy
3
3
  belongs_to :deploy, foreign_key: :parent_id
4
4
 
5
+ state_machine :status do
6
+ after_transition to: :success, do: :lock_reverted_commits
7
+ end
8
+
5
9
  def rollback?
6
10
  true
7
11
  end
@@ -30,6 +34,10 @@ module Shipit
30
34
 
31
35
  private
32
36
 
37
+ def lock_reverted_commits
38
+ stack.lock_reverted_commits!
39
+ end
40
+
33
41
  def create_commit_deployments
34
42
  # Rollback events are confusing in GitHub
35
43
  end
@@ -97,6 +97,7 @@ module Shipit
97
97
  since_commit_id: commit.id,
98
98
  env: definition.filter_envs(env),
99
99
  allow_concurrency: definition.allow_concurrency? || force,
100
+ ignored_safeties: force,
100
101
  )
101
102
  task.enqueue
102
103
  task
@@ -110,6 +111,7 @@ module Shipit
110
111
  since_commit: since_commit,
111
112
  env: filter_deploy_envs(env.try!(:to_h) || {}),
112
113
  allow_concurrency: force,
114
+ ignored_safeties: force || !until_commit.deployable?,
113
115
  )
114
116
  end
115
117
 
@@ -196,14 +198,15 @@ module Shipit
196
198
  commits.reachable.first.try!(:sha)
197
199
  end
198
200
 
199
- def merge_status
201
+ def merge_status(backlog_leniency_factor: 1.5)
200
202
  return 'locked' if locked?
201
203
  return 'failure' if %w(failure error).freeze.include?(branch_status)
202
- if maximum_commits_per_deploy && (undeployed_commits_count > maximum_commits_per_deploy * 1.5)
203
- 'backlogged'
204
- else
205
- 'success'
206
- end
204
+ return 'backlogged' if backlogged?(backlog_leniency_factor: backlog_leniency_factor)
205
+ 'success'
206
+ end
207
+
208
+ def backlogged?(backlog_leniency_factor: 1.5)
209
+ maximum_commits_per_deploy && (undeployed_commits_count > maximum_commits_per_deploy * backlog_leniency_factor)
207
210
  end
208
211
 
209
212
  def branch_status
@@ -219,6 +222,24 @@ module Shipit
219
222
  :default
220
223
  end
221
224
 
225
+ def lock_reverted_commits!
226
+ commits_to_lock = []
227
+
228
+ backlog = undeployed_commits.to_a
229
+ until backlog.empty?
230
+ backlog = backlog.drop_while { |c| !c.revert? }
231
+ if revert = backlog.shift
232
+ commits_to_lock += backlog.reverse.drop_while { |c| !revert.revert_of?(c) }
233
+ end
234
+ end
235
+
236
+ unless commits_to_lock.empty?
237
+ if commits.where(id: commits_to_lock.map(&:id).uniq).update_all(locked: true) > 1
238
+ touch
239
+ end
240
+ end
241
+ end
242
+
222
243
  def undeployed_commits
223
244
  scope = commits.reachable.newer_than(last_deployed_commit).order(id: :asc)
224
245
  yield scope if block_given?
@@ -19,6 +19,7 @@ module Shipit
19
19
  updated_at
20
20
  created_at
21
21
  env
22
+ ignored_safeties
22
23
  ))
23
24
 
24
25
  def revision
@@ -20,6 +20,7 @@
20
20
  <span class="sha"><%= link_to_github_deploy(deploy) %></span>
21
21
  <span class="code-additions">+<%= deploy.additions %></span>
22
22
  <span class="code-deletions">-<%= deploy.deletions %></span>
23
+ <% if deploy.ignored_safeties? %><span class="ignored-safeties">ignoring safeties</span><% end %>
23
24
  </p>
24
25
  <p class="commit-meta">
25
26
  <% if read_only %>
@@ -21,7 +21,7 @@
21
21
  </li>
22
22
  <% if stack.merge_queue_enabled? %>
23
23
  <li class="nav__list__item">
24
- <%= link_to "Pull Requests (#{stack.pull_requests.queued.count})", stack_pull_requests_path(stack) %>
24
+ <%= link_to "Merge Queue (#{stack.pull_requests.queued.count})", stack_pull_requests_path(stack) %>
25
25
  </li>
26
26
  <% end %>
27
27
 
@@ -18,6 +18,7 @@
18
18
  </span>
19
19
  <p class="commit-meta">
20
20
  ran a command
21
+ <% if task.ignored_safeties? %><span class="ignored-safeties">ignoring safeties</span><% end %>
21
22
  </p>
22
23
  <p class="commit-meta">
23
24
  <% if read_only %>
@@ -25,6 +26,7 @@
25
26
  <% else %>
26
27
  <%= timeago_tag(task.created_at, force: true) %>
27
28
  <% end %>
29
+
28
30
  </p>
29
31
  </div>
30
32
  </li>
@@ -0,0 +1,5 @@
1
+ class AddIgnoredSafetiesOnTasks < ActiveRecord::Migration[5.1]
2
+ def change
3
+ add_column :tasks, :ignored_safeties, :boolean, default: false, null: false
4
+ end
5
+ end
data/lib/shipit.rb CHANGED
@@ -57,6 +57,7 @@ module Shipit
57
57
  delegate :table_name_prefix, to: :secrets
58
58
 
59
59
  attr_accessor :disable_api_authentication
60
+ attr_writer :automatically_prepend_bundle_exec
60
61
 
61
62
  def app_name
62
63
  @app_name ||= secrets.app_name || Rails.application.class.name.split(':').first || 'Shipit'
@@ -206,6 +207,17 @@ module Shipit
206
207
  secrets.commands_inactivity_timeout || 5.minutes.to_i
207
208
  end
208
209
 
210
+ def automatically_prepend_bundle_exec
211
+ unless defined?(@automatically_prepend_bundle_exec)
212
+ ActiveSupport::Deprecation.warn(
213
+ 'Automatically prepending `bundle exec` will be removed in a future version of Shipit, '\
214
+ 'set `Shipit.automatically_prepend_bundle_exec = false` to test the new behaviour.',
215
+ )
216
+ @automatically_prepend_bundle_exec = true
217
+ end
218
+ @automatically_prepend_bundle_exec
219
+ end
220
+
209
221
  protected
210
222
 
211
223
  def revision_file
@@ -42,9 +42,9 @@ module Shipit
42
42
  end
43
43
 
44
44
  def with_temporary_working_directory(commit: nil)
45
- if commit
46
- @stack.acquire_git_cache_lock do
47
- fetch.run! unless fetched?(commit).tap(&:run).success?
45
+ @stack.acquire_git_cache_lock do
46
+ if !commit || !fetched?(commit).tap(&:run).success?
47
+ fetch.run!
48
48
  end
49
49
  end
50
50
 
@@ -38,6 +38,7 @@ module Shipit
38
38
  'SHIPIT_LINK' => permalink,
39
39
  'LAST_DEPLOYED_SHA' => @stack.last_deployed_commit.sha,
40
40
  'TASK_ID' => @task.id.to_s,
41
+ 'IGNORED_SAFETIES' => @task.ignored_safeties? ? '1' : '0',
41
42
  ).merge(deploy_spec.machine_env).merge(@task.env)
42
43
  end
43
44
 
@@ -1,3 +1,3 @@
1
1
  module Shipit
2
- VERSION = '0.19.0'.freeze
2
+ VERSION = '0.20.0'.freeze
3
3
  end
data/lib/tasks/cron.rake CHANGED
@@ -7,18 +7,13 @@ namespace :cron do
7
7
  Shipit::PullRequest.schedule_merges
8
8
  end
9
9
 
10
- task hourly: [:rollup, :purge_deliveries, :refresh_users]
10
+ task hourly: [:rollup, :refresh_users]
11
11
 
12
12
  desc "Rolls-up output chunks for completed deploys older than an hour"
13
13
  task rollup: :environment do
14
14
  Shipit::Task.due_for_rollup.find_each(&:schedule_rollup_chunks)
15
15
  end
16
16
 
17
- desc "Delete old hook delivery records"
18
- task purge_deliveries: :environment do
19
- Shipit::Delivery.due_for_deletion.delete_all
20
- end
21
-
22
17
  task refresh_users: :environment do
23
18
  Shipit::User.refresh_shard(Time.now.hour % 24, 24)
24
19
  end
@@ -81,6 +81,14 @@ module Shipit
81
81
  post :trigger, params: {stack_id: @stack.to_param, task_name: 'doesnt_exist'}
82
82
  assert_response :not_found
83
83
  end
84
+
85
+ test "#trigger returns 409 when a task is already running" do
86
+ shipit_deploys(:shipit_running).update!(allow_concurrency: false, status: 'running')
87
+ assert_predicate @stack, :active_task?
88
+ post :trigger, params: {stack_id: @stack.to_param, task_name: 'restart'}
89
+ assert_response :conflict
90
+ assert_json 'message', 'A task is already running.'
91
+ end
84
92
  end
85
93
  end
86
94
  end
Binary file
@@ -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: 20170524125249) do
13
+ ActiveRecord::Schema.define(version: 20170629141736) do
14
14
 
15
15
  create_table "api_clients", force: :cascade do |t|
16
16
  t.text "permissions", limit: 65535
@@ -214,6 +214,7 @@ ActiveRecord::Schema.define(version: 20170524125249) do
214
214
  t.boolean "allow_concurrency", default: false, null: false
215
215
  t.datetime "started_at"
216
216
  t.datetime "ended_at"
217
+ t.boolean "ignored_safeties", default: false, null: false
217
218
  t.index ["rolled_up", "created_at", "status"], name: "index_tasks_on_rolled_up_and_created_at_and_status"
218
219
  t.index ["since_commit_id"], name: "index_tasks_on_since_commit_id"
219
220
  t.index ["stack_id", "allow_concurrency", "status"], name: "index_active_tasks"
Binary file
Binary file
@@ -11,3 +11,4 @@ scheduled_shipit_deploy:
11
11
  "deploy": {
12
12
  }
13
13
  }
14
+ created_at: <%= 5.minutes.ago.to_s(:db) %>
@@ -0,0 +1,15 @@
1
+ require 'test_helper'
2
+
3
+ module Shipit
4
+ class PurgeOldDeliveriesJobTest < ActiveSupport::TestCase
5
+ setup do
6
+ @hook = shipit_hooks(:shipit_deploys)
7
+ @job = PurgeOldDeliveriesJob.new
8
+ end
9
+
10
+ test "calls #purge_old_deliveries! on the hook" do
11
+ @hook.expects(:purge_old_deliveries!).once
12
+ @job.perform(@hook)
13
+ end
14
+ end
15
+ end
@@ -318,9 +318,36 @@ module Shipit
318
318
  assert_equal 'SAFETY_DISABLED', variable_definition.name
319
319
  end
320
320
 
321
- test "task definitions prepend bundle exec if necessary" do
321
+ test "task definitions prepend bundle exec by default" do
322
322
  @spec.expects(:load_config).returns('tasks' => {'restart' => {'steps' => %w(foo)}})
323
323
  @spec.expects(:bundler?).returns(true).at_least_once
324
+ assert_deprecated(/Automatically prepending `bundle exec`/) do
325
+ definition = @spec.find_task_definition('restart')
326
+ assert_equal ['bundle exec foo'], definition.steps
327
+ end
328
+ end
329
+
330
+ test "task definitions prepend bundle exec if enabled" do
331
+ Shipit.expects(:automatically_prepend_bundle_exec).returns(true).at_least_once
332
+ @spec.expects(:load_config).returns('tasks' => {'restart' => {'steps' => %w(foo)}})
333
+ @spec.expects(:bundler?).returns(true).at_least_once
334
+ definition = @spec.find_task_definition('restart')
335
+
336
+ assert_equal ['bundle exec foo'], definition.steps
337
+ end
338
+
339
+ test "task definitions do not prepend bundle exec if disabled" do
340
+ Shipit.expects(:automatically_prepend_bundle_exec).returns(false).at_least_once
341
+ @spec.expects(:load_config).returns('tasks' => {'restart' => {'steps' => %w(foo)}})
342
+ definition = @spec.find_task_definition('restart')
343
+
344
+ assert_equal ['foo'], definition.steps
345
+ end
346
+
347
+ test "task definitions do not prepend bundle exec if the task already does" do
348
+ Shipit.expects(:automatically_prepend_bundle_exec).returns(true).at_least_once
349
+ @spec.expects(:load_config).returns('tasks' => {'restart' => {'steps' => ['bundle exec foo']}})
350
+ @spec.stubs(:bundler?).returns(true)
324
351
  definition = @spec.find_task_definition('restart')
325
352
 
326
353
  assert_equal ['bundle exec foo'], definition.steps
@@ -338,7 +365,7 @@ module Shipit
338
365
  end
339
366
 
340
367
  test "task definitions prepend bundle exec before serialization" do
341
- @spec.expects(:load_config).returns('tasks' => {'restart' => {'steps' => %w(foo)}})
368
+ @spec.expects(:discover_task_definitions).returns('restart' => {'steps' => %w(foo)})
342
369
  @spec.expects(:bundler?).returns(true).at_least_once
343
370
 
344
371
  cached_spec = DeploySpec.load(DeploySpec.dump(@spec))
@@ -339,6 +339,11 @@ module Shipit
339
339
  assert_equal @user, @stack.lock_author
340
340
  end
341
341
 
342
+ test "#trigger_rollback marks the rollback as `ignored_safeties` if the force option was used" do
343
+ rollback = @deploy.trigger_rollback(@user, force: true)
344
+ assert_predicate rollback, :ignored_safeties?
345
+ end
346
+
342
347
  test "abort! transition to `aborting`" do
343
348
  @deploy.ping
344
349
  @deploy.abort!
@@ -426,6 +431,16 @@ module Shipit
426
431
  end
427
432
  end
428
433
 
434
+ test "#reject! bails out if the deploy is canceled already" do
435
+ @deploy = shipit_deploys(:shipit_aborted)
436
+ assert_predicate @deploy, :aborted?
437
+
438
+ Deploy::CONFIRMATIONS_REQUIRED.times do
439
+ @deploy.reject!
440
+ assert_predicate @deploy, :aborted?
441
+ end
442
+ end
443
+
429
444
  test "#reject! first transition to flapping then ultimately to failed if the deploy was successful" do
430
445
  assert_predicate @deploy, :success?
431
446
 
@@ -55,5 +55,13 @@ module Shipit
55
55
  @hook.stack_id = 42
56
56
  assert @hook.scoped?
57
57
  end
58
+
59
+ test "#purge_old_deliveries!" do
60
+ Hook.deliver(:deploy, @stack, 'foo' => 42)
61
+
62
+ assert_difference -> { Delivery.count }, -1 do
63
+ @hook.purge_old_deliveries!(keep: 1)
64
+ end
65
+ end
58
66
  end
59
67
  end
@@ -3,6 +3,7 @@ require 'test_helper'
3
3
  module Shipit
4
4
  class RollbackTest < ActiveSupport::TestCase
5
5
  setup do
6
+ @stack = shipit_stacks(:shipit)
6
7
  @rollback = Rollback.new
7
8
  end
8
9
 
@@ -17,5 +18,38 @@ module Shipit
17
18
  test "#supports_rollback? returns false" do
18
19
  refute @rollback.supports_rollback?
19
20
  end
21
+
22
+ test "when a rollback succeed reverted commits are locked" do
23
+ @stack.tasks.where.not(id: shipit_tasks(:shipit_complete).id).delete_all
24
+
25
+ deploy = @stack.deploys.success.last
26
+ reverted_commit = deploy.until_commit
27
+
28
+ @stack.commits.create!(
29
+ sha: '50ce7d4440fcd8c734f8b7b76c86f8db46706e4f',
30
+ message: %(Revert "#{reverted_commit.message_header}"),
31
+ author: reverted_commit.author,
32
+ committer: reverted_commit.committer,
33
+ authored_at: Time.zone.now,
34
+ committed_at: Time.zone.now,
35
+ )
36
+
37
+ expected = [
38
+ ['Revert "Merge pull request #7 from shipit-engine/yoloshipit"', false],
39
+ ['fix all the things', false],
40
+ ]
41
+ assert_equal expected, @stack.undeployed_commits.map { |c| [c.title, c.locked?] }
42
+
43
+ rollback = deploy.trigger_revert
44
+ rollback.run!
45
+ rollback.complete!
46
+
47
+ expected = [
48
+ ['Revert "Merge pull request #7 from shipit-engine/yoloshipit"', false],
49
+ ['fix all the things', true],
50
+ ['yoloshipit!', true],
51
+ ]
52
+ assert_equal expected, @stack.undeployed_commits.map { |c| [c.title, c.locked?] }
53
+ end
20
54
  end
21
55
  end
@@ -123,7 +123,7 @@ module Shipit
123
123
  assert_equal @stack.commits.first.id, deploy.since_commit_id
124
124
  end
125
125
 
126
- test "#trigger_deploy enqueue a deploy job" do
126
+ test "#trigger_deploy enqueues a deploy job" do
127
127
  @stack.deploys.destroy_all
128
128
  Deploy.any_instance.expects(:enqueue).once
129
129
 
@@ -132,6 +132,22 @@ module Shipit
132
132
  assert_instance_of Deploy, deploy
133
133
  end
134
134
 
135
+ test "#trigger_deploy marks the deploy as `ignored_safeties` if the commit wasn't deployable" do
136
+ last_commit = shipit_commits(:fifth)
137
+ refute_predicate last_commit, :deployable?
138
+
139
+ deploy = @stack.trigger_deploy(last_commit, AnonymousUser.new)
140
+ assert_predicate deploy, :ignored_safeties?
141
+ end
142
+
143
+ test "#trigger_deploy doesn't mark the deploy as `ignored_safeties` if the commit was deployable" do
144
+ last_commit = shipit_commits(:third)
145
+ assert_predicate last_commit, :deployable?
146
+
147
+ deploy = @stack.trigger_deploy(last_commit, AnonymousUser.new)
148
+ refute_predicate deploy, :ignored_safeties?
149
+ end
150
+
135
151
  test "#update_deployed_revision bail out if there is an active deploy" do
136
152
  @stack.deploys_and_rollbacks.last.update_columns(status: 'running')
137
153
  assert_no_difference 'Deploy.count' do
@@ -428,6 +444,13 @@ module Shipit
428
444
  assert_equal 'backlogged', @stack.merge_status
429
445
  end
430
446
 
447
+ test "#merge_status returns success with a higher leniency factor" do
448
+ @stack.deploys_and_rollbacks.destroy_all
449
+ @stack.update_undeployed_commits_count
450
+ @stack.reload
451
+ assert_equal 'success', @stack.merge_status(backlog_leniency_factor: 2.0)
452
+ end
453
+
431
454
  test "#handle_github_redirections update the stack if the repository was renamed" do
432
455
  repo_permalink = 'https://api.github.com/repositories/42'
433
456
 
@@ -188,6 +188,12 @@ module Shipit
188
188
  assert_equal 'BAR', command.env['FOO']
189
189
  end
190
190
 
191
+ test "IGNORED_SAFETIES is exposed" do
192
+ assert_equal '0', @commands.env['IGNORED_SAFETIES']
193
+ @deploy.ignored_safeties = true
194
+ assert_equal '1', @commands.env['IGNORED_SAFETIES']
195
+ end
196
+
191
197
  test "#clear_working_directory rm -rf the working directory" do
192
198
  FileUtils.expects(:rm_rf).with(@deploy.working_directory)
193
199
  @commands.clear_working_directory
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.19.0
4
+ version: 0.20.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: 2017-06-28 00:00:00.000000000 Z
11
+ date: 2017-08-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 0.4.0
89
+ version: 0.5.0
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 0.4.0
96
+ version: 0.5.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: active_model_serializers
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -530,6 +530,7 @@ files:
530
530
  - app/jobs/shipit/merge_pull_requests_job.rb
531
531
  - app/jobs/shipit/perform_commit_checks_job.rb
532
532
  - app/jobs/shipit/perform_task_job.rb
533
+ - app/jobs/shipit/purge_old_deliveries_job.rb
533
534
  - app/jobs/shipit/refresh_github_user_job.rb
534
535
  - app/jobs/shipit/refresh_pull_request_job.rb
535
536
  - app/jobs/shipit/refresh_statuses_job.rb
@@ -675,6 +676,7 @@ files:
675
676
  - db/migrate/20170524084548_index_pull_requests_on_merge_status.rb
676
677
  - db/migrate/20170524104615_index_commits_on_stack_id_and_sha.rb
677
678
  - db/migrate/20170524125249_fix_tasks_index_by_status.rb
679
+ - db/migrate/20170629141736_add_ignored_safeties_on_tasks.rb
678
680
  - lib/shipit-engine.rb
679
681
  - lib/shipit.rb
680
682
  - lib/shipit/command.rb
@@ -780,6 +782,7 @@ files:
780
782
  - test/dummy/db/schema.rb
781
783
  - test/dummy/db/seeds.rb
782
784
  - test/dummy/db/test.sqlite3
785
+ - test/dummy/db/test.sqlite3-journal
783
786
  - test/dummy/public/404.html
784
787
  - test/dummy/public/422.html
785
788
  - test/dummy/public/500.html
@@ -820,6 +823,7 @@ files:
820
823
  - test/jobs/github_sync_job_test.rb
821
824
  - test/jobs/merge_pull_requests_job_test.rb
822
825
  - test/jobs/perform_task_job_test.rb
826
+ - test/jobs/purge_old_deliveries_job_test.rb
823
827
  - test/jobs/refresh_github_user_job_test.rb
824
828
  - test/jobs/refresh_status_job_test.rb
825
829
  - test/jobs/unique_job_test.rb
@@ -959,6 +963,7 @@ test_files:
959
963
  - test/dummy/db/schema.rb
960
964
  - test/dummy/db/seeds.rb
961
965
  - test/dummy/db/test.sqlite3
966
+ - test/dummy/db/test.sqlite3-journal
962
967
  - test/dummy/public/404.html
963
968
  - test/dummy/public/422.html
964
969
  - test/dummy/public/500.html
@@ -1000,6 +1005,7 @@ test_files:
1000
1005
  - test/jobs/github_sync_job_test.rb
1001
1006
  - test/jobs/merge_pull_requests_job_test.rb
1002
1007
  - test/jobs/perform_task_job_test.rb
1008
+ - test/jobs/purge_old_deliveries_job_test.rb
1003
1009
  - test/jobs/refresh_github_user_job_test.rb
1004
1010
  - test/jobs/refresh_status_job_test.rb
1005
1011
  - test/jobs/unique_job_test.rb