renuo-bin-check 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +33 -0
  3. data/.editorconfig +20 -0
  4. data/.gitignore +9 -0
  5. data/.reek +18 -0
  6. data/.rspec +2 -0
  7. data/.rubocop.yml +26 -0
  8. data/.ruby-version +1 -0
  9. data/.travis.yml +32 -0
  10. data/CHANGELOG.md +36 -0
  11. data/CODE_OF_CONDUCT.md +13 -0
  12. data/CONTRIBUTING.md +41 -0
  13. data/Gemfile +3 -0
  14. data/LICENSE +22 -0
  15. data/README.md +142 -0
  16. data/Rakefile +7 -0
  17. data/bin/check +66 -0
  18. data/bin/setup +61 -0
  19. data/lib/renuo-bin-check.rb +8 -0
  20. data/lib/renuo_bin_check/cacher.rb +46 -0
  21. data/lib/renuo_bin_check/default_scripts/default_rails.rb +160 -0
  22. data/lib/renuo_bin_check/initializer.rb +21 -0
  23. data/lib/renuo_bin_check/master_thread.rb +42 -0
  24. data/lib/renuo_bin_check/printer.rb +15 -0
  25. data/lib/renuo_bin_check/result.rb +10 -0
  26. data/lib/renuo_bin_check/script_config.rb +61 -0
  27. data/lib/renuo_bin_check/servant_thread.rb +43 -0
  28. data/lib/renuo_bin_check/version.rb +4 -0
  29. data/renuo-bin-check.gemspec +35 -0
  30. data/spec/code_climate.rb +0 -0
  31. data/spec/code_climate.travis.rb +4 -0
  32. data/spec/factories/cacher.rb +16 -0
  33. data/spec/factories/result.rb +29 -0
  34. data/spec/factories/script_config.rb +41 -0
  35. data/spec/integration/initializer_spec.rb +209 -0
  36. data/spec/renuo/bin-check/cacher_spec.rb +51 -0
  37. data/spec/renuo/bin-check/initializer_spec.rb +23 -0
  38. data/spec/renuo/bin-check/master_thread_spec.rb +46 -0
  39. data/spec/renuo/bin-check/printer_spec.rb +25 -0
  40. data/spec/renuo/bin-check/result_spec.rb +18 -0
  41. data/spec/renuo/bin-check/script_config_spec.rb +69 -0
  42. data/spec/renuo/bin-check/servant_thread_spec.rb +97 -0
  43. data/spec/spec-files/file1 +1 -0
  44. data/spec/spec-files/file2 +1 -0
  45. data/spec/spec-files/file2_copy +1 -0
  46. data/spec/spec-files/test_script_exit0 +5 -0
  47. data/spec/spec-files/test_script_exit1 +5 -0
  48. data/spec/spec-files/test_script_exit1_no_error_output +3 -0
  49. data/spec/spec-files/test_script_sleep1 +2 -0
  50. data/spec/spec-files/test_script_sleep2 +2 -0
  51. data/spec/spec_helper.rb +35 -0
  52. metadata +288 -0
