shipit-engine 0.16.0 → 0.17.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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -0
  3. data/app/assets/images/caret-down.svg +1 -0
  4. data/app/assets/javascripts/shipit/stacks.js.coffee +10 -0
  5. data/app/assets/stylesheets/_base/_banner.scss +7 -3
  6. data/app/assets/stylesheets/_base/_base.scss +0 -74
  7. data/app/assets/stylesheets/_base/_buttons.scss +7 -3
  8. data/app/assets/stylesheets/_base/_colors.scss +2 -0
  9. data/app/assets/stylesheets/_base/_icons.scss +8 -0
  10. data/app/assets/stylesheets/_base/_spacing.scss +21 -0
  11. data/app/assets/stylesheets/_pages/_commits.scss +41 -3
  12. data/app/assets/stylesheets/_structure/_layout.scss +8 -35
  13. data/app/assets/stylesheets/_structure/_main.scss +2 -2
  14. data/app/assets/stylesheets/_structure/_navigation.scss +89 -0
  15. data/app/assets/stylesheets/shipit.scss +3 -0
  16. data/app/controllers/concerns/shipit/api/rendering.rb +3 -6
  17. data/app/controllers/shipit/api/ccmenu_controller.rb +4 -0
  18. data/app/controllers/shipit/commits_controller.rb +18 -0
  19. data/app/jobs/shipit/destroy_stack_job.rb +25 -0
  20. data/app/jobs/shipit/github_sync_job.rb +12 -1
  21. data/app/jobs/shipit/merge_pull_requests_job.rb +3 -0
  22. data/app/models/shipit/commit.rb +14 -2
  23. data/app/models/shipit/deploy.rb +5 -0
  24. data/app/models/shipit/deploy_spec.rb +9 -6
  25. data/app/models/shipit/deploy_spec/kubernetes_discovery.rb +24 -2
  26. data/app/models/shipit/pull_request.rb +16 -1
  27. data/app/models/shipit/stack.rb +11 -4
  28. data/app/models/shipit/task_definition.rb +4 -0
  29. data/app/models/shipit/team.rb +1 -1
  30. data/app/models/shipit/undeployed_commit.rb +1 -2
  31. data/app/models/shipit/user.rb +1 -1
  32. data/app/models/shipit/variable_definition.rb +5 -0
  33. data/app/serializers/shipit/stack_serializer.rb +1 -1
  34. data/app/views/layouts/shipit.html.erb +2 -1
  35. data/app/views/shipit/commits/_commit.html.erb +9 -1
  36. data/app/views/shipit/deploys/rollback.html.erb +1 -1
  37. data/app/views/shipit/stacks/_header.html.erb +15 -3
  38. data/app/views/shipit/stacks/settings.html.erb +1 -1
  39. data/config/locales/en.yml +9 -5
  40. data/config/routes.rb +1 -0
  41. data/db/migrate/20170310164315_add_merged_at_on_pull_requests.rb +9 -0
  42. data/db/migrate/20170314145604_add_last_deployed_at_to_stack.rb +9 -0
  43. data/db/migrate/20170320124156_add_locked_to_commits.rb +5 -0
  44. data/lib/shipit/task_commands.rb +1 -0
  45. data/lib/shipit/version.rb +1 -1
  46. data/test/controllers/api/ccmenu_controller_test.rb +6 -0
  47. data/test/controllers/api/stacks_controller_test.rb +6 -0
  48. data/test/controllers/api/tasks_controller_test.rb +31 -0
  49. data/test/controllers/commits_controller_test.rb +18 -0
  50. data/test/dummy/db/development.sqlite3 +0 -0
  51. data/test/dummy/db/schema.rb +4 -1
  52. data/test/dummy/db/test.sqlite3 +0 -0
  53. data/test/dummy/db/test.sqlite3-journal +0 -0
  54. data/test/fixtures/shipit/commits.yml +1 -1
  55. data/test/fixtures/shipit/pull_requests.yml +33 -0
  56. data/test/fixtures/shipit/stacks.yml +4 -1
  57. data/test/jobs/github_sync_job_test.rb +49 -0
  58. data/test/jobs/merge_pull_requests_job_test.rb +18 -0
  59. data/test/models/commits_test.rb +71 -0
  60. data/test/models/deploy_spec_test.rb +15 -0
  61. data/test/models/deploys_test.rb +7 -0
  62. data/test/models/pull_request_test.rb +19 -1
  63. data/test/models/task_definitions_test.rb +9 -0
  64. data/test/models/undeployed_commits_test.rb +2 -7
  65. data/test/unit/deploy_commands_test.rb +7 -0
  66. data/test/unit/variable_definition_test.rb +10 -0
  67. metadata +15 -7
  68. data/app/assets/images/github.svg +0 -9
  69. data/app/assets/images/refresh.svg +0 -8
  70. data/app/assets/images/settings.svg +0 -33
  71. data/lib/snippets/deploy-to-gke +0 -161
