danger-wcc 0.0.3 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +22 -15
  3. data/danger-wcc.gemspec +3 -3
  4. data/lib/version.rb +1 -1
  5. data/lib/wcc/commit_lint.rb +2 -1
  6. data/lib/wcc/commit_lint/commit_check.rb +0 -1
  7. data/lib/wcc/commit_lint/empty_line_check.rb +0 -1
  8. data/lib/wcc/commit_lint/subject_cap_check.rb +0 -1
  9. data/lib/wcc/commit_lint/subject_length_check.rb +0 -1
  10. data/lib/wcc/commit_lint/subject_period_check.rb +0 -1
  11. data/lib/wcc/commit_lint/subject_words_check.rb +0 -1
  12. data/lib/wcc/defaults.reek +8 -8
  13. data/lib/wcc/dependencies.rb +100 -0
  14. data/lib/wcc/jshint.rb +2 -2
  15. data/lib/wcc/plugin.rb +30 -12
  16. data/lib/wcc/reek.rb +2 -2
  17. data/lib/wcc/rubocop_exceptions.rb +13 -8
  18. data/lib/wcc/todos.rb +5 -4
  19. data/lib/wcc/util/yarn_info.rb +84 -0
  20. data/lib/wcc/utils.rb +17 -5
  21. data/lib/wcc/yarn_deduplicate.rb +72 -0
  22. data/spec/fixtures/dependencies/package.json +112 -0
  23. data/spec/fixtures/dependencies/package.json.diff +28 -0
  24. data/spec/fixtures/dependencies/package.json_patch_bumps_minor.diff +13 -0
  25. data/spec/fixtures/dependencies/package.json_patch_bumps_minor.json +112 -0
  26. data/spec/fixtures/dependencies/package.json_second_level_effect.diff +17 -0
  27. data/spec/fixtures/dependencies/package.json_second_level_effect.json +133 -0
  28. data/spec/fixtures/dependencies/yarn.lock +19609 -0
  29. data/spec/fixtures/dependencies/yarn.lock_patch_bumps_minor.lock +19614 -0
  30. data/spec/fixtures/dependencies/yarn.lock_second_level_effect.lock +20022 -0
  31. data/spec/fixtures/dependencies/yarn_list_second_level_effect.txt +1243 -0
  32. data/spec/fixtures/dependencies/yarn_list_second_level_effect.txt.diff +141 -0
  33. data/spec/fixtures/dependencies/yarn_minor_version.diff +33 -0
  34. data/spec/fixtures/dependencies/yarn_minor_version.txt +1151 -0
  35. data/spec/fixtures/dependencies/yarn_old.txt +1152 -0
  36. data/spec/fixtures/dependencies/yarn_patch_bumps_minor.diff +28 -0
  37. data/spec/fixtures/exception_inline_disabled_rule.diff +12 -0
  38. data/spec/fixtures/rubocop_exception.rb +3 -0
  39. data/spec/fixtures/yarn_deduplicate/list.a.txt +293 -0
  40. data/spec/fixtures/yarn_deduplicate/list.b.txt +295 -0
  41. data/spec/fixtures/yarn_deduplicate/list.diff +11 -0
  42. data/spec/fixtures/yarn_deduplicate/yarn.lock +20031 -0
  43. data/spec/fixtures_helper.rb +0 -1
  44. data/spec/spec_helper.rb +1 -1
  45. data/spec/wcc/commit_lint_spec.rb +6 -10
  46. data/spec/wcc/dependencies_spec.rb +129 -0
  47. data/spec/wcc/github_spec.rb +13 -7
  48. data/spec/wcc/jshint_spec.rb +1 -1
  49. data/spec/wcc/plugin_spec.rb +22 -17
  50. data/spec/wcc/reek_spec.rb +1 -1
  51. data/spec/wcc/rubocop_exceptions_spec.rb +34 -15
  52. data/spec/wcc/todos_spec.rb +10 -10
  53. data/spec/wcc/utils_spec.rb +2 -2
  54. data/spec/wcc/yarn_deduplicate_spec.rb +57 -0
  55. data/spec/wcc_spec.rb +1 -1
  56. metadata +71 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 822cbea6b3d318ccd075ef94c306dff86f5b698f
4
- data.tar.gz: ba50fe979f5d6cfd95cc7b5d55c4599cb7485e45
3
+ metadata.gz: c6061afcb81994d044747055b405da083c2a8f68
4
+ data.tar.gz: 9113729ee91c5f20f20bcbdc7dc193c8767a4118
5
5
  SHA512:
