codeclimate 0.69.0 → 0.70.0

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.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/bin/prep-release +1 -1
  3. data/config/engines.yml +32 -323
  4. data/lib/cc/analyzer.rb +5 -4
  5. data/lib/cc/analyzer/bridge.rb +106 -0
  6. data/lib/cc/analyzer/composite_container_listener.rb +4 -8
  7. data/lib/cc/analyzer/container.rb +44 -41
  8. data/lib/cc/analyzer/container/result.rb +74 -0
  9. data/lib/cc/analyzer/container_listener.rb +2 -7
  10. data/lib/cc/analyzer/engine.rb +53 -45
  11. data/lib/cc/analyzer/engine_output.rb +40 -10
  12. data/lib/cc/analyzer/formatters/formatter.rb +2 -0
  13. data/lib/cc/analyzer/formatters/html_formatter.rb +4 -0
  14. data/lib/cc/analyzer/formatters/json_formatter.rb +1 -0
  15. data/lib/cc/analyzer/formatters/plain_text_formatter.rb +8 -1
  16. data/lib/cc/analyzer/issue.rb +4 -2
  17. data/lib/cc/analyzer/issue_validations/relative_path_validation.rb +6 -2
  18. data/lib/cc/analyzer/issue_validator.rb +3 -32
  19. data/lib/cc/analyzer/logging_container_listener.rb +9 -7
  20. data/lib/cc/analyzer/measurement.rb +22 -0
  21. data/lib/cc/analyzer/measurement_validations.rb +16 -0
  22. data/lib/cc/analyzer/measurement_validations/name_validation.rb +23 -0
  23. data/lib/cc/analyzer/measurement_validations/type_validation.rb +15 -0
  24. data/lib/cc/analyzer/measurement_validations/validation.rb +27 -0
  25. data/lib/cc/analyzer/measurement_validations/value_validation.rb +21 -0
  26. data/lib/cc/analyzer/measurement_validator.rb +11 -0
  27. data/lib/cc/analyzer/raising_container_listener.rb +18 -18
  28. data/lib/cc/analyzer/statsd_container_listener.rb +22 -22
  29. data/lib/cc/analyzer/validator.rb +38 -0
  30. data/lib/cc/cli.rb +12 -12
  31. data/lib/cc/cli/analyze.rb +42 -60
  32. data/lib/cc/cli/analyze/engine_failure.rb +11 -0
  33. data/lib/cc/cli/command.rb +0 -10
  34. data/lib/cc/cli/engines.rb +0 -3
  35. data/lib/cc/cli/engines/engine_command.rb +2 -34
  36. data/lib/cc/cli/engines/install.rb +11 -17
  37. data/lib/cc/cli/engines/list.rb +5 -3
  38. data/lib/cc/cli/prepare.rb +5 -11
  39. data/lib/cc/cli/runner.rb +1 -2
  40. data/lib/cc/cli/test.rb +0 -1
  41. data/lib/cc/cli/validate_config.rb +49 -63
  42. data/lib/cc/cli/version_checker.rb +3 -3
  43. data/lib/cc/config.rb +70 -0
  44. data/lib/cc/config/checks_adapter.rb +40 -0
  45. data/lib/cc/config/default_adapter.rb +52 -0
  46. data/lib/cc/config/engine.rb +41 -0
  47. data/lib/cc/config/engine_set.rb +47 -0
  48. data/lib/cc/config/json_adapter.rb +17 -0
  49. data/lib/cc/config/prepare.rb +92 -0
  50. data/lib/cc/config/validation/check_validator.rb +34 -0
  51. data/lib/cc/config/validation/engine_validator.rb +89 -0
  52. data/lib/cc/config/validation/fetch_validator.rb +78 -0
  53. data/lib/cc/config/validation/file_validator.rb +112 -0
  54. data/lib/cc/config/validation/hash_validations.rb +52 -0
  55. data/lib/cc/config/validation/json.rb +31 -0
  56. data/lib/cc/config/validation/prepare_validator.rb +40 -0
  57. data/lib/cc/config/validation/yaml.rb +66 -0
  58. data/lib/cc/config/yaml_adapter.rb +73 -0
  59. data/lib/cc/engine_registry.rb +74 -0
  60. data/lib/cc/workspace/path_tree/dir_node.rb +1 -1
  61. metadata +36 -55
  62. data/bin/codeclimate-init +0 -6
  63. data/config/coffeelint/coffeelint.json +0 -129
  64. data/config/csslint/.csslintrc +0 -2
  65. data/config/eslint/.eslintignore +0 -1
  66. data/config/eslint/.eslintrc.yml +0 -277
  67. data/config/rubocop/.rubocop.yml +0 -1156
  68. data/lib/cc/analyzer/config.rb +0 -86
  69. data/lib/cc/analyzer/engine_registry.rb +0 -36
  70. data/lib/cc/analyzer/engines_config_builder.rb +0 -97
  71. data/lib/cc/analyzer/engines_runner.rb +0 -64
  72. data/lib/cc/cli/config.rb +0 -44
  73. data/lib/cc/cli/config_generator.rb +0 -108
  74. data/lib/cc/cli/engines/disable.rb +0 -38
  75. data/lib/cc/cli/engines/enable.rb +0 -41
  76. data/lib/cc/cli/engines/remove.rb +0 -35
  77. data/lib/cc/cli/init.rb +0 -117
  78. data/lib/cc/cli/prepare/quality.rb +0 -64
  79. data/lib/cc/cli/upgrade_config_generator.rb +0 -42
