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,5 +1,3 @@
1
- require "cc/cli/config"
2
- require "cc/resolv"
3
1
  require "fileutils"
4
2
  require "ipaddr"
5
3
  require "json"
@@ -7,6 +5,8 @@ require "net/http"
7
5
  require "pathname"
8
6
  require "uri"
9
7
 
8
+ require "cc/resolv"
9
+
10
10
  module CC
11
11
  module CLI
12
12
  class Prepare < Command
@@ -29,13 +29,7 @@ module CC
29
29
  ].freeze
30
30
 
31
31
  def run
32
- require_codeclimate_yml
33
- fatal("No fetches configured") unless fetches.present?
34
-
35
- Dir.chdir(CC::Analyzer::MountedPath.code.container_path) do
36
- ::CC::Resolv.with_fixed_dns { fetch_all }
37
- end
38
- success("All fetches fetched")
32
+ ::CC::Resolv.with_fixed_dns { fetch_all }
39
33
  rescue FetchError, InternalHostError => ex
40
34
  fatal(ex.message)
41
35
  end
@@ -47,11 +41,11 @@ module CC
47
41
  end
48
42
 
49
43
  def fetches
50
- @fetches ||= config[:prepare] && config[:prepare].fetch
44
+ @fetches ||= config.prepare.fetch
51
45
  end
52
46
 
53
47
  def config
54
- @config ||= CC::Yaml.parse(filesystem.read_path(CODECLIMATE_YAML))
48
+ @config ||= CC::Config.load
55
49
  end
56
50
 
57
51
  def fetch_all
@@ -9,8 +9,7 @@ module CC
9
9
  new(argv).run
10
10
  rescue => ex
11
11
  $stderr.puts("error: (#{ex.class}) #{ex.message}")
12
-
13
- CLI.debug("backtrace: #{ex.backtrace.join("\n\t")}")
12
+ CLI.logger.debug("backtrace: #{ex.backtrace.join("\n\t")}")
14
13
  exit 1
15
14
  end
16
15
 
@@ -1,4 +1,3 @@
1
- require "cc/yaml"
2
1
  require "tmpdir"
3
2
 
4
3
  module CC
@@ -1,97 +1,83 @@
1
- require "cc/yaml"
2
-
3
1
  module CC
4
2
  module CLI
5
3
  class ValidateConfig < Command
6
- SHORT_HELP = "Validate your .codeclimate.yml.".freeze
7
-
8
- include CC::Analyzer
9
- include CC::Yaml
10
-
11
- VALID_CONFIG_MESSAGE = "No errors or warnings found in .codeclimate.yml file.".freeze
4
+ NO_CONFIG_MESSAGE = "No checked in config: nothing to validate.".freeze
5
+ TOO_MANY_CONFIG_MESSAGE = "Don't commit both .codeclimate.yml & .codeclimate.json: only the JSON will be used.".freeze
6
+ SHORT_HELP = "Validate your .codeclimate.yml or .codeclimate.json.".freeze
7
+ VALID_CONFIG_MESSAGE = "No errors or warnings found in %s.".freeze
12
8
 
13
9
  def run
14
- require_codeclimate_yml
15
- verify_yaml
16
- end
10
+ require_json_or_yaml
11
+ process_args
17
12
 
18
- private
19
-
20
- def verify_yaml
21
13
  if any_issues?
22
14
  display_issues
23
15
  else
24
- puts colorize(VALID_CONFIG_MESSAGE, :green)
16
+ puts format(VALID_CONFIG_MESSAGE, validator.path)
25
17
  end
26
- end
27
18
 
28
- def any_issues?
29
- parsed_yaml.errors? || parsed_yaml.nested_warnings.any? || parsed_yaml.warnings? || invalid_engines.any?
19
+ exit 1 unless validator.valid?
30
20
  end
31
21
 
32
- def yaml_content
33
- filesystem.read_path(CODECLIMATE_YAML).freeze
34
- end
22
+ private
35
23
 
