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
@@ -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