@@ -1,44 +1,44 @@
1
1
  module CC
2
2
  module Analyzer
3
3
  class StatsdContainerListener < ContainerListener
4
- def initialize(engine_name, statsd)
5
- @engine_name = engine_name
4
+ def initialize(statsd)
6
5
  @statsd = statsd
7
6
  end
8
7
 
9
- def started(_data)
10
- increment("started")
8
+ def started(engine, _details)
9
+ increment(engine.name, "started")
11
10
  end
12
11
 
13
- def timed_out(data)
14
- timing("time", data.duration)
15
- increment("result.error")
16
- increment("result.error.timeout")
17
- end
18
-
19
- def finished(data)
20
- timing("time", data.duration)
21
- increment("finished")
22
-
23
- if data.status.success?
24
- increment("result.success")
12
+ def finished(engine, _details, result)
13
+ timing(engine.name, "time", result.duration)
14
+ increment(engine.name, "finished")
15
+
16
+ if result.timed_out?
17
+ timing(engine.name, "time", result.duration)
18
+ increment(engine.name, "result.error")
19
+ increment(engine.name, "result.error.timeout")
20
+ elsif result.maximum_output_exceeded?
21
+ increment(engine.name, "result.error")
22
+ increment(engine.name, "result.error.output_exceeded")
23
+ elsif result.exit_status.nonzero?
24
+ increment(engine.name, "result.error")
25
25
  else
26
- increment("result.error")
26
+ increment(engine.name, "result.success")
27
27
  end
28
28
  end
29
29
 
30
30
  private
31
31
 
32
- attr_reader :engine_name, :statsd
32
+ attr_reader :statsd
33
33
 
34
- def increment(metric)
34
+ def increment(name, metric)
35
35
  statsd.increment("engines.#{metric}")
36
- statsd.increment("engines.names.#{engine_name}.#{metric}")
36
+ statsd.increment("engines.names.#{name}.#{metric}")
37
37
  end
38
38
 
39
- def timing(metric, ms)
39
+ def timing(name, metric, ms)
40
40
  statsd.timing("engines.#{metric}", ms)
41
- statsd.timing("engines.names.#{engine_name}.#{metric}", ms)
41
+ statsd.timing("engines.names.#{name}.#{metric}", ms)
42
42
  end
43
43
  end
44
44
  end
