= Gemspec

== Gemspec/DependencyVersion

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Disabled
| Yes
| No
| 1.29
| -
|===

Enforce that gem dependency version specifications or a commit reference (branch,
ref, or tag) are either required or forbidden.

=== Examples

==== EnforcedStyle: required (default)

[source,ruby]
----
# bad
Gem::Specification.new do |spec|
  spec.add_dependency 'parser'
end

# bad
Gem::Specification.new do |spec|
  spec.add_development_dependency 'parser'
end

# good
Gem::Specification.new do |spec|
  spec.add_dependency 'parser', '>= 2.3.3.1', '< 3.0'
end

# good
Gem::Specification.new do |spec|
  spec.add_development_dependency 'parser', '>= 2.3.3.1', '< 3.0'
end
----

==== EnforcedStyle: forbidden

[source,ruby]
----
# bad
Gem::Specification.new do |spec|
  spec.add_dependency 'parser', '>= 2.3.3.1', '< 3.0'
end

# bad
Gem::Specification.new do |spec|
  spec.add_development_dependency 'parser', '>= 2.3.3.1', '< 3.0'
end

# good
Gem::Specification.new do |spec|
  spec.add_dependency 'parser'
end

# good
Gem::Specification.new do |spec|
  spec.add_development_dependency 'parser'
end
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| EnforcedStyle
| `required`
| `required`, `forbidden`

| Include
| `+**/*.gemspec+`
| Array

| AllowedGems
| `[]`
| Array
|===

== Gemspec/DeprecatedAttributeAssignment

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Yes
| 1.30
| -
|===

Checks that deprecated attribute attributes are not set in a gemspec file.
Removing deprecated attributes allows the user to receive smaller packed gems.

=== Examples

[source,ruby]
----
# bad
Gem::Specification.new do |spec|
  spec.name = 'your_cool_gem_name'
  spec.test_files = Dir.glob('test/**/*')
end

# bad
Gem::Specification.new do |spec|
  spec.name = 'your_cool_gem_name'
  spec.test_files += Dir.glob('test/**/*')
end

# good
Gem::Specification.new do |spec|
  spec.name = 'your_cool_gem_name'
end
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| Include
| `+**/*.gemspec+`
| Array
|===

== Gemspec/DuplicatedAssignment

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.52
| -
|===

An attribute assignment method calls should be listed only once
in a gemspec.

Assigning to an attribute with the same name using `spec.foo =` will be
an unintended usage. On the other hand, duplication of methods such
as `spec.requirements`, `spec.add_runtime_dependency`, and others are
permitted because it is the intended use of appending values.

=== Examples

[source,ruby]
----
# bad
Gem::Specification.new do |spec|
  spec.name = 'rubocop'
  spec.name = 'rubocop2'
end

# good
Gem::Specification.new do |spec|
  spec.name = 'rubocop'
end

# good
Gem::Specification.new do |spec|
  spec.requirements << 'libmagick, v6.0'
  spec.requirements << 'A good graphics card'
end

# good
Gem::Specification.new do |spec|
  spec.add_runtime_dependency('parallel', '~> 1.10')
  spec.add_runtime_dependency('parser', '>= 2.3.3.1', '< 3.0')
end
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| Include
| `+**/*.gemspec+`
| Array
|===

== Gemspec/OrderedDependencies

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Yes
| 0.51
| -
|===

Dependencies in the gemspec should be alphabetically sorted.

=== Examples

[source,ruby]
----
# bad
spec.add_dependency 'rubocop'
spec.add_dependency 'rspec'

# good
spec.add_dependency 'rspec'
spec.add_dependency 'rubocop'

# good
spec.add_dependency 'rubocop'

spec.add_dependency 'rspec'

# bad
spec.add_development_dependency 'rubocop'
spec.add_development_dependency 'rspec'

# good
spec.add_development_dependency 'rspec'
spec.add_development_dependency 'rubocop'

# good
spec.add_development_dependency 'rubocop'

spec.add_development_dependency 'rspec'

# bad
spec.add_runtime_dependency 'rubocop'
spec.add_runtime_dependency 'rspec'

# good
spec.add_runtime_dependency 'rspec'
spec.add_runtime_dependency 'rubocop'

# good
spec.add_runtime_dependency 'rubocop'