@@ -6,6 +6,7 @@ module Shipit
6
6
  @stack = shipit_stacks(:shipit)
7
7
  @pr = @stack.commits.new
8
8
  @pr.message = "Merge pull request #31 from Shopify/improve-polling\n\nSeveral improvements to polling"
9
+ @stack.reload
9
10
  @commit = shipit_commits(:first)
10
11
  end
11
12
 
@@ -209,6 +210,21 @@ module Shipit
209
210
  end
210
211
  end
211
212
 
213
+ test "#creating a commit for new stack updates last_deployed_at to nil" do
214
+ walrus = shipit_users(:walrus)
215
+ stack = shipit_stacks(:undeployed_stack)
216
+ stack.commits.create!(
217
+ author: walrus,
218
+ committer: walrus,
219
+ sha: "ab12",
220
+ authored_at: DateTime.now,
221
+ committed_at: DateTime.now,
222
+ message: "more fish!",
223
+ )
224
+ stack.reload
225
+ assert_nil stack.last_deployed_at
226
+ end
227
+
212
228
  test ".by_sha! raises if the sha prefix matches multiple commits" do
213
229
  clone = Commit.new(@commit.attributes.except('id'))
214
230
  clone.sha[8..-1] = 'abc12'
@@ -278,6 +294,12 @@ module Shipit
278
294
  refute_predicate shipit_commits(:fifth), :deployable?
279
295
  end
280
296
 
297
+ test "#deployable? is false if commit is locked" do
298
+ commit = shipit_commits(:cyclimse_first)
299
+ commit.update!(locked: true)
300
+ refute_predicate commit, :deployable?
301
+ end
302
+
281
303
  test "#deployable? is false if a required status is missing" do
282
304
  commit = shipit_commits(:cyclimse_first)
283
305
  commit.stack.stubs(:required_statuses).returns(%w(ci/very-important))
@@ -480,6 +502,55 @@ module Shipit
480
502
  assert_nil commit.pull_request
481
503
  end
482
504
 
505
+ test "#revert? returns false if the message doesn't follow the revert convention" do
506
+ commit = Commit.new(message: "Revert stuff")
507
+ refute_predicate commit, :revert?
508
+ end
509
+
510
+ test "#revert? returns true for commits reverted by GitHub" do
511
+ commit = Commit.new(
512
+ message: "Merge pull request #17 from Shopify/revert-16\n\nRevert \"Create README.md\"",
513
+ )
514
+ assert_predicate commit, :revert?
515
+ end
516
+
517
+ test "#revert? returns true for commits reverted from CLI" do
518
+ commit = Commit.new(
519
+ message: "Revert \"Super Feature\"\n\nThis reverts commit 49430d5091abc34f2c576c23ebf369ec7094d8aa.",
520
+ )
521
+ assert_predicate commit, :revert?
522
+ end
523
+
524
+ test "#revert_of? works with pull requests reverted on GitHub" do
525
+ commit = Commit.new(
526
+ message: "Merge pull request #16 from byroot/casperisfine-patch-1\n\nCreate README.md",
527
+ )
528
+ revert = Commit.new(
529
+ message: "Merge pull request #17 from Shopify/revert-16\n\nRevert \"Create README.md\"",
530
+ )
531
+ assert revert.revert_of?(commit)
532
+ end
533
+
534
+ test "#revert_of? works with commits reverted from CLI" do
535
+ commit = Commit.new(
536
+ message: "Create README.md",
537
+ )
538
+ revert = Commit.new(
539
+ message: "Revert \"Create README.md\"\n\nThis reverts commit 49430d5091abc34f2c576c23ebf369ec7094d8aa.",
540
+ )
541
+ assert revert.revert_of?(commit)
542
+ end
543
+
544
+ test "#revert_of? works with pull requests reverted from CLI" do
545
+ commit = Commit.new(
546
+ message: "Merge pull request #19 from byroot/casperisfine-patch-1\n\nUpdate README.md",
547
+ )
548
+ revert = Commit.new(
549
+ message: "Revert \"Merge pull request #19 from byroot/casperisfine-patch-1\"\n\nThis reverts commit fa3722ef8372b47160f5d96010d3c54743d192f9, reversing\nchanges made to 868b6f65f759d003c04d056f2f928f18d6813c7e.",
550
+ )
551
+ assert revert.revert_of?(commit)
552
+ end
553
+
483
554
  private
484
555
 
485
556
  def expect_event(stack)
