satorix 0.0.1 → 1.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +4 -1
  3. data/.gitlab-ci.yml +45 -0
  4. data/.rspec +2 -1
  5. data/.rubocop.yml +11 -0
  6. data/.ruby-version +1 -0
  7. data/Gemfile +2 -0
  8. data/Gemfile.lock +25 -0
  9. data/Procfile +1 -0
  10. data/README.md +93 -1
  11. data/Rakefile +8 -4
  12. data/bin/console +3 -3
  13. data/bin/satorix +8 -0
  14. data/lib/satorix/CI/deploy/flynn/environment_variables.rb +123 -0
  15. data/lib/satorix/CI/deploy/flynn/resources.rb +79 -0
  16. data/lib/satorix/CI/deploy/flynn/routes.rb +267 -0
  17. data/lib/satorix/CI/deploy/flynn/scale.rb +52 -0
  18. data/lib/satorix/CI/deploy/flynn.rb +132 -0
  19. data/lib/satorix/CI/shared/buildpack_manager/buildpack.rb +159 -0
  20. data/lib/satorix/CI/shared/buildpack_manager.rb +220 -0
  21. data/lib/satorix/CI/shared/ruby/gem_manager.rb +80 -0
  22. data/lib/satorix/CI/shared/yarn_manager.rb +25 -0
  23. data/lib/satorix/CI/test/python/django_test.rb +38 -0
  24. data/lib/satorix/CI/test/python/safety.rb +30 -0
  25. data/lib/satorix/CI/test/ruby/brakeman.rb +35 -0
  26. data/lib/satorix/CI/test/ruby/bundler_audit.rb +35 -0
  27. data/lib/satorix/CI/test/ruby/cucumber.rb +29 -0
  28. data/lib/satorix/CI/test/ruby/rails_test.rb +29 -0
  29. data/lib/satorix/CI/test/ruby/rspec.rb +29 -0
  30. data/lib/satorix/CI/test/ruby/rubocop.rb +98 -0
  31. data/lib/satorix/CI/test/shared/database.rb +74 -0
  32. data/lib/satorix/shared/console.rb +157 -0
  33. data/lib/satorix/version.rb +1 -1
  34. data/lib/satorix.rb +343 -2
  35. data/satorix/CI/deploy/ie_gem_server.rb +80 -0
  36. data/satorix/CI/deploy/rubygems.rb +81 -0
  37. data/satorix/custom.rb +21 -0
  38. data/satorix.gemspec +13 -11
  39. metadata +57 -29
  40. data/.travis.yml +0 -5
