shipit-engine 0.19.0 → 0.20.0

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