maximus 0.1.3 → 0.1.4
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.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.rspec +2 -0
- data/.travis.yml +10 -0
- data/README.md +35 -14
- data/lib/maximus/cli.rb +1 -0
- data/lib/maximus/config.rb +148 -135
- data/lib/maximus/git_control.rb +96 -96
- data/lib/maximus/helper.rb +1 -0
- data/lib/maximus/lint.rb +119 -118
- data/lib/maximus/lints/brakeman.rb +14 -14
- data/lib/maximus/lints/railsbp.rb +13 -13
- data/lib/maximus/reporter/git-lines.sh +40 -11
- data/lib/maximus/statistic.rb +30 -25
- data/lib/maximus/statistics/phantomas.rb +11 -11
- data/lib/maximus/statistics/stylestats.rb +52 -55
- data/lib/maximus/statistics/wraith.rb +21 -25
- data/lib/maximus/version.rb +1 -1
- data/maximus.gemspec +4 -0
- data/roadmap.md +3 -6
- data/spec/maximus/config_spec.rb +44 -0
- data/spec/spec_helper.rb +4 -0
- metadata +51 -3
@@ -54,20 +54,20 @@ module Maximus
|
|
54
54
|
|
55
55
|
private
|
56
56
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
57
|
+
# Convert to {file:README.md Maximus format}
|
58
|
+
#
|
59
|
+
# @param error [Hash] lint error
|
60
|
+
# @return [Hash]
|
61
|
+
def hash_for_brakeman(error, type)
|
62
|
+
{
|
63
|
+
linter: error['warning_type'],
|
64
|
+
severity: type.chomp('s'),
|
65
|
+
reason: error['message'],
|
66
|
+
column: 0,
|
67
|
+
line: error['line'].to_i,
|
68
|
+
confidence: error['confidence']
|
69
|
+
}
|
70
|
+
end
|
71
71
|
|
72
72
|
end
|
73
73
|
end
|
@@ -45,19 +45,19 @@ module Maximus
|
|
45
45
|
|
46
46
|
private
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
48
|
+
# Convert to {file:README.md Maximus format}
|
49
|
+
#
|
50
|
+
# @param error [Hash] lint error
|
51
|
+
# @return [Hash]
|
52
|
+
def hash_for_railsbp(error)
|
53
|
+
{
|
54
|
+
linter: error['message'].gsub(/\((.*)\)/, '').strip.parameterize('_').camelize,
|
55
|
+
severity: 'warning',
|
56
|
+
reason: error['message'],
|
57
|
+
column: 0,
|
58
|
+
line: error['line_number'].to_i
|
59
|
+
}
|
60
|
+
end
|
61
61
|
|
62
62
|
end
|
63
63
|
end
|
@@ -7,24 +7,53 @@ function lines-added(){
|
|
7
7
|
local line=
|
8
8
|
local start=
|
9
9
|
local finish=
|
10
|
+
local unified=1
|
10
11
|
while read; do
|
11
12
|
esc=$'\033'
|
12
13
|
if [[ $REPLY =~ ---\ (a/)?.* ]]; then
|
13
14
|
continue
|
14
15
|
elif [[ $REPLY =~ \+\+\+\ (b/)?([^[:blank:]$esc]+).* ]]; then
|
15
16
|
path=${BASH_REMATCH[2]}
|
16
|
-
|
17
|
-
|
17
|
+
# @@ -1,2, +3,4 @@
|
18
|
+
elif [[ $REPLY =~ @@\ -([0-9]+)?,([0-9]+)?\ \+([0-9]+)?,([0-9]+)?\ @@.* ]]; then
|
19
|
+
|
20
|
+
# hunk deletion
|
21
|
+
# @@ -7,5 +7,3 @@
|
22
|
+
# 0..0
|
23
|
+
if [[ ${BASH_REMATCH[2]} > ${BASH_REMATCH[4]} ]]; then
|
18
24
|
line="0..0"
|
19
|
-
|
20
|
-
|
25
|
+
|
26
|
+
# line(s) addition
|
27
|
+
# @@ -3,2, +3,3 @@
|
28
|
+
# 4..4
|
29
|
+
elif [[ ${BASH_REMATCH[1]} = ${BASH_REMATCH[3]} ]]; then
|
30
|
+
line="$((${BASH_REMATCH[1]} + $unified))..$((${BASH_REMATCH[4]} - ${BASH_REMATCH[2]} + ${BASH_REMATCH[1]}))"
|
31
|
+
|
32
|
+
# full deletion
|
33
|
+
# @@ -1,2, +0,0 @@
|
34
|
+
# 0..0
|
35
|
+
elif [[ ${BASH_REMATCH[3]} = ${BASH_REMATCH[4]} ]]; then
|
36
|
+
line="0..0"
|
37
|
+
|
38
|
+
# hunk addition
|
39
|
+
# @@ -0,0, +1,5 @@
|
40
|
+
# 0..4
|
41
|
+
elif [[ ${BASH_REMATCH[1]} = ${BASH_REMATCH[2]} ]]; then
|
42
|
+
line="$((${BASH_REMATCH[3]} - $unified))..$((${BASH_REMATCH[4]} - ${BASH_REMATCH[3]} + $unified))"
|
43
|
+
|
44
|
+
# additions with deletions
|
45
|
+
# @@ -13,3 +11,3 @@
|
46
|
+
# 12..12
|
47
|
+
elif [[ ${BASH_REMATCH[2]} = ${BASH_REMATCH[4]} ]]; then
|
48
|
+
line="$((${BASH_REMATCH[1]} - $unified))..$((${BASH_REMATCH[1]} - $unified))"
|
49
|
+
|
21
50
|
else
|
22
|
-
|
51
|
+
|
52
|
+
# @@ -13,3 +11,4 @@
|
53
|
+
# 12..13
|
54
|
+
line="$((${BASH_REMATCH[1]} - $unified))..${BASH_REMATCH[1]}"
|
55
|
+
|
23
56
|
fi
|
24
|
-
elif [[ $REPLY =~ @@\ -([0-9])?,([0-9]+)?\ \+([0-9]+)?\ @@.* ]]; then
|
25
|
-
line="${BASH_REMATCH[3]}..${BASH_REMATCH[3]}"
|
26
|
-
elif [[ $REPLY =~ @@\ -([0-9]+)?,\ \+([0-9]+)?\ @@.* ]]; then
|
27
|
-
line="0..${BASH_REMATCH[2]}"
|
28
57
|
elif [[ $REPLY =~ ^($esc\[[0-9;]+m)*([\ +-]) ]]; then
|
29
58
|
echo "$path:$line"
|
30
59
|
fi
|
@@ -51,7 +80,7 @@ function diff-lines(){
|
|
51
80
|
}
|
52
81
|
|
53
82
|
if [ -z "$2" ]; then
|
54
|
-
git diff $1^ $1 --unified=
|
83
|
+
git diff $1^ $1 --unified=1 | lines-added
|
55
84
|
else
|
56
|
-
git diff --unified=
|
85
|
+
git diff --unified=1 | lines-added
|
57
86
|
fi
|
data/lib/maximus/statistic.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
module Maximus
|
2
|
+
|
3
|
+
# Parent class for all statistics (inherited by children)
|
2
4
|
# @since 0.1.0
|
3
|
-
# @attr_accessor output [Hash] result of a
|
5
|
+
# @attr_accessor output [Hash] result of a statistic parsed by Statistic#refine
|
4
6
|
class Statistic
|
5
7
|
attr_accessor :output
|
6
8
|
|
@@ -17,6 +19,9 @@ module Maximus
|
|
17
19
|
# end
|
18
20
|
#
|
19
21
|
# Inherits settings from {Config#initialize}
|
22
|
+
#
|
23
|
+
# @see Config#initialize
|
24
|
+
#
|
20
25
|
# @param opts [Hash] ({}) options passed directly to statistic
|
21
26
|
# @option file_paths [Array, String] stat only specific files or directories
|
22
27
|
# Accepts globs too
|
@@ -25,8 +30,8 @@ module Maximus
|
|
25
30
|
# @return [void] this method is used to set up instance variables
|
26
31
|
def initialize(opts = {})
|
27
32
|
|
28
|
-
|
29
|
-
@settings
|
33
|
+
@config = opts[:config] || Maximus::Config.new(opts)
|
34
|
+
@settings = @config.settings
|
30
35
|
|
31
36
|
@path = opts[:file_paths] || @settings[:file_paths]
|
32
37
|
|
@@ -41,34 +46,34 @@ module Maximus
|
|
41
46
|
|
42
47
|
protected
|
43
48
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
49
|
+
# Organize stat output on the @output variable
|
50
|
+
# Adds @output[:statistics][:filepath] with all statistic data
|
51
|
+
# Ignores if is_dev or if stats_cli is blank
|
52
|
+
#
|
53
|
+
# @param stats_cli [String] JSON data from a lint result
|
54
|
+
# @param file_path [String] key value to organize stats output
|
55
|
+
# @return [Hash] organized stats data
|
56
|
+
def refine(stats_cli, file_path)
|
52
57
|
|
53
|
-
|
54
|
-
|
58
|
+
# Stop right there unless you mean business
|
59
|
+
return puts stats_cli if @config.is_dev?
|
55
60
|
|
56
|
-
|
57
|
-
|
61
|
+
# JSON.parse will throw an abortive error if it's given an empty string
|
62
|
+
return false if stats_cli.blank?
|
58
63
|
|
59
|
-
|
60
|
-
|
64
|
+
stats = JSON.parse(stats_cli)
|
65
|
+
@output[:statistics][file_path.to_sym] ||= {}
|
61
66
|
|
62
|
-
|
63
|
-
|
67
|
+
# @todo is there a better way to do this?
|
68
|
+
fp = @output[:statistics][file_path.to_s.to_sym]
|
64
69
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
70
|
+
# @todo Can I do like a self << thing here?
|
71
|
+
stats.each do |stat, value|
|
72
|
+
fp[stat.to_sym] = value
|
73
|
+
end
|
69
74
|
|
70
|
-
|
71
|
-
|
75
|
+
@output
|
76
|
+
end
|
72
77
|
|
73
78
|
end
|
74
79
|
end
|
@@ -13,28 +13,28 @@ module Maximus
|
|
13
13
|
node_module_exists('phantomas')
|
14
14
|
|
15
15
|
@path = @settings[:paths] if @path.blank?
|
16
|
-
@domain =
|
16
|
+
@domain = @config.domain
|
17
17
|
|
18
18
|
# Phantomas doesn't actually skip the skip-modules defined in the config BUT here's to hoping for future support
|
19
19
|
phantomas_cli = "phantomas --config=#{@settings[:phantomas]} "
|
20
|
-
phantomas_cli +=
|
20
|
+
phantomas_cli += @config.is_dev? ? '--colors' : '--reporter=json:no-skip'
|
21
21
|
phantomas_cli += " --proxy=#{@domain}"
|
22
22
|
@path.is_a?(Hash) ? @path.each { |label, url| phantomas_by_url(url, phantomas_cli) } : phantomas_by_url(@path, phantomas_cli)
|
23
|
-
|
23
|
+
@config.destroy_temp('phantomas')
|
24
24
|
@output
|
25
25
|
end
|
26
26
|
|
27
27
|
|
28
28
|
private
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
30
|
+
# Organize stat output on the @output variable
|
31
|
+
# Adds @output[:statistics][:filepath] with all statistic data
|
32
|
+
# @return [void] goes to refine statistics
|
33
|
+
def phantomas_by_url(url, phantomas_cli)
|
34
|
+
puts "Phantomas on #{@domain + url}".color(:green)
|
35
|
+
phantomas = `#{phantomas_cli} #{@domain + url}`
|
36
|
+
refine(phantomas, url)
|
37
|
+
end
|
38
38
|
|
39
39
|
end
|
40
40
|
end
|
@@ -2,9 +2,7 @@ module Maximus
|
|
2
2
|
# @since 0.1.0
|
3
3
|
class Stylestats < Maximus::Statistic
|
4
4
|
|
5
|
-
#
|
6
|
-
# If stylestatting one file, pass that as an array
|
7
|
-
#
|
5
|
+
# Produces CSS statistics
|
8
6
|
# @see Statistic#initialize
|
9
7
|
def result
|
10
8
|
|
@@ -24,8 +22,7 @@ module Maximus
|
|
24
22
|
puts "#{'stylestats'.color(:green)}: #{pretty_name}\n\n"
|
25
23
|
|
26
24
|
# include JSON formatter unless we're in dev
|
27
|
-
stylestats = `stylestats #{file} --config=#{@settings[:stylestats]} #{'--type=json' unless
|
28
|
-
puts stylestats
|
25
|
+
stylestats = `stylestats #{file} --config=#{@settings[:stylestats]} #{'--type=json' unless @config.is_dev?}`
|
29
26
|
refine(stylestats, pretty_name)
|
30
27
|
|
31
28
|
File.delete(file)
|
@@ -34,7 +31,7 @@ module Maximus
|
|
34
31
|
if is_rails?
|
35
32
|
# @todo I'd rather Rake::Task but it's not working in different directories
|
36
33
|
Dir.chdir(@settings[:root_dir]) do
|
37
|
-
if
|
34
|
+
if @config.is_dev?
|
38
35
|
# @todo review that this may not be best practice, but it's really noisy in the console
|
39
36
|
quietly { `rake assets:clobber` }
|
40
37
|
else
|
@@ -42,7 +39,7 @@ module Maximus
|
|
42
39
|
end
|
43
40
|
end
|
44
41
|
end
|
45
|
-
|
42
|
+
@config.destroy_temp('stylestats')
|
46
43
|
@output
|
47
44
|
|
48
45
|
end
|
@@ -50,67 +47,67 @@ module Maximus
|
|
50
47
|
|
51
48
|
private
|
52
49
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
50
|
+
# Find all CSS files or compile.
|
51
|
+
#
|
52
|
+
# Uses sprockets if Rails; Sass engine otherwise.
|
53
|
+
# Compass is supported
|
54
|
+
# @return [Array] CSS files
|
55
|
+
def find_css_files
|
56
|
+
searched_files = []
|
57
|
+
|
58
|
+
if is_rails?
|
59
|
+
# Only load tasks if we're not running a rake task
|
60
|
+
Rails.application.load_tasks unless @config.is_dev?
|
61
|
+
|
62
|
+
puts "\n"
|
63
|
+
puts 'Compiling assets for stylestats...'.color(:blue)
|
64
|
+
|
65
|
+
# @todo I'd rather Rake::Task but it's not working in different directories
|
66
|
+
Dir.chdir(@settings[:root_dir]) do
|
67
|
+
if @config.is_dev?
|
68
|
+
# @todo review that this may not be best practice, but it's really noisy in the console
|
69
|
+
quietly { `rake assets:precompile` }
|
70
|
+
else
|
71
|
+
`rake assets:precompile`
|
72
|
+
end
|
75
73
|
end
|
76
|
-
end
|
77
74
|
|
78
|
-
|
79
|
-
|
80
|
-
|
75
|
+
Dir.glob(@path).select { |f| File.file? f }.each do |file|
|
76
|
+
searched_files << file
|
77
|
+
end
|
81
78
|
|
82
|
-
|
79
|
+
else
|
83
80
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
81
|
+
# Load Compass paths if the gem exists
|
82
|
+
if Gem::Specification::find_all_by_name('compass').any?
|
83
|
+
require 'compass'
|
84
|
+
Compass.sass_engine_options[:load_paths].each do |path|
|
85
|
+
Sass.load_paths << path
|
86
|
+
end
|
89
87
|
end
|
90
|
-
end
|
91
88
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
89
|
+
# Shouldn't need to load paths anymore, but in case this doesn't work
|
90
|
+
# as it should, try the func below
|
91
|
+
# Dir.glob(@path).select { |d| File.directory? d}.each do |directory|
|
92
|
+
# Sass.load_paths << directory
|
93
|
+
# end
|
97
94
|
|
98
|
-
|
95
|
+
@path += ".scss"
|
99
96
|
|
100
|
-
|
101
|
-
|
102
|
-
|
97
|
+
Dir[@path].select { |f| File.file? f }.each do |file|
|
98
|
+
# @todo don't compile file if it starts with an underscore
|
99
|
+
scss_file = File.open(file, 'rb') { |f| f.read }
|
103
100
|
|
104
|
-
|
105
|
-
|
106
|
-
|
101
|
+
output_file = File.open( file.split('.').reverse.drop(1).reverse.join('.'), "w" )
|
102
|
+
output_file << Sass::Engine.new(scss_file, { syntax: :scss, quiet: true, style: :compressed }).render
|
103
|
+
output_file.close
|
107
104
|
|
108
|
-
|
105
|
+
searched_files << output_file.path
|
109
106
|
|
107
|
+
end
|
110
108
|
end
|
109
|
+
searched_files
|
111
110
|
end
|
112
|
-
searched_files
|
113
|
-
end
|
114
111
|
|
115
112
|
end
|
116
113
|
end
|
@@ -2,10 +2,7 @@ module Maximus
|
|
2
2
|
# @since 0.1.0
|
3
3
|
class Wraith < Maximus::Statistic
|
4
4
|
|
5
|
-
#
|
6
|
-
# Requires config to be in config/wraith/history.yaml
|
7
|
-
# Adds a new config/wraith/history.yaml if not present
|
8
|
-
# Path should be an Array defined as [{ label: url }]
|
5
|
+
# Generates screenshots for visual regression testing
|
9
6
|
# @see Statistic#initialize
|
10
7
|
def result
|
11
8
|
|
@@ -30,7 +27,6 @@ module Maximus
|
|
30
27
|
else
|
31
28
|
puts `wraith history #{configpath}`
|
32
29
|
end
|
33
|
-
File.write('said.yml', wraith_yaml.to_yaml)
|
34
30
|
File.delete(configpath)
|
35
31
|
wraith_parse browser
|
36
32
|
end
|
@@ -40,27 +36,27 @@ module Maximus
|
|
40
36
|
|
41
37
|
private
|
42
38
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
39
|
+
# Get a diff percentage of all changes by label and screensize
|
40
|
+
#
|
41
|
+
# @example {:statistics=>{:/=>{:percent_changed=>[{1024=>0.0}, {767=>0.0}, {1024=>0.0}, {767=>0.0}, {1024=>0.0}, {767=>0.0}, {1024=>0.0}, {767=>0.0}] } }}
|
42
|
+
# @param browser [String] headless browser used to generate the gallery
|
43
|
+
# @return [Hash] { path: { percent_changed: [{ size: percent_diff }] } }
|
44
|
+
def wraith_parse(browser)
|
45
|
+
Dir.glob("#{@settings[:root_dir]}/maximus_wraith_#{browser}/**/*.txt").select { |f| File.file? f }.each do |file|
|
46
|
+
file_object = File.open(file, 'rb')
|
47
|
+
orig_label = File.dirname(file).split('/').last
|
48
|
+
label = @settings[:paths][orig_label]
|
49
|
+
@output[:statistics][browser.to_sym] ||= {}
|
50
|
+
@output[:statistics][browser.to_sym][label.to_sym] ||= {}
|
51
|
+
browser_output = @output[:statistics][browser.to_sym][label.to_sym]
|
52
|
+
browser_output ||= {}
|
53
|
+
browser_output[:name] = orig_label
|
54
|
+
browser_output[:percent_changed] ||= []
|
55
|
+
browser_output[:percent_changed] << { File.basename(file).split('_')[0].to_i => file_object.read.to_f }
|
56
|
+
file_object.close
|
57
|
+
end
|
58
|
+
@output
|
61
59
|
end
|
62
|
-
@output
|
63
|
-
end
|
64
60
|
|
65
61
|
end
|
66
62
|
end
|