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?
answer
- new cops ship Enabled: pending
- AllCops NewCops: enable or disable
- department NewCops pinned to a version
- plugins: via lint_roller since 1.72
- require: stays for local custom cops
basics
~20 sPending 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 sRuboCop 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# .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: truego deeper
Recall that new cops arrive as pending and do not run until you set Enabled true or false, or set AllCops NewCops.
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:.
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.
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.