koality 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ quality
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in koality.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Jared Pace
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,128 @@
1
+ # Koality
2
+
3
+ Runs opinionated code metric tools against your code as part of the test
4
+ suite. If the set level of desired quality is not met the build will
5
+ fail.
6
+
7
+ Beware of the drop bears.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'koality', :require => false
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install koality
22
+
23
+ ## Usage
24
+
25
+ Add the following to your applications Rakefile. Place it after
26
+ `MyApp::Application.load_tasks` for Rails apps.
27
+
28
+ begin
29
+ require 'koality/rake_task'
30
+
31
+ Koality::RakeTask.new do |opts|
32
+ # configure options here
33
+ # See [koality_home]/lib/koality/options.rb for defaults
34
+
35
+ # opts.abc_threshold = 10
36
+ end
37
+ task :default => :koality
38
+ rescue LoadError
39
+ warn 'Could not load Koality, skipping Rake task.'
40
+ end
41
+
42
+ Running your test suite with Koality:
43
+
44
+ rake
45
+
46
+ Running koality on its own:
47
+
48
+ rake koality
49
+
50
+
51
+ ## SimpleCov Integration (Optional)
52
+
53
+ Add the following to the top of your spec/spec_helper.rb file.
54
+ Must be before your require your application code.
55
+
56
+ require 'koality/simplecov'
57
+ SimpleCov.start
58
+
59
+ ## Available options
60
+
61
+ All options are shown with their current defaults.
62
+
63
+ Koality::RakeTask.new do |opts|
64
+ opts.abc_file_pattern = '{app,lib}/**/*.rb'
65
+ opts.abc_threshold = 15
66
+ opts.abc_violations_threshold = 0
67
+ opts.abc_enabled = true
68
+
69
+ opts.style_file_pattern = '{app,lib,spec}/**/*.{rb,coffee,js}'
70
+ opts.style_line_length_threshold = 120
71
+ opts.style_violations_threshold = 0
72
+ opts.style_enabled = true
73
+
74
+ opts.doc_file_pattern = '{app,lib}/**/*.rb'
75
+ opts.doc_violations_threshold = 0
76
+ opts.doc_enabled = false
77
+
78
+ opts.code_coverage_threshold = 90
79
+ opts.code_coverage_file = 'code_coverage'
80
+ opts.code_coverage_enabled = true
81
+
82
+ opts.rails_bp_accept_patterns = []
83
+ opts.rails_bp_ignore_patterns = []
84
+ opts.rails_bp_errors_threshold = 0
85
+ opts.rails_bp_error_file = 'rails_best_practices_errors'
86
+ opts.rails_bp_enabled = true
87
+
88
+ opts.custom_thresholds = []
89
+ opts.total_violations_threshold = 0
90
+ opts.abort_on_failure = true
91
+ opts.output_directory = 'quality'
92
+
93
+ opts.colorize_output = true
94
+ end
95
+
96
+ ## Configuring Rails Best Practices
97
+
98
+ Generate the config file (config/rails_best_practices.yml)
99
+
100
+ bundle exec rails_best_practices -g
101
+
102
+ Edit configuration or comment out lines to skip certain checks.
103
+
104
+ ## Common Questions
105
+
106
+ * I don't want to the build to fail if I exceed any thresholds. How do I
107
+ turn that off?
108
+
109
+ opts.abort_on_failure = false
110
+
111
+ * I only want to fail the build if there are over 10 ABC errors. How do
112
+ I set that up?
113
+
114
+ opts.abc_violations_threshold = 10
115
+ opts.total_violations_threshold = -1
116
+
117
+ * How do I keep style violations from breaking the build?
118
+
119
+ opts.style_violations_threshold = -1
120
+ opts.total_violations_threshold = -1
121
+
122
+ ## Contributing
123
+
124
+ 1. Fork it
125
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
126
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
127
+ 4. Push to the branch (`git push origin my-new-feature`)
128
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ task :default => :spec
data/koality.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/koality/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Jared Pace"]
6
+ gem.email = ["jared@thinkrelevance.com"]
7
+ gem.description = %q{Runs opinionated code quality tools as part of you test stuite}
8
+ gem.summary = %q{Runs opinionated code quality tools as part of you test stuite}
9
+ gem.homepage = "https://github.com/relevance/koality"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "koality"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Koality::VERSION
17
+
18
+ # Runtime Dependencies
19
+ gem.add_runtime_dependency 'rails_best_practices', ['~> 1.9']
20
+ gem.add_runtime_dependency 'simplecov', ['~> 0.6']
21
+ gem.add_runtime_dependency 'cane', ['~> 1.3']
22
+ gem.add_runtime_dependency 'terminal-table', ['~> 1.4']
23
+ gem.add_runtime_dependency 'term-ansicolor', ['~> 1.0']
24
+
25
+ # Developmnet Dependencies
26
+ gem.add_development_dependency 'rspec', ['~> 2.10']
27
+ gem.add_development_dependency 'mocha', ['~> 0.11']
28
+ end
data/lib/koality.rb ADDED
@@ -0,0 +1,43 @@
1
+ require 'koality/version'
2
+ require 'koality/options'
3
+ require 'koality/reporter/base'
4
+ require 'koality/reporter/cane'
5
+ require 'koality/reporter/rails_best_practices'
6
+ require 'koality/runner/cane'
7
+ require 'koality/runner/rails_best_practices'
8
+
9
+ module Koality
10
+
11
+ class << self
12
+ def run
13
+ setup_environment
14
+
15
+ run_rails_bp if options.rails_bp_enabled?
16
+
17
+ success = run_cane
18
+ abort if options[:abort_on_failure] && !success
19
+ end
20
+
21
+ def run_rails_bp
22
+ rails_bp = Koality::Runner::RailsBestPractices.new(options)
23
+ rails_bp.run
24
+ end
25
+
26
+ def run_cane
27
+ cane = Koality::Runner::Cane.new(options)
28
+ cane.run
29
+ end
30
+
31
+ def options
32
+ @options ||= Koality::Options.new
33
+ end
34
+
35
+ private
36
+
37
+ def setup_environment
38
+ options.ensure_output_directory_exists
39
+ end
40
+ end
41
+
42
+ end
43
+
@@ -0,0 +1,120 @@
1
+ require 'forwardable'
2
+ require 'fileutils'
3
+
4
+ module Koality
5
+ class Options
6
+ extend Forwardable
7
+
8
+ DEFAULTS = {
9
+ :abc_file_pattern => '{app,lib}/**/*.rb',
10
+ :abc_threshold => 15,
11
+ :abc_violations_threshold => 0,
12
+ :abc_enabled => true,
13
+
14
+ :style_file_pattern => '{app,lib,spec}/**/*.{rb,coffee,js}',
15
+ :style_line_length_threshold => 120,
16
+ :style_violations_threshold => 0,
17
+ :style_enabled => true,
18
+
19
+ :doc_file_pattern => '{app,lib}/**/*.rb',
20
+ :doc_violations_threshold => 0,
21
+ :doc_enabled => false,
22
+
23
+ :code_coverage_threshold => 90,
24
+ :code_coverage_file => 'code_coverage',
25
+ :code_coverage_enabled => true,
26
+
27
+ :rails_bp_accept_patterns => [],
28
+ :rails_bp_ignore_patterns => [],
29
+ :rails_bp_errors_threshold => 0,
30
+ :rails_bp_error_file => 'rails_best_practices_errors',
31
+ :rails_bp_enabled => true,
32
+
33
+ :custom_thresholds => [],
34
+ :total_violations_threshold => 0,
35
+ :abort_on_failure => true,
36
+ :output_directory => 'quality',
37
+
38
+ :colorize_output => true
39
+ }
40
+
41
+ attr_accessor :opts
42
+
43
+ def_delegators :@opts, :[], :[]=
44
+
45
+ def initialize(overrides = {})
46
+ self.opts = DEFAULTS.merge(overrides)
47
+ end
48
+
49
+ # Add a threshold check. If the file exists and it contains a number,
50
+ # compare that number with the given value using the operator.
51
+ def add_threshold(file, operator, value)
52
+ custom_thresholds << [operator, file, value]
53
+ end
54
+
55
+ def thresholds
56
+ custom_thresholds + runner_thresholds
57
+ end
58
+
59
+ def runner_thresholds
60
+ runners = []
61
+ runners << rails_bp_custom_threshold if rails_bp_enabled?
62
+ runners << code_coverage_custom_threshold if code_coverage_enabled?
63
+ runners
64
+ end
65
+
66
+ def ensure_output_directory_exists
67
+ FileUtils.mkdir_p output_directory
68
+ end
69
+
70
+ def output_file(name)
71
+ File.join(output_directory, opts[name])
72
+ end
73
+
74
+ def rails_bp_enabled?
75
+ defined?(Rails) && rails_bp_enabled
76
+ end
77
+
78
+ def code_coverage_enabled?
79
+ code_coverage_enabled
80
+ end
81
+
82
+ def colorize_output?
83
+ colorize_output
84
+ end
85
+
86
+ def respond_to_missing?(method)
87
+ writer?(method) || reader?(method)
88
+ end
89
+
90
+ private
91
+
92
+ def method_missing(method, *args)
93
+ if opt = writer?(method)
94
+ opts[opt] = args.first
95
+ elsif opt = reader?(method)
96
+ opts[opt]
97
+ else
98
+ super
99
+ end
100
+ end
101
+
102
+ def writer?(method)
103
+ /^(?<option>.+)=$/ =~ method.to_s
104
+ option && opts.key?(option.to_sym) && option.to_sym
105
+ end
106
+
107
+ def reader?(method)
108
+ opts.key?(method.to_sym) && method.to_sym
109
+ end
110
+
111
+ def rails_bp_custom_threshold
112
+ [:<=, output_file(:rails_bp_error_file), rails_bp_errors_threshold]
113
+ end
114
+
115
+ def code_coverage_custom_threshold
116
+ [:>=, output_file(:code_coverage_file), code_coverage_threshold]
117
+ end
118
+
119
+ end
120
+ end
@@ -0,0 +1,25 @@
1
+ require 'rake'
2
+ require 'rake/tasklib'
3
+ require 'koality'
4
+
5
+ module Koality
6
+ class RakeTask < ::Rake::TaskLib
7
+
8
+ def initialize(task_name = :koality)
9
+ yield Koality.options if block_given?
10
+
11
+ define_task task_name
12
+ end
13
+
14
+ def define_task(task_name)
15
+ unless ::Rake.application.last_comment
16
+ desc %(Ensures various code metrics are met)
17
+ end
18
+
19
+ task task_name do
20
+ Koality.run
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,39 @@
1
+ require 'terminal-table'
2
+ require 'term/ansicolor'
3
+ require 'benchmark'
4
+
5
+ class String
6
+ include Term::ANSIColor
7
+ end
8
+
9
+ module Koality
10
+ module Reporter
11
+ class Base
12
+
13
+ def self.start(&block)
14
+ reporter = new
15
+
16
+ time = Benchmark.measure do
17
+ yield reporter
18
+ end
19
+
20
+ puts "-- #{'%0.3f' % time.real}s\n\n"
21
+ end
22
+
23
+ private
24
+
25
+ def color(message, color_name)
26
+ if Koality.options.colorize_output?
27
+ message.to_s.send(color_name)
28
+ else
29
+ message
30
+ end
31
+ end
32
+
33
+ def build_table
34
+ Terminal::Table.new :style => {:width => 140, :padding_left => 2, :padding_right => 2}
35
+ end
36
+
37
+ end
38
+ end
39
+ end