gitlab-styles 3.2.0 → 5.1.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +18 -0
  3. data/.gitignore +3 -1
  4. data/.gitlab-ci.yml +25 -4
  5. data/.gitlab/merge_request_templates/Release.md +35 -0
  6. data/.rubocop.yml +3 -1
  7. data/Gemfile +5 -2
  8. data/README.md +5 -0
  9. data/Rakefile +2 -0
  10. data/gitlab-styles.gemspec +8 -5
  11. data/lib/gitlab/styles.rb +2 -0
  12. data/lib/gitlab/styles/rubocop.rb +7 -0
  13. data/lib/gitlab/styles/rubocop/cop/active_record_dependent.rb +4 -2
  14. data/lib/gitlab/styles/rubocop/cop/active_record_serialize.rb +3 -1
  15. data/lib/gitlab/styles/rubocop/cop/code_reuse/active_record.rb +131 -0
  16. data/lib/gitlab/styles/rubocop/cop/custom_error_class.rb +9 -4
  17. data/lib/gitlab/styles/rubocop/cop/gem_fetcher.rb +4 -2
  18. data/lib/gitlab/styles/rubocop/cop/in_batches.rb +3 -1
  19. data/lib/gitlab/styles/rubocop/cop/line_break_after_guard_clauses.rb +4 -2
  20. data/lib/gitlab/styles/rubocop/cop/line_break_around_conditional_block.rb +132 -0
  21. data/lib/gitlab/styles/rubocop/cop/migration/update_large_table.rb +64 -0
  22. data/lib/gitlab/styles/rubocop/cop/polymorphic_associations.rb +4 -2
  23. data/lib/gitlab/styles/rubocop/cop/redirect_with_status.rb +3 -1
  24. data/lib/gitlab/styles/rubocop/cop/rspec/base.rb +18 -0
  25. data/lib/gitlab/styles/rubocop/cop/rspec/empty_line_after_let_block.rb +65 -0
  26. data/lib/gitlab/styles/rubocop/cop/rspec/empty_line_after_shared_example.rb +65 -0
  27. data/lib/gitlab/styles/rubocop/cop/rspec/have_link_parameters.rb +13 -6
  28. data/lib/gitlab/styles/rubocop/cop/rspec/single_line_hook.rb +6 -3
  29. data/lib/gitlab/styles/rubocop/cop/rspec/verbose_include_metadata.rb +13 -14
  30. data/lib/gitlab/styles/rubocop/cop/without_reactive_cache.rb +3 -1
  31. data/lib/gitlab/styles/rubocop/migration_helpers.rb +2 -0
  32. data/lib/gitlab/styles/rubocop/model_helpers.rb +3 -1
  33. data/lib/gitlab/styles/rubocop/rspec/helpers.rb +17 -0
  34. data/lib/gitlab/styles/version.rb +3 -1
  35. data/rubocop-all.yml +2 -1
  36. data/rubocop-bundler.yml +1 -0
  37. data/rubocop-code_reuse.yml +24 -0
  38. data/rubocop-default.yml +2 -0
  39. data/rubocop-gemspec.yml +1 -0
  40. data/rubocop-layout.yml +38 -22
  41. data/rubocop-lint.yml +81 -19
  42. data/rubocop-metrics.yml +1 -4
  43. data/rubocop-migrations.yml +22 -0
  44. data/rubocop-naming.yml +9 -8
  45. data/rubocop-performance.yml +48 -0
  46. data/rubocop-rails.yml +79 -0
  47. data/rubocop-rspec.yml +14 -0
  48. data/rubocop-security.yml +1 -0
  49. data/rubocop-style.yml +119 -15
  50. metadata +27 -17
  51. data/.rubocop_todo.yml +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 592bf0393cc58badea566d11006eba982318048f25803f288e8616f15d9c1a56
4
- data.tar.gz: ace3d41b0da57eea470c4537227bb195aee8db431b59c01c5c31a7fd559b4e2a
3
+ metadata.gz: 30bceb716d5e39ed5e48f4d42fd4457eb0a0608be5419e03ac325a3db385da08
4
+ data.tar.gz: 50058ac5c12783bd57e55e9cf19973ffb9aec21c277e3ff20839849271feb64c
5
5
  SHA512:
6
- metadata.gz: f463f3d74bd39abfeba23713375eb99f8f8ed5a61b259110ef193a0692b6073fddcd89291f57712237ce7834f60414158ebfd83d9dd774a54489bdd4582043c0
7
- data.tar.gz: db51862db754ac163596f6516b882a7c75c3b9822bb9c33a67fed262293b360b792fe471305848e51ecefb06f0d6f63c7d2976f01493fbba60bc6e2d79016142
6
+ metadata.gz: b5f700edd701ed7b465a1e5bac5971dee3e7f31df2603a03dc76fd048feb98ec23e4fb1e70b2704e5f3899eecb0c2f6817a1d508bcf1708a092587e9ba2a4f86
7
+ data.tar.gz: 3ba624b97b7bab08fa1fb26b82cae5f72494e639a1c7cc000d95098ad39807218e15e118654a2518076ae3409f31ee55caa980e3d88cac26394d26e10f079b0f
@@ -0,0 +1,18 @@
1
+ # top-most EditorConfig file
2
+ root = true
3
+
4
+ # Unix-style newlines with a newline ending every file
5
+ [*]
6
+ end_of_line = lf
7
+ trim_trailing_whitespace = true
8
+ insert_final_newline = true
9
+
10
+ [*.{rb,yml}]
11
+ indent_size = 2
12
+
13
+ [*.{rb,yml,md}]
14
+ indent_style = space
15
+ charset = utf-8
16
+
17
+ [*.{md,markdown}]
18
+ trim_trailing_whitespace = false
data/.gitignore CHANGED
@@ -3,10 +3,12 @@
3
3
  /Gemfile.lock
4
4
  /_yardoc/
5
5
  /coverage/
6
- /doc/
7
6
  /pkg/
8
7
  /spec/reports/
9
8
  /tmp/
10
9
 
11
10
  # rspec failure tracking
12
11
  .rspec_status
12
+
13
+ # Ignore IDE specific files
14
+ .idea/
@@ -1,13 +1,34 @@
1
- image: ruby:2.3
1
+ stages:
2
+ - test
3
+ - deploy
2
4
 
3
- before_script:
4
- - bundle --version
5
- - bundle install
5
+ default:
6
+ image: ruby:2.6
7
+ tags:
8
+ - gitlab-org
9
+ before_script:
10
+ - bundle --version
11
+ - bundle install
12
+
13
+ workflow:
14
+ rules:
15
+ # For merge requests, create a pipeline.
16
+ - if: '$CI_MERGE_REQUEST_IID'
17
+ # For `master` branch, create a pipeline (this includes on schedules, pushes, merges, etc.).
18
+ - if: '$CI_COMMIT_BRANCH == "master"'
19
+ # For tags, create a pipeline.
20
+ - if: '$CI_COMMIT_TAG'
6
21
 
7
22
  styles:
23
+ stage: test
8
24
  script:
9
25
  - bundle exec rubocop --debug --parallel
10
26
 
11
27
  specs:
28
+ stage: test
12
29
  script:
13
30
  - bundle exec rspec
