codeclimate 0.69.0 → 0.70.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -2,33 +2,59 @@ module CC
2
2
  module Analyzer
3
3
  class EngineOutput
4
4
  delegate :blank?, to: :raw_output
5
- delegate :to_json, to: :as_issue
6
5
 
7
- def initialize(raw_output)
6
+ def initialize(name, raw_output)
7
+ @name = name
8
8
  @raw_output = raw_output
9
9
  end
10
10
 
11
11
  def issue?
12
- parsed_output &&
13
- parsed_output["type"].present? &&
14
- parsed_output["type"].downcase == "issue"
12
+ valid_with_type?("issue")
13
+ end
14
+
15
+ def measurement?
16
+ valid_with_type?("measurement")
15
17
  end
16
18
 
17
19
  def as_issue
18
- Issue.new(raw_output)
20
+ Issue.new(name, raw_output)
21
+ end
22
+
23
+ def to_json
24
+ if issue?
25
+ as_issue.to_json
26
+ elsif measurement?
27
+ Measurement.new(name, raw_output).to_json
28
+ end
19
29
  end
20
30
 
21
31
  def valid?
22
- validator.valid?
32
+ valid_json? && validator && validator.valid?
23
33
  end
24
34
 
25
35
  def error
26
- validator.error
36
+ if !valid_json?
37
+ { message: "Invalid JSON", output: raw_output }
38
+ elsif !validator.present?
39
+ { message: "Unsupported document type", output: raw_output }
40
+ else
41
+ validator.error
42
+ end
27
43
  end
28
44
 
29
45
  private
30
46
 
31
- attr_accessor :raw_output
47
+ attr_accessor :name, :raw_output
48
+
49
+ def valid_json?
50
+ parsed_output.present?
51
+ end
52
+
53
+ def valid_with_type?(type)
54
+ parsed_output &&
55
+ parsed_output["type"].present? &&
56
+ parsed_output["type"].downcase == type
57
+ end
32
58
 
33
59
  def parsed_output
34
60
  @parsed_output ||= JSON.parse(raw_output)
@@ -37,7 +63,11 @@ module CC
37
63
  end
38
64
 
39
65
  def validator
40
- IssueValidator.new(parsed_output)
66
+ if issue?
67
+ IssueValidator.new(parsed_output)
68
+ elsif measurement?
69
+ MeasurementValidator.new(parsed_output)
70
+ end
41
71
  end
42
72
  end
43
73
  end
@@ -16,6 +16,8 @@ module CC
16
16
  issues << json
17
17
  when "warning"
18
18
  warnings << json
19
+ when "measurement"
20
+ measurements << json
19
21
  else
20
22
  raise "Invalid type found: #{json["type"]}"
21
23
  end
@@ -405,6 +405,10 @@ module CC
405
405
  def warnings
406
406
  @warnings ||= []
407
407
  end
408
+
409
+ def measurements
410
+ @measurements ||= []
411
+ end
408
412
  end
409
413
  end
410
414
  end
@@ -17,6 +17,7 @@ module CC
17
17
 
18
18
  def write(data)
19
19
  document = JSON.parse(data)
20
+ return unless document["type"] == "issue"
20
21
  document["engine_name"] = current_engine.name
21
22
 
22
23
  if @has_begun
@@ -38,7 +38,10 @@ module CC
38
38
 
39
39
  def engine_running(engine, &block)
40
40
  super(engine) do
41
- with_spinner("Running #{current_engine.name}: ", &block)
41
+ result = with_spinner("Running #{current_engine.name}: ", &block)
42
+ if result.skipped?
43
+ puts(colorize("Skipped #{current_engine.name}: #{result.stderr}", :yellow))
44
+ end
42
45
  end
43
46
  end
44
47
 
@@ -85,6 +88,10 @@ module CC
85
88
  @warnings ||= []
86
89
  end
87
90
 
91
+ def measurements
92
+ @measurements ||= []
93
+ end
94
+
88
95
  def pluralize(number, noun)
89
96
  "#{ActiveSupport::NumberHelper.number_to_delimited(number)} #{noun.pluralize(number)}"
90
97
  end
@@ -16,12 +16,14 @@ module CC
16
16
  type
17
17
  ]
18
18
 
