polishgeeks-dev-tools 1.0.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 (66) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +6 -0
  6. data/Gemfile +2 -0
  7. data/Gemfile.lock +193 -0
  8. data/README.md +112 -0
  9. data/Rakefile +20 -0
  10. data/config/haml-lint.yml +74 -0
  11. data/config/rubocop.yml +35 -0
  12. data/config/yardopts +7 -0
  13. data/lib/polishgeeks-dev-tools.rb +43 -0
  14. data/lib/polishgeeks/dev-tools/command/allowed_extensions.rb +62 -0
  15. data/lib/polishgeeks/dev-tools/command/base.rb +73 -0
  16. data/lib/polishgeeks/dev-tools/command/brakeman.rb +46 -0
  17. data/lib/polishgeeks/dev-tools/command/coverage.rb +43 -0
  18. data/lib/polishgeeks/dev-tools/command/examples_comparator.rb +75 -0
  19. data/lib/polishgeeks/dev-tools/command/expires_in.rb +74 -0
  20. data/lib/polishgeeks/dev-tools/command/haml_lint.rb +28 -0
  21. data/lib/polishgeeks/dev-tools/command/readme.rb +32 -0
  22. data/lib/polishgeeks/dev-tools/command/rspec.rb +38 -0
  23. data/lib/polishgeeks/dev-tools/command/rspec_files_names.rb +58 -0
  24. data/lib/polishgeeks/dev-tools/command/rspec_files_structure.rb +134 -0
  25. data/lib/polishgeeks/dev-tools/command/rubocop.rb +50 -0
  26. data/lib/polishgeeks/dev-tools/command/rubycritic.rb +17 -0
  27. data/lib/polishgeeks/dev-tools/command/simplecov.rb +32 -0
  28. data/lib/polishgeeks/dev-tools/command/tasks_files_names.rb +76 -0
  29. data/lib/polishgeeks/dev-tools/command/yard.rb +35 -0
  30. data/lib/polishgeeks/dev-tools/command/yml_parser.rb +85 -0
  31. data/lib/polishgeeks/dev-tools/config.rb +91 -0
  32. data/lib/polishgeeks/dev-tools/hash.rb +24 -0
  33. data/lib/polishgeeks/dev-tools/logger.rb +63 -0
  34. data/lib/polishgeeks/dev-tools/output_storer.rb +17 -0
  35. data/lib/polishgeeks/dev-tools/runner.rb +27 -0
  36. data/lib/polishgeeks/dev-tools/shell.rb +16 -0
  37. data/lib/polishgeeks/dev-tools/tasks/dev-tools.rake +15 -0
  38. data/lib/polishgeeks/dev-tools/version.rb +8 -0
  39. data/polishgeeks_dev_tools.gemspec +36 -0
  40. data/spec/lib/polishgeeks-dev-tools_spec.rb +35 -0
  41. data/spec/lib/polishgeeks/dev-tools/command/allowed_extensions_spec.rb +66 -0
  42. data/spec/lib/polishgeeks/dev-tools/command/base_spec.rb +127 -0
  43. data/spec/lib/polishgeeks/dev-tools/command/brakeman_spec.rb +95 -0
  44. data/spec/lib/polishgeeks/dev-tools/command/coverage_spec.rb +121 -0
  45. data/spec/lib/polishgeeks/dev-tools/command/examples_comparator_spec.rb +171 -0
  46. data/spec/lib/polishgeeks/dev-tools/command/expires_in_spec.rb +69 -0
  47. data/spec/lib/polishgeeks/dev-tools/command/haml_lint_spec.rb +79 -0
  48. data/spec/lib/polishgeeks/dev-tools/command/readme_spec.rb +38 -0
  49. data/spec/lib/polishgeeks/dev-tools/command/rspec_files_names_spec.rb +91 -0
  50. data/spec/lib/polishgeeks/dev-tools/command/rspec_files_structure_spec.rb +262 -0
  51. data/spec/lib/polishgeeks/dev-tools/command/rspec_spec.rb +63 -0
  52. data/spec/lib/polishgeeks/dev-tools/command/rubocop_spec.rb +127 -0
  53. data/spec/lib/polishgeeks/dev-tools/command/rubycritic_spec.rb +27 -0
  54. data/spec/lib/polishgeeks/dev-tools/command/simplecov_spec.rb +53 -0
  55. data/spec/lib/polishgeeks/dev-tools/command/tasks_files_names_spec.rb +108 -0
  56. data/spec/lib/polishgeeks/dev-tools/command/yard_spec.rb +86 -0
  57. data/spec/lib/polishgeeks/dev-tools/command/yml_parser_spec.rb +104 -0
  58. data/spec/lib/polishgeeks/dev-tools/config_spec.rb +78 -0
  59. data/spec/lib/polishgeeks/dev-tools/hash_spec.rb +37 -0
  60. data/spec/lib/polishgeeks/dev-tools/logger_spec.rb +162 -0
  61. data/spec/lib/polishgeeks/dev-tools/output_storer_spec.rb +20 -0
  62. data/spec/lib/polishgeeks/dev-tools/runner_spec.rb +57 -0
  63. data/spec/lib/polishgeeks/dev-tools/shell_spec.rb +13 -0
  64. data/spec/lib/polishgeeks/dev-tools/version_spec.rb +7 -0
  65. data/spec/spec_helper.rb +28 -0
  66. metadata +330 -0
