maximus 0.1.1 → 0.1.2
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/README.md +2 -0
- data/lib/maximus.rb +0 -1
- data/lib/maximus/cli.rb +2 -1
- data/lib/maximus/constants.rb +2 -0
- data/lib/maximus/git_control.rb +94 -33
- data/lib/maximus/helper.rb +73 -36
- data/lib/maximus/lint.rb +46 -29
- data/lib/maximus/lints/brakeman.rb +11 -2
- data/lib/maximus/lints/jshint.rb +3 -0
- data/lib/maximus/lints/railsbp.rb +11 -2
- data/lib/maximus/lints/rubocop.rb +3 -0
- data/lib/maximus/lints/scsslint.rb +3 -0
- data/lib/maximus/reporter/git-lines.sh +1 -1
- data/lib/maximus/statistic.rb +22 -13
- data/lib/maximus/statistics/phantomas.rb +5 -2
- data/lib/maximus/statistics/stylestats.rb +17 -11
- data/lib/maximus/statistics/wraith.rb +8 -4
- data/lib/maximus/version.rb +1 -1
- data/maximus.gemspec +3 -4
- data/roadmap.md +2 -4
- metadata +33 -51
- data/lib/maximus/rake_tasks.rb +0 -13
- data/lib/maximus/tasks/be.rake +0 -35
- data/lib/maximus/tasks/fe.rake +0 -30
- data/lib/maximus/tasks/maximus.rake +0 -39
- data/lib/maximus/tasks/statistic.rake +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 70e71aa9bf1801ab2da6baad0c7a6de45759d5b2
|
4
|
+
data.tar.gz: 1f3fc9752270915bfe051d3e76ba034816c7c42b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2d24180804d7722eeaef5faedabc1ef5b0915af20ff9cee8cb30ce230cff669bd994f1de046894d6e96c35894f35aab4cce5b6248ab4a6d48b39961099bd287a
|
7
|
+
data.tar.gz: 04e6694a21cc3926fc9338b26827480f8423e104fb5562ead917959edb7a563f12a01c180ad154ded26ab4c4bb4ff6433bcc9f684d4ced8559ae98a71fc6334a
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Maximus
|
2
2
|
|
3
|
+
[](http://badge.fury.io/rb/maximus) [](https://codeclimate.com/github/wearefine/maximus)
|
4
|
+
|
3
5
|
The all-in-one linting solution.
|
4
6
|
|
5
7
|
Plays nice with Middleman and Rails.
|
data/lib/maximus.rb
CHANGED
data/lib/maximus/cli.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'thor'
|
2
2
|
|
3
|
+
# @since 0.1.0
|
3
4
|
class Maximus::CLI < Thor
|
4
5
|
include Thor::Actions
|
5
6
|
class_option :path, aliases: ["-p", "-u", "\--url"], default: nil, desc: "Space-separated path(s) to URLs or files"
|
@@ -46,7 +47,7 @@ class Maximus::CLI < Thor
|
|
46
47
|
return Maximus::GitControl.new({ commit: options[:commit], is_dev: true }).lints_and_stats(true)
|
47
48
|
end
|
48
49
|
|
49
|
-
#
|
50
|
+
# @todo something better than just installing in the global npm file
|
50
51
|
# and including phantomjs
|
51
52
|
desc "install", "Install all dependencies"
|
52
53
|
def install
|
data/lib/maximus/constants.rb
CHANGED
data/lib/maximus/git_control.rb
CHANGED
@@ -5,10 +5,23 @@ require 'rainbow'
|
|
5
5
|
require 'rainbow/ext/string'
|
6
6
|
|
7
7
|
module Maximus
|
8
|
+
# @since 0.1.0
|
8
9
|
class GitControl
|
9
10
|
|
10
11
|
include Helper
|
11
12
|
|
13
|
+
# Git management
|
14
|
+
#
|
15
|
+
# @param opts [Hash] the options to initialize and pass to other classes
|
16
|
+
# @option opts [Boolean] :is_dev whether or not the class was initialized from the command line
|
17
|
+
# @option opts [String] :log ('log/maximus_git.log') path to log file
|
18
|
+
# @option opts [String] :root_dir base directory
|
19
|
+
# @option opts [String] :base_url ('http://localhost:3000') the host - used for Statistics
|
20
|
+
# @option opts [String, Integer] :port port number - used for Statistics
|
21
|
+
# @option opts [String, Array] :path ('') path to files. Accepts glob notation
|
22
|
+
# @option opts [String] :commit accepts sha, "working", "last", or "master".
|
23
|
+
# Used in the command line
|
24
|
+
# @return [void] this method is used to set up instance variables
|
12
25
|
def initialize(opts = {})
|
13
26
|
opts[:is_dev] ||= false
|
14
27
|
opts[:log] = Logger.new('log/maximus_git.log') if opts[:log].nil?
|
@@ -24,7 +37,10 @@ module Maximus
|
|
24
37
|
@g = Git.open(@opts[:root_dir], :log => log)
|
25
38
|
end
|
26
39
|
|
27
|
-
#
|
40
|
+
# 30,000 foot view of a commit
|
41
|
+
#
|
42
|
+
# @param commitsha [String] the sha of the commit
|
43
|
+
# @return [Hash] commit data
|
28
44
|
def commit_export(commitsha = sha)
|
29
45
|
ce_commit = vccommit(commitsha)
|
30
46
|
ce_diff = diff(ce_commit, @g.object('HEAD^'))
|
@@ -40,8 +56,21 @@ module Maximus
|
|
40
56
|
end
|
41
57
|
|
42
58
|
# Compare two commits and get line number ranges of changed patches
|
43
|
-
#
|
44
|
-
#
|
59
|
+
#
|
60
|
+
# @example output from the method
|
61
|
+
# {
|
62
|
+
# 'sha': {
|
63
|
+
# rb: {
|
64
|
+
# filename: 'file.rb',
|
65
|
+
# changes: {
|
66
|
+
# ['0..4'],
|
67
|
+
# ['10..20']
|
68
|
+
# }
|
69
|
+
# }
|
70
|
+
# }
|
71
|
+
# }
|
72
|
+
#
|
73
|
+
# @return [Hash] diff_return files changed grouped by file extension and line number
|
45
74
|
def compare(sha1 = master_commit.sha, sha2 = sha)
|
46
75
|
diff_return = {}
|
47
76
|
|
@@ -54,10 +83,10 @@ module Maximus
|
|
54
83
|
end
|
55
84
|
end
|
56
85
|
|
57
|
-
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
#
|
86
|
+
# If working directory, just have a single item array.
|
87
|
+
# The space here is important because git-lines checks for a second arg,
|
88
|
+
# and if one is present, it runs git diff without a commit
|
89
|
+
# or a comparison to a commit.
|
61
90
|
git_diff = @psuedo_commit ? ['working directory'] : `git rev-list #{sha1}..#{sha2} --no-merges`.split("\n")
|
62
91
|
|
63
92
|
# Include the first sha because rev-list is doing a traversal
|
@@ -96,17 +125,29 @@ module Maximus
|
|
96
125
|
diff_return
|
97
126
|
end
|
98
127
|
|
99
|
-
# Run appropriate lint for every sha in commit history
|
100
|
-
#
|
101
|
-
#
|
102
|
-
#
|
103
|
-
#
|
128
|
+
# Run appropriate lint for every sha in commit history.
|
129
|
+
# For each sha a new branch is created then deleted
|
130
|
+
#
|
131
|
+
# @example sample output
|
132
|
+
# {
|
133
|
+
# 'sha': {
|
134
|
+
# lints: {
|
135
|
+
# scsslint: {
|
136
|
+
# files_inspec...
|
137
|
+
# },
|
138
|
+
# },
|
139
|
+
# statisti...
|
140
|
+
# },
|
141
|
+
# 'sha'...
|
142
|
+
# }
|
143
|
+
#
|
144
|
+
# @return [Hash] data all data grouped by task
|
104
145
|
def lints_and_stats(lint_by_path = false, git_shas = compare)
|
105
146
|
return false if git_shas.blank?
|
106
147
|
base_branch = branch
|
107
148
|
git_output = {}
|
108
149
|
git_shas.each do |sha, exts|
|
109
|
-
#
|
150
|
+
# @todo better way to silence git, in case there's a real error?
|
110
151
|
quietly { `git checkout #{sha} -b maximus_#{sha}` } unless @psuedo_commit
|
111
152
|
puts sha.to_s.color(:blue) if @@is_dev
|
112
153
|
git_output[sha.to_sym] = {
|
@@ -126,6 +167,7 @@ module Maximus
|
|
126
167
|
port: @opts[:port],
|
127
168
|
root_dir: @opts[:root_dir]
|
128
169
|
}
|
170
|
+
|
129
171
|
# This is where everything goes down
|
130
172
|
exts.each do |ext, files|
|
131
173
|
# For relevant_lines data
|
@@ -135,27 +177,27 @@ module Maximus
|
|
135
177
|
when :scss
|
136
178
|
lints[:scsslint] = Maximus::Scsslint.new(lint_opts).result
|
137
179
|
|
138
|
-
# Do not run statistics if called
|
180
|
+
# Do not run statistics if called from command line
|
139
181
|
if lint_opts[:commit].blank?
|
140
182
|
|
141
|
-
# stylestat is singular here because model name in Rails is singular.
|
142
|
-
#
|
143
|
-
#
|
183
|
+
# @todo stylestat is singular here because model name in Rails is singular.
|
184
|
+
# But adding a .classify when it's converted to a model chops off the end s on 'phantomas',
|
185
|
+
# which breaks the model name.
|
144
186
|
statistics[:stylestat] = Maximus::Stylestats.new(stat_opts).result
|
145
187
|
|
146
|
-
#
|
188
|
+
# @todo double pipe here is best way to say, if it's already run, don't run again, right?
|
147
189
|
statistics[:phantomas] ||= Maximus::Phantomas.new(stat_opts).result
|
148
190
|
statistics[:wraith] = Maximus::Wraith.new(stat_opts).result
|
149
191
|
end
|
150
192
|
when :js
|
151
193
|
lints[:jshint] = Maximus::Jshint.new(lint_opts).result
|
152
194
|
|
153
|
-
# Do not run statistics if called
|
195
|
+
# Do not run statistics if called from command line
|
154
196
|
if lint_opts[:commit].blank?
|
155
197
|
|
156
198
|
statistics[:phantomas] = Maximus::Phantomas.new(stat_opts).result
|
157
199
|
|
158
|
-
#
|
200
|
+
# @todo double pipe here is best way to say, if it's already run, don't run again, right?
|
159
201
|
statistics[:wraith] ||= Maximus::Wraith.new(stat_opts).result
|
160
202
|
end
|
161
203
|
when :ruby
|
@@ -166,7 +208,7 @@ module Maximus
|
|
166
208
|
lints[:railsbp] ||= Maximus::Railsbp.new(lint_opts).result
|
167
209
|
end
|
168
210
|
end
|
169
|
-
#
|
211
|
+
# @todo better way to silence git, in case there's a real error?
|
170
212
|
quietly {
|
171
213
|
@g.branch(base_branch).checkout
|
172
214
|
@g.branch("maximus_#{sha}").delete
|
@@ -179,15 +221,28 @@ module Maximus
|
|
179
221
|
protected
|
180
222
|
|
181
223
|
# Get list of file paths
|
182
|
-
#
|
224
|
+
#
|
225
|
+
# @param files [Hash] hash of files denoted by key 'filename'
|
226
|
+
# @param ext [String] file extension - different extensions are joined different ways
|
227
|
+
# @return [String] file paths delimited by comma or space
|
183
228
|
def lint_file_paths(files, ext)
|
184
229
|
file_list = files.map { |f| f[:filename] }.compact
|
185
230
|
# Lints accept files differently
|
186
231
|
ext == :ruby ? file_list.join(' ') : file_list.join(',')
|
187
232
|
end
|
188
233
|
|
189
|
-
#
|
190
|
-
#
|
234
|
+
# Determine which lines were added (where and how many) in a commit
|
235
|
+
#
|
236
|
+
# @example output from method
|
237
|
+
# {
|
238
|
+
# 'filename': [
|
239
|
+
# '0..10',
|
240
|
+
# '11..14'
|
241
|
+
# ]
|
242
|
+
# }
|
243
|
+
#
|
244
|
+
# @param git_sha [String] sha of the commit
|
245
|
+
# @return [Hash] ranges by lines added in a commit by file name
|
191
246
|
def lines_added(git_sha)
|
192
247
|
new_lines = {}
|
193
248
|
lines_added = `#{File.join(File.dirname(__FILE__), 'reporter/git-lines.sh')} #{git_sha}`.split("\n")
|
@@ -204,44 +259,50 @@ module Maximus
|
|
204
259
|
end
|
205
260
|
|
206
261
|
# Get last commit on current branch
|
207
|
-
#
|
262
|
+
#
|
263
|
+
# @return [String] sha
|
208
264
|
def sha
|
209
265
|
@g.object('HEAD').sha
|
210
266
|
end
|
211
267
|
|
212
|
-
# Get branch name
|
213
|
-
#
|
268
|
+
# Get current branch name
|
269
|
+
#
|
270
|
+
# @return [String]
|
214
271
|
def branch
|
215
272
|
`env -i git rev-parse --abbrev-ref HEAD`.strip!
|
216
273
|
end
|
217
274
|
|
218
275
|
# Get last commit on the master branch
|
219
|
-
#
|
276
|
+
#
|
277
|
+
# @return [Git::Object]
|
220
278
|
def master_commit
|
221
279
|
@g.branches[:master].gcommit
|
222
280
|
end
|
223
281
|
|
224
282
|
# Store last commit as Ruby Git::Object
|
225
|
-
#
|
283
|
+
# @param commitsha [String]
|
284
|
+
# @return [Git::Object]
|
226
285
|
def vccommit(commitsha = sha)
|
227
286
|
@g.gcommit(commitsha)
|
228
287
|
end
|
229
288
|
|
230
289
|
# Get general stats of commit on HEAD versus last commit on master branch
|
231
|
-
#
|
232
|
-
#
|
290
|
+
#
|
291
|
+
# @return [Git::Diff]
|
233
292
|
def diff(new_commit = vccommit, old_commit = master_commit)
|
234
293
|
@g.diff(new_commit, old_commit).stats
|
235
294
|
end
|
236
295
|
|
237
296
|
# Get remote URL
|
238
|
-
#
|
297
|
+
#
|
298
|
+
# @return [String, nil] nil returns if remotes is blank
|
239
299
|
def remote
|
240
300
|
@g.remotes.first.url unless @g.remotes.blank?
|
241
301
|
end
|
242
302
|
|
243
303
|
# Define associations to linters based on file extension
|
244
|
-
#
|
304
|
+
#
|
305
|
+
# @return [Hash] linters and extension arrays
|
245
306
|
def associations
|
246
307
|
{
|
247
308
|
scss: ['scss', 'sass'],
|
data/lib/maximus/helper.rb
CHANGED
@@ -5,51 +5,70 @@ require 'active_support/core_ext/object/blank'
|
|
5
5
|
require 'yaml'
|
6
6
|
|
7
7
|
module Maximus
|
8
|
+
# @since 0.1.0
|
8
9
|
module Helper
|
9
10
|
|
10
|
-
# See if
|
11
|
-
# This will usually be stored as a class variable in the inherited class
|
12
|
-
#
|
11
|
+
# See if project linted is a Rails app
|
12
|
+
# This will usually be stored as a class variable in the inherited class
|
13
|
+
# @example class variable
|
14
|
+
# @@is_rails = is_rails?
|
15
|
+
#
|
16
|
+
# @see Lint#initialize
|
17
|
+
#
|
18
|
+
# @return [Boolean]
|
13
19
|
def is_rails?
|
14
20
|
defined?(Rails)
|
15
21
|
end
|
16
22
|
|
17
23
|
# Get root directory of file being called
|
18
|
-
#
|
24
|
+
#
|
25
|
+
# @return [String] absolute path to root directory
|
19
26
|
def root_dir
|
20
27
|
is_rails? ? Rails.root.to_s : Dir.pwd.to_s
|
21
28
|
end
|
22
29
|
|
23
|
-
# Verify that
|
24
|
-
#
|
25
|
-
|
26
|
-
|
30
|
+
# Verify that command is available on the box before continuing
|
31
|
+
#
|
32
|
+
# @param command [String] command to check
|
33
|
+
# @param install_instructions [String] how to install the missing command
|
34
|
+
# @return [void] aborts the action if command not found
|
35
|
+
def node_module_exists(command, install_instructions = 'npm install -g')
|
36
|
+
cmd = `if hash #{command} 2>/dev/null; then
|
27
37
|
echo "true"
|
28
38
|
else
|
29
39
|
echo "false"
|
30
40
|
fi`
|
31
41
|
if cmd.include? "false"
|
32
|
-
command_msg = "Missing command #{
|
33
|
-
abort "#{command_msg}: Please run `#{install_instructions} #{
|
42
|
+
command_msg = "Missing command #{command}".color(:red)
|
43
|
+
abort "#{command_msg}: Please run `#{install_instructions} #{command}` And try again\n"
|
44
|
+
exit 1
|
34
45
|
end
|
35
46
|
end
|
36
47
|
|
37
|
-
# Look for a custom config in the app's config/ directory;
|
38
|
-
#
|
39
|
-
#
|
48
|
+
# Look for a custom config in the app's config/ directory;
|
49
|
+
# otherwise, use the built-in one.
|
50
|
+
# @todo best practice that this inherits the @opts from the model it's being included in?
|
51
|
+
#
|
52
|
+
# @param filename [String]
|
53
|
+
# @return [String] absolute path to the reporter file
|
40
54
|
def check_default(filename)
|
41
55
|
user_file = "#{@opts[:root_dir]}/config/#{filename}"
|
42
56
|
File.exist?(user_file) ? user_file : File.join(File.dirname(__FILE__), "config/#{filename}")
|
43
57
|
end
|
44
58
|
|
45
59
|
# Grab the absolute path of the reporter file
|
46
|
-
#
|
60
|
+
#
|
61
|
+
# @param filename [String]
|
62
|
+
# @return [String] absolute path to the reporter file
|
47
63
|
def reporter_path(filename)
|
48
64
|
File.join(File.dirname(__FILE__),"reporter/#{filename}")
|
49
65
|
end
|
50
66
|
|
51
67
|
# Find all files that were linted by extension
|
52
|
-
#
|
68
|
+
#
|
69
|
+
# @param path [String] path to folders
|
70
|
+
# @param ext [String] file extension to search for
|
71
|
+
# @return [Array<String>] list of file paths
|
53
72
|
def file_list(path, ext = 'scss', remover = '')
|
54
73
|
# Necessary so that directories aren't counted
|
55
74
|
collect_path = path.include?("*") ? path : "#{path}/**/*.#{ext}"
|
@@ -58,20 +77,26 @@ module Maximus
|
|
58
77
|
end
|
59
78
|
|
60
79
|
# Count how many files were linted
|
61
|
-
#
|
80
|
+
#
|
81
|
+
# @param path [String] path to folders
|
82
|
+
# @param ext [String] file extension to search for
|
83
|
+
# @return [Integer] number of files matched by the path
|
62
84
|
def file_count(path, ext = 'scss')
|
63
85
|
file_list(path, ext).length
|
64
86
|
end
|
65
87
|
|
66
88
|
# Convert string to boolean
|
67
|
-
#
|
89
|
+
#
|
90
|
+
# @param str [String] the string to evaluate
|
91
|
+
# @return [Boolean] whether or not the string is true
|
68
92
|
def truthy(str)
|
69
93
|
return true if str == true || str =~ (/^(true|t|yes|y|1)$/i)
|
70
94
|
return false if str == false || str.blank? || str =~ (/^(false|f|no|n|0)$/i)
|
71
95
|
end
|
72
96
|
|
73
97
|
# Edit and save a YAML file
|
74
|
-
#
|
98
|
+
#
|
99
|
+
# @return [void]
|
75
100
|
def edit_yaml(yaml_location, &block)
|
76
101
|
d = YAML.load_file(yaml_location)
|
77
102
|
block.call(d)
|
@@ -79,41 +104,53 @@ module Maximus
|
|
79
104
|
end
|
80
105
|
|
81
106
|
# Request user input
|
82
|
-
#
|
107
|
+
#
|
108
|
+
# @param args [Array<String>] prompts to request
|
109
|
+
# @return [String] user input to use elsewhere
|
83
110
|
def prompt(*args)
|
84
111
|
print(*args)
|
85
112
|
STDIN.gets
|
86
113
|
end
|
87
114
|
|
88
|
-
# Defines base
|
89
|
-
#
|
115
|
+
# Defines base logger
|
116
|
+
#
|
117
|
+
# @return [Logger] @@log for logging use
|
90
118
|
def mlog
|
91
119
|
@@log ||= Logger.new(STDOUT)
|
92
120
|
@@log.level ||= Logger::INFO
|
93
121
|
@@log
|
94
122
|
end
|
95
123
|
|
96
|
-
# Determine if current process was called by a rake task
|
97
|
-
# Returns Boolean
|
98
|
-
# http://stackoverflow.com/questions/2467208/how-can-i-tell-if-rails-code-is-being-run-via-rake-or-script-generate
|
99
|
-
def is_rake_task?
|
100
|
-
File.basename($0) == 'rake'
|
101
|
-
end
|
102
|
-
|
103
124
|
# Convert the array from lines_added into spelled-out ranges
|
104
|
-
#
|
105
|
-
#
|
106
|
-
#
|
107
|
-
#
|
108
|
-
#
|
109
|
-
#
|
125
|
+
# This is a GitControl helper but it's used in Lint
|
126
|
+
# @see GitControl#lines_added
|
127
|
+
# @see Lint#relevant_lint
|
128
|
+
#
|
129
|
+
# @example typical output
|
130
|
+
# lines_added = {'filename' => ['0..10', '11..14']}
|
131
|
+
# lines_added_to_range(lines_added)
|
132
|
+
# # output
|
133
|
+
# {
|
134
|
+
# 'filename': {
|
135
|
+
# {
|
136
|
+
# [0,1,2,3,4,5,6,7,8,9,10],
|
137
|
+
# [11,12,13,14]
|
138
|
+
# }
|
139
|
+
# }
|
140
|
+
# }
|
141
|
+
#
|
142
|
+
# @todo I'm sure there's a better way of doing this
|
143
|
+
# @todo figure out a better place to put this than in Helper
|
144
|
+
# @return [Hash] changes_array of spelled-out arrays of integers
|
110
145
|
def lines_added_to_range(file)
|
111
146
|
changes_array = file[:changes].map { |ch| ch.split("..").map(&:to_i) }
|
112
147
|
changes_array.map { |e| (e[0]..e[1]).to_a }.flatten!
|
113
148
|
end
|
114
149
|
|
115
|
-
# Ensure
|
116
|
-
#
|
150
|
+
# Ensure path exists
|
151
|
+
#
|
152
|
+
# @param path [String, Array] path to files can be directory or glob
|
153
|
+
# @return [Boolean]
|
117
154
|
def path_exists(path = @path)
|
118
155
|
path = path.split(' ') if path.is_a?(String) && path.include?(' ')
|
119
156
|
if path.is_a?(Array)
|