data/bin/setup ADDED
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+ require 'pathname'
3
+
4
+ # path to your application root.
5
+ APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
6
+
7
+ def run(name, file_which_must_not_exist = nil)
8
+ unless file_which_must_not_exist && File.exist?(file_which_must_not_exist)
9
+ puts "== #{name} =="
10
+ yield
11
+ puts
12
+ end
13
+ end
14
+
15
+ def install_or_update_gem(gem)
16
+ if ENV['UPDATE']
17
+ system "gem install #{gem}"
18
+ else
19
+ system "which #{gem.gsub('_', '-')} || gem install #{gem}"
20
+ end
21
+ end
22
+
23
+ Dir.chdir APP_ROOT do
24
+ run 'Installing dependencies' do
25
+ system 'gem install bundler --conservative'
26
+ system 'bundle check || bundle install --jobs=3 --retry=3'
27
+ install_or_update_gem('pry')
28
+ install_or_update_gem('rubocop')
29
+ install_or_update_gem('reek')
30
+ install_or_update_gem('filewatcher')
31
+ end
32
+
33
+ run 'Installing JS dependencies' do
34
+ system 'which coffeelint || npm install -g coffeelint'
35
+ system 'which tsc || npm install -g typescript'
36
+ system 'which tslint || npm install -g tslint'
37
+ end
38
+
39
+ run 'Copying config/application.yml', 'config/application.yml' do
40
+ system 'cp config/application.example.yml config/application.yml'
41
+ end
42
+
43
+ run('Preparing database') do
44
+ system 'bin/rake db:version >> /dev/null 2>&1 || bin/rake db:create:all && bin/rake db:setup'
45
+ end
46
+
47
+ run 'Removing old logs and tempfiles' do
48
+ system 'rm -f log/*'
49
+ system 'rm -rf tmp/cache'
50
+ end
51
+
52
+ run 'Creating pre-commit hook link', '.git/hooks/pre-commit' do
53
+ system 'ln -s ../../bin/check .git/hooks/pre-commit'
54
+ end
55
+
56
+ run('Setting dev host in /etc/hosts') do
57
+ system 'grep \'<appname>.dev\' /etc/hosts || echo \'127.0.0.1 <appname>.dev\' | sudo tee -a /etc/hosts'
58
+ end
59
+
60
+ run('Running checks') { abort('bin/check failed') unless system('bin/check') }
61
+ end
@@ -0,0 +1,8 @@
1
+ require 'renuo_bin_check/cacher'
2
+ require 'renuo_bin_check/initializer'
3
+ require 'renuo_bin_check/master_thread'
4
+ require 'renuo_bin_check/printer'
5
+ require 'renuo_bin_check/result'
6
+ require 'renuo_bin_check/script_config'
7
+ require 'renuo_bin_check/servant_thread'
8
+ require 'renuo_bin_check/version'
@@ -0,0 +1,46 @@
1
+ require 'digest'
2
+ require 'fileutils'
3
+ require 'renuo_bin_check/result'
4
+
5
+ module RenuoBinCheck
6
+ class Cacher
7
+ def initialize(name, paths)
8
+ @name = name
9
+ @file_names = paths.map { |path| Dir[path] }.flatten.sort
10
+ @hash = hash_files
11
+ end
12
+
13
+ def exists?
14
+ File.exist?("tmp/bin-check/#{@name}/#{@hash}")
15
+ end
16
+
17
+ def result
18
+ read
19
+ end
20
+
21
+ def cache(result)
22
+ FileUtils.mkdir_p "tmp/bin-check/#{@name}/#{@hash}"
23
+ File.write "tmp/bin-check/#{@name}/#{@hash}/standard_output", result.standard_output
24
+ File.write "tmp/bin-check/#{@name}/#{@hash}/error_output", result.error_output
25
+ File.write "tmp/bin-check/#{@name}/#{@hash}/exit_code", result.exit_code
26
+ end
27
+
28
+ private
29
+
30
+ def read
31
+ standard_output = File.read("tmp/bin-check/#{@name}/#{@hash}/standard_output")
32
+ error_output = File.read("tmp/bin-check/#{@name}/#{@hash}/error_output")
33
+ exit_code = File.read("tmp/bin-check/#{@name}/#{@hash}/exit_code").to_i
34
+ Result.new(standard_output, error_output, exit_code)
35
+ end
36
+
37
+ def hash_files
38
+ Digest::MD5.hexdigest @file_names.map { |file_name| hash_file(file_name) if File.file? file_name }.to_s
39
+ end
40
+
41
+ #:reek:UtilityFunction
42
+ def hash_file(file_name)
43
+ Digest::MD5.file(file_name).hexdigest + Digest::MD5.hexdigest(file_name)
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,160 @@
1
+ module RenuoBinCheck
2
+ # rubocop:disable Metrics/ModuleLength
3
+ module DefaultScripts
4
+ # rubocop:disable Metrics/AbcSize
5
+ # rubocop:disable Metrics/MethodLength
6
+ # :reek:TooManyStatements
7
+ def rails
8
+ bin_check = RenuoBinCheck::Initializer.new
9
+
10
+ mini_profiler(bin_check)
11
+ todo(bin_check)
12
+ console_log(bin_check)
13
+ put_without_brackets(bin_check)
14
+ put_with_brackets(bin_check)
15
+ pp_and_p(bin_check)
16
+ p_with_brackets(bin_check)
17
+ rubocop_autocorrect(bin_check)
18
+ slim_lint(bin_check)
19
+ scss_lint(bin_check)
20
+ tslint(bin_check)
21
+ brakeman(bin_check)
22
+ reek(bin_check)
23
+ rspec(bin_check)
24
+
25
+ bin_check.run
26
+ end
27
+ # rubocop:enable Metrics/AbcSize
28
+ # rubocop:enable Metrics/MethodLength
29
+
30
+ def mini_profiler(bin_check)
31
+ bin_check.check do |config|
32
+ config.command "grep 'rack-mini-profiler' Gemfile.lock >> /dev/null"
33
+ config.reversed_exit true
34
+ config.files ['Gemfile.lock']
35
+ end
36
+ end
37
+
38
+ def todo(bin_check)
39
+ bin_check.check do |config|
40
+ config.command "grep --exclude-dir='app/assets/typings/**' -i -r 'TODO' app spec config db Rakefile README.md"\
41
+ ' Gemfile'
42
+ config.reversed_exit true
43
+ config.files ['app/**/*', 'spec/**/*', 'config/**/*', 'db/**/*', 'Rakefile', 'README.md', 'Gemfile']
44
+ end
45
+ end
46
+
47
+ def console_log(bin_check)
48
+ bin_check.check do |config|
49
+ config.command "grep -i -r 'console.log' app spec"
50
+ config.reversed_exit true
51
+ config.files ['app/**/*', 'spec/**/*']
52
+ end
53
+ end
54
+
55
+ def put_without_brackets(bin_check)
56
+ bin_check.check do |config|
57
+ config.command "grep -i -r ' puts ' app spec"
58
+ config.reversed_exit true
59
+ config.files ['app/**/*', 'spec/**/*']
60
+ end
61
+ end
62
+
63
+ def put_with_brackets(bin_check)
64
+ bin_check.check do |config|
65
+ config.command "grep -i -r ' puts(' app spec"
66
+ config.reversed_exit true
67
+ config.files ['app/**/*', 'spec/**/*']
68
+ end
69
+ end
70
+
71
+ def pp_and_p(bin_check)
72
+ bin_check.check do |config|
73
+ config.command "grep -i -r '( pp? [^=])|(= pp? )' app spec"
74
+ config.reversed_exit true
75
+ config.files ['app/**/*', 'spec/**/*']
76
+ end
77
+ end
78
+
79
+ def p_with_brackets(bin_check)
80
+ bin_check.check do |config|
81
+ config.command "grep -i -r ' p(' app spec"
82
+ config.reversed_exit true
83
+ config.files ['app/**/*', 'spec/**/*']
84
+ end
85
+ end
86
+
87
+ def rubocop_autocorrect(bin_check)
88
+ bin_check.check do |config|
89
+ config.command 'bundle exec rubocop -a -D -c .rubocop.yml'
90
+ config.files ['app/**/*.rb', 'spec/**/*.rb']
91
+ end
92
+ end
93
+
94
+ def slim_lint(bin_check)
95
+ bin_check.check do |config|
96
+ config.command 'bundle exec slim-lint app/views/ -c .slim-lint.yml'
97
+ config.files ['app/views/**/*.slim']
98
+ end
99
+ end
100
+
101
+ def scss_lint(bin_check)
102
+ bin_check.check do |config|
103
+ config.command 'scss-lint app/assets/stylesheets/**/*.scss'
104
+ config.files ['app/assets/stylesheets/**/*.scss']
105
+ end
106
+ end
107
+
108
+ def tslint(bin_check)
109
+ bin_check.check do |config|
110
+ config.command 'tslint -c tslint.json app/assets/javascripts/**/*.ts'
111
+ config.files ['app/assets/javascripts/**/*.ts']
112
+ end
113
+ end
114
+
115
+ def coffeelint(bin_check)
116
+ bin_check.check do |config|
117
+ config.command 'coffeelint -f .coffeelint.json app/assets/javascripts/**/*.coffee'
118
+ config.files ['app/assets/javascripts/**/*.coffee']
119
+ end
120
+ end
121
+
122
+ def brakeman(bin_check)
123
+ bin_check.check do |config|
124
+ config.command 'bundle exec brakeman -q -z --summary > /dev/null'
125
+ end
126
+ end
127
+
128
+ def reek(bin_check)
129
+ bin_check.check do |config|
130
+ config.command 'bundle exec reek'
131
+ config.files ['app/**/*.rb']
132
+ end
133
+ end
134
+
135
+ def rspec(bin_check)
136
+ bin_check.check do |config|
137
+ config.command 'bundle exec rspec'
138
+ config.files ['app/**/*.rb', 'spec/**/*.rb']
139
+ end
140
+ end
141
+
142
+ module_function :rails
143
+ module_function :mini_profiler
144
+ module_function :todo
145
+ module_function :console_log
146
+ module_function :put_without_brackets
147
+ module_function :put_with_brackets
148
+ module_function :pp_and_p
149
+ module_function :p_with_brackets
150
+ module_function :rubocop_autocorrect
151
+ module_function :slim_lint
152
+ module_function :scss_lint
153
+ module_function :tslint
154
+ module_function :coffeelint
155
+ module_function :brakeman
156
+ module_function :reek
157
+ module_function :rspec
158
+ end
159
+ # rubocop:enable Metrics/ModuleLength
160
+ end
@@ -0,0 +1,21 @@
1
+ require 'renuo_bin_check/printer'
2
+
3
+ module RenuoBinCheck
4
+ class Initializer
5
+ attr_reader :master_thread
6
+
7
+ def initialize
8
+ @master_thread = MasterThread.new(Printer.new)
9
+ end
10
+
11
+ def check
12
+ config = ScriptConfig.new
13
+ yield(config)
14
+ @master_thread.add_thread(config)
15
+ end
16
+
17
+ def run
18
+ @master_thread.finalize
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,42 @@
1
+ require 'thwait'
2
+
3
+ module RenuoBinCheck
4
+ class MasterThread
5
+ attr_reader :threads, :printer
6
+
7
+ def initialize(printer)
8
+ @threads = []
9
+ @results = []
10
+ @printer = printer
11
+ end
12
+
13
+ def add_thread(script_config)
14
+ threads << Thread.new do
15
+ servant = ServantThread.new(script_config)
16
+ Thread.current[:result] = servant.run
17
+ end
18
+ end
19
+
20
+ def finalize
21
+ waiter = ThreadsWait.new(threads)
22
+ until waiter.empty?
23
+ result = waiter.next_wait[:result]
24
+ @results << result
25
+ exit_with_error(result) if result.exit_code == 1
26
+ end
27
+ exit_with_success
28
+ end
29
+
30
+ private
31
+
32
+ def exit_with_error(result)
33
+ @printer.print_error_output(result)
34
+ exit 1
35
+ end
36
+
37
+ def exit_with_success
38
+ @printer.print_standard_output(@results)
39
+ exit 0
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,15 @@
1
+ module RenuoBinCheck
2
+ class Printer
3
+ # :reek:UtilityFunction
4
+ def print_standard_output(results)
5
+ results.each { |result| $stdout.puts result.standard_output }
6
+ end
7
+
8
+ # :reek:UtilityFunction
9
+ def print_error_output(result)
10
+ error_output = result.error_output
11
+ error_output = result.standard_output if error_output == ''
12
+ $stderr.puts error_output
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,10 @@
1
+ module RenuoBinCheck
2
+ class Result
3
+ attr_reader :standard_output, :error_output, :exit_code
4
+ def initialize(standard_output, error_output, exit_code)
5
+ @standard_output = standard_output
6
+ @error_output = error_output
7
+ @exit_code = exit_code
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,61 @@
1
+ module RenuoBinCheck
2
+ # :reek:TooManyInstanceVariables:
3
+ class ScriptConfig
4
+ attr_accessor :script_command, :script_files, :script_name, :script_reversed_exit, :script_standard_output,
5
+ :script_error_output, :appended_standard_output, :appended_error_output
6
+
7
+ def command(command)
8
+ @script_command = command
9
+ end
10
+
11
+ def files(files)
12
+ @script_files = files
13
+ end
14
+
15
+ def name(name)
16
+ @script_name = name
17
+ end
18
+
19
+ def success_message(standard_output)
20
+ if standard_output[0] == '+'
21
+ @appended_standard_output = standard_output.sub('+', '')
22
+ else
23
+ @script_standard_output = standard_output
24
+ end
25
+ end
26
+
27
+ def error_message(error_output)
28
+ if error_output[0] == '+'
29
+ @appended_error_output = error_output.sub('+', '')
30
+ else
31
+ @script_error_output = error_output
32
+ end
33
+ end
34
+
35
+ def reversed_exit(reversed_exit)
36
+ @script_reversed_exit = reversed_exit
37
+ end
38
+
39
+ def script_name
40
+ @script_name ||= Digest::MD5.hexdigest(@script_command)
41
+ end
42
+
43
+ def reversed_exit?
44
+ @script_reversed_exit
45
+ end
46
+
47
+ def appended_standard_output
48
+ @appended_standard_output ||= ''
49
+ end
50
+
51
+ def appended_error_output
52
+ @appended_error_output ||= ''
53
+ end
54
+
55
+ def script_command
56
+ raise 'There must be a command set for each script you want to run. Find further instruction on how to use this' \
57
+ ' Gem here in the Readme: https://github.com/renuo/renuo-bin-check' unless @script_command
58
+ @script_command
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,43 @@
1
+ require 'open3'
2
+ require 'renuo_bin_check/result'
3
+
4
+ module RenuoBinCheck
5
+ class ServantThread
6
+ attr_reader :script_config
7
+ def initialize(script_config)
8
+ @script_config = script_config
9
+ script_files = @script_config.script_files
10
+ @cacher = Cacher.new(@script_config.script_name, script_files) if script_files
11
+ end
12
+
13
+ def run
14
+ @script_config.script_files ? run_with_cache : run_command
15
+ end
16
+
17
+ private
18
+
19
+ def run_with_cache
20
+ @cacher.cache(run_command) unless @cacher.exists?
21
+ @cacher.result
22
+ end
23
+
24
+ def run_command
25
+ standard_output, error_output, process = Open3.capture3(@script_config.script_command)
26
+ @result = Result.new(standard_output, error_output, process.exitstatus)
27
+ override_output
28
+ @script_config.reversed_exit? ? reverse_result : @result
29
+ end
30
+
31
+ def override_output
32
+ standard_output = @script_config.script_standard_output ||= @result.standard_output
33
+ error_output = @script_config.script_error_output ||= @result.error_output
34
+ @result = Result.new(standard_output + @script_config.appended_standard_output,
35
+ error_output + @script_config.appended_error_output,
36
+ @result.exit_code)
37
+ end
38
+
39
+ def reverse_result
40
+ Result.new(@result.error_output, @result.standard_output, @result.exit_code == 0 ? 1 : 0)
41
+ end
42
+ end
43
+ end