shipit-engine 0.35.1 → 0.37.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 +20 -7
- data/app/controllers/concerns/shipit/authentication.rb +5 -1
- data/app/controllers/shipit/api/base_controller.rb +13 -1
- data/app/controllers/shipit/api/rollbacks_controller.rb +1 -1
- data/app/controllers/shipit/api/stacks_controller.rb +10 -2
- data/app/controllers/shipit/api/tasks_controller.rb +19 -2
- data/app/controllers/shipit/rollbacks_controller.rb +5 -1
- data/app/helpers/shipit/stacks_helper.rb +11 -0
- data/app/models/concerns/shipit/deferred_touch.rb +3 -3
- data/app/models/shipit/anonymous_user.rb +4 -0
- data/app/models/shipit/api_client.rb +1 -1
- data/app/models/shipit/commit_checks.rb +3 -3
- data/app/models/shipit/delivery.rb +1 -1
- data/app/models/shipit/deploy.rb +1 -0
- data/app/models/shipit/deploy_spec/file_system.rb +32 -4
- data/app/models/shipit/pull_request.rb +1 -1
- data/app/models/shipit/stack.rb +10 -10
- data/app/models/shipit/task.rb +31 -4
- data/app/models/shipit/user.rb +23 -9
- data/app/serializers/shipit/stack_serializer.rb +1 -1
- data/app/views/shipit/deploys/_deploy.html.erb +1 -5
- data/app/views/shipit/stacks/_banners.html.erb +1 -1
- data/app/views/shipit/stacks/_settings_form.erb +55 -0
- data/app/views/shipit/stacks/settings.html.erb +1 -55
- data/app/views/shipit/stacks/show.html.erb +1 -1
- data/config/locales/en.yml +1 -1
- data/config/routes.rb +4 -0
- data/db/migrate/20211103154121_increase_github_team_slug_size.rb +5 -0
- data/lib/shipit/engine.rb +15 -5
- data/lib/shipit/stack_commands.rb +9 -2
- data/lib/shipit/task_commands.rb +8 -1
- data/lib/shipit/version.rb +1 -1
- data/lib/shipit.rb +55 -3
- data/lib/snippets/fetch-gem-version +1 -1
- data/test/controllers/api/hooks_controller_test.rb +1 -1
- data/test/controllers/api/rollback_controller_test.rb +1 -0
- data/test/controllers/api/stacks_controller_test.rb +34 -0
- data/test/controllers/api/tasks_controller_test.rb +56 -0
- data/test/controllers/stacks_controller_test.rb +11 -0
- data/test/dummy/config/application.rb +1 -2
- data/test/dummy/db/schema.rb +2 -2
- data/test/fixtures/shipit/check_runs.yml +3 -3
- data/test/fixtures/shipit/commits.yml +101 -101
- data/test/fixtures/shipit/deliveries.yml +1 -1
- data/test/fixtures/shipit/merge_requests.yml +19 -19
- data/test/fixtures/shipit/stacks.yml +28 -28
- data/test/fixtures/shipit/statuses.yml +16 -16
- data/test/fixtures/shipit/tasks.yml +77 -65
- data/test/fixtures/shipit/users.yml +2 -5
- data/test/models/commits_test.rb +6 -6
- data/test/models/deploy_spec_test.rb +0 -23
- data/test/models/deploys_test.rb +26 -0
- data/test/models/shipit/deploy_spec/file_system_test.rb +81 -0
- data/test/models/tasks_test.rb +14 -2
- data/test/models/team_test.rb +21 -2
- data/test/models/users_test.rb +29 -9
- data/test/unit/deploy_commands_test.rb +6 -2
- metadata +189 -185
data/test/models/deploys_test.rb
CHANGED
@@ -459,6 +459,32 @@ module Shipit
|
|
459
459
|
end
|
460
460
|
end
|
461
461
|
|
462
|
+
test "transitioning to aborted locks the stack if a rollback is scheduled" do
|
463
|
+
refute @stack.locked?
|
464
|
+
|
465
|
+
@deploy = shipit_deploys(:shipit_running)
|
466
|
+
@deploy.ping
|
467
|
+
@deploy.pid = 42
|
468
|
+
@deploy.abort!(rollback_once_aborted: true, aborted_by: @user)
|
469
|
+
@deploy.aborted!
|
470
|
+
|
471
|
+
assert_predicate @stack.reload, :locked?
|
472
|
+
assert_equal @user, @stack.lock_author
|
473
|
+
end
|
474
|
+
|
475
|
+
test "transitioning to aborted emits a lock hook if a rollback is scheduled" do
|
476
|
+
refute_predicate @stack, :locked?
|
477
|
+
|
478
|
+
@deploy = shipit_deploys(:shipit_running)
|
479
|
+
@deploy.ping
|
480
|
+
@deploy.pid = 42
|
481
|
+
@deploy.abort!(rollback_once_aborted: true, aborted_by: @user)
|
482
|
+
|
483
|
+
expect_hook(:lock, @stack, locked: true, lock_details: nil, stack: @stack) do
|
484
|
+
@deploy.aborted!
|
485
|
+
end
|
486
|
+
end
|
487
|
+
|
462
488
|
test "#build_rollback returns an unsaved record" do
|
463
489
|
assert @deploy.build_rollback.new_record?
|
464
490
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'test_helper'
|
3
|
+
require 'tmpdir'
|
4
|
+
|
5
|
+
module Shipit
|
6
|
+
class DeploySpec
|
7
|
+
class FileSystemTest < ActiveSupport::TestCase
|
8
|
+
test 'deploy.pre calls "exit 1" if there is a bare shipit file and Shipit is configured to ignore' do
|
9
|
+
Shipit.expects(:respect_bare_shipit_file?).returns(false).at_least_once
|
10
|
+
deploy_spec = Shipit::DeploySpec::FileSystem.new(Dir.tmpdir, 'env')
|
11
|
+
deploy_spec.expects(:config_file_path).returns(Pathname.new(Dir.tmpdir) + '/shipit.yml').at_least_once
|
12
|
+
deploy_spec.expects(:read_config).never
|
13
|
+
pre_commands = deploy_spec.send(:config, 'deploy', 'pre')
|
14
|
+
assert pre_commands.include?('exit 1')
|
15
|
+
assert pre_commands.first.include?('configured to ignore')
|
16
|
+
refute pre_commands.include?('test 2')
|
17
|
+
end
|
18
|
+
|
19
|
+
test 'deploy.pre does not call "exit 1" if Shipit is not configured to do so' do
|
20
|
+
Shipit.expects(:respect_bare_shipit_file?).returns(true).at_least_once
|
21
|
+
deploy_spec = Shipit::DeploySpec::FileSystem.new(Dir.tmpdir, 'env')
|
22
|
+
deploy_spec.expects(:config_file_path).returns(Pathname.new(Dir.tmpdir) + '/shipit.yml').at_least_once
|
23
|
+
deploy_spec.expects(:read_config).returns(SafeYAML.load(deploy_spec_yaml))
|
24
|
+
pre_commands = deploy_spec.send(:config, 'deploy', 'pre')
|
25
|
+
refute pre_commands.include?('exit 1')
|
26
|
+
assert pre_commands.include?('test 2')
|
27
|
+
end
|
28
|
+
|
29
|
+
test 'Shipit.respect_bare_shipit_file? has no effect if the file is not a bare file' do
|
30
|
+
[true, false].each do |obey_val|
|
31
|
+
Shipit.expects(:respect_bare_shipit_file?).returns(obey_val).at_least_once
|
32
|
+
deploy_spec = Shipit::DeploySpec::FileSystem.new(Dir.tmpdir, 'env')
|
33
|
+
deploy_spec.expects(:config_file_path).returns(Pathname.new(Dir.tmpdir) + '/shipit.env.yml').at_least_once
|
34
|
+
deploy_spec.expects(:read_config).returns(SafeYAML.load(deploy_spec_yaml))
|
35
|
+
pre_commands = deploy_spec.send(:config, 'deploy', 'pre')
|
36
|
+
refute pre_commands.include?('exit 1')
|
37
|
+
assert pre_commands.include?('test 2')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
test '#load_config does not error if the file is empty' do
|
42
|
+
Shipit.expects(:respect_bare_shipit_file?).returns(true).at_least_once
|
43
|
+
deploy_spec = Shipit::DeploySpec::FileSystem.new(Dir.tmpdir, 'env')
|
44
|
+
deploy_spec.expects(:config_file_path).returns(Pathname.new(Dir.tmpdir) + '/shipit.env.yml').at_least_once
|
45
|
+
deploy_spec.expects(:read_config).at_least_once.returns(false)
|
46
|
+
loaded_config = deploy_spec.send(:cacheable_config)
|
47
|
+
refute loaded_config == false
|
48
|
+
end
|
49
|
+
|
50
|
+
test '#load_config does not error if there is no "deploy" key' do
|
51
|
+
Shipit.expects(:respect_bare_shipit_file?).returns(false).at_least_once
|
52
|
+
deploy_spec = Shipit::DeploySpec::FileSystem.new(Dir.tmpdir, 'env')
|
53
|
+
deploy_spec.expects(:config_file_path).returns(Pathname.new(Dir.tmpdir) + '/shipit.yml').at_least_once
|
54
|
+
deploy_spec.expects(:read_config).never
|
55
|
+
loaded_config = deploy_spec.send(:load_config)
|
56
|
+
assert loaded_config.key?("deploy")
|
57
|
+
assert loaded_config["deploy"].key?("pre")
|
58
|
+
assert loaded_config["deploy"]["pre"].include?('exit 1')
|
59
|
+
end
|
60
|
+
|
61
|
+
def deploy_spec_yaml
|
62
|
+
<<~EOYAML
|
63
|
+
deploy:
|
64
|
+
pre:
|
65
|
+
- test 2
|
66
|
+
override:
|
67
|
+
- test 1
|
68
|
+
EOYAML
|
69
|
+
end
|
70
|
+
|
71
|
+
def deploy_spec_missing_deploy_yaml
|
72
|
+
<<~EOYAML
|
73
|
+
production_platform:
|
74
|
+
application: test-application
|
75
|
+
runtime_ids:
|
76
|
+
- production-unrestricted-1234
|
77
|
+
EOYAML
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/test/models/tasks_test.rb
CHANGED
@@ -93,7 +93,7 @@ module Shipit
|
|
93
93
|
task = shipit_tasks(:shipit)
|
94
94
|
task.update(
|
95
95
|
rolled_up: false,
|
96
|
-
created_at: (60 + 1).minutes.ago.
|
96
|
+
created_at: (60 + 1).minutes.ago.to_formatted_s(:db),
|
97
97
|
status: "success",
|
98
98
|
)
|
99
99
|
|
@@ -104,11 +104,23 @@ module Shipit
|
|
104
104
|
task = shipit_tasks(:shipit)
|
105
105
|
task.update(
|
106
106
|
rolled_up: false,
|
107
|
-
created_at: (60 + 1).minutes.ago.
|
107
|
+
created_at: (60 + 1).minutes.ago.to_formatted_s(:db),
|
108
108
|
status: "error",
|
109
109
|
)
|
110
110
|
|
111
111
|
assert_includes Shipit::Task.due_for_rollup, task
|
112
112
|
end
|
113
|
+
|
114
|
+
test "load legacy YAML records" do
|
115
|
+
task = Shipit::Task.find(shipit_tasks(:shipit_legacy_yaml_task).id)
|
116
|
+
assert_equal({ "POD_ID" => "12" }, task.env)
|
117
|
+
assert_equal Hash, task.env.class
|
118
|
+
|
119
|
+
task.save
|
120
|
+
task.reload
|
121
|
+
|
122
|
+
assert_equal({ "POD_ID" => "12" }, task.env)
|
123
|
+
assert_equal Hash, task.env.class
|
124
|
+
end
|
113
125
|
end
|
114
126
|
end
|
data/test/models/team_test.rb
CHANGED
@@ -29,6 +29,25 @@ module Shipit
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
+
test ".find_or_create_by_handle accepts large slugs" do
|
33
|
+
limit = Shipit::Team.columns_hash['slug'].limit
|
34
|
+
skip unless limit
|
35
|
+
|
36
|
+
slug = 'a' * 255
|
37
|
+
team = new_team(slug: slug)
|
38
|
+
|
39
|
+
response = stub(rels: {}, data: [team])
|
40
|
+
Shipit.github.api.expects(:org_teams).with('shopify', per_page: 100).returns(response.data)
|
41
|
+
Shipit.github.api.expects(:last_response).returns(response)
|
42
|
+
|
43
|
+
assert_difference -> { Team.count }, 1 do
|
44
|
+
Team.find_or_create_by_handle("Shopify/#{slug}")
|
45
|
+
end
|
46
|
+
|
47
|
+
team_record = Team.find_by(name: team.name)
|
48
|
+
assert_equal limit, team_record.slug.bytesize
|
49
|
+
end
|
50
|
+
|
32
51
|
private
|
33
52
|
|
34
53
|
def members_resource
|
@@ -46,11 +65,11 @@ module Shipit
|
|
46
65
|
)
|
47
66
|
end
|
48
67
|
|
49
|
-
def new_team
|
68
|
+
def new_team(slug: 'new-team')
|
50
69
|
stub(
|
51
70
|
id: 24,
|
52
71
|
name: 'New Team',
|
53
|
-
slug:
|
72
|
+
slug: slug,
|
54
73
|
url: 'https://example.com',
|
55
74
|
description: 'The Best one',
|
56
75
|
organization: 'shopify',
|
data/test/models/users_test.rb
CHANGED
@@ -216,19 +216,24 @@ module Shipit
|
|
216
216
|
end
|
217
217
|
|
218
218
|
test "users with legacy encrypted access token get their token reset automatically" do
|
219
|
-
# See: https://github.com/attr-encrypted/attr_encrypted/blob/53266da546a21afaa1f1b93a461b912f4ccf363b/README.md#upgrading-from-attr_encrypted-v2x-to-v3x
|
220
219
|
legacy = shipit_users(:legacy)
|
221
|
-
assert_not_nil legacy.encrypted_github_access_token
|
222
|
-
assert_not_nil legacy.encrypted_github_access_token_iv
|
223
|
-
|
224
220
|
assert_nil legacy.github_access_token
|
225
|
-
legacy.reload
|
226
|
-
assert_nil legacy.encrypted_github_access_token
|
227
|
-
assert_nil legacy.encrypted_github_access_token_iv
|
228
221
|
|
229
|
-
legacy.update!(github_access_token: '
|
222
|
+
legacy.update!(github_access_token: 'ghu_t0k3n')
|
223
|
+
assert_equal 'ghu_t0k3n', legacy.github_access_token
|
224
|
+
end
|
225
|
+
|
226
|
+
test "users with legacy encrypted access token can be updated" do
|
227
|
+
legacy = shipit_users(:legacy)
|
228
|
+
legacy.update!(github_access_token: 'ghu_t0k3n')
|
230
229
|
legacy.reload
|
231
|
-
assert_equal '
|
230
|
+
assert_equal 'ghu_t0k3n', legacy.github_access_token
|
231
|
+
end
|
232
|
+
|
233
|
+
test "users with legacy encrypted access token can have unrelated attributes updated" do
|
234
|
+
legacy = shipit_users(:legacy)
|
235
|
+
legacy.update!(name: 'Test')
|
236
|
+
assert_equal 'Test', legacy.name
|
232
237
|
end
|
233
238
|
|
234
239
|
test "users are always logged_in?" do
|
@@ -274,6 +279,21 @@ module Shipit
|
|
274
279
|
assert_equal user, found_user
|
275
280
|
end
|
276
281
|
|
282
|
+
test "requires_fresh_login? defaults to false" do
|
283
|
+
u = User.new
|
284
|
+
refute_predicate u, :requires_fresh_login?
|
285
|
+
end
|
286
|
+
|
287
|
+
test "requires_fresh_login? is true for users with legacy github_access_token" do
|
288
|
+
@user.update!(github_access_token: 'some_legacy_value')
|
289
|
+
assert_predicate @user, :requires_fresh_login?
|
290
|
+
end
|
291
|
+
|
292
|
+
test "requires_fresh_login? is false for users with a new format github_access_token" do
|
293
|
+
@user.update!(github_access_token: 'ghu_tok3n')
|
294
|
+
refute_predicate @user, :requires_fresh_login?
|
295
|
+
end
|
296
|
+
|
277
297
|
private
|
278
298
|
|
279
299
|
def fetch_user
|
@@ -27,7 +27,7 @@ module Shipit
|
|
27
27
|
|
28
28
|
command = @commands.fetch
|
29
29
|
|
30
|
-
assert_equal %w(git fetch origin --tags master), command.args
|
30
|
+
assert_equal %w(git fetch origin --quiet --tags master), command.args
|
31
31
|
end
|
32
32
|
|
33
33
|
test "#fetch calls git fetch in git_path directory if repository cache already exist" do
|
@@ -134,7 +134,11 @@ module Shipit
|
|
134
134
|
|
135
135
|
test "#checkout checks out the deployed commit" do
|
136
136
|
command = @commands.checkout(@deploy.until_commit)
|
137
|
-
|
137
|
+
checkout_args = [
|
138
|
+
'git', '-c', 'advice.detachedHead=false', 'checkout', '--quiet',
|
139
|
+
@deploy.until_commit.sha,
|
140
|
+
]
|
141
|
+
assert_equal checkout_args, command.args
|
138
142
|
end
|
139
143
|
|
140
144
|
test "#checkout checks out the deployed commit from the working directory" do
|