19
- def initialize(output)
19
+ def initialize(engine_name, output)
20
+ @engine_name = engine_name
20
21
  @output = output
21
22
  end
22
23
 
23
24
  def as_json(*)
24
25
  parsed_output.reverse_merge!(
26
+ "engine_name" => engine_name,
25
27
  "fingerprint" => fingerprint,
26
28
  ).merge!("severity" => severity)
27
29
  end
@@ -43,7 +45,7 @@ module CC
43
45
 
44
46
  private
45
47
 
46
- attr_reader :output
48
+ attr_reader :engine_name, :output
47
49
 
48
50
  def default_fingerprint
49
51
  SourceFingerprint.new(self).compute
@@ -4,10 +4,14 @@ module CC
4
4
  module Analyzer
5
5
  module IssueValidations
6
6
  class RelativePathValidation < Validation
7
+ BUILDER_CODE_PATH = "/tmp/workspace/code".freeze
8
+
7
9
  def valid?
8
10
  path &&
9
- !path.start_with?("/") &&
10
- relative_to?(MountedPath.code.container_path)
11
+ !path.start_with?("/") && (
12
+ relative_to?(MountedPath.code.container_path) ||
13
+ relative_to?(BUILDER_CODE_PATH)
14
+ )
11
15
  end
12
16
 
13
17
  def message
@@ -1,39 +1,10 @@
1
1
  module CC
2
2
  module Analyzer
3
3
  class IssueValidator
4
- CHECKS = IssueValidations.validations.freeze
4
+ include Validator
5
5
 
6
- attr_reader :error
7
-
8
- def initialize(issue)
9
- @issue = issue
10
- validate
11
- end
12
-
13
- def validate
14
- return @valid unless @valid.nil?
15
-
16
- if issue && invalid_messages.any?
17
- @error = {
18
- message: "#{invalid_messages.join("; ")}: `#{issue}`.",
19
- issue: issue,
20
- }
21
- @valid = false
22
- else
23
- @valid = true
24
- end
25
- end
26
- alias valid? validate
27
-
28
- private
29
-
30
- attr_reader :issue
31
-
32
- def invalid_messages
33
- @invalid_messages ||= CHECKS.each_with_object([]) do |check, result|
34
- validator = check.new(issue)
35
- result << validator.message unless validator.valid?
36
- end
6
+ def self.validations
7
+ IssueValidations.validations
37
8
  end
38
9
  end
39
10
  end
@@ -1,22 +1,24 @@
1
1
  module CC
2
2
  module Analyzer
3
3
  class LoggingContainerListener < ContainerListener
4
- def initialize(engine_name, logger)
5
- @engine_name = engine_name
4
+ def initialize(logger)
6
5
  @logger = logger
7
6
  end
8
7
 
9
- def started(_data)
10
- logger.info("starting engine #{engine_name}")
8
+ def started(engine, _details)
9
+ logger.info("starting engine #{engine.name}")
11
10
  end
12
11
 
13
- def finished(_data)
14
- logger.info("finished engine #{engine_name}")
12
+ def finished(engine, _details, result)
13
+ logger.info("finished engine #{engine.name}")
14
+ if result.skipped?
15
+ logger.warn("skipped engine #{engine.name}: #{result.stderr}")
16
+ end
15
17
  end
16
18
 
17
19
  private
18
20
 
19
- attr_reader :engine_name, :logger
21
+ attr_reader :logger
20
22
  end
21
23
  end
22
24
  end