@@ -0,0 +1,220 @@
1
+ module Satorix
2
+ module CI
3
+ module Shared
4
+
5
+
6
+ # This code was inspired by:
7
+ # herokuish - https://github.com/gliderlabs/herokuish
8
+ # flynn - https://github.com/flynn/flynn/blob/master/slugbuilder/builder/build.sh
9
+ module BuildpackManager
10
+
11
+
12
+ require 'fileutils'
13
+
14
+
15
+ include Satorix::Shared::Console
16
+
17
+
18
+ extend self
19
+
20
+
21
+ def go
22
+ abort_if_skip_buildpack
23
+ prepare_buildpack_environment
24
+ run_buildpacks
25
+ load_dot_release_file
26
+ switch_context_to_new_test_slug
27
+ end
28
+
29
+
30
+ def active_buildpack_list
31
+ custom_buildpack_list || stack_buildpack_list
32
+ end
33
+
34
+
35
+ def active_buildpacks
36
+ active_buildpack_list.split.map { |buildpack| Buildpack.new buildpack }
37
+ end
38
+
39
+
40
+ def cedar_14?
41
+ stack_version == 'cedar-14'
42
+ end
43
+
44
+
45
+ def copy_app_dir
46
+ FileUtils.cp_r File.join(Satorix.build_dir, '/.'), Satorix.app_dir, remove_destination: true
47
+ end
48
+
49
+
50
+ def custom_buildpack_list
51
+ IO.binread(files[:dot_buildpacks]).strip if custom_buildpacks?
52
+ end
53
+
54
+
55
+ def custom_buildpacks?
56
+ File.exist? files[:dot_buildpacks]
57
+ end
58
+
59
+
60
+ def default_buildpack_list
61
+ # When updating, pull from the most recent nightly release listed at https://releases.flynn.io/.
62
+ # Below was taken from https://github.com/flynn/flynn/blob/v20190814.0/slugbuilder/builder/buildpacks.txt
63
+ <<-THESE_ARE_THE_BUILDPACKS_OFFICIALLY_SUPPORTED_BY_FLYNN.strip
64
+ https://github.com/heroku/heroku-buildpack-multi.git#ed950773
65
+ https://github.com/cloudfoundry/staticfile-buildpack.git#e482e8f2
66
+ https://github.com/heroku/heroku-buildpack-ruby.git#4ca71a9d
67
+ https://github.com/heroku/heroku-buildpack-nodejs.git#a4fb9419
68
+ https://github.com/heroku/heroku-buildpack-clojure.git#5858bad3
69
+ https://github.com/heroku/heroku-buildpack-python.git#9dcabe24
70
+ https://github.com/heroku/heroku-buildpack-java.git#354d2a79
71
+ https://github.com/heroku/heroku-buildpack-gradle.git#b89c8c38
72
+ https://github.com/heroku/heroku-buildpack-scala.git#41c296d4
73
+ https://github.com/heroku/heroku-buildpack-php.git#62a691bf
74
+ https://github.com/heroku/heroku-buildpack-go.git#6f80fd9c
75
+ THESE_ARE_THE_BUILDPACKS_OFFICIALLY_SUPPORTED_BY_FLYNN
76
+ end
77
+
78
+
79
+ def default_cedar_14_buildpack_list
80
+ # When updating, pull from the most recent stable release listed at https://releases.flynn.io/.
81
+ # Below was taken from https://github.com/flynn/flynn/blob/v20170321.0/slugbuilder/builder/buildpacks.txt
82
+ <<-THESE_ARE_THE_BUILDPACKS_OFFICIALLY_SUPPORTED_BY_FLYNN.strip
83
+ https://github.com/heroku/heroku-buildpack-multi.git#ed950773
84
+ https://github.com/cloudfoundry/staticfile-buildpack.git#206728f9
85
+ https://github.com/heroku/heroku-buildpack-ruby.git#6988832f
86
+ https://github.com/heroku/heroku-buildpack-nodejs.git#9b8a98d8
87
+ https://github.com/heroku/heroku-buildpack-clojure.git#8768a8ff
88
+ https://github.com/heroku/heroku-buildpack-python.git#cafd4182
89
+ https://github.com/heroku/heroku-buildpack-java.git#8c34efe9
90
+ https://github.com/heroku/heroku-buildpack-gradle.git#13fa1fe7
91
+ https://github.com/heroku/heroku-buildpack-scala.git#dd0dd806
92
+ https://github.com/heroku/heroku-buildpack-play.git#cc5e6166
93
+ https://github.com/heroku/heroku-buildpack-php.git#e0499a7f
94
+ https://github.com/heroku/heroku-buildpack-go.git#bd1acfe5
95
+ THESE_ARE_THE_BUILDPACKS_OFFICIALLY_SUPPORTED_BY_FLYNN
96
+ end
97
+
98
+
99
+ def files
100
+ build_dir = Satorix.build_dir
101
+ { dot_buildpacks: File.join(build_dir, '.buildpacks'),
102
+ dot_env: File.join(build_dir, '.env'),
103
+ dot_release: File.join(build_dir, '.release') }
104
+ end
105
+
106
+
107
+ def load_dot_release_file
108
+ # TODO : Currently not required. Maybe should be implemented for maximum compatibility?
109
+ log_error_and_abort "Unhandled file '#{ files[:dot_release] }'." if File.exists? files[:dot_release]
110
+ end
111
+
112
+
113
+ def prepare_buildpack_environment
114
+ log_bench 'Preparing buildpack environment...' do
115
+ set_buildpack_expectations
116
+ process_dot_env_file
117
+ end
118
+ end
119
+
120
+
121
+ def process_dot_env_file
122
+ # TODO : Currently not required. Maybe should be implemented for maximum compatibility?
123
+ log_error_and_abort "Unhandled file '#{ files[:dot_env] }'" if File.exists? files[:dot_env]
124
+ end
125
+
126
+
127
+ def load_env
128
+ # TODO : Currently not required. Maybe should be implemented for maximum compatibility?
129
+ log_error_and_abort 'Unhandled load_env' unless (Dir.entries(Satorix.paths[:env]) - %w(. ..)).empty?
130
+ end
131
+
132
+
133
+ def load_profile
134
+ profile_locations.each do |profile_location|
135
+ Dir.glob(profile_location) do |shell_file|
136
+ # Uncomment below to debug profile loading
137
+ # run_command "cat #{ shell_file }"
138
+ source_env_from shell_file
139
+ end
140
+ end
141
+ end
142
+
143
+
144
+ def profile_locations
145
+ [File.join('/etc/profile.d', '*.sh'),
146
+ File.join(Satorix.app_dir, '.profile.d', '*.sh')]
147
+ end
148
+
149
+
150
+ def run_buildpacks
151
+ buildpacks = []
152
+
153
+ log_bench('Detecting application type...') do
154
+ active_buildpacks.each(&:ensure_correctness)
155
+ buildpacks = active_buildpacks.keep_if(&:detected?)
156
+
157
+ if buildpacks.empty?
158
+ log_error_and_abort 'Unable to select a buildpack!'
159
+ elsif buildpacks.length > 1 && !custom_buildpacks?
160
+ log_error("\n\nWarning: Multiple default buildpacks reported the ability to handle this app."\
161
+ " The first buildpack in the list above will be used.\n\n")
162
+ buildpacks = buildpacks.first(1)
163
+ end
164
+ end
165
+
166
+ buildpacks.each(&:compile)
167
+ end
168
+
169
+
170
+ def set_buildpack_expectations
171
+ ENV['APP_DIR'] = Satorix.app_dir
172
+ ENV['REQUEST_ID'] = "commit-#{ Satorix.ci_commit_sha }"
173
+ ENV['STACK'] = stack_version
174
+ ENV['DATABASE_URL'] = Satorix::CI::Test::Shared::Database.url
175
+
176
+ ENV['CURL_CONNECT_TIMEOUT'] = '30'
177
+ ENV['CURL_TIMEOUT'] = '600'
178
+ end
179
+
180
+
181
+ def abort_if_skip_buildpack
182
+ if ENV['SKIP_BUILDPACK']
183
+ log_error_and_abort("\n\nDEPRECATED: Skipping buildpack is no longer supported, please update your .gitlab-ci.yml.\n\n")
184
+ end
185
+ end
186
+
187
+
188
+ def stack_version
189
+ if File.exists?('/etc/lsb-release')
190
+ File.open('/etc/lsb-release', 'r').read.each_line do |line|
191
+ if line =~ /DISTRIB_RELEASE=14.04/
192
+ return 'cedar-14'
193
+ elsif line =~ /DISTRIB_RELEASE=18.04/
194
+ return 'heroku-18'
195
+ end
196
+ end
197
+ end
198
+ # Fallback to heroku-18 if we can't determine a stack
199
+ return 'heroku-18'
200
+ end
201
+
202
+
203
+ def stack_buildpack_list
204
+ cedar_14? ? default_cedar_14_buildpack_list : default_buildpack_list
205
+ end
206
+
207
+
208
+ def switch_context_to_new_test_slug
209
+ log_bench 'Switching context to the newly built application...' do
210
+ copy_app_dir
211
+ load_env
212
+ load_profile
213
+ end
214
+ end
215
+
216
+
217
+ end
218
+ end
219
+ end
220
+ end
@@ -0,0 +1,80 @@
1
+ module Satorix
2
+ module CI
3
+ module Shared
4
+ module Ruby
5
+ module GemManager
6
+
7
+ include Satorix::Shared::Console
8
+
9
+ extend self
10
+
11
+
12
+ def go(quiet = true)
13
+ if Satorix.ci_job_stage == 'deploy'
14
+ prepare_gem_for_deployment(quiet)
15
+ else
16
+ prepare_gem_environment_for_test(quiet)
17
+ end
18
+ end
19
+
20
+
21
+ def prepare_gem_for_deployment(quiet = true)
22
+ log_bench 'Preparing gem for deployment...' do
23
+ # Development dependencies should not be included in the Gemfile.lock
24
+ # otherwise they will become dependencies of the implementing application
25
+ remove_development_dependencies_from_gemspec(quiet)
26
+ regenerate_gemfile_lock(quiet)
27
+ end
28
+ end
29
+
30
+
31
+ def prepare_gem_environment_for_test(quiet = true)
32
+ log_bench 'Preparing gem environment...' do
33
+ restore_missing_gems(quiet)
34
+ end
35
+ end
36
+
37
+
38
+ def restore_missing_gems(quiet = true)
39
+ # The buildpack incorrectly removes gems that are included using add_development_dependency.
40
+ # These gems must remain available for testing.
41
+ run_command('bundle install --with development', quiet: quiet)
42
+ end
43
+
44
+
45
+ def remove_development_dependencies_from_gemspec(quiet = true)
46
+ Dir[File.join(Satorix.app_dir, '*.gemspec')].each do |file|
47
+ log File.read(file) unless quiet
48
+
49
+ backup_file_name = "#{ file }.satorix.old"
50
+ FileUtils.mv(file, backup_file_name)
51
+
52
+ File.open(file, 'w') do |modified_file|
53
+ File.foreach(backup_file_name) do |line|
54
+ modified_file.puts line unless line =~ /\.add_development_dependency/
55
+ end
56
+ end
57
+
58
+ File.delete(backup_file_name)
59
+
60
+ log File.read(file) unless quiet
61
+ end
62
+
63
+ end
64
+
65
+
66
+ def regenerate_gemfile_lock(quiet = true)
67
+ run_command('bundle config --local frozen false', quiet: quiet)
68
+ run_command('bundle install', quiet: quiet)
69
+ log "\n\n#{ File.read(File.join(Satorix.app_dir, 'Gemfile.lock')) }" unless quiet
70
+ end
71
+
72
+
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+
80
+
@@ -0,0 +1,25 @@
1
+ module Satorix
2
+ module CI
3
+ module Shared
4
+
5
+ module YarnManager
6
+
7
+
8
+ include Satorix::Shared::Console
9
+
10
+
11
+ extend self
12
+
13
+
14
+ def go
15
+ log_bench('Installing yarn dependencies...') { run_command 'yarn install' }
16
+ end
17
+
18
+
19
+ private ########################################################################################################
20
+
21
+
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,38 @@
1
+ module Satorix
2
+ module CI
3
+ module Test
4
+ module Python
5
+ module DjangoTest
6
+
7
+
8
+ include Satorix::Shared::Console
9
+
10
+
11
+ extend self
12
+
13
+
14
+ def go
15
+ log_bench('Displaying current Python version...') { run_command 'python --version' }
16
+ log_bench('Running tests...') { run_tests }
17
+ end
18
+
19
+
20
+ def run_tests
21
+ run_command "#{ manage } collectstatic"
22
+ run_command "#{ manage } test public"
23
+ end
24
+
25
+
26
+ private ######################################################################################################
27
+
28
+
29
+ def manage
30
+ File.join(Satorix.app_dir, 'public', 'manage.py')
31
+ end
32
+
33
+
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,30 @@
1
+ module Satorix
2
+ module CI
3
+ module Test
4
+ module Python
5
+ module Safety
6
+
7
+
8
+ include Satorix::Shared::Console
9
+
10
+
11
+ extend self
12
+
13
+
14
+ def go
15
+ log_bench('Displaying current Python version...') { run_command 'python --version' }
16
+ log_bench('Installing Safety...') {run_command 'pip install safety'}
17
+ log_bench('Auditing requirements.txt...') { run_scan }
18
+ end
19
+
20
+
21
+ def run_scan
22
+ run_command "safety check -r requirements.txt"
23
+ end
24
+
25
+
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,35 @@
1
+ module Satorix
2
+ module CI
3
+ module Test
4
+ module Ruby
5
+ module Brakeman
6
+
7
+
8
+ include Satorix::Shared::Console
9
+
10
+
11
+ extend self
12
+
13
+
14
+ def go
15
+ log_bench('Displaying current Ruby version...') { run_command 'ruby -v' }
16
+ log_bench('Installing Brakeman...') { install_gem }
17
+ log_bench('Running Brakeman scan...') { run_scan }
18
+ end
19
+
20
+
21
+ def install_gem
22
+ run_command "gem install brakeman --no-document --bindir #{ Satorix.bin_dir }"
23
+ end
24
+
25
+
26
+ def run_scan
27
+ run_command "brakeman -z --table-width 1200 --exit-on-error --path #{ Satorix.app_dir }"
28
+ end
29
+
30
+
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ module Satorix
2
+ module CI
3
+ module Test
4
+ module Ruby
5
+ module BundlerAudit
6
+
7
+
8
+ include Satorix::Shared::Console
9
+
10
+
11
+ extend self
12
+
13
+
14
+ def go
15
+ log_bench('Displaying current Ruby version...') { run_command 'ruby -v' }
16
+ log_bench('Installing bundler-audit...') { install_gem }
17
+ log_bench('Auditing Gemfile.lock...') { run_scan }
18
+ end
19
+
20
+
21
+ def install_gem
22
+ run_command "gem install bundler-audit --no-document --bindir #{ Satorix.bin_dir }"
23
+ end
24
+
25
+
26
+ def run_scan
27
+ run_command 'bundle-audit check --update'
28
+ end
29
+
30
+
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,29 @@
1
+ module Satorix
2
+ module CI
3
+ module Test
4
+ module Ruby
5
+ module Cucumber
6
+
7
+
8
+ include Satorix::Shared::Console
9
+
10
+
11
+ extend self
12
+
13
+
14
+ def go
15
+ log_bench('Displaying current Ruby version...') { run_command 'ruby -v' }
16
+ log_bench('Running Cucumber...') { run_cucumber }
17
+ end
18
+
19
+
20
+ def run_cucumber
21
+ run_command 'bundle exec cucumber'
22
+ end
23
+
24
+
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ module Satorix
2
+ module CI
3
+ module Test
4
+ module Ruby
5
+ module RailsTest
6
+
7
+
8
+ include Satorix::Shared::Console
9
+
10
+
11
+ extend self
12
+
13
+
14
+ def go
15
+ log_bench('Displaying current Ruby version...') { run_command 'ruby -v' }
16
+ log_bench('Running Rails test...') { run_scan }
17
+ end
18
+
19
+
20
+ def run_scan
21
+ run_command 'rails test'
22
+ end
23
+
24
+
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ module Satorix
2
+ module CI
3
+ module Test
4
+ module Ruby
5
+ module Rspec
6
+
7
+
8
+ include Satorix::Shared::Console
9
+
10
+
11
+ extend self
12
+
13
+
14
+ def go
15
+ log_bench('Displaying current Ruby version...') { run_command 'ruby -v' }
16
+ log_bench('Running specs...') { run_specs }
17
+ end
18
+
19
+
20
+ def run_specs
21
+ run_command 'rspec spec'
22
+ end
23
+
24
+
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,98 @@
1
+ module Satorix
2
+ module CI
3
+ module Test
4
+ module Ruby
5
+ module Rubocop
6
+
7
+
8
+ include Satorix::Shared::Console
9
+
10
+
11
+ extend self
12
+
13
+
14
+ def go
15
+ log_bench('Displaying current Ruby version...') { run_command 'ruby -v' }
16
+ log_bench('Installing Rubocop...') { install_gems }
17
+ log_bench('Configuring Rubocop...') { create_rubocop_config }
18
+ log_bench('Running Rubocop inspection...') { run_scan }
19
+ end
20
+
21
+
22
+ def install_gems
23
+ run_command "gem install rubocop --no-document --bindir #{ Satorix.bin_dir }"
24
+ run_command "gem install rubocop-performance --no-document --bindir #{ Satorix.bin_dir }"
25
+ run_command "gem install rubocop-rails_config --no-document --bindir #{ Satorix.bin_dir }" if Satorix.rails_app?
26
+ end
27
+
28
+
29
+ def create_rubocop_config
30
+ if config_exist?
31
+ log 'Using existing .rubocop.yml file from project.'
32
+ else
33
+ log 'A .rubocop.yml file was not found, generating a default configuration file for this project.'
34
+ content = Satorix.rails_app? ? config_content_rails : config_content_default
35
+ save_rubocop_config content
36
+ end
37
+ log 'For more information, please refer to https://www.satorix.com/docs/articles/app_using_ruby_on_rails#rubocop.'
38
+ end
39
+
40
+
41
+ def run_scan
42
+ run_command "rubocop --require rubocop-performance #{ '--require rubocop-rails ' if Satorix.rails_app? }--display-cop-names --extra-details --display-style-guide --parallel"
43
+ end
44
+
45
+
46
+ private ######################################################################################################
47
+
48
+
49
+ def rubocop_config_file
50
+ File.join(Satorix.app_dir, '.rubocop.yml')
51
+ end
52
+
53
+
54
+ def save_rubocop_config(config)
55
+ File.open(rubocop_config_file, 'w') { |f| f.write(config) }
56
+ end
57
+
58
+
59
+ def config_exist?
60
+ File.exist? rubocop_config_file
61
+ end
62
+
63
+
64
+ def ruby_version
65
+ version = run_command 'bundle platform --ruby', quiet: true
66
+ version.match(/\d+\.\d+\.\d+/)[0]
67
+ end
68
+
69
+
70
+ def config_content_default
71
+ <<~CONTENT
72
+ AllCops:
73
+ TargetRubyVersion: #{ ruby_version }
74
+ Exclude:
75
+ - '**/tmp/**/*'
76
+ - '**/templates/**/*'
77
+ - '**/vendor/**/*'
78
+ CONTENT
79
+ end
80
+
81
+
82
+ def config_content_rails
83
+ <<~CONTENT
84
+ inherit_gem:
85
+ rubocop-rails_config:
86
+ - config/rails.yml
87
+
88
+ AllCops:
89
+ TargetRubyVersion: #{ ruby_version }
90
+ CONTENT
91
+ end
92
+
93
+
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end