spec.add_runtime_dependency 'rspec'

# good only if TreatCommentsAsGroupSeparators is true
# For code quality
spec.add_dependency 'rubocop'
# For tests
spec.add_dependency 'rspec'
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| TreatCommentsAsGroupSeparators
| `true`
| Boolean

| ConsiderPunctuation
| `false`
| Boolean

| Include
| `+**/*.gemspec+`
| Array
|===

== Gemspec/RequireMFA

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Yes
| 1.23
| -
|===

Requires a gemspec to have `rubygems_mfa_required` metadata set.

This setting tells RubyGems that MFA (Multi-Factor Authentication) is
required for accounts to be able perform privileged operations, such as
(see RubyGems' documentation for the full list of privileged
operations):

* `gem push`
* `gem yank`
* `gem owner --add/remove`
* adding or removing owners using gem ownership page

This helps make your gem more secure, as users can be more
confident that gem updates were pushed by maintainers.

=== Examples

[source,ruby]
----
# bad
Gem::Specification.new do |spec|
  # no `rubygems_mfa_required` metadata specified
end

# good
Gem::Specification.new do |spec|
  spec.metadata = {
    'rubygems_mfa_required' => 'true'
  }
end

# good
Gem::Specification.new do |spec|
  spec.metadata['rubygems_mfa_required'] = 'true'
end

# bad
Gem::Specification.new do |spec|
  spec.metadata = {
    'rubygems_mfa_required' => 'false'
  }
end

# good
Gem::Specification.new do |spec|
  spec.metadata = {
    'rubygems_mfa_required' => 'true'
  }
end

# bad
Gem::Specification.new do |spec|
  spec.metadata['rubygems_mfa_required'] = 'false'
end

# good
Gem::Specification.new do |spec|
  spec.metadata['rubygems_mfa_required'] = 'true'
end
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| Include
| `+**/*.gemspec+`
| Array
|===

=== References

* https://guides.rubygems.org/mfa-requirement-opt-in/

== Gemspec/RequiredRubyVersion

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.52
| 1.22
|===

Checks that `required_ruby_version` in a gemspec file is set to a valid
value (non-blank) and matches `TargetRubyVersion` as set in RuboCop's
configuration for the gem.

This ensures that RuboCop is using the same Ruby version as the gem.

=== Examples

[source,ruby]
----
# When `TargetRubyVersion` of .rubocop.yml is `2.5`.

# bad
Gem::Specification.new do |spec|
  # no `required_ruby_version` specified
end

# bad
Gem::Specification.new do |spec|
  spec.required_ruby_version = '>= 2.4.0'
end

# bad
Gem::Specification.new do |spec|
  spec.required_ruby_version = '>= 2.6.0'
end

# bad
Gem::Specification.new do |spec|
  spec.required_ruby_version = ''
end

# good
Gem::Specification.new do |spec|
  spec.required_ruby_version = '>= 2.5.0'
end

# good
Gem::Specification.new do |spec|
  spec.required_ruby_version = '>= 2.5'
end

# accepted but not recommended
Gem::Specification.new do |spec|
  spec.required_ruby_version = ['>= 2.5.0', '< 2.7.0']
end

# accepted but not recommended, since
# Ruby does not really follow semantic versioning
Gem::Specification.new do |spec|
  spec.required_ruby_version = '~> 2.5'
end
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| Include
| `+**/*.gemspec+`
| Array
|===

== Gemspec/RubyVersionGlobalsUsage

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.72
| -
|===

Checks that `RUBY_VERSION` constant is not used in gemspec.
Using `RUBY_VERSION` is dangerous because value of the
constant is determined by `rake release`.
It's possible to have dependency based on ruby version used
to execute `rake release` and not user's ruby version.

=== Examples

[source,ruby]
----
# bad
Gem::Specification.new do |spec|
  if RUBY_VERSION >= '3.0'
    spec.add_runtime_dependency 'gem_a'
  else
    spec.add_runtime_dependency 'gem_b'
  end
end

# good
Gem::Specification.new do |spec|
  spec.add_runtime_dependency 'gem_a'
end
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| Include
| `+**/*.gemspec+`
| Array
|===

=== References

* https://rubystyle.guide#no-ruby-version-in-the-gemspec