@@ -0,0 +1,22 @@
1
+ module CC
2
+ module Analyzer
3
+ class Measurement
4
+ def initialize(engine_name, output)
5
+ @engine_name = engine_name
6
+ @output = output
7
+ end
8
+
9
+ def as_json(*)
10
+ parsed_output.merge("engine_name" => engine_name)
11
+ end
12
+
13
+ private
14
+
15
+ attr_reader :engine_name, :output
16
+
17
+ def parsed_output
18
+ @parsed_output ||= JSON.parse(output)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,16 @@
1
+ module CC
2
+ module Analyzer
3
+ module MeasurementValidations
4
+ autoload :NameValidation, "cc/analyzer/measurement_validations/name_validation"
5
+ autoload :TypeValidation, "cc/analyzer/measurement_validations/type_validation"
6
+ autoload :ValueValidation, "cc/analyzer/measurement_validations/value_validation"
7
+ autoload :Validation, "cc/analyzer/measurement_validations/validation"
8
+
9
+ def self.validations
10
+ constants.sort.map(&method(:const_get)).select do |klass|
11
+ klass.is_a?(Class) && klass.superclass == Validation
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,23 @@
1
+ module CC
2
+ module Analyzer
3
+ module MeasurementValidations
4
+ class NameValidation < Validation
5
+ REGEX = /^[A-Za-z0-9_\.\-]+$/
6
+
7
+ def valid?
8
+ name && name.is_a?(String) && REGEX.match?(name)
9
+ end
10
+
11
+ def message
12
+ "Name must be present and contain only letters, numbers, periods, hyphens, and underscores"
13
+ end
14
+
15
+ private
16
+
17
+ def name
18
+ object["name"]
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,15 @@
1
+ module CC
2
+ module Analyzer
3
+ module MeasurementValidations
4
+ class TypeValidation < Validation
5
+ def valid?
6
+ type && type.casecmp("measurement").zero?
7
+ end
8
+
9
+ def message
10
+ "Type must be 'measurement' but was '#{type}'"
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,27 @@
1
+ module CC
2
+ module Analyzer
3
+ module MeasurementValidations
4
+ class Validation
5
+ def initialize(object)
6
+ @object = object
7
+ end
8
+
9
+ def valid?
10
+ raise NotImplementedError
11
+ end
12
+
13
+ def message
14
+ raise NotImplementedError
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :object
20
+
21
+ def type
22
+ object["type"]
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ module CC
2
+ module Analyzer
3
+ module MeasurementValidations
4
+ class ValueValidation < Validation
5
+ def valid?
6
+ value && value.is_a?(Numeric)
7
+ end
8
+
9
+ def message
10
+ "Value must be present and numeric"
11
+ end
12
+
13
+ private
14
+
15
+ def value
16
+ object["value"]
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,11 @@
1
+ module CC
2
+ module Analyzer
3
+ class MeasurementValidator
4
+ include Validator
5
+
6
+ def self.validations
7
+ MeasurementValidations.validations
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,32 +1,32 @@
1
1
  module CC
2
2
  module Analyzer
3
3
  class RaisingContainerListener < ContainerListener
4
- def initialize(engine_name, failure_ex, timeout_ex)
5
- @engine_name = engine_name
4
+ def initialize(failure_ex, timeout_ex = nil, maximum_output_ex = nil)
6
5
  @failure_ex = failure_ex
7
- @timeout_ex = timeout_ex
6
+ @timeout_ex = timeout_ex || failure_ex
7
+ @maximum_output_ex = maximum_output_ex || failure_ex
8
8
  end
9
9
 
10
- def timed_out(data)
11
- message = "engine #{engine_name} ran for #{data.duration / 1000} seconds"
12
- message << " and was killed"
13
-
14
- raise timeout_ex, message
15
- end
16
-
17
- def finished(data)
18
- unless data.status.success?
19
- message = "engine #{engine_name} failed"
20
- message << " with status #{data.status.exitstatus}"
21
- message << " and stderr \n#{data.stderr}"
22
-
23
- raise failure_ex, message
10
+ def finished(engine, _details, result)
11
+ if result.timed_out?
12
+ message = "engine #{engine.name} ran for #{result.duration / 1000}"
13
+ message << " seconds and was killed"
14
+ raise timeout_ex.new(message, engine.name)
15
+ elsif result.maximum_output_exceeded?
16
+ message = "engine #{engine.name} produced too much output"
17
+ message << " (#{result.output_byte_count} bytes)"
18
+ raise maximum_output_ex.new(message, engine.name)
19
+ elsif result.exit_status.nonzero?
20
+ message = "engine #{engine.name} failed"
21
+ message << " with status #{result.exit_status}"
22
+ message << " and stderr \n#{result.stderr}"
23
+ raise failure_ex.new(message, engine.name)
24
24
  end
25
25
  end
26
26
 
27
27
  private
28
28
 
29
- attr_reader :engine_name, :failure_ex, :timeout_ex
29
+ attr_reader :failure_ex, :timeout_ex, :maximum_output_ex
30
30
  end
31
31
  end
32
32
  end