6
- metadata.gz: 4e4d2b1be606ce15f16feb52cfda344c032da630940fd57028c13e641e2f39902064c01f49404c10280e1e201a1894ca42514c295189da55bfcf37ac6303404e
7
- data.tar.gz: ba579966648a14056ea708c522235058cda132b556de9fa3c04d8277b0be08f57ad37d7c2c5688c5cb4740d66bd20d1c4eac82d66d8510a1b22256bc2d09e5df
6
+ metadata.gz: 1912d4617cea797c14e831c2fe0ba7669b85153944169f1345611eca4e4c4b6de6c3963f3735d6b1e1e51a76c29d2756534b59edbef3f15f0c56e2c78288ba3b
7
+ data.tar.gz: cabc48b95b641fdc38a403e6587788d5268a2c6325ab9542252e203c7fbb4968961e1d2bce2e3210804c5b343732b6575eee311f53194187234aeae88caaaa49
data/.rubocop.yml CHANGED
@@ -2,6 +2,7 @@ AllCops:
2
2
  DisplayCopNames: true
3
3
  TargetRubyVersion: 2.3
4
4
  Exclude:
5
+ - 'spec/fixtures/**/*'
5
6
  # generated by rails/binstubs
6
7
  - 'bin/**/*'
7
8
 
@@ -46,26 +47,36 @@ Metrics/ModuleLength:
46
47
  - 'lib/wcc/utils.rb'
47
48
  - 'spec/**/*.rb'
48
49
 
49
- Performance/HashEachMethods:
50
- Exclude:
51
- - 'spec/**/*.rb'
52
-
53
- Performance/UnfreezeString:
54
- Exclude:
55
- - 'spec/**/*.rb'
50
+ Naming/MethodParameterName:
51
+ Enabled: false
56
52
 
57
- Style/BracesAroundHashParameters:
53
+ Naming/MemoizedInstanceVariableName:
58
54
  Enabled: false
59
55
 
60
56
  Lint/AssignmentInCondition:
61
57
  Enabled: false
62
58
 
59
+ Lint/RaiseException:
60
+ Enabled: true
61
+
62
+ Lint/StructNewOverride:
63
+ Enabled: true
64
+
63
65
  Style/EmptyMethod:
64
66
  EnforcedStyle: expanded
65
67
 
66
68
  Style/Alias:
67
69
  EnforcedStyle: prefer_alias_method
68
70
 
71
+ Style/HashEachMethods:
72
+ Enabled: true
73
+
74
+ Style/HashTransformKeys:
75
+ Enabled: true
76
+
77
+ Style/HashTransformValues:
78
+ Enabled: true
79
+
69
80
  Style/NumericPredicate:
70
81
  EnforcedStyle: comparison
71
82
 
@@ -76,13 +87,13 @@ Style/RegexpLiteral:
76
87
  Style/SignalException:
77
88
  Enabled: false
78
89
 
79
- Layout/AlignParameters:
90
+ Layout/ParameterAlignment:
80
91
  EnforcedStyle: with_fixed_indentation
81
92
 
82
- Layout/IndentHash:
93
+ Layout/FirstHashElementIndentation:
83
94
  EnforcedStyle: consistent
84
95
 
85
- Layout/AlignHash:
96
+ Layout/HashAlignment:
86
97
  # allow coder to get around alignment rules by explicitly defining the hash param
87
98
  EnforcedLastArgumentHashStyle: ignore_explicit
88
99
 
@@ -124,10 +135,6 @@ Layout/MultilineAssignmentLayout:
124
135
  StyleGuide: '#indent-conditional-assignment'
125
136
  Enabled: true
126
137
 
127
- Lint/UnneededDisable:
128
- Exclude:
129
- - 'spec/fixtures/**/*'
130
-
131
138
  Lint/MissingCopEnableDirective:
132
139
  Exclude:
133
140
  - 'spec/fixtures/**/*'
data/danger-wcc.gemspec CHANGED
@@ -1,7 +1,6 @@
1
-
2
1
  # frozen_string_literal: true
3
2
 
4
- lib = File.expand_path('../lib', __FILE__)
3
+ lib = File.expand_path('lib', __dir__)
5
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
5
  require 'version'
7
6
 
@@ -20,6 +19,7 @@ Gem::Specification.new do |spec|
20
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
20
  spec.require_paths = ['lib']
22
21
 
22
+ spec.add_runtime_dependency 'activesupport', '> 5'
23
23
  spec.add_runtime_dependency 'brakeman'
24
24
  spec.add_runtime_dependency 'danger-plugin-api', '~> 1.0'
25
25
  spec.add_runtime_dependency 'flay'
