shipit-engine 0.27.1 → 0.28.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +30 -1
- data/app/assets/stylesheets/_pages/_commits.scss +2 -0
- data/app/assets/stylesheets/_pages/_deploy.scss +6 -0
- data/app/controllers/shipit/api/release_statuses_controller.rb +22 -0
- data/app/controllers/shipit/api/stacks_controller.rb +6 -1
- data/app/controllers/shipit/commits_controller.rb +12 -1
- data/app/controllers/shipit/deploys_controller.rb +11 -0
- data/app/controllers/shipit/stacks_controller.rb +29 -1
- data/app/controllers/shipit/tasks_controller.rb +13 -1
- data/app/helpers/shipit/merge_status_helper.rb +2 -2
- data/app/helpers/shipit/stacks_helper.rb +10 -4
- data/app/jobs/shipit/perform_task_job.rb +1 -0
- data/app/jobs/shipit/update_github_last_deployed_ref_job.rb +41 -0
- data/app/models/shipit/command_line_user.rb +58 -0
- data/app/models/shipit/commit.rb +42 -2
- data/app/models/shipit/deploy.rb +31 -2
- data/app/models/shipit/deploy_spec/lerna_discovery.rb +43 -19
- data/app/models/shipit/deploy_spec/pypi_discovery.rb +5 -1
- data/app/models/shipit/rollback.rb +4 -2
- data/app/models/shipit/stack.rb +72 -15
- data/app/models/shipit/task.rb +30 -0
- data/app/models/shipit/undeployed_commit.rb +10 -1
- data/app/serializers/shipit/command_line_user_serializer.rb +4 -0
- data/app/views/layouts/shipit.html.erb +5 -1
- data/app/views/shipit/commits/_commit.html.erb +7 -2
- data/app/views/shipit/merge_status/_commit_count_warning.html.erb +1 -5
- data/app/views/shipit/merge_status/backlogged.html.erb +1 -1
- data/app/views/shipit/merge_status/failure.html.erb +1 -1
- data/app/views/shipit/merge_status/locked.html.erb +1 -1
- data/app/views/shipit/merge_status/success.html.erb +1 -1
- data/app/views/shipit/stacks/show.html.erb +10 -1
- data/app/views/shipit/tasks/_task_output.html.erb +2 -2
- data/config/locales/en.yml +2 -1
- data/config/routes.rb +8 -1
- data/db/migrate/20190502020249_add_lock_author_id_to_commits.rb +5 -0
- data/lib/shipit.rb +14 -2
- data/lib/shipit/cast_value.rb +9 -0
- data/lib/shipit/command.rb +62 -16
- data/lib/shipit/line_buffer.rb +42 -0
- data/lib/shipit/version.rb +1 -1
- data/lib/tasks/shipit.rake +27 -0
- data/test/controllers/api/release_statuses_controller_test.rb +66 -0
- data/test/controllers/api/stacks_controller_test.rb +19 -0
- data/test/controllers/commits_controller_test.rb +30 -6
- data/test/controllers/deploys_controller_test.rb +51 -2
- data/test/controllers/tasks_controller_test.rb +24 -0
- data/test/dummy/db/schema.rb +2 -1
- data/test/dummy/db/seeds.rb +2 -0
- data/test/fixtures/shipit/check_runs.yml +11 -0
- data/test/fixtures/shipit/commits.yml +104 -0
- data/test/fixtures/shipit/stacks.yml +98 -3
- data/test/fixtures/shipit/tasks.yml +42 -0
- data/test/jobs/update_github_last_deployed_ref_job_test.rb +88 -0
- data/test/models/commits_test.rb +88 -1
- data/test/models/deploy_spec_test.rb +34 -6
- data/test/models/deploys_test.rb +308 -6
- data/test/models/rollbacks_test.rb +17 -11
- data/test/models/stacks_test.rb +217 -4
- data/test/models/tasks_test.rb +13 -0
- data/test/models/undeployed_commits_test.rb +62 -3
- data/test/test_helper.rb +0 -1
- data/test/unit/command_test.rb +55 -0
- data/test/unit/line_buffer_test.rb +20 -0
- metadata +142 -128
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Shipit
|
4
|
+
class UpdateGithubLastDeployedRefJobTest < ActiveSupport::TestCase
|
5
|
+
setup do
|
6
|
+
@stack = shipit_stacks(:shipit)
|
7
|
+
@job = UpdateGithubLastDeployedRefJob.new
|
8
|
+
@deploy = @stack.deploys.last
|
9
|
+
@commit = @deploy.until_commit
|
10
|
+
@api_client = Shipit.github.api
|
11
|
+
@expected_ref_prefix = "shipit-deploy/#{@stack.environment}"
|
12
|
+
@expected_name = @stack.github_repo_name
|
13
|
+
@expected_sha = @commit.sha
|
14
|
+
|
15
|
+
expected_ref = ["refs", @expected_ref_prefix].join('/')
|
16
|
+
ref_url = "http://api.github.test.com/shopify/shipit-engine/git/#{expected_ref}"
|
17
|
+
commit_url = "https://api.github.test.com/repos/shopify/shipit-engine/git/commits/#{@commit.sha}"
|
18
|
+
response_inner_obj = OpenStruct.new(sha: @commit.sha, type: "commit", url: commit_url)
|
19
|
+
@response = OpenStruct.new(ref: expected_ref, node_id: "blah", url: ref_url, object: response_inner_obj)
|
20
|
+
end
|
21
|
+
|
22
|
+
test "#perform will create a ref when one is not present" do
|
23
|
+
Octokit::UnprocessableEntity.any_instance.stubs(:build_error_message).returns("Reference does not exist")
|
24
|
+
|
25
|
+
@api_client.expects(:update_ref).with(@expected_name, @expected_ref_prefix, @expected_sha).raises(Octokit::UnprocessableEntity)
|
26
|
+
@api_client.expects(:create_ref).with(@expected_name, @expected_ref_prefix, @expected_sha).returns(@response)
|
27
|
+
|
28
|
+
result = @job.perform(@stack)
|
29
|
+
|
30
|
+
assert_equal @response, result
|
31
|
+
end
|
32
|
+
|
33
|
+
test "#perform will update a ref when one is present" do
|
34
|
+
prior_response = @response.dup
|
35
|
+
prior_response.object = prior_response.object.dup
|
36
|
+
new_sha = "some_new_sha"
|
37
|
+
@response.object.sha = new_sha
|
38
|
+
@commit.sha = new_sha
|
39
|
+
@commit.save
|
40
|
+
|
41
|
+
@api_client.expects(:update_ref).with(@expected_name, @expected_ref_prefix, new_sha).returns(@response)
|
42
|
+
|
43
|
+
result = @job.perform(@stack)
|
44
|
+
|
45
|
+
assert_equal @response, result
|
46
|
+
end
|
47
|
+
|
48
|
+
test '#perform will raise an exception for non ref existence errors' do
|
49
|
+
Octokit::UnprocessableEntity.any_instance.stubs(:build_error_message).returns("Some other error.")
|
50
|
+
|
51
|
+
@api_client.expects(:update_ref).with(@expected_name, @expected_ref_prefix, @expected_sha).raises(Octokit::UnprocessableEntity)
|
52
|
+
@api_client.expects(:create_ref).with(@expected_name, @expected_ref_prefix, @expected_sha).never
|
53
|
+
|
54
|
+
assert_raises Octokit::UnprocessableEntity do
|
55
|
+
@job.perform(@stack)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
test '#perform skips unsuccessful deploys when finding sha to use' do
|
60
|
+
prior_response = @response.dup
|
61
|
+
prior_response.object = prior_response.object.dup
|
62
|
+
new_sha = "some_new_sha"
|
63
|
+
@response.object.sha = new_sha
|
64
|
+
@commit.sha = new_sha
|
65
|
+
@commit.save
|
66
|
+
|
67
|
+
new_deploy = @stack.deploys.last.dup
|
68
|
+
new_commit = new_deploy.until_commit.dup
|
69
|
+
new_commit.sha = "some fake sha"
|
70
|
+
new_deploy.until_commit = new_commit
|
71
|
+
new_deploy.id = nil
|
72
|
+
new_deploy.status = "faulty"
|
73
|
+
new_deploy.save
|
74
|
+
|
75
|
+
@api_client.expects(:update_ref).with(@expected_name, @expected_ref_prefix, new_sha).returns(@response)
|
76
|
+
result = @job.perform(@stack)
|
77
|
+
|
78
|
+
assert_equal @response, result
|
79
|
+
|
80
|
+
new_deploy.reload
|
81
|
+
new_deploy.status = "success"
|
82
|
+
new_deploy.save
|
83
|
+
|
84
|
+
@api_client.expects(:update_ref).with(@expected_name, @expected_ref_prefix, new_commit.sha).returns(@response)
|
85
|
+
@job.perform(@stack)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/test/models/commits_test.rb
CHANGED
@@ -35,6 +35,33 @@ module Shipit
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
+
test '.create_from_github handle commits with empty message' do
|
39
|
+
assert_difference -> { Commit.count }, +1 do
|
40
|
+
@stack.commits.create_from_github!(
|
41
|
+
resource(
|
42
|
+
sha: '2adaad1ad30c235d3a6e7981dfc1742f7ecb1e85',
|
43
|
+
author: {},
|
44
|
+
committer: {},
|
45
|
+
commit: {
|
46
|
+
author: {
|
47
|
+
name: 'Lando Walrussian',
|
48
|
+
email: 'walrus@shopify.com',
|
49
|
+
date: Time.now,
|
50
|
+
},
|
51
|
+
committer: {
|
52
|
+
name: 'Lando Walrussian',
|
53
|
+
email: 'walrus@shopify.com',
|
54
|
+
date: Time.now,
|
55
|
+
},
|
56
|
+
message: '',
|
57
|
+
},
|
58
|
+
),
|
59
|
+
)
|
60
|
+
end
|
61
|
+
commit = Commit.last
|
62
|
+
refute_predicate commit, :revert?
|
63
|
+
end
|
64
|
+
|
38
65
|
test '.create_from_github handle PRs merged by another Shipit stacks' do
|
39
66
|
assert_difference -> { Commit.count }, +1 do
|
40
67
|
@stack.commits.create_from_github!(
|
@@ -247,7 +274,7 @@ module Shipit
|
|
247
274
|
|
248
275
|
test "#creating a commit update the undeployed_commits_count" do
|
249
276
|
walrus = shipit_users(:walrus)
|
250
|
-
assert_equal
|
277
|
+
assert_equal 2, @stack.undeployed_commits_count
|
251
278
|
@stack.commits.create!(
|
252
279
|
author: walrus,
|
253
280
|
committer: walrus,
|
@@ -417,6 +444,66 @@ module Shipit
|
|
417
444
|
assert_predicate commit, :deployable?
|
418
445
|
end
|
419
446
|
|
447
|
+
test "#lock sets the lock author and sets the locked flag" do
|
448
|
+
user = shipit_users(:shipit)
|
449
|
+
|
450
|
+
@commit.lock(user)
|
451
|
+
|
452
|
+
assert_predicate(@commit, :locked?)
|
453
|
+
assert_equal(user, @commit.lock_author)
|
454
|
+
end
|
455
|
+
|
456
|
+
test "#lock does not set the lock author if the user is anonymous" do
|
457
|
+
user = Shipit::AnonymousUser.new
|
458
|
+
|
459
|
+
@commit.lock(user)
|
460
|
+
|
461
|
+
assert_predicate(@commit, :locked?)
|
462
|
+
assert_nil(@commit.lock_author_id)
|
463
|
+
end
|
464
|
+
|
465
|
+
test ".lock_all sets the lock author and sets the locked flag" do
|
466
|
+
user = shipit_users(:shipit)
|
467
|
+
|
468
|
+
Commit.where(id: [@commit.id]).lock_all(user)
|
469
|
+
|
470
|
+
@commit.reload
|
471
|
+
assert_predicate(@commit, :locked?)
|
472
|
+
assert_equal(user, @commit.lock_author)
|
473
|
+
end
|
474
|
+
|
475
|
+
test ".lock_all does not set the lock author if the user is anonymous" do
|
476
|
+
user = Shipit::AnonymousUser.new
|
477
|
+
|
478
|
+
Commit.where(id: [@commit.id]).lock_all(user)
|
479
|
+
|
480
|
+
@commit.reload
|
481
|
+
assert_predicate(@commit, :locked?)
|
482
|
+
assert_nil(@commit.lock_author_id)
|
483
|
+
end
|
484
|
+
|
485
|
+
test "#lock_author defaults to AnonymousUser" do
|
486
|
+
assert_nil(@commit.lock_author_id)
|
487
|
+
assert_kind_of(Shipit::AnonymousUser, @commit.lock_author)
|
488
|
+
|
489
|
+
user = shipit_users(:shipit)
|
490
|
+
@commit.lock(user)
|
491
|
+
|
492
|
+
assert_kind_of(Shipit::User, @commit.lock_author)
|
493
|
+
end
|
494
|
+
|
495
|
+
test "#unlock clears the lock author and resets the locked flag" do
|
496
|
+
user = shipit_users(:shipit)
|
497
|
+
@commit.lock(user)
|
498
|
+
assert_predicate(@commit, :locked?)
|
499
|
+
assert_equal(user, @commit.lock_author)
|
500
|
+
|
501
|
+
@commit.unlock
|
502
|
+
|
503
|
+
refute_predicate(@commit, :locked?)
|
504
|
+
assert_nil(@commit.lock_author_id)
|
505
|
+
end
|
506
|
+
|
420
507
|
expected_webhook_transitions = { # we expect deployable_status to fire on these transitions, and not on any others
|
421
508
|
'unknown' => %w(pending success failure error),
|
422
509
|
'pending' => %w(success failure error),
|
@@ -323,7 +323,11 @@ module Shipit
|
|
323
323
|
file = Pathname.new('/tmp/fake_setup.py')
|
324
324
|
file.write('foo')
|
325
325
|
@spec.stubs(:setup_dot_py).returns(file)
|
326
|
-
steps = [
|
326
|
+
steps = [
|
327
|
+
'assert-egg-version-tag /tmp/fake_setup.py',
|
328
|
+
'python setup.py register sdist',
|
329
|
+
'twine upload dist/*',
|
330
|
+
]
|
327
331
|
assert_equal steps, @spec.deploy_steps
|
328
332
|
end
|
329
333
|
|
@@ -732,6 +736,7 @@ module Shipit
|
|
732
736
|
|
733
737
|
test 'lerna monorepos have a checklist' do
|
734
738
|
@spec.stubs(:lerna?).returns(true).at_least_once
|
739
|
+
@spec.stubs(:lerna_config).returns('lerna' => '2.0.0', 'version' => '1.0.0')
|
735
740
|
assert_match(/lerna publish --skip-npm/, @spec.review_checklist[0])
|
736
741
|
end
|
737
742
|
|
@@ -744,10 +749,18 @@ module Shipit
|
|
744
749
|
file = Pathname.new('/tmp/fake_lerna.json')
|
745
750
|
file.write('{"version": "1.0.0-beta.1"}')
|
746
751
|
|
747
|
-
@spec.expects(:lerna_json).returns(file)
|
752
|
+
@spec.expects(:lerna_json).at_least_once.returns(file)
|
748
753
|
assert_equal '1.0.0-beta.1', @spec.lerna_version
|
749
754
|
end
|
750
755
|
|
756
|
+
test '#lerna_lerna returns the lerna version specified' do
|
757
|
+
file = Pathname.new('/tmp/fake_lerna.json')
|
758
|
+
file.write('{"version": "1.0.0-beta.1", "lerna": "3.13.3"}')
|
759
|
+
|
760
|
+
@spec.expects(:lerna_json).at_least_once.returns(file)
|
761
|
+
assert_equal Gem::Version.new('3.13.3'), @spec.lerna_lerna
|
762
|
+
end
|
763
|
+
|
751
764
|
test '#package_version returns the version number' do
|
752
765
|
file = Pathname.new('/tmp/fake_package.json')
|
753
766
|
file.write('{"version": "1.0.0-beta.1"}')
|
@@ -780,18 +793,32 @@ module Shipit
|
|
780
793
|
|
781
794
|
test '#publish_lerna_packages checks if independent version tags exist, and then invokes lerna deploy script' do
|
782
795
|
@spec.stubs(:lerna?).returns(true)
|
783
|
-
@spec.stubs(:
|
796
|
+
@spec.stubs(:lerna_config).returns('lerna' => '2.0.0', 'version' => 'independent')
|
784
797
|
assert_equal 'assert-lerna-independent-version-tags', @spec.deploy_steps[0]
|
785
798
|
assert_equal 'publish-lerna-independent-packages', @spec.deploy_steps[1]
|
786
799
|
end
|
787
800
|
|
788
801
|
test '#publish_lerna_packages checks if fixed version tag exists, and then invokes lerna deploy script' do
|
789
802
|
@spec.stubs(:lerna?).returns(true)
|
790
|
-
@spec.stubs(:
|
803
|
+
@spec.stubs(:lerna_config).returns('lerna' => '2.0.0', 'version' => '1.0.0')
|
791
804
|
assert_equal 'assert-lerna-fixed-version-tag', @spec.deploy_steps[0]
|
792
805
|
assert_equal 'node_modules/.bin/lerna publish --yes --skip-git --repo-version 1.0.0 --force-publish=* --npm-tag latest --npm-client=npm --skip-npm=false', @spec.deploy_steps[1]
|
793
806
|
end
|
794
807
|
|
808
|
+
test '#publish_lerna_packages checks if a newer version of lerna is used, and will then use the new publish syntax, correctly setting the `latest` dist tag' do
|
809
|
+
@spec.stubs(:lerna?).returns(true)
|
810
|
+
@spec.stubs(:lerna_config).returns('lerna' => '3.0.0', 'version' => '1.0.0')
|
811
|
+
assert_equal 'assert-lerna-fixed-version-tag', @spec.deploy_steps[0]
|
812
|
+
assert_equal 'node_modules/.bin/lerna publish from-git --yes --dist-tag latest', @spec.deploy_steps[1]
|
813
|
+
end
|
814
|
+
|
815
|
+
test '#publish_lerna_packages checks if a newer version of lerna is used, and will then use the new publish syntax, correctly setting the `next` dist tag' do
|
816
|
+
@spec.stubs(:lerna?).returns(true)
|
817
|
+
@spec.stubs(:lerna_config).returns('lerna' => '3.0.0', 'version' => 'v1.3.1-alpha.2')
|
818
|
+
assert_equal 'assert-lerna-fixed-version-tag', @spec.deploy_steps[0]
|
819
|
+
assert_equal 'node_modules/.bin/lerna publish from-git --yes --dist-tag next', @spec.deploy_steps[1]
|
820
|
+
end
|
821
|
+
|
795
822
|
test '#enforce_publish_config? is false when Shipit.enforce_publish_config is nil' do
|
796
823
|
Shipit.stubs(:enforce_publish_config).returns(nil)
|
797
824
|
refute @spec.enforce_publish_config?
|
@@ -829,7 +856,8 @@ module Shipit
|
|
829
856
|
end
|
830
857
|
|
831
858
|
test '#valid_publish_config? is true when shipit does not enforce a publishConfig' do
|
832
|
-
@spec.stubs(:
|
859
|
+
@spec.stubs(:lerna?).returns(true)
|
860
|
+
@spec.stubs(:lerna_config).returns('lerna' => '2.0.0', 'version' => '1.0.0')
|
833
861
|
assert @spec.valid_publish_config?
|
834
862
|
end
|
835
863
|
|
@@ -946,7 +974,7 @@ module Shipit
|
|
946
974
|
|
947
975
|
test '#publish_lerna_packages guesses npm tag' do
|
948
976
|
@spec.stubs(:lerna?).returns(true)
|
949
|
-
@spec.stubs(:
|
977
|
+
@spec.stubs(:lerna_config).returns('lerna' => '2.0.0', 'version' => '1.0.0-alpha.1')
|
950
978
|
assert_match(/--npm-tag next/, @spec.deploy_steps.last)
|
951
979
|
end
|
952
980
|
|
data/test/models/deploys_test.rb
CHANGED
@@ -23,6 +23,16 @@ module Shipit
|
|
23
23
|
assert_raise(RuntimeError) { Deploy.new.enqueue }
|
24
24
|
end
|
25
25
|
|
26
|
+
test "run_now! when not persisted" do
|
27
|
+
assert_raise(RuntimeError) { Deploy.new.run_now! }
|
28
|
+
end
|
29
|
+
|
30
|
+
test "run_now! runs in foreground" do
|
31
|
+
PerformTaskJob.any_instance.expects(:perform).once
|
32
|
+
|
33
|
+
@deploy.run_now!
|
34
|
+
end
|
35
|
+
|
26
36
|
test "working_directory" do
|
27
37
|
assert_equal File.join(@deploy.stack.deploys_path, @deploy.id.to_s), @deploy.working_directory
|
28
38
|
end
|
@@ -235,6 +245,13 @@ module Shipit
|
|
235
245
|
end
|
236
246
|
end
|
237
247
|
|
248
|
+
test "transitioning to success enqueues a last-deployed git reference update" do
|
249
|
+
@deploy = shipit_deploys(:shipit_running)
|
250
|
+
assert_enqueued_with(job: UpdateGithubLastDeployedRefJob, args: [@deploy.stack]) do
|
251
|
+
@deploy.complete!
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
238
255
|
test "transitions to any state updates last deploy time to stack record" do
|
239
256
|
@deploy = shipit_deploys(:shipit_running)
|
240
257
|
@deploy.complete!
|
@@ -321,12 +338,289 @@ module Shipit
|
|
321
338
|
assert_equal shipit_commits(:second), @stack.last_deployed_commit
|
322
339
|
end
|
323
340
|
|
341
|
+
def create_test_stack
|
342
|
+
Shipit::Stack.create(
|
343
|
+
repo_owner: "shopify-test",
|
344
|
+
repo_name: "shipit-engine-test",
|
345
|
+
environment: 'production',
|
346
|
+
branch: "master",
|
347
|
+
merge_queue_enabled: true,
|
348
|
+
created_at: "2019-01-01 00:00:00",
|
349
|
+
updated_at: "2019-01-02 10:10:10",
|
350
|
+
)
|
351
|
+
end
|
352
|
+
|
353
|
+
def create_test_commit(stack_id:, user_id:)
|
354
|
+
Shipit::Commit.new(
|
355
|
+
stack_id: stack_id,
|
356
|
+
author_id: user_id,
|
357
|
+
sha: SecureRandom.hex(20),
|
358
|
+
additions: 2,
|
359
|
+
deletions: 0,
|
360
|
+
committer_id: user_id,
|
361
|
+
message: "Some commit message.",
|
362
|
+
authored_at: "2019-01-02 10:11:10",
|
363
|
+
committed_at: "2019-01-02 10:11:10",
|
364
|
+
)
|
365
|
+
end
|
366
|
+
|
367
|
+
def create_test_status(commit_id:, stack_id:, state: "success")
|
368
|
+
Shipit::Status.new(
|
369
|
+
description: "Description for commit #{commit_id}",
|
370
|
+
stack_id: stack_id,
|
371
|
+
commit_id: commit_id,
|
372
|
+
state: state,
|
373
|
+
)
|
374
|
+
end
|
375
|
+
|
376
|
+
def create_test_deploy(stack_id:, user_id:, since_commit_id:, until_commit_id: since_commit_id)
|
377
|
+
Shipit::Deploy.new(
|
378
|
+
stack_id: stack_id,
|
379
|
+
user_id: user_id,
|
380
|
+
since_commit_id: since_commit_id,
|
381
|
+
until_commit_id: until_commit_id,
|
382
|
+
status: "success",
|
383
|
+
type: "Shipit::Deploy",
|
384
|
+
)
|
385
|
+
end
|
386
|
+
|
387
|
+
# For test purposes, we want to fail fast if a series of records are given sequential ids.
|
388
|
+
# Check that the next item in the series is 1 greater than the last.
|
389
|
+
def assert_generated_record_ids_are_sequential(record_id_series)
|
390
|
+
record_id_series[0..-2].each_with_index do |id_element, index|
|
391
|
+
assert_equal id_element + 1, record_id_series[index + 1]
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
def generate_commits(amount:, stack_id:, user_id:, validate:)
|
396
|
+
commit_ids = []
|
397
|
+
amount.times do
|
398
|
+
commit = create_test_commit(stack_id: stack_id, user_id: user_id)
|
399
|
+
commit.save
|
400
|
+
commit.reload
|
401
|
+
commit_ids << commit.id
|
402
|
+
end
|
403
|
+
|
404
|
+
if validate then assert_generated_record_ids_are_sequential(commit_ids) end
|
405
|
+
commit_ids
|
406
|
+
end
|
407
|
+
|
324
408
|
test "#trigger_revert rolls the stack back to before this deploy" do
|
325
|
-
|
326
|
-
|
409
|
+
user_id = @user.id
|
410
|
+
test_stack = create_test_stack
|
411
|
+
test_stack.save
|
412
|
+
test_stack.reload
|
413
|
+
stack_id = test_stack.id
|
414
|
+
|
415
|
+
# Create valid commit history for the stack. We need several commits to deploy and roll back through.
|
416
|
+
commit_ids = generate_commits(amount: 4, stack_id: stack_id, user_id: user_id, validate: true)
|
417
|
+
commit_ids.each { |commit_id| create_test_status(commit_id: commit_id, stack_id: stack_id, state: "success").save }
|
418
|
+
|
419
|
+
# Three deploys of commits 1-2, 2-3 and 3-4 respectively. Reverting last should result in Deploy 3 (commit 3) being latest.
|
420
|
+
3.times { |index| create_test_deploy(stack_id: stack_id, user_id: user_id, since_commit_id: commit_ids[index], until_commit_id: commit_ids[index + 1]).save }
|
421
|
+
|
422
|
+
# Get the reference with Rails-mutated field values.
|
423
|
+
commit3 = Shipit::Commit.second_to_last
|
424
|
+
commit4 = Shipit::Commit.last
|
425
|
+
deploy3 = Shipit::Deploy.last
|
426
|
+
|
427
|
+
assert_equal commit4, test_stack.last_deployed_commit
|
428
|
+
|
429
|
+
deploy_to_revert = test_stack.deploys.last
|
430
|
+
|
431
|
+
assert_equal deploy3, deploy_to_revert
|
432
|
+
|
433
|
+
rollback = deploy_to_revert.trigger_revert
|
327
434
|
rollback.run!
|
328
435
|
rollback.complete!
|
329
|
-
|
436
|
+
|
437
|
+
last_deploy = test_stack.last_completed_deploy
|
438
|
+
|
439
|
+
assert_equal commit3, test_stack.last_deployed_commit
|
440
|
+
assert_equal commit3, last_deploy.until_commit
|
441
|
+
assert_equal "Shipit::Rollback", last_deploy.type
|
442
|
+
end
|
443
|
+
|
444
|
+
test "#trigger_revert skips unsuccessful deploys when reverting" do
|
445
|
+
user_id = @user.id
|
446
|
+
test_stack = create_test_stack
|
447
|
+
test_stack.save
|
448
|
+
test_stack.reload
|
449
|
+
stack_id = test_stack.id
|
450
|
+
|
451
|
+
# Create valid commit history for the stack. We need several commits to deploy and roll back through.
|
452
|
+
commit_ids = generate_commits(amount: 4, stack_id: stack_id, user_id: user_id, validate: true)
|
453
|
+
commit_ids.each { |commit_id| create_test_status(commit_id: commit_id, stack_id: stack_id, state: "success").save }
|
454
|
+
|
455
|
+
# We want the following order of Deploys:
|
456
|
+
# 1. Success (commits 1-2)
|
457
|
+
# 2. Faulty (commits 2-3)
|
458
|
+
# 3. Rollback to Success (-> commits 1-2)
|
459
|
+
# 4. Running (commits 3-4)
|
460
|
+
# 5. Reversion of the running deploy to the last successful deploy. (-> commits 1-2, i.e. the successful deploy.)
|
461
|
+
|
462
|
+
deploy1 = create_test_deploy(stack_id: stack_id, user_id: user_id, since_commit_id: commit_ids[0], until_commit_id: commit_ids[1])
|
463
|
+
deploy1.save
|
464
|
+
|
465
|
+
deploy2 = create_test_deploy(stack_id: stack_id, user_id: user_id, since_commit_id: commit_ids[1], until_commit_id: commit_ids[2])
|
466
|
+
deploy2.status = "faulty"
|
467
|
+
deploy2.save
|
468
|
+
|
469
|
+
rollback = test_stack.deploys.second_to_last.trigger_rollback(@user)
|
470
|
+
rollback.run!
|
471
|
+
rollback.complete!
|
472
|
+
|
473
|
+
assert_equal commit_ids[1], test_stack.last_deployed_commit.id
|
474
|
+
|
475
|
+
deploy3 = create_test_deploy(stack_id: stack_id, user_id: user_id, since_commit_id: commit_ids[2], until_commit_id: commit_ids[3])
|
476
|
+
deploy3.status = "running"
|
477
|
+
deploy3.rollback_once_aborted = false
|
478
|
+
deploy3.save
|
479
|
+
|
480
|
+
running_deploy = deploy3.reload
|
481
|
+
running_deploy.abort!(aborted_by: @user)
|
482
|
+
running_deploy.reload
|
483
|
+
|
484
|
+
assert_equal "error", running_deploy.status
|
485
|
+
|
486
|
+
final_rollback = running_deploy.trigger_revert
|
487
|
+
final_rollback.run!
|
488
|
+
final_rollback.complete!
|
489
|
+
|
490
|
+
last_deploy = test_stack.last_completed_deploy
|
491
|
+
|
492
|
+
# The rollback deploy should be from the last commit until the second commit.
|
493
|
+
assert_equal "success", last_deploy.status
|
494
|
+
assert_equal "Shipit::Rollback", last_deploy.type
|
495
|
+
assert_equal commit_ids[-1], last_deploy.since_commit_id
|
496
|
+
assert_equal commit_ids[1], last_deploy.until_commit_id
|
497
|
+
assert_equal commit_ids[1], test_stack.last_deployed_commit.id
|
498
|
+
end
|
499
|
+
|
500
|
+
test "#trigger_revert skips non-deploy tasks when rolling back" do
|
501
|
+
# The revert functionality should only consider Shipit::Deploy and Shipit::Rollback when selecting a target to roll back to for the user.
|
502
|
+
# But it is possible for other task types to be defined, so we want to ensure that they are properly skipped, as we can't know whether they are 'valid' to roll back to.
|
503
|
+
user_id = @user.id
|
504
|
+
test_stack = create_test_stack
|
505
|
+
test_stack.save
|
506
|
+
test_stack.reload
|
507
|
+
stack_id = test_stack.id
|
508
|
+
|
509
|
+
# Create valid commit history for the stack. We need several commits to deploy and roll back through.
|
510
|
+
commit_ids = generate_commits(amount: 4, stack_id: stack_id, user_id: user_id, validate: true)
|
511
|
+
commit_ids.each { |commit_id| create_test_status(commit_id: commit_id, stack_id: stack_id, state: "success").save }
|
512
|
+
|
513
|
+
# We want the following order of Deploys:
|
514
|
+
# 1. Success (commits 1-2)
|
515
|
+
# 2. Success, but type is not of deploy (commits 2-3)
|
516
|
+
# 3. Running (commits 3-4)
|
517
|
+
# 4. Reversion of the running deploy to the last successful deploy. (-> commits 1-2, i.e. the successful deploy.)
|
518
|
+
# If the revert functionality doesn't restrict to deploys and rollbacks, then commit 3 will be latest deployed when the reversion is done.
|
519
|
+
|
520
|
+
deploy1 = create_test_deploy(stack_id: stack_id, user_id: user_id, since_commit_id: commit_ids[0], until_commit_id: commit_ids[1])
|
521
|
+
deploy1.save
|
522
|
+
|
523
|
+
deploy2 = create_test_deploy(stack_id: stack_id, user_id: user_id, since_commit_id: commit_ids[1], until_commit_id: commit_ids[2])
|
524
|
+
deploy2.type = "Shipit::Fake"
|
525
|
+
deploy2.save
|
526
|
+
|
527
|
+
deploy3 = create_test_deploy(stack_id: stack_id, user_id: user_id, since_commit_id: commit_ids[2], until_commit_id: commit_ids[3])
|
528
|
+
deploy3.status = "running"
|
529
|
+
deploy3.rollback_once_aborted = false
|
530
|
+
deploy3.save
|
531
|
+
|
532
|
+
running_deploy = deploy3.reload
|
533
|
+
running_deploy.abort!(aborted_by: @user)
|
534
|
+
running_deploy.reload
|
535
|
+
|
536
|
+
rollback = running_deploy.trigger_revert
|
537
|
+
rollback.run!
|
538
|
+
rollback.complete!
|
539
|
+
|
540
|
+
last_deploy = test_stack.last_completed_deploy
|
541
|
+
assert_equal "success", last_deploy.status
|
542
|
+
assert_equal "Shipit::Rollback", last_deploy.type
|
543
|
+
assert_equal commit_ids[-1], last_deploy.since_commit_id
|
544
|
+
assert_equal commit_ids[1], last_deploy.until_commit_id
|
545
|
+
assert_equal commit_ids[1], test_stack.last_deployed_commit.id
|
546
|
+
end
|
547
|
+
|
548
|
+
test "#trigger_revert skips deploys from other stacks" do
|
549
|
+
# The revert functionality should only consider Shipit::Deploy and Shipit::Rollback's from the same stack when selecting a target to roll back to for the user.
|
550
|
+
# But deploys and commits from other stacks can have ids between the current and the previous of this stack, so we want a test to ensure that the deploy
|
551
|
+
# from the correct stack is selected.
|
552
|
+
user_id = @user.id
|
553
|
+
test_stack = create_test_stack
|
554
|
+
test_stack.save
|
555
|
+
other_stack = create_test_stack
|
556
|
+
other_stack.repo_name += "_other"
|
557
|
+
other_stack.save
|
558
|
+
other_stack.reload
|
559
|
+
stack_id = test_stack.id
|
560
|
+
|
561
|
+
# Create valid commit history for the stack. We need several commits to deploy and roll back through.
|
562
|
+
commit_ids = generate_commits(amount: 4, stack_id: stack_id, user_id: user_id, validate: true)
|
563
|
+
commit_ids.each { |commit_id| create_test_status(commit_id: commit_id, stack_id: stack_id, state: "success").save }
|
564
|
+
|
565
|
+
# We want the following order of Deploys:
|
566
|
+
# 1. Success (commits 1-2)
|
567
|
+
# 2. Success, but belongs to a different stack (commits 2-3)
|
568
|
+
# 3. Running (commits 3-4)
|
569
|
+
# 4. Reversion of the running deploy to the last successful deploy of the same stack. (-> commits 1-2, i.e. the successful deploy.)
|
570
|
+
# If the revert functionality doesn't restrict to the correct stack, then commit 3 will be latest deployed when the reversion is done.
|
571
|
+
|
572
|
+
deploy1 = create_test_deploy(stack_id: stack_id, user_id: user_id, since_commit_id: commit_ids[0], until_commit_id: commit_ids[1])
|
573
|
+
deploy1.save
|
574
|
+
|
575
|
+
deploy2 = create_test_deploy(stack_id: other_stack.id, user_id: user_id, since_commit_id: commit_ids[1], until_commit_id: commit_ids[2])
|
576
|
+
deploy2.save
|
577
|
+
|
578
|
+
deploy3 = create_test_deploy(stack_id: stack_id, user_id: user_id, since_commit_id: commit_ids[2], until_commit_id: commit_ids[3])
|
579
|
+
deploy3.status = "running"
|
580
|
+
deploy3.rollback_once_aborted = false
|
581
|
+
deploy3.save
|
582
|
+
|
583
|
+
running_deploy = deploy3.reload
|
584
|
+
running_deploy.abort!(aborted_by: @user)
|
585
|
+
running_deploy.reload
|
586
|
+
|
587
|
+
rollback = running_deploy.trigger_revert
|
588
|
+
rollback.run!
|
589
|
+
rollback.complete!
|
590
|
+
|
591
|
+
last_deploy = test_stack.last_completed_deploy
|
592
|
+
assert_equal "success", last_deploy.status
|
593
|
+
assert_equal "Shipit::Rollback", last_deploy.type
|
594
|
+
assert_equal commit_ids[-1], last_deploy.since_commit_id
|
595
|
+
assert_equal commit_ids[1], last_deploy.until_commit_id
|
596
|
+
assert_equal commit_ids[1], test_stack.last_deployed_commit.id
|
597
|
+
end
|
598
|
+
|
599
|
+
test "#trigger_revert no prior deploy to roll back to" do
|
600
|
+
user_id = @user.id
|
601
|
+
test_stack = create_test_stack
|
602
|
+
test_stack.save
|
603
|
+
test_stack.reload
|
604
|
+
stack_id = test_stack.id
|
605
|
+
|
606
|
+
commit_ids = generate_commits(amount: 2, stack_id: stack_id, user_id: user_id, validate: true)
|
607
|
+
commit_ids.each { |commit_id| create_test_status(commit_id: commit_id, stack_id: stack_id, state: "success").save }
|
608
|
+
deploy1 = create_test_deploy(stack_id: stack_id, user_id: user_id, since_commit_id: commit_ids[0], until_commit_id: commit_ids[1])
|
609
|
+
deploy1.save
|
610
|
+
|
611
|
+
rollback = deploy1.trigger_revert
|
612
|
+
rollback.run!
|
613
|
+
rollback.complete!
|
614
|
+
|
615
|
+
assert_equal deploy1.until_commit_id, rollback.since_commit_id
|
616
|
+
assert_equal deploy1.since_commit_id, rollback.until_commit_id
|
617
|
+
|
618
|
+
last_deploy = test_stack.last_completed_deploy
|
619
|
+
assert_equal "success", last_deploy.status
|
620
|
+
assert_equal "Shipit::Rollback", last_deploy.type
|
621
|
+
assert_equal deploy1.until_commit_id, last_deploy.since_commit_id
|
622
|
+
assert_equal deploy1.since_commit_id, last_deploy.until_commit_id
|
623
|
+
assert_equal deploy1.since_commit_id, test_stack.last_deployed_commit.id
|
330
624
|
end
|
331
625
|
|
332
626
|
test "#trigger_rollback creates a new Rollback" do
|
@@ -525,7 +819,7 @@ module Shipit
|
|
525
819
|
@deploy = shipit_deploys(:canaries_running)
|
526
820
|
@deploy.ping
|
527
821
|
|
528
|
-
assert_difference -> { ReleaseStatus.count }, +
|
822
|
+
assert_difference -> { ReleaseStatus.count }, +2 do
|
529
823
|
assert_equal 'running', @deploy.status
|
530
824
|
assert_not_equal 'failure', @deploy.last_release_status.state
|
531
825
|
|
@@ -545,16 +839,24 @@ module Shipit
|
|
545
839
|
|
546
840
|
test "manually triggered rollbacks sets the release status as failure" do
|
547
841
|
@deploy = shipit_deploys(:canaries_validating)
|
842
|
+
@middle_deploy = shipit_deploys(:canaries_faulty)
|
843
|
+
@rollback_to_deploy = shipit_deploys(:canaries_success)
|
548
844
|
|
549
|
-
assert_difference -> { ReleaseStatus.count }, +
|
845
|
+
assert_difference -> { ReleaseStatus.count }, +2 do
|
550
846
|
assert_equal 'validating', @deploy.status
|
551
847
|
assert_equal 'pending', @deploy.last_release_status.state
|
552
848
|
|
553
|
-
@
|
849
|
+
@rollback_to_deploy.trigger_rollback(force: true)
|
850
|
+
@rollback_to_deploy.reload
|
554
851
|
@deploy.reload
|
555
852
|
|
556
853
|
assert_equal 'faulty', @deploy.status
|
557
854
|
assert_equal 'failure', @deploy.last_release_status.state
|
855
|
+
|
856
|
+
assert_equal 'faulty', @middle_deploy.status
|
857
|
+
assert_equal 'failure', @middle_deploy.last_release_status.state
|
858
|
+
|
859
|
+
assert_equal 'success', @rollback_to_deploy.status
|
558
860
|
end
|
559
861
|
end
|
560
862
|
|