@@ -0,0 +1,38 @@
1
+ module CC
2
+ module Analyzer
3
+ module Validator
4
+ attr_reader :error
5
+
6
+ def initialize(document)
7
+ @document = document
8
+ validate
9
+ end
10
+
11
+ def validate
12
+ return @valid unless @valid.nil?
13
+
14
+ if document && invalid_messages.any?
15
+ @error = {
16
+ message: "#{invalid_messages.join("; ")}: `#{document}`.",
17
+ document: document,
18
+ }
19
+ @valid = false
20
+ else
21
+ @valid = true
22
+ end
23
+ end
24
+ alias valid? validate
25
+
26
+ private
27
+
28
+ attr_reader :document
29
+
30
+ def invalid_messages
31
+ @invalid_messages ||= self.class.validations.each_with_object([]) do |check, result|
32
+ validator = check.new(document)
33
+ result << validator.message unless validator.valid?
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,20 +1,18 @@
1
1
  require "active_support"
2
- require "active_support/core_ext/module/remove_method" # Temporary, see https://github.com/codeclimate/codeclimate/pull/658
3
2
  require "active_support/core_ext"
4
3
  require "yaml"
5
4
  require "cc/analyzer"
5
+ require "cc/config"
6
+ require "cc/engine_registry"
6
7
  require "cc/workspace"
7
- require "cc/yaml"
8
8
 
9
9
  require "cc/cli/analyze"
10
10
  require "cc/cli/command"
11
11
  require "cc/cli/console"
12
12
  require "cc/cli/engines"
13
13
  require "cc/cli/help"
14
- require "cc/cli/init"
15
14
  require "cc/cli/output"
16
15
  require "cc/cli/prepare"
17
- require "cc/cli/prepare/quality"
18
16
  require "cc/cli/runner"
19
17
  require "cc/cli/test"
20
18
  require "cc/cli/validate_config"
@@ -26,15 +24,17 @@ module CC
26
24
  ENV["CODECLIMATE_DEBUG"]
27
25
  end
28
26
 
29
- def self.debug(message, values = {})
30
- if debug?
31
- if values.any?
32
- message << " "
33
- message << values.map { |k, v| "#{k}=#{v.inspect}" }.join(" ")
34
- end
35
-
36
- $stderr.puts("[DEBUG] #{message}")
27
+ def self.logger
28
+ @logger ||= ::Logger.new(STDERR).tap do |logger|
29
+ logger.level =
30
+ if debug?
31
+ ::Logger::DEBUG
32
+ else
33
+ ::Logger::ERROR
34
+ end
37
35
  end
38
36
  end
39
37
  end
38
+
39
+ Analyzer.logger = CLI.logger
40
40
  end
@@ -12,32 +12,33 @@ module CC
12
12
  " --dev Run in development mode. Engines installed locally that are not in the manifest will be run.\n" \
13
13
  " path Path to check. Can be specified multiple times.".freeze
14
14
 
15
+ autoload :EngineFailure, "cc/cli/analyze/engine_failure"
16
+
15
17
  include CC::Analyzer
16
18
 
17
- def initialize(_args = [])
18
- super
19
- @engine_options = []
20
- @path_options = []
19
+ def run
20
+ # Load config here so it sees ./.codeclimate.yml
21
+ @config = Config.load
21
22
 
23
+ # process args after, so it modifies loaded configuration
22
24
  process_args
23
- apply_config_options
24
- end
25
-
26
- def run
27
- require_codeclimate_yml
28
25
 
29
- Dir.chdir(MountedPath.code.container_path) do
30
- runner = EnginesRunner.new(registry, formatter, source_dir, config, path_options)
31
- runner.run
32
- end
33
- rescue EnginesRunner::NoEnabledEngines
34
- fatal("No enabled engines. Add some to your .codeclimate.yml file!")
26
+ bridge = Bridge.new(
27
+ config: config,
28
+ formatter: formatter,
29
+ listener: CompositeContainerListener.new(
30
+ LoggingContainerListener.new(Analyzer.logger),
31
+ RaisingContainerListener.new(EngineFailure),
32
+ ),
33
+ registry: EngineRegistry.new,
34
+ )
35
+
36
+ bridge.run
35
37
  end