@@ -36,7 +36,7 @@ Gem::Specification.new do |spec|
36
36
  spec.add_development_dependency 'webmock', '~> 3.1'
37
37
 
38
38
  # Linting code and docs
39
- spec.add_development_dependency 'rubocop'
39
+ spec.add_development_dependency 'rubocop', '~> 0.81'
40
40
  spec.add_development_dependency 'yard'
41
41
 
42
42
  # Makes testing easy via `bundle exec guard`
data/lib/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DangerWCC
4
- VERSION = '0.0.3'
4
+ VERSION = '0.1.1'
5
5
  end
@@ -102,7 +102,7 @@ class Danger::DangerWCC < Danger::Plugin
102
102
  return unless c.fail?
103
103
 
104
104
  messaging.issue([c.message, message[:sha]].join("\n"),
105
- severity: severity)
105
+ severity: severity)
106
106
  end
107
107
 
108
108
  def checkers
@@ -141,6 +141,7 @@ class Danger::DangerWCC < Danger::Plugin
141
141
 
142
142
  def warning_checks
143
143
  return checks if @config[:warn] == :all
144
+
144
145
  @config[:warn] || []
145
146
  end
146
147
 
@@ -1,4 +1,3 @@
1
-
2
1
  # frozen_string_literal: true
3
2
 
4
3
  class CommitCheck
@@ -1,4 +1,3 @@
1
-
2
1
  # frozen_string_literal: true
3
2
 
4
3
  class EmptyLineCheck < CommitCheck
@@ -1,4 +1,3 @@
1
-
2
1
  # frozen_string_literal: true
3
2
 
4
3
  class SubjectCapCheck < CommitCheck
@@ -1,4 +1,3 @@
1
-
2
1
  # frozen_string_literal: true
3
2
 
4
3
  class SubjectLengthCheck < CommitCheck
@@ -1,4 +1,3 @@
1
-
2
1
  # frozen_string_literal: true
3
2
 
4
3
  class SubjectPeriodCheck < CommitCheck
@@ -1,4 +1,3 @@
1
-
2
1
  # frozen_string_literal: true
3
2
 
4
3
  class SubjectWordsCheck < CommitCheck
@@ -23,10 +23,10 @@ DuplicateMethodCall:
23
23
  allow_calls: []
24
24
  FeatureEnvy:
25
25
  enabled: true
26
- exclude: []
26
+ exclude: ["Helper"]
27
27
  InstanceVariableAssumption:
28
28
  enabled: true
29
- exclude: []
29
+ exclude: ["Controller"]
30
30
  IrresponsibleModule:
31
31
  enabled: false
32
32
  exclude: []
@@ -54,7 +54,7 @@ NestedIterators:
54
54
  ignore_iterators:
55
55
  - tap
56
56
  NilCheck:
57
- enabled: true
57
+ enabled: false
58
58
  exclude: []
59
59
  PrimaDonnaMethod:
60
60
  enabled: true
@@ -70,15 +70,15 @@ Syntax:
70
70
  enabled: true
71
71
  exclude: []
72
72
  TooManyConstants:
73
- enabled: false
73
+ enabled: true
74
74
  exclude: []
75
75
  max_constants: 5
76
76
  TooManyInstanceVariables:
77
- enabled: false
77
+ enabled: true
78
78
  exclude: []
79
79
  max_instance_variables: 5
80
80
  TooManyMethods:
81
- enabled: false
81
+ enabled: true
82
82
  exclude: []
83
83
  max_methods: 15
84
84
  TooManyStatements:
@@ -127,5 +127,5 @@ UnusedPrivateMethod:
127
127
  exclude: []
128
128
  UtilityFunction:
129
129
  enabled: true