36
- def parsed_yaml
37
- @parsed_yaml ||= CC::Yaml.parse(yaml_content)
38
- end
24
+ attr_reader :config, :registry_path, :registry_prefix, :validator
39
25
 
40
- def warnings
41
- @warnings ||= parsed_yaml.warnings
42
- end
26
+ def process_args
27
+ @registry_path = EngineRegistry::DEFAULT_MANIFEST_PATH
28
+ @registry_prefix = ""
43
29
 
44
- def nested_warnings
45
- @nested_warnings ||= parsed_yaml.nested_warnings
30
+ # Undocumented; we only need these from Builder so we can validate
31
+ # engines/channels against our own registry and prefix.
32
+ while (arg = @args.shift)
33
+ case arg
34
+ when "--registry" then @registry_path = @args.shift
35
+ when "--registry-prefix" then @registry_prefix = @args.shift
36
+ end
37
+ end
46
38
  end
47
39
 
48
- def errors
49
- @errors ||= parsed_yaml.errors
40
+ def any_issues?
41
+ validator.errors.any? ||
42
+ validator.warnings.any?
50
43
  end
51
44
 
52
45
  def display_issues
53
- display_errors
54
- display_warnings
55
- display_invalid_engines
56
- display_nested_warnings
57
- end
58
-
59
- def display_errors
60
- errors.each do |error|
61
- puts colorize("ERROR: #{error}", :red)
62
- end
63
- end
64
-
65
- def display_nested_warnings
66
- nested_warnings.each do |nested_warning|
67
- if nested_warning[0][0]
68
- puts colorize("WARNING in #{nested_warning[0][0]}: #{nested_warning[1]}", :red)
69
- end
46
+ validator.errors.each do |error|
47
+ puts "#{colorize("ERROR", :red)}: #{error}"
70
48
  end
71
- end
72
49
 
73
- def display_warnings
74
- warnings.each do |warning|
75
- puts colorize("WARNING: #{warning}", :red)
50
+ validator.warnings.each do |warning|
51
+ puts "#{colorize("WARNING", :yellow)}: #{warning}"
76
52
  end
77
53
  end
78
54
 
79
- def display_invalid_engines
80
- invalid_engines.each do |engine_name|
81
- puts colorize("WARNING: unknown engine <#{engine_name}>", :red)
55
+ def require_json_or_yaml
56
+ if !filesystem.exist?(Config::YAMLAdapter::DEFAULT_PATH) && !filesystem.exist?(Config::JSONAdapter::DEFAULT_PATH)
57
+ puts NO_CONFIG_MESSAGE
58
+ exit 0
59
+ elsif filesystem.exist?(Config::YAMLAdapter::DEFAULT_PATH) && filesystem.exist?(Config::JSONAdapter::DEFAULT_PATH)
60
+ puts "#{colorize("WARNING", :yellow)}: #{TOO_MANY_CONFIG_MESSAGE}"
82
61
  end
83
62
  end
84
63
 
85
- def invalid_engines
86
- @invalid_engines ||= engine_names.reject { |engine_name| engine_registry.exists? engine_name }
87
- end
88
-
89
- def engine_names
90
- @engine_names ||= engines.keys
64
+ def validator
65
+ @validator =
66
+ if filesystem.exist?(Config::JSONAdapter::DEFAULT_PATH)
67
+ Config::Validation::JSON.new(
68
+ Config::JSONAdapter::DEFAULT_PATH,
69
+ engine_registry,
70
+ )
71
+ elsif filesystem.exist?(Config::YAMLAdapter::DEFAULT_PATH)
72
+ Config::Validation::YAML.new(
73
+ Config::YAMLAdapter::DEFAULT_PATH,
74
+ engine_registry,
75
+ )
76
+ end
91
77
  end
92
78
 
93
- def engines
94
- @engines ||= parsed_yaml.engines || {}
79
+ def engine_registry
80
+ EngineRegistry.new(registry_path, registry_prefix)
95
81
  end
96
82
  end
97
83
  end
@@ -16,7 +16,7 @@ module CC
16
16
 
17
17
  global_config.save
18
18
  rescue => error
