codeclimate 0.0.0 → 0.0.1
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/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
|