130
- exclude: []
131
- public_methods_only: false
130
+ exclude: ["Helper", "util"]
131
+ public_methods_only: true
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+ require_relative 'utils'
5
+
6
+ class Danger::DangerWCC < Danger::Plugin
7
+ class Dependencies
8
+ include Utils
9
+
10
+ DEFAULT_OPTIONS = {
11
+ lockfile: 'yarn.lock',
12
+ severity: :warn
13
+ }.freeze
14
+
15
+ def yarn_info
16
+ @yarn_info ||=
17
+ Danger::DangerWCC::Util::YarnInfo.new(self, @options)
18
+ end
19
+
20
+ def initialize(plugin, options = {})
21
+ @plugin = plugin
22
+ @options = DEFAULT_OPTIONS.merge(options)
23
+ end
24
+
25
+ def perform
26
+ return unless File.exist?(@options[:lockfile])
27
+
28
+ find_yarn_violations
29
+ end
30
+
31
+ private
32
+
33
+ def issue_yarn_violation(package, versions)
34
+ line_index = yarn_info.find_index_in_lockfile(package, versions[1])
35
+
36
+ msg = "Dangerous change! #{package} was updated "\
37
+ "from #{versions[0]} to #{versions[1]}"\
38
+ ' without a corresponding change to package.json!'
39
+ plugin.public_send(
40
+ @options[:severity],
41
+ msg,
42
+ file: @options[:lockfile],
43
+ line: line_index
44
+ )
45
+ end
46
+
47
+ def find_yarn_violations # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
48
+ # if there are any explicit major version changes in top level deps,
49
+ # say nothing about anything b/c it'll likely be noisy
50
+ has_explicit_mods =
51
+ yarn_info.modified_yarn_dependencies
52
+ .slice(*yarn_info.package_json_changes)
53
+ .any? { |_, v| major_version_change?(v[0], v[1]) }
54
+ return if has_explicit_mods
55
+
56
+ # Do say something if top level minor version change induces dangerous
57
+ # changes in other deps
58
+
59
+ mods =
60
+ yarn_info.modified_yarn_dependencies
61
+ .select { |_, versions| dangerous_change?(versions[0], versions[1]) }
62
+
63
+ has_dangerous_top_level_changes = false
64
+ mods.slice(*yarn_info.package_json_dependencies)
65
+ .each do |package, versions|
66
+ has_dangerous_top_level_changes = true
67
+ issue_yarn_violation(package, versions)
68
+ end
69
+
70
+ # issue warnings if a sub-dependency changed without a dangerous change in
71
+ # a top level dependency
72
+ return if has_dangerous_top_level_changes
73
+
74
+ mods.except(*yarn_info.package_json_dependencies)
75
+ .each do |package, versions|
76
+ issue_yarn_violation(package, versions)
77
+ end
78
+ end
79
+
80
+ def major_version_change?(old_version, new_version)
81
+ return false unless new_version
82
+
83
+ new_version.segments[0] > old_version.segments[0]
84
+ end
85
+
86
+ def dangerous_change?(old_version, new_version)
87
+ # the package was deleted
88
+ return true unless new_version
89
+
90
+ old_segments = old_version.segments
91
+ new_segments = new_version.segments
92
+
93
+ # the major or minor version changed.
94
+ new_segments[0] > old_segments[0] ||
95
+ new_segments[1] > old_segments[1]
96
+ end
97
+ end
98
+ end
99
+
100
+ require_relative './util/yarn_info'
data/lib/wcc/jshint.rb CHANGED
@@ -56,8 +56,8 @@ class Danger::DangerWCC < Danger::Plugin
56
56
  )
57
57
 
58
58
  plugin.warn(warning.captures[2],
59
- file: warning.captures[0],
60
- line: warning.captures[1].to_i)
59
+ file: warning.captures[0],
60
+ line: warning.captures[1].to_i)
61
61
  end
62
62
  end
63
63
  end
data/lib/wcc/plugin.rb CHANGED
@@ -7,28 +7,36 @@ require_relative 'rubocop_exceptions'
7
7
  require_relative 'commit_lint'
8
8
  require_relative 'reek'
9
9
  require_relative 'jshint'
10
+ require_relative 'dependencies'
11
+ require_relative 'yarn_deduplicate'
10
12
 
11
- class Danger::DangerWCC < Danger::Plugin
13
+ class Danger::DangerWCC < Danger::Plugin # rubocop:disable Metrics/ClassLength
12
14
  include Utils
13
15
  include Github
14
16
 
15
- CHECKS = %i[
16
- rubocop_exceptions
17
- todos
18
- commit_lint
19
- reek
20
- flay
21
- brakeman
22
- jshint
23
- ].freeze
17
+ DEFAULT_OPTIONS = {
18
+ rubocop_exceptions: true,
19
+ todos: true,
20
+ brakeman: true,
21
+ dependencies: true,
22
+ yarn_deduplicate: true,
23
+
24
+ commit_lint: false,
25
+ reek: false,
26
+ jshint: false,
27
+ flay: false
28
+ }.freeze
24
29
 
25
30
  # Runs all the included checks in the plugin
26
31
  def all(options = {})
27
- to_run = CHECKS.reject { |check_name| options[check_name] == false }
32
+ options = DEFAULT_OPTIONS.merge(options)
33
+
34
+ to_run = options.keys.reject { |check_name| options[check_name] == false }
28
35
  raise ArgumentError, 'No Enabled Checks' if to_run.empty?
29
36
 
30
37
  to_run.each do |check_name|
31
- public_send(check_name, options.fetch(check_name, {}))
38
+ check_options = options.fetch(check_name, {})
39
+ public_send(check_name, check_options == true ? {} : check_options)
32
40
  end