19
- CLI.debug(error)
19
+ CLI.logger.debug(error)
20
20
  end
21
21
 
22
22
  private
@@ -42,7 +42,7 @@ module CC
42
42
  begin
43
43
  cache! JSON.parse(api_response_body)
44
44
  rescue JSON::ParserError => error
45
- CLI.debug(error)
45
+ CLI.logger.debug(error)
46
46
  {
47
47
  "outdated" => false,
48
48
  }
@@ -56,7 +56,7 @@ module CC
56
56
  raise Net::HTTPFatalError.new("HTTP Error", http_response)
57
57
  end
58
58
  rescue Net::HTTPFatalError => error
59
- CLI.debug(error)
59
+ CLI.logger.debug(error)
60
60
  ""
61
61
  end
62
62
 
@@ -0,0 +1,70 @@
1
+ require "cc/config/checks_adapter"
2
+ require "cc/config/default_adapter"
3
+ require "cc/config/engine"
4
+ require "cc/config/engine_set"
5
+ require "cc/config/json_adapter"
6
+ require "cc/config/prepare"
7
+ require "cc/config/validation/hash_validations"
8
+ require "cc/config/validation/check_validator"
9
+ require "cc/config/validation/engine_validator"
10
+ require "cc/config/validation/fetch_validator"
11
+ require "cc/config/validation/file_validator"
12
+ require "cc/config/validation/json"
13
+ require "cc/config/validation/prepare_validator"
14
+ require "cc/config/validation/yaml"
15
+ require "cc/config/yaml_adapter"
16
+
17
+ module CC
18
+ class Config
19
+ attr_reader \
20
+ :analysis_paths,
21
+ :engines,
22
+ :exclude_patterns,
23
+ :prepare
24
+
25
+ attr_writer \
26
+ :development
27
+
28
+ def self.load
29
+ config =
30
+ if File.exist?(JSONAdapter::DEFAULT_PATH)
31
+ JSONAdapter.load.config
32
+ elsif File.exist?(YAMLAdapter::DEFAULT_PATH)
33
+ YAMLAdapter.load.config
34
+ else
35
+ {}
36
+ end
37
+ config = DefaultAdapter.new(config).config
38
+ config = ChecksAdapter.new(config).config
39
+ build(config)
40
+ end
41
+
42
+ def self.build(data)
43
+ new(
44
+ engines: EngineSet.new(data.fetch("plugins", {})).engines,
45
+ exclude_patterns: data.fetch("exclude_patterns", DefaultAdapter::EXCLUDE_PATTERNS),
46
+ prepare: Prepare.from_data(data["prepare"]),
47
+ )
48
+ end
49
+
50
+ def initialize(analysis_paths: [], development: false, engines: [], exclude_patterns: [], prepare: Prepare.new)
51
+ @analysis_paths = analysis_paths
52
+ @development = development
53
+ @engines = engines
54
+ @exclude_patterns = exclude_patterns
55
+ @prepare = prepare
56
+ end
57
+
58
+ def merge(other)
59
+ Merge.new(self, other).run
60
+ end
61
+
62
+ def development?
63
+ @development
64
+ end
65
+
66
+ def disable_plugins!
67
+ @engines.delete_if(&:plugin?)
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,40 @@
1
+ module CC
2
+ class Config
3
+ class ChecksAdapter
4
+ attr_reader :config
5
+
6
+ def initialize(data = {})
7
+ @config = data
8
+
9
+ return unless checks.present?
10
+ copy_qm_checks_config
11
+ end
12
+
13
+ private
14
+
15
+ def copy_qm_checks_config
16
+ DefaultAdapter::ENGINES.keys.each do |name|
17
+ copy_checks(name)
18
+ end
19
+ end
20
+
21
+ def copy_checks(engine_name)
22
+ engine = config.fetch("plugins", {}).fetch(engine_name, {})
23
+ engine["config"] ||= {}
24
+
25
+ if engine["config"].is_a?(String)
26
+ engine["config"] = {
27
+ "file" => engine["config"],
28
+ "checks" => checks,
29
+ }
30
+ elsif engine["config"].is_a?(Hash)
31
+ engine["config"]["checks"] = checks
32
+ end
33
+ end
34
+
35
+ def checks
36
+ config["checks"]
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,52 @@
1
+ module CC
2
+ class Config
3
+ class DefaultAdapter
4
+ # intentionally not sorted: we want them in a particular order
5
+ ENGINES = {
6
+ "structure".freeze => "stable".freeze,
7
+ "duplication".freeze => "cronopio".freeze,
8
+ }.freeze
9
+
10
+ EXCLUDE_PATTERNS = %w[
11
+ config/
12
+ db/
13
+ dist/
14
+ features/
15
+ **/node_modules/
16
+ script/
17
+ **/spec/
18
+ **/test/
19
+ **/tests/
20
+ **/vendor/
21
+ **/*.d.ts
22
+ ].freeze
23
+
24
+ attr_reader :config
25
+
26
+ def initialize(data = {})
27
+ @config = data
28
+
29
+ apply_default_excludes
30
+ apply_default_engines
31
+ end
32
+
33
+ private
34
+
35
+ def apply_default_engines
36
+ config["plugins"] ||= {}
37
+
38
+ ENGINES.each do |name, channel|
39
+ config["plugins"][name] ||= {}
40
+ unless [true, false].include?(config["plugins"][name]["enabled"])
41
+ config["plugins"][name]["enabled"] = true
42
+ end
43
+ config["plugins"][name]["channel"] ||= channel
44
+ end
45
+ end
46
+
47
+ def apply_default_excludes
48
+ config["exclude_patterns"] ||= EXCLUDE_PATTERNS
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,41 @@
1
+ module CC
2
+ class Config
3
+ class Engine
4
+ DEFAULT_CHANNEL = "stable".freeze
5
+
6
+ attr_accessor :channel
7
+ attr_reader :name, :config, :exclude_patterns
8
+ attr_writer :enabled
9
+
10
+ def initialize(name, enabled: false, channel: nil, config: nil, exclude_patterns: [])
11
+ @name = name
12
+ @enabled = enabled
13
+ @channel = channel || DEFAULT_CHANNEL
14
+ @config = config || {}
15
+ @exclude_patterns = exclude_patterns
16
+ end
17
+
18
+ def enabled?
19
+ @enabled
20
+ end
21
+
22
+ def plugin?
23
+ !DefaultAdapter::ENGINES.keys.include?(name)
24
+ end
25
+
26
+ def container_label
27
+ @container_label ||= SecureRandom.uuid
28
+ end
29
+
30
+ def hash
31
+ name.hash
32
+ end
33
+
34
+ def eql?(other)
35
+ other.is_a?(self.class) && name.eql?(other.name)
36
+ end
37
+ alias_method :==, :eql?
38
+ alias_method :equal?, :eql?
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,47 @@
1
+ module CC
2
+ class Config
3
+ class EngineSet
4
+ attr_reader :engines
5
+
6
+ def initialize(data)
7
+ @data = data
8
+ @engines = []
9
+
10
+ build_set
11
+ end
12
+
13
+ private
14
+
15
+ attr_reader :data
16
+
17
+ def build_set
18
+ DefaultAdapter::ENGINES.keys.each do |name|
19
+ if (engine = extract_engine(name))
20
+ engines << engine
21
+ end
22
+ end
23
+
24
+ data.each do |name, engine_data|
25
+ engines << build_engine(name, engine_data)
26
+ end
27
+ end
28
+
29
+ def extract_engine(name)
30
+ if data[name]
31
+ engine_data = data.delete(name)
32
+ build_engine(name, engine_data)
33
+ end
34
+ end
35
+
36
+ def build_engine(name, data)
37
+ Config::Engine.new(
38
+ name,
39
+ enabled: data.fetch("enabled", true),
40
+ channel: data["channel"],
41
+ config: data,
42
+ exclude_patterns: data.fetch("exclude_patterns", []),
43
+ )
44
+ end
45
+ end
46
+ end
47
+ end