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,86 +0,0 @@
1
- module CC
2
- module Analyzer
3
- # TODO: replace each use of this with CC::Yaml and remove it
4
- class Config
5
- def initialize(config_body)
6
- @config = YAML.safe_load(config_body) || { "engines" => {} }
7
- @config["engines"] ||= {}
8
-
9
- expand_shorthand
10
- end
11
-
12
- def to_hash
13
- @config
14
- end
15
-
16
- def engine_config(engine_name)
17
- @config["engines"][engine_name] || {}
18
- end
19
-
20
- def engine_names
21
- @config["engines"].keys.select { |name| engine_enabled?(name) }
22
- end
23
-
24
- def engine_present?(engine_name)
25
- @config["engines"][engine_name].present?
26
- end
27
-
28
- def engine_enabled?(engine_name)
29
- @config["engines"][engine_name] && @config["engines"][engine_name]["enabled"]
30
- end
31
-
32
- def enable_engine(engine_name)
33
- if engine_present?(engine_name)
34
- @config["engines"][engine_name]["enabled"] = true
35
- else
36
- @config["engines"][engine_name] = { "enabled" => true }
37
- enable_default_config(engine_name) if default_config(engine_name)
38
- end
39
- end
40
-
41
- def enable_default_config(engine_name)
42
- @config["engines"][engine_name]["config"] = default_config(engine_name)
43
- end
44
-
45
- def exclude_paths
46
- @config["exclude_paths"]
47
- end
48
-
49
- def disable_engine(engine_name)
50
- if engine_present?(engine_name) && engine_enabled?(engine_name)
51
- @config["engines"][engine_name]["enabled"] = false
52
- end
53
- end
54
-
55
- def remove_engine(engine_name)
56
- if engine_present?(engine_name)
57
- @config["engines"].delete(engine_name)
58
- end
59
- end
60
-
61
- def to_yaml
62
- @config.to_yaml
63
- end
64
-
65
- private
66
-
67
- def expand_shorthand
68
- @config["engines"].each do |name, engine_config|
69
- if [true, false].include?(engine_config)
70
- @config["engines"][name] = { "enabled" => engine_config }
71
- end
72
- end
73
- end
74
-
75
- def default_config(engine_name)
76
- if (engine_config = engine_registry[engine_name])
77
- engine_config["default_config"]
78
- end
79
- end
80
-
81
- def engine_registry
82
- @engine_registry ||= CC::Analyzer::EngineRegistry.new
83
- end
84
- end
85
- end
86
- end
@@ -1,36 +0,0 @@
1
- module CC
2
- module Analyzer
3
- class EngineRegistry
4
- def initialize(dev_mode = false)
5
- @path = File.expand_path("../../../../config/engines.yml", __FILE__)
6
- @config = YAML.safe_load(File.read(@path))
7
- @dev_mode = dev_mode
8
- end
9
-
10
- def [](engine_name)
11
- if dev_mode?
12
- { "channels" => { "stable" => "codeclimate/codeclimate-#{engine_name}:latest" } }
13
- else
14
- @config[engine_name]
15
- end
16
- end
17
-
18
- def list
19
- @config
20
- end
21
-
22
- def key?(engine_name)
23
- return true if dev_mode?
24
- list.key?(engine_name)
25
- end
26
-
27
- alias_method :exists?, :key?
28
-
29
- private
30
-
31
- def dev_mode?
32
- @dev_mode
33
- end
34
- end
35
- end
36
- end
@@ -1,97 +0,0 @@
1
- require "securerandom"
2
-
3
- module CC
4
- module Analyzer
5
- class EnginesConfigBuilder
6
- class RegistryAdapter < SimpleDelegator
7
- # Calling this is guarded by Registry#key?(name) so we can assume
8
- # metadata itself will be present. We own the YAML loaded into the
9
- # registry, so we can also assume the "channels" key will be present. We
10
- # can't assume it will have a key for the given channel, but the nil
11
- # value for the returned image key will trigger the desired error
12
- # handling.
13
- def fetch(name, channel)
14
- metadata = self[name]
15
- metadata.merge("image" => metadata["channels"][channel.to_s])
16
- end
17
- end
18
-
19
- Result = Struct.new(
20
- :name,
21
- :registry_entry,
22
- :code_path,
23
- :config,
24
- :container_label,
25
- )
26
-
27
- def initialize(registry:, config:, container_label:, source_dir:, requested_paths:)
28
- @registry = RegistryAdapter.new(registry)
29
- @config = config
30
- @container_label = container_label
31
- @requested_paths = requested_paths
32
- @source_dir = source_dir
33
- end
34
-
35
- def run
36
- names_and_raw_engine_configs.map do |name, raw_engine_config|
37
- label = @container_label || SecureRandom.uuid
38
- engine_config = engine_config(raw_engine_config)
39
- engine_metadata = @registry.fetch(name, raw_engine_config.channel)
40
- Result.new(name, engine_metadata, @source_dir, engine_config, label)
41
- end
42
- end
43
-
44
- private
45
-
46
- def engine_config(raw_engine_config)
47
- engine_workspace = engine_workspace(raw_engine_config)
48
- config = raw_engine_config.merge(
49
- include_paths: engine_workspace.paths,
50
- )
51
-
52
- normalize_config_file(config)
53
-
54
- config
55
- end
56
-
57
- def engine_workspace(raw_engine_config)
58
- if raw_engine_config.key?("exclude_paths") && !@requested_paths.present?
59
- base_workspace.clone.tap do |workspace|
60
- workspace.remove(raw_engine_config["exclude_paths"])
61
- end
62
- else
63
- base_workspace
64
- end
65
- end
66
-
67
- def names_and_raw_engine_configs
68
- {}.tap do |ret|
69
- (@config.engines || {}).each do |name, raw_engine_config|
70
- if raw_engine_config.enabled? && @registry.key?(name)
71
- ret[name] = raw_engine_config
72
- end
73
- end
74
- end
75
- end
76
-
77
- def base_workspace
78
- @base_workspace ||= Workspace.new.tap do |workspace|
79
- workspace.add(@requested_paths)
80
- unless @requested_paths.present?
81
- workspace.remove([".git"])
82
- workspace.remove(@config.exclude_paths)
83
- end
84
- end
85
- end
86
-
87
- # The yaml gem turns a config file string into a hash, but engines expect
88
- # the string. So we (for now) need to turn it into a string in that one
89
- # scenario.
90
- def normalize_config_file(config)
91
- if config.fetch("config", {}).keys.size == 1 && config["config"].key?("file")
92
- config["config"] = config["config"]["file"]
93
- end
94
- end
95
- end
96
- end
97
- end
@@ -1,64 +0,0 @@
1
- require "securerandom"
2
-
3
- module CC
4
- module Analyzer
5
- class EnginesRunner
6
- NoEnabledEngines = Class.new(StandardError)
7
-
8
- def initialize(registry, formatter, source_dir, config, requested_paths = [], container_label = nil)
9
- @registry = registry
10
- @formatter = formatter
11
- @source_dir = source_dir
12
- @config = config
13
- @requested_paths = requested_paths
14
- @container_label = container_label
15
- end
16
-
17
- def run(container_listener = ContainerListener.new)
18
- raise NoEnabledEngines if engines.empty?
19
-
20
- @formatter.started
21
-
22
- engines.each { |engine| run_engine(engine, container_listener) }
23
-
24
- @formatter.finished
25
- ensure
26
- @formatter.close if @formatter.respond_to?(:close)
27
- end
28
-
29
- private
30
-
31
- attr_reader :requested_paths
32
-
33
- def build_engine(built_config)
34
- Engine.new(
35
- built_config.name,
36
- built_config.registry_entry,
37
- built_config.code_path,
38
- built_config.config,
39
- built_config.container_label,
40
- )
41
- end
42
-
43
- def configs
44
- EnginesConfigBuilder.new(
45
- registry: @registry,
46
- config: @config,
47
- container_label: @container_label,
48
- source_dir: @source_dir,
49
- requested_paths: requested_paths,
50
- ).run
51
- end
52
-
53
- def engines
54
- @engines ||= configs.map { |result| build_engine(result) }
55
- end
56
-
57
- def run_engine(engine, container_listener)
58
- @formatter.engine_running(engine) do
59
- engine.run(@formatter, container_listener)
60
- end
61
- end
62
- end
63
- end
64
- end
@@ -1,44 +0,0 @@
1
- module CC
2
- module CLI
3
- class Config
4
- delegate :to_yaml, to: :config
5
-
6
- def initialize(config = {})
7
- @config = default_config.merge(config)
8
- end
9
-
10
- def add_engine(engine_name, engine_config)
11
- config["engines"][engine_name] = { "enabled" => true }
12
-
13
- if engine_config["default_config"].present?
14
- config["engines"][engine_name]["config"] = engine_config["default_config"]
15
- end
16
-
17
- # we may not want this code in the general case.
18
- # for now, we need it to test one of our own Maintainability engines
19
- # which is in the 'beta' channel
20
- if engine_config.key?("channels") && !engine_config["channels"].include?("stable")
21
- config["engines"][engine_name]["channel"] = engine_config["channels"].first.first
22
- end
23
-
24
- config["ratings"]["paths"] |= engine_config["default_ratings_paths"]
25
- end
26
-
27
- def add_exclude_paths(paths)
28
- config["exclude_paths"] ||= []
29
- config["exclude_paths"] |= paths
30
- end
31
-
32
- private
33
-
34
- attr_reader :config
35
-
36
- def default_config
37
- {
38
- "engines" => {},
39
- "ratings" => { "paths" => [] },
40
- }
41
- end
42
- end
43
- end
44
- end
@@ -1,108 +0,0 @@
1
- require "posix/spawn"
2
- require "shellwords"
3
-
4
- module CC
5
- module CLI
6
- class ConfigGenerator
7
- CODECLIMATE_YAML = Command::CODECLIMATE_YAML
8
- AUTO_EXCLUDE_PATHS = %w(config/ db/ dist/ features/ node_modules/ script/ spec/ test/ tests/ vendor/).freeze
9
-
10
- ConfigGeneratorError = Class.new(StandardError)
11
-
12
- def self.for(filesystem, engine_registry, upgrade_requested)
13
- if upgrade_requested && upgrade_needed?(filesystem)
14
- UpgradeConfigGenerator.new(filesystem, engine_registry)
15
- else
16
- ConfigGenerator.new(filesystem, engine_registry)
17
- end
18
- end
19
-
20
- def initialize(filesystem, engine_registry)
21
- @filesystem = filesystem
22
- @engine_registry = engine_registry
23
- end
24
-
25
- def can_generate?
26
- true
27
- end
28
-
29
- def eligible_engines
30
- return @eligible_engines if @eligible_engines
31
-
32
- engines = engine_registry.list
33
- @eligible_engines = engines.each_with_object({}) do |(name, config), result|
34
- if engine_eligible?(config)
35
- result[name] = config
36
- end
37
- end
38
- end
39
-
40
- def errors
41
- []
42
- end
43
-
44
- def exclude_paths
45
- @exclude_paths ||= AUTO_EXCLUDE_PATHS.select { |path| filesystem.exist?(path) }
46
- end
47
-
48
- def post_generation_verb
49
- "generated"
50
- end
51
-
52
- private
53
-
54
- attr_reader :engine_registry, :filesystem
55
-
56
- def self.upgrade_needed?(filesystem)
57
- if filesystem.exist?(CODECLIMATE_YAML)
58
- YAML.safe_load(File.read(CODECLIMATE_YAML))["languages"].present?
59
- end
60
- end
61
-
62
- def engine_eligible?(engine)
63
- engine["channels"].keys.any? { |channel| channel == "stable" } &&
64
- !engine["community"] &&
65
- engine["enable_regexps"].present? &&
66
- files_exist?(engine)
67
- end
68
-
69
- def files_exist?(engine)
70
- workspace_files.any? do |path|
71
- engine["enable_regexps"].any? { |re| Regexp.new(re).match(path) }
72
- end
73
- end
74
-
75
- def non_excluded_paths
76
- @non_excluded_paths ||= begin
77
- excludes = exclude_paths.map { |path| path.chomp("/") }
78
- filesystem.ls.reject do |path|
79
- path.starts_with?("-") || path.starts_with?(".") || excludes.include?(path)
80
- end
81
- end
82
- end
83
-
84
- def workspace_files
85
- @workspace_files ||= Dir.chdir(filesystem.root) do
86
- if non_excluded_paths.empty?
87
- []
88
- else
89
- find_workspace_files
90
- end
91
- end
92
- end
93
-
94
- def find_workspace_files
95
- find_cmd = %w[find] + non_excluded_paths + %w[-type f -print0]
96
- child = POSIX::Spawn::Child.new(*find_cmd)
97
-
98
- if child.status.success?
99
- child.out.strip.split("\0").map do |path|
100
- path.sub(%r{^\.\/}, "")
101
- end
102
- else
103
- raise ConfigGeneratorError, "Failed to find analyzable files.\nRan '#{find_cmd.shelljoin}', exited with code #{child.status.to_i} and stderr:\n'#{child.err}'"
104
- end
105
- end
106
- end
107
- end
108
- end
@@ -1,38 +0,0 @@
1
- require "cc/analyzer"
2
- require "cc/cli/engines/engine_command"
3
-
4
- module CC
5
- module CLI
6
- module Engines
7
- class Disable < EngineCommand
8
- ARGUMENT_LIST = "<engine_name>".freeze
9
- SHORT_HELP = "Disable an engine in your codeclimate.yml.".freeze
10
- HELP = "#{SHORT_HELP}\n" \
11
- "\n"\
12
- " <engine_name> Engine to disable in your codeclimate.yml".freeze
13
-
14
- def run
15
- require_codeclimate_yml
16
-
17
- if !engine_exists?
18
- say "Engine not found. Run 'codeclimate engines:list' for a list of valid engines."
19
- elsif !engine_present_in_yaml?
20
- say "Engine not found in .codeclimate.yml."
21
- elsif !engine_enabled?
22
- say "Engine already disabled."
23
- else
24
- disable_engine
25
- update_yaml
26
- say "Engine disabled."
27
- end
28
- end
29
-
30
- private
31
-
32
- def disable_engine
33
- parsed_yaml.disable_engine(engine_name)
34
- end
35
- end
36
- end
37
- end
38
- end