33
41
  end
34
42
 
@@ -92,6 +100,16 @@ class Danger::DangerWCC < Danger::Plugin
92
100
  Jshint.new(self, options).perform
93
101
  end
94
102
 
103
+ def dependencies(options = {})
104
+ logger.info "dependencies: #{options}"
105
+ Dependencies.new(self, options).perform
106
+ end
107
+
108
+ def yarn_deduplicate(options = {})
109
+ logger.info "yarn_deduplicate: #{options}"
110
+ YarnDeduplicate.new(self, options).perform
111
+ end
112
+
95
113
  private
96
114
 
97
115
  def parse_flay_results
data/lib/wcc/reek.rb CHANGED
@@ -49,8 +49,8 @@ class Danger::DangerWCC < Danger::Plugin
49
49
 
50
50
  line_info = with_line_number.match(/^\s*([^\:]+)\:(\d+)\:/i)
51
51
  plugin.warn(format_links_as_markdown(warning.captures[0]),
52
- file: line_info.captures[0],
53
- line: line_info.captures[1].to_i)
52
+ file: line_info.captures[0],
53
+ line: line_info.captures[1].to_i)
54
54
  end
55
55
  end
56
56
  end
@@ -6,9 +6,9 @@ class Danger::DangerWCC < Danger::Plugin
6
6
  class RubocopExceptions
7
7
  include Utils
8
8
 
9
- DISABLE_REGEX = /^(?:\+\s)?.*\#\s*rubocop\:disable\s+(\S+)/i
10
- ENABLE_REGEX = /^(?:\+\s)?\s*\#\s*rubocop\:enable\s+(\S+)/i
11
- COMMENT_LINE_REGEX = /^(?:\+\s)?\s*\#\s*(.+)$/i
9
+ DISABLE_REGEX = /^(?:\+\s)?.*\#\s*rubocop\:disable\s+(\S+)/i.freeze
10
+ ENABLE_REGEX = /^(?:\+\s)?\s*\#\s*rubocop\:enable\s+(\S+)/i.freeze
11
+ COMMENT_LINE_REGEX = /^(?:\+\s)?\s*\#\s*(.+)$/i.freeze
12
12
 
13
13
  def initialize(plugin, options = {})
14
14
  @plugin = plugin
@@ -20,7 +20,7 @@ class Danger::DangerWCC < Danger::Plugin
20
20
  message = build_message(e)
21
21
  severity = message_severity(e)
22
22
  issue(message,
23
- severity: severity, file: e[:file], line: e[:disabled_at])
23
+ severity: severity, file: e[:file], line: e[:disabled_at])
24
24
  end
25
25
  end
26
26
 
@@ -35,7 +35,7 @@ class Danger::DangerWCC < Danger::Plugin
35
35
  else
36
36
  " \nPlease provide an explanation why this rule was disabled."
37
37
  end
38
- unless e[:reenabled]
38
+ unless e[:inline] || e[:reenabled]
39
39
  message += "\n\nThe rule was not reenabled!\n"\
40
40
  'Please add a `rubocop:enable` comment so the rule is disabled '\
41
41
  'for the minimal scope.'
@@ -44,7 +44,7 @@ class Danger::DangerWCC < Danger::Plugin
44
44
  end
45
45
 
46
46
  def message_severity(e)
47
- if !e[:reenabled]
47
+ if !e[:inline] && !e[:reenabled]
48
48
  'fail'
49
49
  elsif e[:context_lines].empty?
50
50
  'warn'
@@ -60,18 +60,23 @@ class Danger::DangerWCC < Danger::Plugin
60
60
  end
61
61
  end
62
62
 
63
+ # rubocop:disable Metrics/AbcSize
63
64
  def make_violation(file_contents, hunk, line, rule)
65
+ is_inline_comment = !/^\s*\+?\s*\#/.match(line.content)
66
+
64
67
  reenable_line_offset = find_reenable(file_contents,
65
- line.line_number.right,
66
- rule)
68
+ line.line_number.right,
69
+ rule)
67
70
 
68
71
  {
69
72
  rule: rule,
70
73
  disabled_at: line.line_number.right,
74
+ inline: is_inline_comment,
71
75
  reenabled: !reenable_line_offset.nil?,
72
76
  context_lines: find_context(hunk.lines.drop(hunk.lines.index(line)))
73
77
  }
74
78
  end
79
+ # rubocop:enable Metrics/AbcSize
75
80
 
76
81
  def find_context(diff_lines)
77
82
  # search for all non-`rubocop:` comment lines immediately