36
38
 
37
39
  private
38
40
 
39
- attr_accessor :config
40
- attr_reader :engine_options, :path_options
41
+ attr_reader :config, :engines_disabled, :listener, :registry
41
42
 
42
43
  def process_args
43
44
  while (arg = @args.shift)
@@ -45,62 +46,43 @@ module CC
45
46
  when "-f", "--format"
46
47
  @formatter = Formatters.resolve(@args.shift).new(filesystem)
47
48
  when "-e", "--engine"
48
- @engine_options << @args.shift
49
+ disable_all_engines!
50
+ name, channel = @args.shift.split(":", 2)
51
+ enable_engine(name, channel)
49
52
  when "--dev"
50
- @dev_mode = true
53
+ config.development = true
54
+ when "--no-plugins"
55
+ config.disable_plugins!
51
56
  else
52
- @path_options << arg
57
+ config.analysis_paths << arg
53
58
  end
54
59
  end
55
- rescue Formatters::Formatter::InvalidFormatterError => e
56
- fatal(e.message)
57
- end
58
-
59
- def registry
60
- EngineRegistry.new(@dev_mode)
60
+ rescue Formatters::Formatter::InvalidFormatterError => ex
61
+ fatal(ex.message)
61
62
  end
62
63
 
63
64
  def formatter
64
65
  @formatter ||= Formatters::PlainTextFormatter.new(filesystem)
65
66
  end
66
67
 
67
- def source_dir
68
- MountedPath.code.host_path
69
- end
70
-
71
- def config
72
- @config ||= CC::Yaml.parse(filesystem.read_path(CODECLIMATE_YAML))
73
- end
74
-
75
- def apply_config_options
76
- if engine_options.any? && config.engines?
77
- filter_by_engine_options
78
- elsif engine_options.any?
79
- config["engines"] = CC::Yaml::Nodes::EngineList.new(config).with_value({})
68
+ def disable_all_engines!
69
+ unless engines_disabled
70
+ config.engines.each { |e| e.enabled = false }
71
+ @engines_disabled = true
80
72
  end
81
- add_engine_options
82
73
  end
83
74
 
84
- def filter_by_engine_options
85
- config.engines.keys.each do |engine|
86
- unless engine_options.include?(engine)
87
- config.engines.delete(engine)
88
- end
89
- end
90
- end
91
-
92
- def add_engine_options
93
- engine_options.each do |engine|
94
- name, channel = engine.split(":", 2)
95
-
96
- if config.engines.include?(engine)
97
- config.engines[name].enabled = true
98
- config.engines[name].channel = channel if channel
99
- else
100
- value = { "enabled" => true }
101
- value["channel"] = channel if channel
102
- config.engines[name] = CC::Yaml::Nodes::Engine.new(config.engines).with_value(value)
103
- end
75
+ def enable_engine(name, channel)
76
+ existing_engine = config.engines.detect { |e| e.name == name }
77
+ if existing_engine.present?
78
+ existing_engine.enabled = true
79
+ existing_engine.channel = channel if channel.present?
80
+ else
81
+ config.engines << Config::Engine.new(
82
+ name,
83
+ channel: channel,
84
+ enabled: true,
85
+ )
104
86
  end
105
87
  end
106
88
  end
@@ -0,0 +1,11 @@
1
+ module CC
2
+ module CLI
3
+ class Analyze < Command
4
+ class EngineFailure < StandardError
5
+ def initialize(message, _engine_name)
6
+ super(message)
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -73,12 +73,6 @@ module CC
73
73
  run
74
74
  end
75
75
 
76
- def require_codeclimate_yml
77
- unless filesystem.exist?(CODECLIMATE_YAML)
78
- fatal("No '.codeclimate.yml' file found. Run 'codeclimate init' to generate a config file.")
79
- end
80
- end
81
-
82
76
  private
83
77
 
84
78
  def filesystem
@@ -86,10 +80,6 @@ module CC
86
80
  CC::Analyzer::MountedPath.code.container_path,
