danger-wcc 0.0.4 → 0.1.2

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 (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 +98 -0
  20. data/lib/wcc/utils.rb +18 -8
  21. data/lib/wcc/yarn_deduplicate.rb +71 -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 +130 -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: dad1e51611091d1975c1e79440afed906f5d2119
4
- data.tar.gz: 608950050d3e357cbd078ac47e2fb1afa89e1086
3
+ metadata.gz: 5129a6e15f66a145fda1a0791144cfe4b4735150
4
+ data.tar.gz: 90d46909a0c85b829aaea23b543b99a61b2141f0
5
5
  SHA512:
6
- metadata.gz: e8bb8cd98d97f1664c34e54c893dc8995171317094602fc7034fe37adeca823230ced817c6fd7fd47247edbda6c1de250ab953c74a8f61dc0f3d2dc91ce7e31e
7
- data.tar.gz: 48b2f49e8a642e049e2ae34ff85bf3053aea695c4ad3404de4db4c3f828921941dbc929fe1f7cc2dfe82be656cf1c18f8de5aff7198b0bf1025566287e9a9d06
6
+ metadata.gz: 0a695fb8019f7d4e90dd6499ec656e579719737dbb173fc524d17bab8162d2b8438a44f6a205d38f2b10e32ff289856fc2730eec8be54a9d0aec0294fdc2cb6b
7
+ data.tar.gz: 9e30b7eadb23699642caf8c56345121b741e9d2d91f74d574c3c3365a1b38c9f487ba0b78a23c3d6544d50540abcafa964fc417943c6094935abb77c219d32f6
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.4'
4
+ VERSION = '0.1.2'
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