codeclimate 0.0.0 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/codeclimate +8 -0
- data/config/engines.yml +95 -0
- data/lib/cc/analyzer.rb +26 -0
- data/lib/cc/analyzer/config.rb +73 -0
- data/lib/cc/analyzer/engine.rb +108 -0
- data/lib/cc/analyzer/engine_registry.rb +21 -0
- data/lib/cc/analyzer/filesystem.rb +48 -0
- data/lib/cc/analyzer/formatters.rb +19 -0
- data/lib/cc/analyzer/formatters/formatter.rb +29 -0
- data/lib/cc/analyzer/formatters/json_formatter.rb +28 -0
- data/lib/cc/analyzer/formatters/plain_text_formatter.rb +114 -0
- data/lib/cc/analyzer/formatters/spinner.rb +34 -0
- data/lib/cc/analyzer/issue_sorter.rb +30 -0
- data/lib/cc/analyzer/location_description.rb +51 -0
- data/lib/cc/analyzer/null_config.rb +9 -0
- data/lib/cc/analyzer/source_buffer.rb +49 -0
- data/lib/cc/analyzer/unit_name.rb +14 -0
- data/lib/cc/cli.rb +17 -0
- data/lib/cc/cli/analyze.rb +91 -0
- data/lib/cc/cli/command.rb +65 -0
- data/lib/cc/cli/console.rb +12 -0
- data/lib/cc/cli/engines.rb +14 -0
- data/lib/cc/cli/engines/disable.rb +31 -0
- data/lib/cc/cli/engines/enable.rb +35 -0
- data/lib/cc/cli/engines/engine_command.rb +47 -0
- data/lib/cc/cli/engines/install.rb +49 -0
- data/lib/cc/cli/engines/list.rb +14 -0
- data/lib/cc/cli/engines/remove.rb +29 -0
- data/lib/cc/cli/help.rb +36 -0
- data/lib/cc/cli/init.rb +53 -0
- data/lib/cc/cli/runner.rb +60 -0
- data/lib/cc/cli/validate_config.rb +75 -0
- data/lib/cc/cli/version.rb +15 -0
- metadata +217 -10
- data/lib/codeclimate.rb +0 -0
@@ -0,0 +1,65 @@
|
|
1
|
+
require "highline"
|
2
|
+
require "active_support"
|
3
|
+
require "active_support/core_ext"
|
4
|
+
require "rainbow"
|
5
|
+
|
6
|
+
module CC
|
7
|
+
module CLI
|
8
|
+
class Command
|
9
|
+
CODECLIMATE_YAML = ".codeclimate.yml".freeze
|
10
|
+
|
11
|
+
def initialize(args = [])
|
12
|
+
@args = args
|
13
|
+
end
|
14
|
+
|
15
|
+
def run
|
16
|
+
$stderr.puts "unknown command #{self.class.name.split('::').last.underscore}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.command_name
|
20
|
+
name[/[^:]*$/].split(/(?=[A-Z])/).map(&:downcase).join('-')
|
21
|
+
end
|
22
|
+
|
23
|
+
def execute
|
24
|
+
run
|
25
|
+
end
|
26
|
+
|
27
|
+
def say(message)
|
28
|
+
terminal.say message
|
29
|
+
end
|
30
|
+
|
31
|
+
def warn(message)
|
32
|
+
terminal.say(colorize("WARNING: #{message}", :yellow))
|
33
|
+
end
|
34
|
+
|
35
|
+
def fatal(message)
|
36
|
+
$stderr.puts colorize(message, :red)
|
37
|
+
exit 1
|
38
|
+
end
|
39
|
+
|
40
|
+
def require_codeclimate_yml
|
41
|
+
if !filesystem.exist?(CODECLIMATE_YAML)
|
42
|
+
fatal("No '.codeclimate.yml' file found. Run 'codeclimate init' to generate a config file.")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def colorize(string, *args)
|
49
|
+
rainbow.wrap(string).color(*args)
|
50
|
+
end
|
51
|
+
|
52
|
+
def rainbow
|
53
|
+
@rainbow ||= Rainbow.new
|
54
|
+
end
|
55
|
+
|
56
|
+
def filesystem
|
57
|
+
@filesystem ||= CC::Analyzer::Filesystem.new(ENV['FILESYSTEM_DIR'])
|
58
|
+
end
|
59
|
+
|
60
|
+
def terminal
|
61
|
+
@terminal ||= HighLine.new($stdin, $stdout)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "cc/analyzer"
|
2
|
+
|
3
|
+
module CC
|
4
|
+
module CLI
|
5
|
+
module Engines
|
6
|
+
autoload :Disable, "cc/cli/engines/disable"
|
7
|
+
autoload :Enable, "cc/cli/engines/enable"
|
8
|
+
autoload :EngineCommand, "cc/cli/engines/engine_command"
|
9
|
+
autoload :Install, "cc/cli/engines/install"
|
10
|
+
autoload :List, "cc/cli/engines/list"
|
11
|
+
autoload :Remove, "cc/cli/engines/remove"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "cc/analyzer"
|
2
|
+
|
3
|
+
module CC
|
4
|
+
module CLI
|
5
|
+
module Engines
|
6
|
+
class Disable < EngineCommand
|
7
|
+
def run
|
8
|
+
require_codeclimate_yml
|
9
|
+
|
10
|
+
if !engine_exists?
|
11
|
+
say "Engine not found. Run 'codeclimate engines:list' for a list of valid engines."
|
12
|
+
elsif !engine_present_in_yaml?
|
13
|
+
say "Engine not found in .codeclimate.yml."
|
14
|
+
elsif !engine_enabled?
|
15
|
+
say "Engine already disabled."
|
16
|
+
else
|
17
|
+
disable_engine
|
18
|
+
update_yaml
|
19
|
+
say "Engine disabled."
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def disable_engine
|
26
|
+
parsed_yaml.disable_engine(engine_name)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "cc/analyzer"
|
2
|
+
|
3
|
+
module CC
|
4
|
+
module CLI
|
5
|
+
module Engines
|
6
|
+
class Enable < EngineCommand
|
7
|
+
def run
|
8
|
+
require_codeclimate_yml
|
9
|
+
|
10
|
+
if !engine_exists?
|
11
|
+
say "Engine not found. Run 'codeclimate engines:list' for a list of valid engines."
|
12
|
+
elsif engine_enabled?
|
13
|
+
say "Engine already enabled."
|
14
|
+
pull_docker_images
|
15
|
+
else
|
16
|
+
enable_engine
|
17
|
+
update_yaml
|
18
|
+
say "Engine added to .codeclimate.yml."
|
19
|
+
pull_docker_images
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def pull_docker_images
|
26
|
+
Engines::Install.new.run
|
27
|
+
end
|
28
|
+
|
29
|
+
def enable_engine
|
30
|
+
parsed_yaml.enable_engine(engine_name)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require "cc/analyzer"
|
2
|
+
|
3
|
+
module CC
|
4
|
+
module CLI
|
5
|
+
module Engines
|
6
|
+
class EngineCommand < Command
|
7
|
+
include CC::Analyzer
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def engine_name
|
12
|
+
@engine_name ||= @args.first
|
13
|
+
end
|
14
|
+
|
15
|
+
def parsed_yaml
|
16
|
+
@parsed_yaml ||= CC::Analyzer::Config.new(yaml_content)
|
17
|
+
end
|
18
|
+
|
19
|
+
def yaml_content
|
20
|
+
File.read(filesystem.path_for(CODECLIMATE_YAML)).freeze
|
21
|
+
end
|
22
|
+
|
23
|
+
def update_yaml
|
24
|
+
File.open(filesystem.path_for(CODECLIMATE_YAML), "w") do |f|
|
25
|
+
f.write(parsed_yaml.to_yaml)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def engine_present_in_yaml?
|
30
|
+
parsed_yaml.engine_present?(engine_name)
|
31
|
+
end
|
32
|
+
|
33
|
+
def engine_enabled?
|
34
|
+
parsed_yaml.engine_enabled?(engine_name)
|
35
|
+
end
|
36
|
+
|
37
|
+
def engine_exists?
|
38
|
+
engines_registry_list.keys.include?(engine_name)
|
39
|
+
end
|
40
|
+
|
41
|
+
def engines_registry_list
|
42
|
+
@engines_registry_list ||= CC::Analyzer::EngineRegistry.new.list
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require "cc/analyzer"
|
2
|
+
|
3
|
+
module CC
|
4
|
+
module CLI
|
5
|
+
module Engines
|
6
|
+
class Install < EngineCommand
|
7
|
+
ImagePullFailure = Class.new(StandardError)
|
8
|
+
|
9
|
+
def run
|
10
|
+
require_codeclimate_yml
|
11
|
+
|
12
|
+
say "Pulling docker images."
|
13
|
+
pull_docker_images
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def pull_docker_images
|
19
|
+
engine_names.each do |name|
|
20
|
+
if engine_exists?(name)
|
21
|
+
image = engine_image(name)
|
22
|
+
pull_engine_image(image)
|
23
|
+
else
|
24
|
+
warn("unknown engine name: #{name}")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def engine_names
|
30
|
+
@engine_names ||= parsed_yaml.engine_names
|
31
|
+
end
|
32
|
+
|
33
|
+
def engine_exists?(engine_name)
|
34
|
+
engines_registry_list.keys.include?(engine_name)
|
35
|
+
end
|
36
|
+
|
37
|
+
def engine_image(engine_name)
|
38
|
+
engines_registry_list[engine_name]["image_name"]
|
39
|
+
end
|
40
|
+
|
41
|
+
def pull_engine_image(engine_image)
|
42
|
+
if !system("docker pull #{engine_image}")
|
43
|
+
raise ImagePullFailure, "unable to pull image #{engine_image}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module CC
|
2
|
+
module CLI
|
3
|
+
module Engines
|
4
|
+
class List < EngineCommand
|
5
|
+
def run
|
6
|
+
say "Available engines:"
|
7
|
+
engines_registry_list.sort_by { |name, _| name }.each do |name, attributes|
|
8
|
+
say "- #{name}: #{attributes["description"]}"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "cc/analyzer"
|
2
|
+
|
3
|
+
module CC
|
4
|
+
module CLI
|
5
|
+
module Engines
|
6
|
+
class Remove < EngineCommand
|
7
|
+
def run
|
8
|
+
require_codeclimate_yml
|
9
|
+
|
10
|
+
if !engine_exists?
|
11
|
+
say "Engine not found. Run 'codeclimate engines:list' for a list of valid engines."
|
12
|
+
elsif !engine_present_in_yaml?
|
13
|
+
say "Engine not found in .codeclimate.yml."
|
14
|
+
else
|
15
|
+
remove_engine
|
16
|
+
update_yaml
|
17
|
+
say "Engine removed from .codeclimate.yml."
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def remove_engine
|
24
|
+
parsed_yaml.remove_engine(engine_name)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/cc/cli/help.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require "rainbow"
|
2
|
+
|
3
|
+
module CC
|
4
|
+
module CLI
|
5
|
+
class Help < Command
|
6
|
+
def run
|
7
|
+
say "Usage: codeclimate COMMAND ...\n\nAvailable commands:\n"
|
8
|
+
commands.each do |command|
|
9
|
+
say " #{command}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def commands
|
16
|
+
[
|
17
|
+
"analyze [-f format]",
|
18
|
+
"console",
|
19
|
+
"engines:disable #{underline('engine_name')}",
|
20
|
+
"engines:enable #{underline('engine_name')}",
|
21
|
+
"engines:install",
|
22
|
+
"engines:list",
|
23
|
+
"engines:remove #{underline('engine_name')}",
|
24
|
+
"help",
|
25
|
+
"init",
|
26
|
+
"validate-config",
|
27
|
+
"version"
|
28
|
+
].freeze
|
29
|
+
end
|
30
|
+
|
31
|
+
def underline(string)
|
32
|
+
return Rainbow.new.wrap(string).underline
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/cc/cli/init.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
module CC
|
2
|
+
module CLI
|
3
|
+
class Init < Command
|
4
|
+
include CC::Analyzer
|
5
|
+
|
6
|
+
def run
|
7
|
+
if filesystem.exist?(CODECLIMATE_YAML)
|
8
|
+
say "Config file .codeclimate.yml already present.\nTry running 'validate-config' to check configuration."
|
9
|
+
else
|
10
|
+
create_codeclimate_yaml
|
11
|
+
say "Config file .codeclimate.yml successfully generated.\nEdit and then try running 'validate-config' to check configuration."
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def create_codeclimate_yaml
|
18
|
+
config = { "engines" => {} }
|
19
|
+
eligible_engines.each do |engine_name, engine_config|
|
20
|
+
config["engines"][engine_name] = {
|
21
|
+
"enabled" => true
|
22
|
+
}
|
23
|
+
config["ratings"] ||= {}
|
24
|
+
config["ratings"]["paths"] ||= []
|
25
|
+
|
26
|
+
config["ratings"]["paths"] |= engine_config["default_ratings_paths"]
|
27
|
+
end
|
28
|
+
|
29
|
+
if filesystem.exist?("vendor")
|
30
|
+
config["exclude_paths"] = ["vendor/**/*"]
|
31
|
+
end
|
32
|
+
|
33
|
+
File.write(filesystem.path_for(CODECLIMATE_YAML), config.to_yaml)
|
34
|
+
end
|
35
|
+
|
36
|
+
def engine_eligible?(engine)
|
37
|
+
!engine["community"] &&
|
38
|
+
engine["enable_regexps"].present? &&
|
39
|
+
filesystem.any? do |path|
|
40
|
+
engine["enable_regexps"].any? { |re| Regexp.new(re).match(path) }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def eligible_engines
|
45
|
+
CC::Analyzer::EngineRegistry.new.list.each_with_object({}) do |(engine_name, config), result|
|
46
|
+
if engine_eligible?(config)
|
47
|
+
result[engine_name] = config
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require "active_support"
|
2
|
+
require "active_support/core_ext"
|
3
|
+
|
4
|
+
module CC
|
5
|
+
module CLI
|
6
|
+
class Runner
|
7
|
+
|
8
|
+
def self.run(argv)
|
9
|
+
new(argv).run
|
10
|
+
rescue => ex
|
11
|
+
$stderr.puts("error: (#{ex.class}) #{ex.message}")
|
12
|
+
|
13
|
+
if ENV["CODECLIMATE_DEBUG"]
|
14
|
+
$stderr.puts("backtrace: #{ex.backtrace.join("\n\t")}")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(args)
|
19
|
+
@args = args
|
20
|
+
end
|
21
|
+
|
22
|
+
def run
|
23
|
+
if command_class
|
24
|
+
command = command_class.new(command_arguments)
|
25
|
+
command.execute
|
26
|
+
else
|
27
|
+
command_not_found
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def command_not_found
|
32
|
+
$stderr.puts "unknown command #{command}"
|
33
|
+
exit 1
|
34
|
+
end
|
35
|
+
|
36
|
+
def command_class
|
37
|
+
CLI.const_get(command_name)
|
38
|
+
rescue NameError
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
|
42
|
+
def command_name
|
43
|
+
case command
|
44
|
+
when nil, '-h', '-?', '--help' then 'Help'
|
45
|
+
when '-v', '--version' then 'Version'
|
46
|
+
else command.sub(":", "::").underscore.camelize
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def command_arguments
|
51
|
+
@args[1..-1]
|
52
|
+
end
|
53
|
+
|
54
|
+
def command
|
55
|
+
@args.first
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|