@@ -346,6 +346,21 @@ module Shipit
346
346
  assert_equal ['bundle exec foo'], definition.steps
347
347
  end
348
348
 
349
+ test "#task_definitions returns kubernetes commands as well as comands from the config" do
350
+ @spec.stubs(:load_config).returns(
351
+ 'tasks' => {'another_task' => {'steps' => %w(foo)}},
352
+ 'kubernetes' => {
353
+ 'namespace' => 'foo',
354
+ 'context' => 'bar',
355
+ },
356
+ )
357
+ tasks = @spec.task_definitions
358
+ assert_equal 2, tasks.size
359
+
360
+ restart_task = tasks.find { |t| t.id == "restart" }
361
+ assert_equal ["kubernetes-restart foo bar"], restart_task.steps
362
+ end
363
+
349
364
  test "task definitions returns an array of VariableDefinition instances" do
350
365
  @spec.expects(:load_config).returns('tasks' =>
351
366
  {'restart' =>
@@ -225,6 +225,13 @@ module Shipit
225
225
  end
226
226
  end
227
227
 
228
+ test "transitions to any state updates last deploy time to stack record" do
229
+ @deploy = shipit_deploys(:shipit_running)
230
+ @deploy.complete!
231
+ @stack.reload
232
+ assert_in_delta @deploy.ended_at, @stack.last_deployed_at, 1
233
+ end
234
+
228
235
  test "transitioning to success schedule a MergePullRequests job" do
229
236
  @deploy = shipit_deploys(:shipit_running)
230
237
  assert_enqueued_with(job: MergePullRequestsJob, args: [@deploy.stack]) do
@@ -18,7 +18,7 @@ module Shipit
18
18
 
19
19
  test ".request_merge! only track pull requests once" do
20
20
  assert_difference -> { PullRequest.count }, +1 do
21
- 5.times { PullRequest.request_merge!(@stack, 65, @user) }
21
+ 5.times { PullRequest.request_merge!(@stack, 999, @user) }
22
22
  end
23
23
  end
24
24
 
@@ -77,6 +77,7 @@ module Shipit
77
77
  mergeable: true,
78
78
  additions: 24,
79
79
  deletions: 5,
80
+ merged_at: nil,
80
81
  head: stub(
81
82
  ref: 'super-branch',
82
83
  sha: head_sha,
@@ -193,5 +194,22 @@ module Shipit
193
194
  assert_json 'pull_request.rejection_reason', 'merge_conflict', document: params['payload']
194
195
  assert_json 'pull_request.number', @pr.number, document: params['payload']
195
196
  end
197
+
198
+ test "#merge! doesnt delete the branch if there are open PRs against it" do
199
+ Shipit.github_api.expects(:merge_pull_request).once.returns(true)
200
+ Shipit.github_api.expects(:pull_requests).once.with(@stack.github_repo_name, base: @pr.branch).returns([1])
201
+ Shipit.github_api.expects(:delete_branch).never.returns(false)
202
+ assert_equal true, @pr.merge!
203
+ end
204
+
205
+ test "#merge! increments undeployed_commits_count" do
206
+ Shipit.github_api.expects(:merge_pull_request).once.returns(true)
207
+ Shipit.github_api.expects(:pull_requests).once.returns([])
208
+ Shipit.github_api.expects(:delete_branch).once.returns(true)
209
+ assert_difference '@stack.undeployed_commits_count' do
210
+ @pr.merge!
211
+ @stack.reload
212
+ end
213
+ end
196
214
  end
197
215
  end
@@ -12,6 +12,8 @@ module Shipit
12
12
  'variables' => [
13
13
  {'name' => 'FOO', 'title' => 'Set to 0 to foo', 'default' => '1'},
14
14
  {'name' => 'BAR', 'title' => 'Set to 1 to bar', 'default' => '0'},
15
+ {'name' => 'WALRUS', 'title' => 'Use with caution', 'default' => ' '},
16
+ {'name' => 'NODEFAULT', 'title' => 'Variable without default'},
15
17
  ],
16
18
  )
17
19
  end
@@ -25,6 +27,11 @@ module Shipit
25
27
  assert_nil TaskDefinition.dump(nil)
26
28
  end
27
29
 
30
+ test "#variables" do
31
+ assert_equal 4, @definition.variables.size
32
+ assert_equal 3, @definition.variables_with_defaults.size
33
+ end
34
+
28
35
  test "serialization works" do
29
36
  as_json = {
30
37
  id: 'restart',
@@ -36,6 +43,8 @@ module Shipit
36
43
  variables: [
37
44
  {'name' => 'FOO', 'title' => 'Set to 0 to foo', 'default' => '1', 'select' => nil},
38
45
  {'name' => 'BAR', 'title' => 'Set to 1 to bar', 'default' => '0', 'select' => nil},
46
+ {'name' => 'WALRUS', 'title' => 'Use with caution', 'default' => ' ', 'select' => nil},
47
+ {'name' => 'NODEFAULT', 'title' => 'Variable without default', 'default' => '', 'select' => nil},
39
48
  ],
40
49
  }
41
50
  assert_equal as_json, TaskDefinition.load(TaskDefinition.dump(@definition)).as_json
@@ -43,8 +43,8 @@ module Shipit
43
43
  assert_equal 'allowed', @commit.deploy_state
44
44
  end
45
45
 
46
- test "#deploy_state returns `locked` if the stack is locked" do
47
- @stack.update!(lock_reason: "Let's eat some chips!")
46
+ test "#deploy_state returns `locked` if the commit is locked" do
47
+ @commit.update!(locked: true)
48
48
  assert_equal 'locked', @commit.deploy_state
49
49
  end
50
50
 
@@ -72,11 +72,6 @@ module Shipit
72
72
  assert_equal 'allowed', @commit.redeploy_state
73
73
  end
74
74
 
75
- test "#redeploy_state returns `locked` if the stack is locked" do
76
- @stack.update!(lock_reason: "Let's eat some chips!")
77
- assert_equal 'locked', @commit.redeploy_state
78
- end
79
-
80
75
  test "#redeploy_state returns `allowed` if the stack is locked but the safeties are ignored" do
81
76
  @stack.update!(lock_reason: "Let's eat some chips!")
82
77
  assert_equal 'allowed', @commit.redeploy_state(true)
@@ -134,6 +134,13 @@ module Shipit
134
134
  assert_equal @deploy.stack.last_deployed_commit.sha, command.env['LAST_DEPLOYED_SHA']
135
135
  end
136
136
 
137
+ test "#perform calls cap $environment deploy with the TASK_ID in the environment" do
138
+ commands = @commands.perform
139
+ assert_equal 1, commands.length
140
+ command = commands.first
141
+ assert_equal @deploy.id.to_s, command.env['TASK_ID']
142
+ end
143
+
137
144
  test "#perform transliterates the user name" do
138
145
  @deploy.user = User.new(login: 'Sirupsen', name: "Simon Hørup Eskildsen")
139
146
  commands = @commands.perform
@@ -18,6 +18,7 @@ module Shipit
18
18
  assert_equal "Variable title", subject.title
19
19
  assert_equal "Variable default", subject.default
20
20
  assert_nil subject.select
21
+ assert subject.default_provided?
21
22
  end
22
23
 
23
24
  test "#initialize name is required" do
@@ -48,6 +49,15 @@ module Shipit
48
49
  assert_nil subject.select
49
50
  end
50
51
 
52
+ test "#default_provided?" do
53
+ attributes = {
54
+ "name" => "Variable name",
55
+ "title" => "Variable title",
56
+ }
57
+ subject = Shipit::VariableDefinition.new(attributes)
58
+ refute subject.default_provided?
59
+ end
60
+
51
61
  test "#to_h returns hash version" do
52
62
  assert_equal @attributes.merge("select" => nil), Shipit::VariableDefinition.new(@attributes).to_h
53
63
  end
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.16.0
4
+ version: 0.17.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-02-22 00:00:00.000000000 Z
11
+ date: 2017-05-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -499,6 +499,7 @@ files:
499
499
  - app/assets/images/aborted.svg
500
500
  - app/assets/images/aborting.svg
501
501
  - app/assets/images/anchor.svg
502
+ - app/assets/images/caret-down.svg
502
503
  - app/assets/images/default.svg
503
504
  - app/assets/images/deploy_error.jpg
504
505
  - app/assets/images/deploy_failed.jpg
@@ -511,15 +512,12 @@ files:
511
512
  - app/assets/images/failure.svg
512
513
  - app/assets/images/favicon.ico
513
514
  - app/assets/images/flapping.svg
514
- - app/assets/images/github.svg
515
515
  - app/assets/images/lock.svg
516
516
  - app/assets/images/logo.svg
517
517
  - app/assets/images/pending-small.svg
518
518
  - app/assets/images/pending.gif
519
- - app/assets/images/refresh.svg
520
519
  - app/assets/images/search-active.svg
521
520
  - app/assets/images/search.svg
522
- - app/assets/images/settings.svg
523
521
  - app/assets/images/ship.png
524
522
  - app/assets/images/success-small.svg
525
523
  - app/assets/images/success.svg
@@ -548,7 +546,9 @@ files:
548
546
  - app/assets/stylesheets/_base/_buttons.scss
549
547
  - app/assets/stylesheets/_base/_colors.scss
550
548
  - app/assets/stylesheets/_base/_forms.scss
549
+ - app/assets/stylesheets/_base/_icons.scss
551
550
  - app/assets/stylesheets/_base/_media-queries.scss
551
+ - app/assets/stylesheets/_base/_spacing.scss
552
552
  - app/assets/stylesheets/_base/_status-items.scss
553
553
  - app/assets/stylesheets/_base/_utility.scss
554
554
  - app/assets/stylesheets/_pages/_commits.scss
@@ -557,6 +557,7 @@ files:
557
557
  - app/assets/stylesheets/_pages/_stacks.scss
558
558
  - app/assets/stylesheets/_structure/_layout.scss
559
559
  - app/assets/stylesheets/_structure/_main.scss
560
+ - app/assets/stylesheets/_structure/_navigation.scss
560
561
  - app/assets/stylesheets/shipit.scss
561
562
  - app/assets/stylesheets/shipit_bs.scss
562
563
  - app/assets/webfonts/CheckoutSymbols-Regular.eot
@@ -580,6 +581,7 @@ files:
580
581
  - app/controllers/shipit/api/tasks_controller.rb
581
582
  - app/controllers/shipit/ccmenu_url_controller.rb
582
583
  - app/controllers/shipit/commit_checks_controller.rb
584
+ - app/controllers/shipit/commits_controller.rb
583
585
  - app/controllers/shipit/deploys_controller.rb
584
586
  - app/controllers/shipit/github_authentication_controller.rb
585
587
  - app/controllers/shipit/pull_requests_controller.rb
@@ -750,6 +752,9 @@ files:
750
752
  - db/migrate/20170220152410_improve_users_indexing.rb
751
753
  - db/migrate/20170221102128_improve_tasks_indexing.rb
752
754
  - db/migrate/20170221130336_add_last_revalidated_at_on_pull_requests.rb
755
+ - db/migrate/20170310164315_add_merged_at_on_pull_requests.rb
756
+ - db/migrate/20170314145604_add_last_deployed_at_to_stack.rb
757
+ - db/migrate/20170320124156_add_locked_to_commits.rb
753
758
  - lib/shipit-engine.rb
754
759
  - lib/shipit.rb
755
760
  - lib/shipit/command.rb
@@ -773,7 +778,6 @@ files:
773
778
  - lib/snippets/assert-egg-version-tag
774
779
  - lib/snippets/assert-gem-version-tag
775
780
  - lib/snippets/assert-npm-version-tag
776
- - lib/snippets/deploy-to-gke
777
781
  - lib/snippets/extract-egg-version
778
782
  - lib/snippets/extract-gem-version
779
783
  - lib/snippets/fetch-gem-version
@@ -795,6 +799,7 @@ files:
795
799
  - test/controllers/api/tasks_controller_test.rb
796
800
  - test/controllers/ccmenu_controller_test.rb
797
801
  - test/controllers/commit_checks_controller_test.rb
802
+ - test/controllers/commits_controller_test.rb
798
803
  - test/controllers/deploys_controller_test.rb
799
804
  - test/controllers/github_authentication_controller_test.rb
800
805
  - test/controllers/pull_requests_controller_test.rb
@@ -855,6 +860,7 @@ files:
855
860
  - test/dummy/db/schema.rb
856
861
  - test/dummy/db/seeds.rb
857
862
  - test/dummy/db/test.sqlite3
863
+ - test/dummy/db/test.sqlite3-journal
858
864
  - test/dummy/public/404.html
859
865
  - test/dummy/public/422.html
860
866
  - test/dummy/public/500.html
@@ -957,7 +963,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
957
963
  version: '0'
958
964
  requirements: []
959
965
  rubyforge_project:
960
- rubygems_version: 2.6.6
966
+ rubygems_version: 2.4.5.1
961
967
  signing_key:
962
968
  specification_version: 4
963
969
  summary: Application deployment software
@@ -974,6 +980,7 @@ test_files:
974
980
  - test/controllers/api/tasks_controller_test.rb
975
981
  - test/controllers/ccmenu_controller_test.rb
976
982
  - test/controllers/commit_checks_controller_test.rb
983
+ - test/controllers/commits_controller_test.rb
977
984
  - test/controllers/deploys_controller_test.rb
978
985
  - test/controllers/github_authentication_controller_test.rb
979
986
  - test/controllers/pull_requests_controller_test.rb
@@ -1033,6 +1040,7 @@ test_files:
1033
1040
  - test/dummy/db/schema.rb
1034
1041
  - test/dummy/db/seeds.rb
1035
1042
  - test/dummy/db/test.sqlite3
1043
+ - test/dummy/db/test.sqlite3-journal
1036
1044
  - test/dummy/public/404.html
1037
1045
  - test/dummy/public/422.html
1038
1046
  - test/dummy/public/500.html
@@ -1,9 +0,0 @@
1
- <?xml version="1.0" encoding="utf-8"?>
2
- <!-- Generator: Adobe Illustrator 17.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3
- <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
- <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="18px"
5
- height="18px" viewBox="0 0 42 42" enable-background="new 0 0 18 18" xml:space="preserve">
6
- <g transform="matrix(1,0,0,-1,20,5)">
7
- <path d="m 0,0 c -8.995,0 -16.288,-7.293 -16.288,-16.29 0,-7.197 4.667,-13.302 11.14,-15.457 0.815,-0.149 1.112,0.354 1.112,0.786 0,0.386 -0.014,1.411 -0.022,2.77 -4.531,-0.984 -5.487,2.184 -5.487,2.184 -0.741,1.882 -1.809,2.383 -1.809,2.383 -1.479,1.01 0.112,0.99 0.112,0.99 1.635,-0.115 2.495,-1.679 2.495,-1.679 1.453,-2.489 3.813,-1.77 4.741,-1.353 0.148,1.052 0.568,1.77 1.034,2.177 -3.617,0.411 -7.42,1.809 -7.42,8.051 0,1.778 0.635,3.232 1.677,4.371 -0.168,0.412 -0.727,2.068 0.159,4.311 0,0 1.368,0.438 4.48,-1.67 1.299,0.362 2.693,0.542 4.078,0.548 1.383,-0.006 2.777,-0.186 4.078,-0.548 3.11,2.108 4.475,1.67 4.475,1.67 0.889,-2.243 0.33,-3.899 0.162,-4.311 1.044,-1.139 1.675,-2.593 1.675,-4.371 0,-6.258 -3.809,-7.635 -7.438,-8.038 0.585,-0.503 1.106,-1.497 1.106,-3.017 0,-2.177 -0.02,-3.934 -0.02,-4.468 0,-0.436 0.293,-0.943 1.12,-0.784 6.468,2.159 11.131,8.26 11.131,15.455 C 16.291,-7.293 8.997,0 0,0" style="fill:#FFF;fill-opacity:1;fill-rule:evenodd;stroke:none"/>
8
- </g>
9
- </svg>
@@ -1,8 +0,0 @@
1
- <?xml version="1.0" encoding="utf-8"?>
2
- <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
3
- <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="tiny" x="0px" y="0px" width="480px" height="480px" viewBox="0 0 480 480" xml:space="preserve">
4
- <g id="refresh" fill="#FFF">
5
- <path d="M383.434,172.502c-25.336-58.241-81.998-95.648-145.861-95.648c-65.309,0-125,40.928-148.514,101.827l49.5,19.117 c15.672-40.617,55.469-67.894,99.014-67.894c42.02,0,79.197,24.386,96.408,62.332l-36.117,14.428l92.352,53.279l27.01-100.933 L383.434,172.502z"/>
6
- <path d="M237.573,342.101c-41.639,0-79.615-25.115-96.592-62.819l35.604-13.763l-91.387-52.119l-27.975,98.249l34.08-13.172 c24.852,58.018,82.859,96.671,146.27,96.671c65.551,0,123.598-39.336,147.871-100.196l-49.268-19.652 C319.981,315.877,281.288,342.101,237.573,342.101z"/>
7
- </g>
8
- </svg>
@@ -1,33 +0,0 @@
1
- <?xml version="1.0" encoding="utf-8"?>
2
- <!-- Generator: Adobe Illustrator 17.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3
- <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
- <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="18px"
5
- height="18px" viewBox="0 0 18 18" enable-background="new 0 0 18 18" xml:space="preserve">
6
- <g id="Layer_1">
7
- <g>
8
- <path fill="#FFFFFF" d="M15.667,10.042l1.729,1.5c0.139,0.098,0.174,0.229,0.104,0.396c-0.348,1.07-0.917,2.056-1.708,2.959
9
- c-0.111,0.139-0.243,0.174-0.396,0.104l-2.166-0.75c-0.556,0.445-1.153,0.792-1.792,1.042L11,17.542
10
- c-0.028,0.167-0.125,0.264-0.292,0.292C10.111,17.945,9.542,18,9,18s-1.111-0.055-1.708-0.166C7.125,17.806,7.027,17.709,7,17.542
11
- l-0.438-2.25c-0.681-0.264-1.278-0.611-1.792-1.042L2.604,15c-0.153,0.07-0.285,0.035-0.396-0.104
12
- c-0.792-0.903-1.361-1.889-1.708-2.959c-0.07-0.166-0.035-0.298,0.104-0.396l1.729-1.5C2.278,9.75,2.25,9.403,2.25,9
13
- s0.028-0.75,0.083-1.042l-1.729-1.5C0.465,6.362,0.43,6.229,0.5,6.063c0.347-1.069,0.917-2.055,1.708-2.958
14
- C2.319,2.966,2.451,2.931,2.604,3l2.167,0.75c0.514-0.43,1.111-0.778,1.792-1.042L7,0.459c0.027-0.167,0.125-0.264,0.292-0.292
15
- c1.139-0.236,2.277-0.236,3.416,0C10.875,0.195,10.972,0.292,11,0.459l0.438,2.25c0.639,0.25,1.236,0.597,1.792,1.042L15.396,3
16
- c0.153-0.069,0.285-0.035,0.396,0.104c0.791,0.903,1.36,1.889,1.708,2.958c0.069,0.167,0.034,0.299-0.104,0.396l-1.729,1.5
17
- C15.722,8.25,15.75,8.598,15.75,9S15.722,9.75,15.667,10.042z M9,12.375c0.931,0,1.726-0.329,2.386-0.989
18
- c0.659-0.659,0.989-1.455,0.989-2.385c0-0.93-0.33-1.726-0.989-2.385c-0.66-0.66-1.455-0.99-2.386-0.99s-1.726,0.33-2.385,0.99
19
- C5.955,7.275,5.625,8.07,5.625,9c0,0.945,0.326,1.743,0.979,2.396C7.257,12.049,8.056,12.375,9,12.375z"/>
20
- </g>
21
- </g>
22
- <g id="Layer_1_copy" display="none">
23
- <g display="inline">
24
- <path fill="#FFFFFF" d="M13.872,2.629h-1.479c0.229,0.521,0.354,1.125,0.354,1.791c0,2.479-1.771,4.124-3.958,4.208
25
- c-0.646,1.021-0.479,1.624,0.459,2.249c2.582,0.104,4.624,1.604,4.624,3.562c0,2.083-2.188,3.562-4.874,3.562
26
- c-2.687,0-4.874-1.499-4.874-3.562c0-1.333,0.917-2.437,2.312-3.041c-1.312-1.291-0.854-2.582,0.062-3.332
27
- c-1.208-0.688-2-1.979-2-3.645c0-2.541,1.854-4.228,4.124-4.228c0.833,0,1.604,0.229,2.249,0.625c2.229-0.146,3-0.812,3-0.812
28
- V2.629z M6.749,14.438c0,0.729,0.875,1.312,2.25,1.312c1.374,0,2.249-0.583,2.249-1.312c0-0.729-0.875-1.312-2.249-1.312
29
- C7.623,13.126,6.749,13.71,6.749,14.438z M10.122,4.316c0-1.312-0.666-2.062-1.499-2.062s-1.5,0.75-1.5,2.062
30
- s0.667,2.062,1.5,2.062S10.122,5.628,10.122,4.316z"/>
31
- </g>
32
- </g>
33
- </svg>
@@ -1,161 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- # Usage: deploy-to-gke <app's namespace> <gcloud deployment> <gcloud project>
4
-
5
- # Requires the following to be available on Shipit machine:
6
- # - gcloud binary available on the shipit machine's path
7
- # - kubectl binary available in the shipit machine's path
8
- # - $GCLOUD_CREDENTIALS_DIR/my-gcloud-project-name.json must exist
9
-
10
- # Optionally, the following variables can be used to override script defaults:
11
- # - K8S_TEMPLATE_FOLDER: location of Kubernetes files to deploy. Default is config/deploy/#{environment}.
12
-
13
- require 'open3'
14
- require 'securerandom'
15
- require 'erb'
16
- require 'json'
17
- require 'yaml'
18
- require 'shellwords'
19
- require 'tempfile'
20
-
21
- class GKEDeployment
22
- class FatalDeploymentError < StandardError; end
23
-
24
- def initialize(namespace:, gcloud_deployment:, gcloud_project:, environment:, current_sha:, key_file:, template_folder: nil)
25
- @namespace = namespace
26
- @gcloud_deployment = gcloud_deployment
27
- @gcloud_project = gcloud_project
28
- @current_sha = current_sha
29
- @key_file = key_file
30
- @template_path = './' + (template_folder || "config/deploy/#{environment}")
31
-
32
- # Validate params + check existance of auth key and template(s)
33
- enforce_required_params
34
- preliminary_check
35
-
36
- # Max length of podname is only 63chars so try to save some room by truncating sha to 8 chars
37
- @id = current_sha[0...8] + "-#{SecureRandom.hex(4)}"
38
- end
39
-
40
- def run
41
- authorize_gcloud
42
- fetch_clusters.each do |cluster|
43
- set_kubectl_cluster(cluster)
44
- apply_all_templates
45
- end
46
- rescue FatalDeploymentError => error
47
- print_error(error.message)
48
- exit 1
49
- end
50
-
51
- def template_variables
52
- {
53
- 'current_sha' => @current_sha,
54
- 'deployment_id' => @id,
55
- }
56
- end
57
-
58
- private
59
-
60
- def enforce_required_params
61
- [@namespace, @gcloud_project, @gcloud_deployment, @current_sha, @key_file].each do |required_param|
62
- raise ArgumentError, "#{required_param} is required" unless required_param && !required_param.empty?
63
- end
64
- end
65
-
66
- def preliminary_check
67
- raise FatalDeploymentError, "Project config missing at #{@key_file}" unless File.file?(@key_file)
68
- raise FatalDeploymentError, "#{@template_path} doesn't exist" unless File.directory?(@template_path)
69
- raise FatalDeploymentError, "#{@template_path} doesn't have files with postfix .yml or .yml.erb" unless Dir.entries(@template_path).select {|file| file =~ /\.yml(.erb)?$/}.size > 0
70
- end
71
-
72
- def apply_all_templates
73
- found = 0
74
- Dir.foreach(@template_path) do |file|
75
- file_path = "#{@template_path}/#{file}"
76
- if File.extname(file) == '.yml'
77
- found += 1
78
- apply_template(file_path)
79
- elsif File.extname(file) == '.erb'
80
- found += 1
81
- render_and_apply_template(file_path)
82
- end
83
- end
84
- raise FatalDeploymentError, "No templates found in #{@template_path}" if found.zero?
85
- end
86
-
87
- def render_and_apply_template(file_path)
88
- erb_template = ERB.new(File.read(file_path))
89
- erb_binding = binding
90
- template_variables.each do |var_name, value|
91
- erb_binding.local_variable_set(var_name, value)
92
- end
93
- content = erb_template.result(erb_binding)
94
-
95
- f = Tempfile.new(['kube_template', '.yml'])
96
- f.write(content)
97
- f.close
98
- apply_template(f.path, original_path: file_path)
99
- ensure
100
- f.unlink if f
101
- end
102
-
103
- def apply_template(path, original_path: nil)
104
- status = run_command('kubectl', 'apply', '-f', path, "--namespace=#{@namespace}")
105
- raise FatalDeploymentError, "Failed to apply template #{original_path || path}" unless status
106
- end
107
-
108
- def authorize_gcloud
109
- status = run_command('gcloud', '-q', 'auth', 'activate-service-account', '--key-file', @key_file)
110
- status = run_command('gcloud', '-q', 'config', 'set', 'project', @gcloud_project) if status
111
- raise FatalDeploymentError, "Failed to set gcloud project #{@gcloud_project}" unless status
112
- end
113
-
114
- def set_kubectl_cluster(cluster)
115
- cluster_name = cluster[0]
116
- cluster_zone = cluster[1]
117
- status = run_command('gcloud', '-q', 'container', 'clusters', 'get-credentials', cluster_name, '--zone', cluster_zone)
118
- raise FatalDeploymentError, "Failed to set cluster #{cluster_name}/#{cluster_zone}" unless status
119
- end
120
-
121
- def fetch_clusters
122
- result = query_deployments
123
- result['resources'].each_with_object([]) do |resource, data|
124
- next unless resource['type'] == 'container.v1.cluster'
125
- properties = YAML.load(resource['finalProperties'])
126
- data << [resource['name'], properties['zone']]
127
- end
128
- end
129
-
130
- def run_command(*args)
131
- puts Shellwords.join(args)
132
- out, err, st = Open3.capture3(*args)
133
- puts out
134
- print_error(err) unless st.success?
135
- st.success?
136
- end
137
-
138
- def print_error(msg)
139
- puts "\033[0;31m#{msg}\033[0m"
140
- end
141
-
142
- def query_deployments
143
- out, err, st = Open3.capture3('gcloud', '-q', 'deployment-manager', 'deployments', 'describe', @gcloud_deployment, '--format=json')
144
- unless st.success?
145
- print_error(err)
146
- raise FatalDeploymentError, "Failed to fetch cluster with deployment #{@gcloud_deployment}"
147
- end
148
- JSON.parse(out)
149
- end
150
- end
151
-
152
- deployment = GKEDeployment.new(
153
- namespace: ARGV[0],
154
- gcloud_deployment: ARGV[1],
155
- gcloud_project: ARGV[2],
156
- environment: ENV['ENVIRONMENT'],
157
- template_folder: ENV['K8S_TEMPLATE_FOLDER'],
158
- current_sha: ENV['REVISION'],
159
- key_file: ENV['GOOGLE_APPLICATION_CREDENTIALS']
160
- )
161
- deployment.run