Add missing `feature_category` metadata to RSpec files clearing RSpec/FeatureCategory todos
Everyone can contribute. Help move this issue forward while earning points, leveling up and collecting rewards.
Summary
3,295 spec files are excluded from the RSpec/FeatureCategory cop via
.rubocop_todo/rspec/feature_category.yml
due to a missing feature_category: tag on their top-level RSpec.describe.
To kick off, give an AI agent the following prompt:
Work on #600670
Relates to: gitlab-org/quality#275 (closed)
Agent Guidelines
- Batch size: 25 files per MR (max 30).
- Only add missing values. Skip files that already have any
feature_category:(even:shared); leave them in the rubocop_todo. - Valid categories:
config/feature_categories.yml+tooling,test_platform,rails_platform.:sharedis not valid. - Top-level only. Only modify the
RSpec.describeline; never nestedcontext/describe.
Determining the category (in order):
- Source file —
feature_category :xxxin the corresponding class - Sibling specs in the same directory that already have the tag
- Base (non-EE) equivalent spec
- CODEOWNERS group → team's primary category
- Module/class name
Learned patterns
RuboCop cop specs (spec/rubocop/)
Match category to what the cop enforces, not just the directory:
| Cop type | Category |
|---|---|
cop/database/, ActiveRecord/ORM performance cops |
:database |
cop/api/, cop/graphql/ |
:api |
cop/scalability/, Sidekiq worker cops |
:scalability |
cop/migration/ |
:database |
cop/gitlab/feature_flag*, cop/feature_flag* |
:scalability |
cop/gettext/ |
:internationalization |
| Security/file-safety cops | :vulnerability_management |
| General code quality / tooling helpers | :tooling |
cop/qa/, QA helpers |
:test_platform |
cop/usage_data/ |
:service_ping |
cop/user_admin |
:system_access |
cop/static_translation_definition |
:internationalization |
Sidekiq/Redis cops (sidekiq_*, redis_*) |
:scalability |
rails_platform is for Rails core framework gems only (rails, zeitwerk) — not for cops enforcing Rails patterns.
Important: Many spec/rubocop/cop/ files already have feature_category: :shared (set by the shared copconfig). Always check grep "^RSpec.describe" before editing — skip files that already have any feature_category: value.
spec/lib/gitlab/database/
All files in this directory tree → :database.
Running RuboCop locally
bundle exec rubocop may fail with Could not find gitlab_query_language (native gem missing in GDK setup). Use the system rubocop directly instead:
REVEAL_RUBOCOP_TODO=0 rubocop --only RSpec/FeatureCategory <files>For commits/pushes, exclude the failing hooks:
LEFTHOOK_EXCLUDE=rubocop git commit ...
LEFTHOOK_EXCLUDE=openapi_docs,rubocop,danger,commit-message-linting git push origin <branch>Instructions
Setup (once)
Resolve and reuse across all batches:
- Current user ID:
get_user(no args) →id - Current milestone ID: search
gitlab-orggroup milestones for the lowest-version active milestone (e.g.19.1) →id
Pre-flight (REQUIRED before every batch)
Step 0 — Pull master.
git checkout master && git pull origin masterStep 1 — Build an exclusion set of already-claimed files.
Use the GitLab MCP tool search (scope: merge_requests, project: gitlab-org/gitlab) to find all open MRs whose title contains "Add feature_category metadata". For each result, call list_merge_request_diffs and collect every new_path ending in _spec.rb. Also call list_merge_requests_related_to_issue (issue IID 600670) and repeat for any open ones. Union all paths into a single exclusion set.
Step 2 — Check for branch name collisions.
git ls-remote --heads origin '*add-feature-category-batch-*'The naming convention is add-feature-category-batch-NNN. Pick the next unused number (e.g. if add-feature-category-batch-001 exists, use add-feature-category-batch-002).
Step 3 — Select files (spread across the YAML to avoid conflicts).
Read .rubocop_todo/rspec/feature_category.yml. Extract all entries (including those already excluded or tagged) to get the full list in YAML order. Call this list all_entries (length N_total).
Conflict-avoidance — this takes priority over everything else. The sole source of merge conflicts is .rubocop_todo/rspec/feature_category.yml. When multiple MRs are open simultaneously, their diff hunks must not overlap in that file. The critical insight: stride must be computed over YAML positions (the full entry list), not over the filtered candidate list. Striding over candidates fails when many consecutive YAML entries are all eligible — they map to adjacent YAML lines regardless of candidate-list distance.
- Let
N_total= total entries in the YAML file (all entries, not just candidates),B= batch size (25). - Compute stride
S = N_total / B(round to nearest integer). With ~3100 entries this givesS ≈ 125. - For
iin0..B-1: start at YAML indexi * S. Advance forward until finding an entry that is (a) not in the exclusion set and (b) does not already havefeature_category:on itsRSpec.describeline. Select that entry. This guarantees each selected deletion is ~SYAML lines from the next — well beyond git's 3-line context window (which needs only 7 lines of separation to avoid conflicts).
Secondary goal — minimize distinct CODEOWNERS groups. After the stride selection, check whether the chosen files cluster into one or two CODEOWNERS groups. If swapping a few stride-selected files for nearby unclaimed ones (within ±S/4 positions in the YAML) would reduce the reviewer count without closing the gap between hunks below 20 lines, make that swap. Do not override the spread to achieve grouping — a few extra reviewers is cheaper than a conflict rebase.
Per batch
- Edit: add
, feature_category: :symbolbeforedoon theRSpec.describeline. - Remove the file from
.rubocop_todo/rspec/feature_category.yml. - Verify:
REVEAL_RUBOCOP_TODO=0 rubocop --only RSpec/FeatureCategory <files> - Commit:
Use the full URL — the commit-msg linter rejects short references.
Add feature_category metadata to batch-NNN specs Adds missing `feature_category:` metadata to N spec files and removes them from .rubocop_todo/rspec/feature_category.yml. Contributes to https://gitlab.com/gitlab-org/gitlab/-/issues/600670 - Push:
(
LEFTHOOK_EXCLUDE=openapi_docs,rubocop,danger,commit-message-linting git push origin <branch>openapi_docsrequires a dev database absent in standard GDK setups;rubocop/danger/commit-message-lintingmay fail ifgitlab_query_languagenative gem is not installed.) - Create MR via GitLab MCP:
title:Add feature_category metadata to batch-NNN specslabels:pipeline::tier-1squash:true,remove_source_branch:trueassignee_ids: current user ID,milestone_id: current milestone IDdescription:## Summary Adds missing `feature_category:` metadata to N spec files and removes them from `.rubocop_todo/rspec/feature_category.yml`. | File | `feature_category` | Rationale | |---|---|---| | `path/to/spec.rb` | `:category` | rationale | Contributes to https://gitlab.com/gitlab-org/gitlab/-/issues/600670
- Update this issue if new knowledge was gained during the batch — e.g. category assignment patterns, edge cases, or gotchas discovered — by editing the Agent Guidelines or adding to the Learned patterns section. This keeps future batches consistent.
Definition of Done
- All files missing
feature_category:have a valid tag -
.rubocop_todo/rspec/feature_category.ymlcontains only pre-existing non-standard values or is empty - CI passes
- Every assigned category exists in
config/feature_categories.yml