@@ -0,0 +1,35 @@
1
+ module PolishGeeks
2
+ module DevTools
3
+ module Command
4
+ # Command wrapper for Yard statistics
5
+ # @note It validates if everything is well documented
6
+ class Yard < Base
7
+ self.type = :validator
8
+
9
+ # Regexp used to match Yard output to check if there are things that
10
+ # are not documented or that include warnings
11
+ MATCH_REGEXP = /(Undocumented Objects|warn)/i
12
+
13
+ # Executes this command
14
+ # @return [String] command output
15
+ def execute
16
+ @output = Shell.new.execute("bundle exec yard stats #{options}")
17
+ end
18
+
19
+ # @return [Boolean] true if everything is documented and without warnings
20
+ def valid?
21
+ output[MATCH_REGEXP].nil?
22
+ end
23
+
24
+ private
25
+
26
+ # Settings for yard - they are directly taken from yardopts file in config dir
27
+ # @return [String] yard options that should be used to generate documentation
28
+ def options
29
+ config = File.join(DevTools.gem_root, 'config', 'yardopts')
30
+ File.readlines(config).join(' ').delete("\n") + ' --list-undoc'
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,85 @@
1
+ module PolishGeeks
2
+ module DevTools
3
+ module Command
4
+ # Verifying parameters in example YAML config files
5
+ class YmlParser < Base
6
+ self.type = :validator
7
+
8
+ # Executes this command
9
+ # @return [Array] command output
10
+ def execute
11
+ @output = []
12
+ Dir[config_path].each do |file|
13
+ parsed_file = parse_yaml(file)
14
+ nil_params = check_params(parsed_file)
15
+ next if nil_params.empty?
16
+ @output << {
17
+ file: file,
18
+ lines: nil_params
19
+ }
20
+ end
21
+
22
+ @output
23
+ end
24
+
25
+ # @return [String] label with this validator description
26
+ def label
27
+ 'Yaml parser'
28
+ end
29
+
30
+ # @return [String] error message
31
+ def error_message
32
+ err = 'Following yml files have nil as a value:'
33
+ @output.each { |row| err << file_error(row) }
34
+ err << "\n"
35
+ end
36
+
37
+ # @return [Boolean] true if all parameters in YAML files
38
+ # have not nil value
39
+ def valid?
40
+ @output.empty?
41
+ end
42
+
43
+ private
44
+
45
+ # @return [String] error message with file name and parameters which have nil value
46
+ def file_error(err_message)
47
+ err = "\n#{sanitize(err_message[:file])}:"
48
+ err_message[:lines].each { |line| err << "\n - Key '#{line}'" }
49
+ err
50
+ end
51
+
52
+ # @return [String] config path with all yaml files
53
+ def config_path
54
+ "#{File.expand_path(PolishGeeks::DevTools.app_root + '/config')}/**/*.yml.example"
55
+ end
56
+
57
+ # @param [String] file name that we want to sanitize
58
+ # @return [String] sanitized file name
59
+ # @example
60
+ # file = /home/something/app/condig/settings.rb
61
+ # sanitize(file) #=> settings.rb
62
+ def sanitize(file)
63
+ file.gsub!(PolishGeeks::DevTools.app_root + '/config/', '')
64
+ file
65
+ end
66
+
67
+ # @param [String] file name that we want to load
68
+ # @return [Hash] data serialization in YAML format
69
+ def parse_yaml(file)
70
+ YAML.load(File.open(file))
71
+ end
72
+
73
+ # recursion method to find key with nil value
74
+ # @param [Hash] hash which we want to check
75
+ # @return [Array] parameters with nil value
76
+ def check_params(hash)
77
+ hash.map do |k, v|
78
+ return k if v.nil?
79
+ check_params(v) if v.is_a?(::Hash)
80
+ end.compact.flatten
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,91 @@
1
+ module PolishGeeks
2
+ module DevTools
3
+ # Configurator for enabling specific command runners
4
+ # @note No commands are enabled by default
5
+ # @example Enable only rubocop
6
+ # Config.configure do |conf|
7
+ # conf.rubocop = true
8
+ # end
9
+ class Config
10
+ class << self
11
+ attr_accessor :config
12
+
13
+ # @return [PolishGeeks::DevTools::Config] config for dev tools
14
+ # @note We check if it initialized, because if user wants to use it
15
+ # with all the commands enabled and without any changes, he won't create
16
+ # a polishgeeks_dev_tools.rb initializer file so we need to configure it
17
+ # with defaults
18
+ def config
19
+ @config || setup {}
20
+ end
21
+ end
22
+
23
+ attr_accessor :simplecov_threshold
24
+ attr_accessor :rspec_files_structure_ignored
25
+ attr_accessor :expires_in_files_ignored
26
+
27
+ # Available commands
28
+ # All commands will be executed in this order (first rubocop, then rspec, etc)
29
+ COMMANDS = %i(
30
+ readme
31
+ expires_in
32
+ brakeman
33
+ rubocop
34
+ haml_lint
35
+ allowed_extensions
36
+ yml_parser
37
+ rspec_files_names
38
+ rspec_files_structure
39
+ tasks_files_names
40
+ rspec
41
+ simplecov
42
+ coverage
43
+ yard
44
+ examples_comparator
45
+ rubycritic
46
+ )
47
+
48
+ COMMANDS.each do |attr_name|
49
+ attr_accessor attr_name
50
+
51
+ # @return [Boolean] is given command enabled
52
+ define_method :"#{attr_name}?" do
53
+ public_send(attr_name) == true
54
+ end
55
+ end
56
+
57
+ # Initializes configuration and turn on by default
58
+ # all the commands
59
+ def initialize
60
+ COMMANDS.each do |attr_name|
61
+ public_send(:"#{attr_name}=", true)
62
+ end
63
+
64
+ self.simplecov_threshold = 100
65
+ end
66
+
67
+ # Configurating method
68
+ def self.setup(&block)
69
+ self.config = new
70
+
71
+ config.detect_framework
72
+
73
+ block.call(config)
74
+ config.freeze
75
+ end
76
+
77
+ # Detects if we use Rails, Sinatra or nothing
78
+ # We need to set it because some of the commands might work only for Rails
79
+ # or Sinatra (like brakeman for example - only Rails)
80
+ def detect_framework
81
+ define_singleton_method :rails? do
82
+ !defined?(Rails).nil?
83
+ end
84
+
85
+ define_singleton_method :sinatra? do
86
+ !defined?(App).nil?
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,24 @@
1
+ module PolishGeeks
2
+ module DevTools
3
+ # Hash extensions required only by rake tasks in this rake file
4
+ # No need to add them to app itself
5
+ # We don't put it directly into hash, since it won't be used outside of
6
+ # this gem
7
+ class Hash < ::Hash
8
+ # @param other [Hash] different hash that we want to compare with
9
+ # @return [Boolean] true if both hashes have same keys and same keys structure
10
+ def same_key_structure?(other)
11
+ return false unless keys == other.keys &&
12
+ keys.all? { |inside| inside.is_a?(Symbol) || inside.is_a?(String) }
13
+
14
+ keys.all? do |inside|
15
+ if self[inside].is_a?(::Hash)
16
+ self.class.new.merge(self[inside]).same_key_structure?(other[inside])
17
+ else
18
+ !other[inside].is_a?(::Hash)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,63 @@
1
+ module PolishGeeks
2
+ module DevTools
3
+ # Basic logger used to print output from commands
4
+ class Logger
5
+ # Regexp used to get only the class name without module names
6
+ CLASS_NAME_REGEXP = /^.*::/
7
+
8
+ # Raised when it is a type of task that we don't recognize
9
+ class UnknownTaskType < StandardError; end
10
+ # Raised when any of tasks fail
11
+ class RequirementsError < StandardError; end
12
+
13
+ # Method will print appropriate output with colors and comments
14
+ # @param [PolishGeeks::DevTools::Command::Base] task that was executed
15
+ # @raise [PolishGeeks::DevTools::Logger::RequirementsError] raised when task
16
+ # has failed
17
+ # @example Log output of a current_task
18
+ # PolishGeeks::DevTools::Logger.new.log(current_task) #=> console output
19
+ def log(task)
20
+ if task.class.generator? || task.valid?
21
+ info(task)
22
+ else
23
+ fatal(task)
24
+ fail RequirementsError
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ # Will print message when task didn't fail while running
31
+ # @note Handles also generators that never fail
32
+ # @param [PolishGeeks::DevTools::Command::Base] task that was executed
33
+ # @raise [PolishGeeks::DevTools::Logger::UnknownTaskType] raised when task type is
34
+ # not supported (we don't know how to handle it)
35
+ def info(task)
36
+ msg = 'GENERATED' if task.class.generator?
37
+ msg = 'OK' if task.class.validator?
38
+
39
+ fail UnknownTaskType unless msg
40
+
41
+ printf('%-40s %2s', "#{label(task)} ", "\e[32m#{msg}\e[0m\n")
42
+ end
43
+
44
+ # Will print message when task did fail while running
45
+ # @param [PolishGeeks::DevTools::Command::Base] task that was executed
46
+ def fatal(task)
47
+ printf('%-30s %20s', "#{label(task)} ", "\e[31mFAILURE\e[0m\n\n")
48
+ puts task.error_message + "\n"
49
+ end
50
+
51
+ # Generates a label describing a given task
52
+ # @note Will use a task class name if task doesn't respond to label method
53
+ # @param [PolishGeeks::DevTools::Command::Base] task that was executed
54
+ # @return [String] label describing task
55
+ # @example Get label for a current_task task
56
+ # label(current_task) #=> 'Rubocop'
57
+ def label(task)
58
+ label = task.label if task.respond_to?(:label)
59
+ label || task.class.to_s.gsub(CLASS_NAME_REGEXP, '')
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,17 @@
1
+ require 'ostruct'
2
+
3
+ module PolishGeeks
4
+ module DevTools
5
+ # Class used to store output from every executed command
6
+ # We store this data because it might be used by other commands
7
+ class OutputStorer < OpenStruct
8
+ # Creates a result storer instance
9
+ def initialize
10
+ init = {}
11
+ Config::COMMANDS.each { |command| init[command] = '' }
12
+
13
+ super(init)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,27 @@
1
+ module PolishGeeks
2
+ module DevTools
3
+ # Class used to execute appropriate commands based on config settings
4
+ class Runner
5
+ # Executes the whole tool
6
+ # @param logger [PolishGeeks::DevTools::Logger] logger instance
7
+ # @example Run all defined elements
8
+ # PolishGeeks::DevTools::Runner.new.execute(
9
+ # PolishGeeks::DevTools::Logger.new
10
+ # )
11
+ def execute(logger)
12
+ output = OutputStorer.new
13
+
14
+ Config::COMMANDS.each do |command|
15
+ next unless DevTools.config.public_send(:"#{command}?")
16
+
17
+ klass = command.to_s.gsub(/(?<=_|^)(\w)/) { |el| el.upcase }.gsub(/(?:_)(\w)/, '\1')
18
+ cmd = Object.const_get("PolishGeeks::DevTools::Command::#{klass}").new
19
+ cmd.stored_output = output
20
+ cmd.execute
21
+ output.public_send(:"#{command}=", cmd.output)
22
+ logger.log(cmd)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,16 @@
1
+ module PolishGeeks
2
+ module DevTools
3
+ # Class wrapping shell commands executing
4
+ class Shell
5
+ # Executes a given command in a system shell and returns its output
6
+ # @param [String] command that should be executed
7
+ # @return [String] executed command output
8
+ # @example Run 'ls' command and assing the output
9
+ # ls = PolishGeeks::DevTools::Shell.new.execute('ls')
10
+ # print ls #=> 'app app.rb Capfile ...'
11
+ def execute(command)
12
+ `#{command}`
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ require 'rake'
2
+
3
+ namespace :polishgeeks do
4
+ namespace :'dev-tools' do
5
+ desc 'Executed all tests and checks for given project'
6
+ task :check do
7
+ # Load Rails framework if it's Rails app
8
+ Rake::Task[:environment].invoke if Rake::Task.task_defined?(:environment)
9
+
10
+ PolishGeeks::DevTools::Runner.new.execute(
11
+ PolishGeeks::DevTools::Logger.new
12
+ )
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,8 @@
1
+ # Module encapsulating PolishGeeks specific code
2
+ module PolishGeeks
3
+ # Dev Tools for PolishGeeks developers
4
+ module DevTools
5
+ # Current version of dev tools
6
+ VERSION = '1.0.0'
7
+ end
8
+ end
@@ -0,0 +1,36 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ require 'rake'
4
+ require 'polishgeeks/dev-tools/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'polishgeeks-dev-tools'
8
+ s.version = PolishGeeks::DevTools::VERSION
9
+ s.platform = Gem::Platform::RUBY
10
+ s.authors = ['Maciej Mensfeld']
11
+ s.email = ['maciej@mensfeld.pl']
12
+ s.homepage = ''
13
+ s.summary = %q(Set of tools used when developing Ruby based apps)
14
+ s.description = %q(Set of tools used when developing Ruby based apps)
15
+
16
+ s.add_development_dependency 'bundler'
17
+ s.add_development_dependency 'rake'
18
+
19
+ s.add_dependency 'simplecov'
20
+ s.add_dependency 'rubycritic', '1.2.1'
21
+ s.add_dependency 'pry'
22
+ s.add_dependency 'yard'
23
+ s.add_dependency 'faker'
24
+ s.add_dependency 'shoulda'
25
+ s.add_dependency 'rspec'
26
+ s.add_dependency 'rubocop'
27
+ s.add_dependency 'timecop'
28
+ s.add_dependency 'brakeman'
29
+ s.add_dependency 'haml-lint'
30
+ s.add_dependency 'mongoid-rspec'
31
+
32
+ s.files = `git ls-files -z`.split("\x0")
33
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
34
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
35
+ s.require_paths = %w( lib )
36
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe PolishGeeks::DevTools do
4
+ subject { described_class }
5
+
6
+ describe '.gem_root' do
7
+ context 'when we want to get gem root path' do
8
+ let(:path) { Dir.pwd }
9
+ it do
10
+ expect(subject.gem_root).to eq path
11
+ end
12
+ end
13
+ end
14
+
15
+ describe '.app_root' do
16
+ context 'when we want to get app root path' do
17
+ before do
18
+ expect(ENV).to receive(:[]).with('BUNDLE_GEMFILE').and_return('/')
19
+ end
20
+
21
+ it { expect(subject.app_root).to eq '/' }
22
+ end
23
+ end
24
+
25
+ describe '.setup' do
26
+ let(:config_block) { ->{} }
27
+
28
+ it 'should pass it to Config setup method' do
29
+ expect(described_class::Config)
30
+ .to receive(:setup)
31
+
32
+ subject.setup(&config_block)
33
+ end
34
+ end
35
+ end