31
+
32
+ include:
33
+ - project: 'gitlab-org/quality/pipeline-common'
34
+ file: '/ci/gem-release.yml'
@@ -0,0 +1,35 @@
1
+ <!-- Replace `v4.5.0` with the previous release here, and `e18d76b309e42888759c1effe96767f13e34ae55`
2
+ with the latest commit from https://gitlab.com/gitlab-org/gitlab-styles/commits/master that will be included in the release. -->
3
+ - Diff: https://gitlab.com/gitlab-org/gitlab-styles/compare/v4.5.0...e18d76b309e42888759c1effe96767f13e34ae55
4
+
5
+ - Release notes:
6
+
7
+ <!-- Keep the sections order but remove the empty sections -->
8
+
9
+ ```markdown
10
+ ### New features and features updates
11
+
12
+ - !aaa <Title of the aaa MR>.
13
+
14
+ ### Fixes
15
+
16
+ - !bbb <Title of the bbb MR>.
17
+
18
+ ### Doc changes
19
+
20
+ - !ccc <Title of the ccc MR>.
21
+
22
+ ### Other changes (tooling, technical debt)
23
+
24
+ - !ddd <Title of the ddd MR>.
25
+ ```
26
+
27
+ - Checklist before merging:
28
+ - [ ] Diff link is up-to-date.
29
+ - [ ] Based on the diff, `lib/gitlab/styles/version.rb` is updated, according to [SemVer](https://semver.org).
30
+ - [ ] Release notes are accurate.
31
+
32
+ - Checklist after merging:
33
+ - [ ] [Update the release notes for the newly created tag](docs/release_process.md#how-to).
34
+
35
+ /label ~"Engineering Productivity" ~"feature" ~"feature::maintenance" ~"static code analysis"
@@ -1,3 +1,5 @@
1
1
  inherit_from:
2
2
  - rubocop-default.yml
3
- - .rubocop_todo.yml
3
+
4
+ require:
5
+ - rubocop/cop/internal_affairs
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in gitlab-rubocop.gemspec
@@ -5,6 +7,7 @@ gemspec
5
7
 
6
8
  group :test do
7
9
  # Pin these dependencies, otherwise a new rule could break the CI pipelines
8
- gem 'rubocop', '0.74.0'
9
- gem 'rubocop-rspec', '1.36.0'
10
+ gem 'rubocop', '0.89.1'
11
+ gem 'rubocop-rspec', '1.44.1'
12
+ gem 'rspec-parameterized', '0.4.2', require: false
10
13
  end
data/README.md CHANGED
@@ -42,6 +42,7 @@ rules:
42
42
  - `rubocop-gemspec.yml`
43
43
  - `rubocop-layout.yml`
44
44
  - `rubocop-lint.yml`
45
+ - `rubocop-migrations.yml`
45
46
  - `rubocop-metrics.yml`
46
47
  - `rubocop-naming.yml`
47
48
  - `rubocop-performance.yml`
@@ -77,6 +78,10 @@ https://gitlab.com/gitlab-org/gitlab-styles. This project is intended to be a
77
78
  safe, welcoming space for collaboration, and contributors are expected to adhere
78
79
  to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
79
80
 
81
+ ## Release Process
82
+
83
+ Please refer to the [Release Process](docs/release_process.md).
84
+
80
85
  ## License
81
86
 
82
87
  The gem is available as open source under the terms of the
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/gem_tasks'
2
4
  require 'rspec/core/rake_task'
3
5
 
@@ -1,8 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  lib = File.expand_path('lib', __dir__)
2
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
5
  require 'gitlab/styles/version'
4
6
 
5
7
  Gem::Specification.new do |spec|
8
+ spec.required_ruby_version = '>= 2.6'
6
9
  spec.name = 'gitlab-styles'
7
10
  spec.version = Gitlab::Styles::VERSION
8
11
  spec.authors = ['GitLab']
@@ -13,17 +16,17 @@ Gem::Specification.new do |spec|
13
16
  spec.license = 'MIT'
14
17
 
15
18
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
16
- f.match(%r{^(test|spec|features)/})
19
+ f.match(%r{^(docs|test|spec|features)/})
17
20
  end
18
21
  spec.bindir = 'exe'
19
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
23
  spec.require_paths = ['lib']
21
24
 
22
- spec.add_dependency 'rubocop', '~> 0.74.0'
25
+ spec.add_dependency 'rubocop', '~> 0.89.1'
23
26
  spec.add_dependency 'rubocop-gitlab-security', '~> 0.1.0'
24
- spec.add_dependency 'rubocop-performance', '~> 1.4.1'
25
- spec.add_dependency 'rubocop-rails', '~> 2.0'
26
- spec.add_dependency 'rubocop-rspec', '~> 1.36'
27
+ spec.add_dependency 'rubocop-performance', '~> 1.8.1'
28
+ spec.add_dependency 'rubocop-rails', '~> 2.8'
29
+ spec.add_dependency 'rubocop-rspec', '~> 1.44'
27
30
 
28
31
  spec.add_development_dependency 'bundler', '~> 1.16'
29
32
  spec.add_development_dependency 'rake', '~> 10.0'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'gitlab/styles/version'
2
4
 
3
5
  module Gitlab
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'gitlab/styles/rubocop/cop/custom_error_class'
2
4
  require 'gitlab/styles/rubocop/cop/gem_fetcher'
3
5
  require 'gitlab/styles/rubocop/cop/active_record_serialize'
@@ -6,10 +8,15 @@ require 'gitlab/styles/rubocop/cop/polymorphic_associations'
6
8
  require 'gitlab/styles/rubocop/cop/active_record_dependent'
7
9
  require 'gitlab/styles/rubocop/cop/in_batches'
8
10
  require 'gitlab/styles/rubocop/cop/line_break_after_guard_clauses'
11
+ require 'gitlab/styles/rubocop/cop/line_break_around_conditional_block'
12
+ require 'gitlab/styles/rubocop/cop/code_reuse/active_record'
13
+ require 'gitlab/styles/rubocop/cop/migration/update_large_table'
9
14
  require 'gitlab/styles/rubocop/cop/without_reactive_cache'
10
15
  require 'gitlab/styles/rubocop/cop/rspec/single_line_hook'
11
16
  require 'gitlab/styles/rubocop/cop/rspec/have_link_parameters'
12
17
  require 'gitlab/styles/rubocop/cop/rspec/verbose_include_metadata'
18
+ require 'gitlab/styles/rubocop/cop/rspec/empty_line_after_shared_example'
19
+ require 'gitlab/styles/rubocop/cop/rspec/empty_line_after_let_block'
13
20
 
14
21
  module Gitlab
15
22
  module Styles
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../model_helpers'
2
4
 
3
5
  module Gitlab
@@ -9,7 +11,7 @@ module Gitlab
9
11
  include ModelHelpers
10
12
 
11
13
  MSG = 'Do not use `dependent: to remove associated data, ' \
12
- 'use foreign keys with cascading deletes instead'.freeze
14
+ 'use foreign keys with cascading deletes instead'
13
15
 
14
16
  METHOD_NAMES = [:has_many, :has_one, :belongs_to].freeze
15
17
 
@@ -20,7 +22,7 @@ module Gitlab
20
22
  node.children.last.each_node(:pair) do |pair|
21
23
  key_name = pair.children[0].children[0]
22
24
 
23
- add_offense(pair, location: :expression) if key_name == :dependent
25
+ add_offense(pair) if key_name == :dependent
24
26
  end
25
27
  end
26
28
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../model_helpers'
2
4
 
3
5
  module Gitlab
@@ -8,7 +10,7 @@ module Gitlab
8
10
  class ActiveRecordSerialize < RuboCop::Cop::Cop
9
11
  include ModelHelpers
10
12
 
11
- MSG = 'Do not store serialized data in the database, use separate columns and/or tables instead'.freeze
13
+ MSG = 'Do not store serialized data in the database, use separate columns and/or tables instead'
12
14
 
13
15
  def on_send(node)
14
16
  return unless in_model?(node)
@@ -0,0 +1,131 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module Styles
5
+ module Rubocop
6
+ module Cop
7
+ module CodeReuse
8
+ # Cop that denies the use of ActiveRecord methods outside of models.
9
+ class ActiveRecord < RuboCop::Cop::Cop
10
+ MSG = 'This method can only be used inside an ActiveRecord model: ' \
11
+ 'https://gitlab.com/gitlab-org/gitlab-foss/issues/49653'
12
+
13
+ # Various methods from ActiveRecord::Querying that are denied. We
14
+ # exclude some generic ones such as `any?` and `first`, as these may
15
+ # lead to too many false positives, since `Array` also supports these
16
+ # methods.
17
+ #
18
+ # The keys of this Hash are the denied method names. The values are
19
+ # booleans that indicate if the method should only be denied if any
20
+ # arguments are provided.
21
+ NOT_ALLOWED = {
22
+ average: true,
23
+ calculate: true,
24
+ count_by_sql: true,
25
+ create_with: true,
26
+ distinct: false,
27
+ eager_load: true,
28
+ exists?: true,
29
+ find_by: true,
30
+ find_by!: true,
31
+ find_by_sql: true,
32
+ find_each: true,
33
+ find_in_batches: true,
34
+ find_or_create_by: true,
35
+ find_or_create_by!: true,
36
+ find_or_initialize_by: true,
37
+ first!: false,
38
+ first_or_create: true,
39
+ first_or_create!: true,
40
+ first_or_initialize: true,
41
+ from: true,
42
+ group: true,
43
+ having: true,
44
+ ids: false,
45
+ includes: true,
46
+ joins: true,
47
+ limit: true,
48
+ lock: false,
49
+ many?: false,
50
+ offset: true,
51
+ order: true,
52
+ pluck: true,
53
+ preload: true,
54
+ readonly: false,
55
+ references: true,
56
+ reorder: true,
57
+ rewhere: true,
58
+ take: false,
59
+ take!: false,
60
+ unscope: false,
61
+ where: false,
62
+ with: true
63
+ }.freeze
64
+
65
+ def on_send(node)
66
+ receiver = node.children[0]
67
+ send_name = node.children[1]
68
+ first_arg = node.children[2]
69
+
70
+ return unless receiver && NOT_ALLOWED.key?(send_name)
71
+
72
+ # If the rule requires an argument to be given, but none are
73
+ # provided, we won't register an offense. This prevents us from
74
+ # adding offenses for `project.group`, while still covering
75
+ # `Project.group(:name)`.
76
+ return if NOT_ALLOWED[send_name] && !first_arg
77
+
78
+ add_offense(node, location: :selector)
79
+ end
80
+
81
+ # We can not auto correct code like this, as it requires manual
82
+ # refactoring. Instead, we'll just allow the surrounding scope.
83
+ #
84
+ # Despite this method's presence, you should not use it. This method
85
+ # exists to make it possible to allow large chunks of offenses we
86
+ # can't fix in the short term. If you are writing new code, follow the
87
+ # code reuse guidelines, instead of allowing any new offenses.
88
+ def autocorrect(node)
89
+ scope = surrounding_scope_of(node)
90
+ indent = indentation_of(scope)
91
+
92
+ lambda do |corrector|
93
+ # This prevents us from inserting the same enable/disable comment
94
+ # for a method or block that has multiple offenses.
95
+ next if allowed_scopes.include?(scope)
96
+
97
+ corrector.insert_before(
98
+ scope.source_range,
99
+ "# rubocop: disable #{cop_name}\n#{indent}"
100
+ )
101
+
102
+ corrector.insert_after(
103
+ scope.source_range,
104
+ "\n#{indent}# rubocop: enable #{cop_name}"
105
+ )
106
+
107
+ allowed_scopes << scope
108
+ end
109
+ end
110
+
111
+ def indentation_of(node)
112
+ ' ' * node.loc.expression.source_line[/\A */].length
113
+ end
114
+
115
+ def surrounding_scope_of(node)
116
+ %i[def defs block begin].each do |type|
117
+ if (found = node.each_ancestor(type).first)
118
+ return found
119
+ end
120
+ end
121
+ end
122
+
123
+ def allowed_scopes
124
+ @allowed_scopes ||= Set.new
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Gitlab
2
4
  module Styles
3
5
  module Rubocop
@@ -16,10 +18,11 @@ module Gitlab
16
18
  # # good
17
19
  # FooError = Class.new(StandardError)
18
20
  class CustomErrorClass < RuboCop::Cop::Cop
19
- MSG = 'Use `Class.new(SuperClass)` to define an empty custom error class.'.freeze
21
+ MSG = 'Use `Class.new(SuperClass)` to define an empty custom error class.'
20
22
 
21
23
  def on_class(node)
22
- _klass, parent, body = node.children
24
+ parent = node.parent_class
25
+ body = node.body
23
26
 
24
27
  return if body
25
28
 
@@ -27,11 +30,13 @@ module Gitlab
27
30
 
28
31
  return unless parent_klass&.to_s&.end_with?('Error')
29
32
 
30
- add_offense(node, location: :expression)
33
+ add_offense(node)
31
34
  end
32
35
 
33
36
  def autocorrect(node)
34
- klass, parent, _body = node.children
37
+ klass = node.identifier
38
+ parent = node.parent_class
39
+
35
40
  replacement = "#{class_name_from_node(klass)} = Class.new(#{class_name_from_node(parent)})"
36
41
 
37
42
  lambda do |corrector|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Gitlab
2
4
  module Styles
3
5
  module Rubocop
@@ -6,7 +8,7 @@ module Gitlab
6
8
  # `Gemfile` in order to avoid additional points of failure beyond
7
9
  # rubygems.org.
8
10
  class GemFetcher < RuboCop::Cop::Cop
9
- MSG = 'Do not use gems from git repositories, only use gems from RubyGems.'.freeze
11
+ MSG = 'Do not use gems from git repositories, only use gems from RubyGems.'
10
12
 
11
13
  GIT_KEYS = [:git, :github].freeze
12
14
 
@@ -18,7 +20,7 @@ module Gitlab
18
20
 
19
21
  node.children.last.each_node(:pair) do |pair|
20
22
  key_name = pair.children[0].children[0].to_sym
21
- add_offense(node, location: pair.source_range, message: MSG) if GIT_KEYS.include?(key_name)
23
+ add_offense(node, location: pair.source_range) if GIT_KEYS.include?(key_name)
22
24
  end
23
25
  end
24
26