shipit-engine 0.35.0 → 0.36.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +20 -7
  3. data/app/controllers/concerns/shipit/authentication.rb +5 -1
  4. data/app/controllers/shipit/api/base_controller.rb +13 -1
  5. data/app/controllers/shipit/api/rollbacks_controller.rb +1 -1
  6. data/app/controllers/shipit/api/stacks_controller.rb +8 -2
  7. data/app/controllers/shipit/api/tasks_controller.rb +19 -2
  8. data/app/controllers/shipit/rollbacks_controller.rb +5 -1
  9. data/app/helpers/shipit/stacks_helper.rb +11 -0
  10. data/app/models/concerns/shipit/deferred_touch.rb +3 -3
  11. data/app/models/shipit/anonymous_user.rb +4 -0
  12. data/app/models/shipit/api_client.rb +1 -1
  13. data/app/models/shipit/commit_checks.rb +3 -3
  14. data/app/models/shipit/delivery.rb +1 -1
  15. data/app/models/shipit/deploy.rb +1 -0
  16. data/app/models/shipit/deploy_spec/file_system.rb +32 -4
  17. data/app/models/shipit/pull_request.rb +1 -1
  18. data/app/models/shipit/stack.rb +10 -10
  19. data/app/models/shipit/task.rb +31 -4
  20. data/app/models/shipit/user.rb +23 -9
  21. data/app/serializers/shipit/stack_serializer.rb +1 -1
  22. data/app/views/shipit/deploys/_deploy.html.erb +1 -5
  23. data/app/views/shipit/stacks/_banners.html.erb +1 -1
  24. data/app/views/shipit/stacks/_settings_form.erb +55 -0
  25. data/app/views/shipit/stacks/settings.html.erb +1 -55
  26. data/app/views/shipit/stacks/show.html.erb +1 -1
  27. data/config/locales/en.yml +1 -1
  28. data/config/routes.rb +4 -0
  29. data/db/migrate/20211103154121_increase_github_team_slug_size.rb +5 -0
  30. data/lib/shipit/engine.rb +15 -5
  31. data/lib/shipit/stack_commands.rb +2 -2
  32. data/lib/shipit/task_commands.rb +1 -1
  33. data/lib/shipit/version.rb +1 -1
  34. data/lib/shipit.rb +55 -3
  35. data/lib/snippets/fetch-gem-version +1 -1
  36. data/test/controllers/api/hooks_controller_test.rb +1 -1
  37. data/test/controllers/api/rollback_controller_test.rb +1 -0
  38. data/test/controllers/api/stacks_controller_test.rb +25 -0
  39. data/test/controllers/api/tasks_controller_test.rb +56 -0
  40. data/test/controllers/stacks_controller_test.rb +11 -0
  41. data/test/dummy/config/application.rb +1 -2
  42. data/test/dummy/db/schema.rb +2 -2
  43. data/test/fixtures/shipit/check_runs.yml +3 -3
  44. data/test/fixtures/shipit/commits.yml +101 -101
  45. data/test/fixtures/shipit/deliveries.yml +1 -1
  46. data/test/fixtures/shipit/merge_requests.yml +19 -19
  47. data/test/fixtures/shipit/stacks.yml +28 -28
  48. data/test/fixtures/shipit/statuses.yml +16 -16
  49. data/test/fixtures/shipit/tasks.yml +77 -65
  50. data/test/fixtures/shipit/users.yml +2 -5
  51. data/test/models/commits_test.rb +6 -6
  52. data/test/models/deploy_spec_test.rb +0 -23
  53. data/test/models/deploys_test.rb +26 -0
  54. data/test/models/shipit/deploy_spec/file_system_test.rb +81 -0
  55. data/test/models/tasks_test.rb +14 -2
  56. data/test/models/team_test.rb +21 -2
  57. data/test/models/users_test.rb +29 -9
  58. data/test/unit/deploy_commands_test.rb +2 -2
  59. metadata +189 -171
@@ -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
@@ -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.to_s(:db),
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.to_s(:db),
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
@@ -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: 'new-team',
72
+ slug: slug,
54
73
  url: 'https://example.com',
55
74
  description: 'The Best one',
56
75
  organization: 'shopify',
@@ -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: 't0k3n')
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 't0k3n', legacy.github_access_token
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,7 @@ module Shipit
134
134
 
135
135
  test "#checkout checks out the deployed commit" do
136
136
  command = @commands.checkout(@deploy.until_commit)
137
- assert_equal ['git', 'checkout', @deploy.until_commit.sha], command.args
137
+ assert_equal ['git', '-c', 'advice.detachedHead=false', 'checkout', @deploy.until_commit.sha], command.args
138
138
  end
139
139
 
140
140
  test "#checkout checks out the deployed commit from the working directory" do