87
81
  )
88
82
  end
89
-
90
- def engine_registry
91
- @engine_registry ||= CC::Analyzer::EngineRegistry.new
92
- end
93
83
  end
94
84
  end
95
85
  end
@@ -1,8 +1,5 @@
1
1
  require "cc/analyzer"
2
2
 
3
- require "cc/cli/engines/disable"
4
- require "cc/cli/engines/enable"
5
3
  require "cc/cli/engines/engine_command"
6
4
  require "cc/cli/engines/install"
7
5
  require "cc/cli/engines/list"
8
- require "cc/cli/engines/remove"
@@ -4,42 +4,10 @@ module CC
4
4
  module CLI
5
5
  module Engines
6
6
  class EngineCommand < Command
7
- include CC::Analyzer
8
-
9
7
  abstract!
10
8
 
11
- private
12
-
13
- def engine_name
14
- @engine_name ||= @args.first
15
- end
16
-
17
- def parsed_yaml
18
- @parsed_yaml ||= CC::Analyzer::Config.new(yaml_content)
19
- end
20
-
21
- def yaml_content
22
- filesystem.read_path(CODECLIMATE_YAML).freeze
23
- end
24
-
25
- def update_yaml
26
- filesystem.write_path(CODECLIMATE_YAML, parsed_yaml.to_yaml)
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
- engine_registry.exists?(engine_name)
39
- end
40
-
41
- def engine_registry_list
42
- engine_registry.list
9
+ def engine_registry
10
+ @engine_registry ||= EngineRegistry.new
43
11
  end
44
12
  end
45
13
  end
@@ -2,38 +2,32 @@ module CC
2
2
  module CLI
3
3
  module Engines
4
4
  class Install < EngineCommand
5
- SHORT_HELP = "Pull the latest images for enabled engines in your codeclimate.yml.".freeze
5
+ SHORT_HELP = "Pull the latest images for enabled engines in your configuration".freeze
6
6
 
7
7
  ImagePullFailure = Class.new(StandardError)
8
8
 
9
9
  def run
10
- require_codeclimate_yml
11
-
12
10
  say "Pulling docker images."
13
11
  pull_docker_images
14
12
  end
15
13
 
16
14
  private
17
15
 
18
- def pull_docker_images
19
- engine_names.each do |name|
20
- if engine_registry.exists?(name)
21
- images = engine_registry[name]["channels"].values
22
- images.each { |image| pull_engine_image(image) }
23
- else
24
- warn("unknown engine name: #{name}")
25
- end
26
- end
16
+ def config
17
+ @config ||= CC::Config.load
27
18
  end
28
19
 
29
- def engine_names
30
- @engine_names ||= parsed_yaml.engine_names
20
+ def pull_docker_images
21
+ config.engines.each(&method(:pull_engine))
31
22
  end
32
23
 
33
- def pull_engine_image(engine_image)
34
- unless system("docker pull #{engine_image}")
35
- raise ImagePullFailure, "unable to pull image #{engine_image}"
24
+ def pull_engine(engine)
25
+ metadata = engine_registry.fetch_engine_details(engine)
26
+ unless system("docker pull #{metadata.image}")
27
+ raise ImagePullFailure, "unable to pull image #{metadata.image}"
36
28
  end
29
+ rescue EngineRegistry::EngineDetailsNotFoundError
30
+ warn("unknown engine <#{engine.name}:#{engine.channel}>")
37
31
  end
38
32
  end
39
33
  end
@@ -6,9 +6,11 @@ module CC
6
6
 
7
7
  def run
8
8
  say "Available engines:"
9
- engine_registry_list.sort_by { |name, _| name }.each do |name, attributes|
10
- say "- #{name}: #{attributes["description"]}"
11
- end
9
+ engine_registry.
10
+ sort_by { |engine, _| engine.name }.
11
+ each do |engine, metadata|
12
+ say "- #{engine.name}: #{metadata.description}"
13
+ end
12
14
  end
13
15
  end
14
16
  end