skip to content

After a RuboCop upgrade, a run warns about pending cops and about `require: rubocop-performance` - what does each warning mean, and how do you fix the .rubocop.yml?

level: seniorimportance: should knowfreq 35%

answer

  1. new cops ship Enabled: pending
  2. AllCops NewCops: enable or disable
  3. department NewCops pinned to a version
  4. plugins: via lint_roller since 1.72
  5. require: stays for local custom cops

basics

~20 s

Pending cops are new cops that stay off until you decide; set each one's Enabled, or NewCops for all or per department. The require: warning means the gem is now a plugin, so list it under plugins: instead.

solid answer

~40 s

RuboCop adds new cops in minor releases with `Enabled: pending`: they do not run, and every run lists them until you decide. You can decide per cop (`Enabled: true` or `false`), in bulk with `AllCops: NewCops: enable` or `disable` (the `--enable-pending-cops` and `--disable-pending-cops` flags override it), or, since 1.90, per department: `Style: NewCops: "1.88"` enables the pending `Style` cops added up to 1.88 and keeps warning about newer ones. The next major release enables all pending cops anyway. The second warning, `rubocop-performance extension supports plugin, specify plugins: rubocop-performance instead of require: rubocop-performance`, appears because RuboCop 1.72 introduced **plugins** built on `lint_roller`: `plugins:` loads the extension and its default config through a documented API, while `require:` just calls `Kernel#require`. Move published extensions to `plugins:`; keep `require:` for local custom-cop files.

code

yaml · 18 lines
yaml
# .rubocop.yml
plugins:
  - rubocop-performance

require:
  - ./lib/custom_cops/no_sleep_in_specs.rb

AllCops:
  NewCops: disable

Lint:
  NewCops: enable

Style:
  NewCops: "1.88"   # quoted: an unquoted 1.20 would read as 1.2

Lint/MisplacedMagicComment:
  Enabled: true

go deeper

for a junior

Recall that new cops arrive as pending and do not run until you set Enabled true or false, or set AllCops NewCops.

for a middle

Explain the choices for pending cops, per cop, per department with a quoted version, globally, or by flag, and why extensions moved from require: to plugins:.

for a senior

Run upgrades as their own pull request: move plugin-capable gems to plugins:, decide every pending cop, and pick enable or a version pin to fit the repository.

for a principal

Set the policy for shared configs: version-pinned departments let many teams absorb new cops at their own pace without a surprise at the next major release.

## Why an upgrade produces warnings RuboCop follows semantic versioning for its configuration. Minor releases add cops but aim not to break a green build, and changed defaults wait for a major release. Two mechanisms carry that promise, and both surface as warnings right after a `bundle update rubocop`. ## Pending cops A cop added between major versions ships in `config/default.yml` with **`Enabled: pending`**. A pending cop does not run. Instead, every run prints a list headed `The following cops were added to RuboCop, but are not configured`, with each cop's version, until the project records a decision. The options, from narrowest to broadest: 1. **Per cop** - `Lint/MisplacedMagicComment: Enabled: true` (or `false`). 2. **Per department, since RuboCop 1.90** - `NewCops` under a department key accepts `enable`, `disable`, `pending`, or a **version**. `Style: NewCops: "1.88"` enables every pending `Style` cop whose `VersionAdded` is 1.88 or earlier and keeps warning about later ones. Quote the version: YAML reads an unquoted `1.20` as `1.2`. Extension departments are pinned to the extension's own version scheme. 3. **Globally** - `AllCops: NewCops: enable` or `disable`. At `AllCops` level only the three keywords are accepted. 4. **For one run** - `--enable-pending-cops` or `--disable-pending-cops`, which override the file. A department setting beats the `AllCops` setting for that department's cops. On a **major** upgrade (1.x to 2.0) all pending cops become enabled in bulk. The one documented exception is a cop that reports configuration that silently does nothing: `Lint/CopDirectiveSyntax` was enabled in the 1.91 minor release. | Choice | Upgrade experience | Risk | |---|---|---| | `NewCops: enable` | new offenses appear in the upgrade pull request | noisy upgrades | | `NewCops: disable` | silence | useful cops never adopted; a big jump at 2.0 | | department version pin | review a batch per department | a little bookkeeping | Since `Gemfile.lock` pins RuboCop, `enable` is safe for an application: new offenses appear in the upgrade pull request, where someone is looking. A shared config gem that many teams inherit is better off pinning versions per department. `pending` is not the same as `preview`. RuboCop 1.91 added `Enabled: preview` for cops that are still experimental; `NewCops: enable` does not turn those on; `AllCops: Preview: true` or `--preview` does, and `--only` can still run one by name. ## `plugins:` versus `require:` Before 1.72 an extension such as rubocop-performance was loaded with `require:`. That simply called `Kernel#require` on the name, and the extension used an undocumented hook to inject its own `config/default.yml` into RuboCop's defaults. RuboCop 1.72 introduced **plugins**, built on the `lint_roller` library: - a plugin gem declares `default_lint_roller_plugin` in its gemspec metadata and ships a `LintRoller::Plugin` subclass; - `plugins:` in `.rubocop.yml` (or `--plugin` on the command line) loads it, and the plugin hands RuboCop its rules and default configuration through that API; - if a gem that supports the plugin API is still listed under `require:`, RuboCop prints the warning and loads it as a plugin anyway, so the fix is a config edit, not a behaviour change. `require:` is not deprecated for everything. Paths are handed to `Kernel#require`; a path starting with `.` is resolved relative to the `.rubocop.yml`, so a project's own cop in `./lib/custom_cops/no_sleep.rb` stays under `require:`. The documentation says there are no plans to remove it. ## Reading the two warnings side by side | Warning | Meaning | Fix | |---|---|---| | `The following cops were added to RuboCop, but are not configured` | pending cops exist and do not run | decide them: `Enabled`, department `NewCops`, or `AllCops: NewCops` | | `... extension supports plugin, specify plugins: ... instead of require: ...` | the gem ships a `lint_roller` plugin | move the gem name from `require:` to `plugins:` | Neither warning changes the exit status, which is why both are easy to ignore for months. A pending list that keeps growing means new checks never reach the codebase; a lingering `require:` keeps a published extension on the compatibility path RuboCop maintains for pre-plugin configurations, with a warning on every run. ## A clean upgrade routine - Upgrade RuboCop and its extensions in their own pull request. - Move every extension that prints the plugin warning from `require:` to `plugins:`. - Decide the pending cops explicitly, one by one or per department, so the list stays empty. - Run the whole suite and fix or configure the new offenses in the same pull request.

  • Does AllCops NewCops: enable also turn on cops marked Enabled: preview in RuboCop 1.91?
    No. Pending and preview are independent channels. `NewCops: enable` resolves pending cops, which RuboCop has already decided to turn on at the next major release. Preview cops are experimental and run only when the project opts in with `AllCops: Preview: true` or the `--preview` flag, or names them with `--only`.
  • Why can a project's own custom cop stay under require: after the plugin migration?
    `plugins:` expects a gem or class that implements the `lint_roller` plugin API. A single local file that defines a cop class just needs loading, and `require:` hands its path to `Kernel#require`, resolving a path that starts with `.` relative to the `.rubocop.yml`. RuboCop's documentation says `require:` stays for such internal extensions.

saying these in an interview costs you the question

  • Pending cops already run on every file; the warning only says they are new.
  • AllCops NewCops accepts a version number such as 1.88.
  • NewCops: enable also turns on cops marked Enabled: preview.
  • require: is deprecated and will stop loading local custom cop files.
  • A plugin-capable gem left under require: is skipped entirely.