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.
@@ -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,12 @@
1
+ module CC
2
+ module CLI
3
+ class Console < Command
4
+
5
+ def run
6
+ require "pry"
7
+ binding.pry(quiet: true, prompt: Pry::SIMPLE_PROMPT, output: $stdout)
8
+ end
9
+
10
+ end
11
+ end
12
+ 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
@@ -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
@@ -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