From 273ee2d651da95b8974f3810e16f40f6bb2094fe Mon Sep 17 00:00:00 2001 From: Vlad Wolanyk Date: Tue, 7 Oct 2025 09:46:47 -0400 Subject: [PATCH 1/6] Add description success response Changelog: changed --- .rubocop.yml | 14 +++-- .../cop/api/description_success_response.rb | 51 +++++++++++++++++++ 2 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 rubocop/cop/api/description_success_response.rb diff --git a/.rubocop.yml b/.rubocop.yml index 9322efd8591ef1..3ab01b807c57cc 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -840,15 +840,21 @@ API/ClassLevelAllowAccessWithScope: API/DescriptionDetail: Enabled: true Include: - - 'lib/**/api/**/*.rb' - - 'ee/lib/**/api/**/*.rb' + - 'lib/**/api/**/*.rb' + - 'ee/lib/**/api/**/*.rb' + +API/DescriptionSuccessResponse: + Enabled: true + Include: + - 'lib/**/api/**/*.rb' + - 'ee/lib/**/api/**/*.rb' API/DescriptionTags: Enabled: true SafeAutoCorrect: false Include: - - 'lib/**/api/**/*.rb' - - 'ee/lib/**/api/**/*.rb' + - 'lib/**/api/**/*.rb' + - 'ee/lib/**/api/**/*.rb' API/ParameterDescription: Enabled: true diff --git a/rubocop/cop/api/description_success_response.rb b/rubocop/cop/api/description_success_response.rb new file mode 100644 index 00000000000000..3cc7cb9110bbdb --- /dev/null +++ b/rubocop/cop/api/description_success_response.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +require_relative '../../code_reuse_helpers' + +module RuboCop + module Cop + module API + # Checks that API desc blocks define a valid detail + # + # @example + # + # # bad + # desc 'Get a specific thing' do + # detail 'This feature was introduced in GitLab 18.2.' + # tags ['things'] + # ... + # end + # + # # good + # desc 'Get a specific thing' do + # detail 'This feature was introduced in GitLab 18.2.' + # success Entities::Thing + # tags ['things'] + # ... + # end + class DescriptionSuccessResponse < RuboCop::Cop::Base + include CodeReuseHelpers + + MSG = 'API desc blocks must define a success response. https://docs.gitlab.com/development/api_styleguide/#methods-and-parameters-description.' + RESTRICT_ON_SEND = %i[desc].freeze + + # @!method has_success_response?(node) + def_node_matcher :has_success_response?, <<~PATTERN + ^(block + _ + (args) + (begin <(send nil? :success ...) ...>) + ) + PATTERN + + def on_send(node) + return if has_success_response?(node) + + add_offense(node) + end + + alias_method :on_csend, :on_send + end + end + end +end -- GitLab From b29f262114c84ef0a130cc3e5d50b7fc30c3b5a4 Mon Sep 17 00:00:00 2001 From: Vlad Wolanyk Date: Thu, 16 Oct 2025 18:16:00 -0400 Subject: [PATCH 2/6] Add spec and todos Changelog: changed --- .../api/description_success_response.yml | 111 ++++++++++++++++++ doc/development/api_styleguide.md | 9 ++ .../cop/api/description_success_response.rb | 29 ++++- .../api/description_success_response_spec.rb | 29 +++++ 4 files changed, 172 insertions(+), 6 deletions(-) create mode 100644 .rubocop_todo/api/description_success_response.yml create mode 100644 spec/rubocop/cop/api/description_success_response_spec.rb diff --git a/.rubocop_todo/api/description_success_response.yml b/.rubocop_todo/api/description_success_response.yml new file mode 100644 index 00000000000000..b40bb474908177 --- /dev/null +++ b/.rubocop_todo/api/description_success_response.yml @@ -0,0 +1,111 @@ +API/DescriptionSuccessResponse: + Details: grace period + Exclude: + - 'ee/lib/api/admin/search/migrations.rb' + - 'ee/lib/api/admin/search/zoekt.rb' + - 'ee/lib/api/ai/duo_workflows/workflows_internal.rb' + - 'ee/lib/api/analytics/code_review_analytics.rb' + - 'ee/lib/api/audit_events.rb' + - 'ee/lib/api/clusters/agent_url_configurations.rb' + - 'ee/lib/api/elasticsearch_indexed_namespaces.rb' + - 'ee/lib/api/gitlab_subscriptions/subscriptions.rb' + - 'ee/lib/api/group_approval_rules.rb' + - 'ee/lib/api/group_enterprise_users.rb' + - 'ee/lib/api/group_security_settings.rb' + - 'ee/lib/api/group_service_accounts.rb' + - 'ee/lib/api/internal/ai/x_ray/scan.rb' + - 'ee/lib/api/internal/search/zoekt.rb' + - 'ee/lib/api/ldap_group_links.rb' + - 'ee/lib/api/license.rb' + - 'ee/lib/api/manage/groups.rb' + - 'ee/lib/api/project_google_cloud_integration.rb' + - 'ee/lib/api/project_security_settings.rb' + - 'ee/lib/api/protected_environments.rb' + - 'ee/lib/api/provider_identity.rb' + - 'ee/lib/api/remote_development/internal/agents/agentw/agent_info.rb' + - 'ee/lib/api/remote_development/internal/agents/agentw/authorize_user_access.rb' + - 'ee/lib/api/remote_development/internal/agents/agentw/server_config.rb' + - 'ee/lib/api/sbom/occurrences.rb' + - 'ee/lib/api/scim/group_scim.rb' + - 'ee/lib/api/scim/instance_scim.rb' + - 'ee/lib/api/status_checks.rb' + - 'ee/lib/api/virtual_registries/cleanup/policies.rb' + - 'ee/lib/api/vulnerabilities.rb' + - 'ee/lib/api/vulnerability_archive_exports.rb' + - 'ee/lib/api/vulnerability_exports.rb' + - 'ee/lib/api/vulnerability_issue_links.rb' + - 'ee/lib/ee/api/group_milestones.rb' + - 'ee/lib/ee/api/groups.rb' + - 'ee/lib/ee/api/internal/kubernetes.rb' + - 'ee/lib/ee/api/issues.rb' + - 'ee/lib/ee/api/members.rb' + - 'ee/lib/ee/api/merge_request_approvals.rb' + - 'ee/lib/ee/api/namespaces.rb' + - 'ee/lib/ee/api/project_milestones.rb' + - 'ee/lib/ee/api/projects.rb' + - 'ee/lib/ee/api/todos.rb' + - 'ee/lib/gitlab_subscriptions/api/internal/members.rb' + - 'ee/lib/gitlab_subscriptions/api/internal/subscriptions.rb' + - 'ee/lib/gitlab_subscriptions/api/internal/users.rb' + - 'lib/api/access_requests.rb' + - 'lib/api/admin/token.rb' + - 'lib/api/appearance.rb' + - 'lib/api/avatar.rb' + - 'lib/api/badges.rb' + - 'lib/api/ci/job_artifacts.rb' + - 'lib/api/ci/pipelines.rb' + - 'lib/api/ci/runner.rb' + - 'lib/api/ci/secure_files.rb' + - 'lib/api/clusters/agent_tokens.rb' + - 'lib/api/clusters/agents.rb' + - 'lib/api/custom_attributes_endpoints.rb' + - 'lib/api/deploy_keys.rb' + - 'lib/api/deploy_tokens.rb' + - 'lib/api/deployments.rb' + - 'lib/api/discussions.rb' + - 'lib/api/environments.rb' + - 'lib/api/feature_flags_user_lists.rb' + - 'lib/api/features.rb' + - 'lib/api/files.rb' + - 'lib/api/go_proxy.rb' + - 'lib/api/group_import.rb' + - 'lib/api/group_milestones.rb' + - 'lib/api/group_placeholder_reassignments.rb' + - 'lib/api/groups.rb' + - 'lib/api/integrations.rb' + - 'lib/api/internal/auto_flow.rb' + - 'lib/api/internal/kubernetes.rb' + - 'lib/api/internal/lfs.rb' + - 'lib/api/internal/pages.rb' + - 'lib/api/issues.rb' + - 'lib/api/labels.rb' + - 'lib/api/members.rb' + - 'lib/api/merge_request_approvals.rb' + - 'lib/api/merge_requests.rb' + - 'lib/api/ml/mlflow/entrypoint.rb' + - 'lib/api/ml/mlflow/experiments.rb' + - 'lib/api/ml/mlflow/registered_models.rb' + - 'lib/api/ml/mlflow/runs.rb' + - 'lib/api/ml/mlflow_artifacts/artifacts.rb' + - 'lib/api/ml/mlflow_artifacts/entrypoint.rb' + - 'lib/api/notes.rb' + - 'lib/api/pages_domains.rb' + - 'lib/api/project_events.rb' + - 'lib/api/project_import.rb' + - 'lib/api/project_milestones.rb' + - 'lib/api/projects.rb' + - 'lib/api/releases.rb' + - 'lib/api/repositories.rb' + - 'lib/api/resource_state_events.rb' + - 'lib/api/rpm_project_packages.rb' + - 'lib/api/rubygem_packages.rb' + - 'lib/api/search.rb' + - 'lib/api/settings.rb' + - 'lib/api/snippets.rb' + - 'lib/api/statistics.rb' + - 'lib/api/subscriptions.rb' + - 'lib/api/supply_chain/attestations.rb' + - 'lib/api/todos.rb' + - 'lib/api/topics.rb' + - 'lib/api/unleash.rb' + - 'lib/api/users.rb' diff --git a/doc/development/api_styleguide.md b/doc/development/api_styleguide.md index ed976d64da346a..5bc5b5fc9ec9bd 100644 --- a/doc/development/api_styleguide.md +++ b/doc/development/api_styleguide.md @@ -48,6 +48,7 @@ for a good example): - `desc` for the method summary. - `detail` for each `desc` block. This must be a string. +- `success` for each `desc` block. This defines the success response. - `tags` for each `desc` block. This should be a string, or array of strings. - `params` for the method parameters. This acts as description, [validation, and coercion of the parameters](https://github.com/ruby-grape/grape#parameter-validation-and-coercion) @@ -80,6 +81,14 @@ The `detail` should describe any additional details not covered by the `desc` su - If it is behind a feature flag, mention that instead: `This feature is gated by the :feature\_flag\_symbol feature flag.` - If the endpoint is deprecated, and if so, its planned removal date +### Defining endpoint success + +Every endpoint must have a `success` value for each `desc` block. The value should accurately describe a success response for the endpoint. + +- If the response is one of `API::Entities` use the entity class for the success value ie `success Entities::System::BroadcastMessage` +- If it does not return an entity the value should include the status code and message ie `success code: 204, message: 'Record was deleted'` +- The `http_codes` option should not be used to document an endpoint's success response. + ### Choosing a tag Every endpoint must have at least one value defined in `tags` per `desc` block. diff --git a/rubocop/cop/api/description_success_response.rb b/rubocop/cop/api/description_success_response.rb index 3cc7cb9110bbdb..ca20480f2387f6 100644 --- a/rubocop/cop/api/description_success_response.rb +++ b/rubocop/cop/api/description_success_response.rb @@ -5,7 +5,7 @@ module RuboCop module Cop module API - # Checks that API desc blocks define a valid detail + # Checks that API desc blocks define a valid success response # # @example # @@ -16,6 +16,14 @@ module API # ... # end # + # # bad + # desc 'Get a specific thing' do + # detail 'This feature was introduced in GitLab 18.2.' + # http_codes [[204, 'Thing was deleted'], [403, 'Forbidden']] + # tags ['things'] + # ... + # end + # # good # desc 'Get a specific thing' do # detail 'This feature was introduced in GitLab 18.2.' @@ -23,28 +31,37 @@ module API # tags ['things'] # ... # end + # + # # good + # desc 'Get a specific thing' do + # detail 'This feature was introduced in GitLab 18.2.' + # success code: 204, message: 'Thing was deleted' + # failure [{ code: 403, message: 'Forbidden' }] + # tags ['things'] + # ... + # end class DescriptionSuccessResponse < RuboCop::Cop::Base include CodeReuseHelpers MSG = 'API desc blocks must define a success response. https://docs.gitlab.com/development/api_styleguide/#methods-and-parameters-description.' - RESTRICT_ON_SEND = %i[desc].freeze # @!method has_success_response?(node) def_node_matcher :has_success_response?, <<~PATTERN - ^(block - _ + (block + (send nil? :desc ...) (args) (begin <(send nil? :success ...) ...>) ) PATTERN - def on_send(node) + def on_block(node) + return unless node.method?(:desc) return if has_success_response?(node) add_offense(node) end - alias_method :on_csend, :on_send + alias_method :on_numblock, :on_block end end end diff --git a/spec/rubocop/cop/api/description_success_response_spec.rb b/spec/rubocop/cop/api/description_success_response_spec.rb new file mode 100644 index 00000000000000..0a499791f1cba7 --- /dev/null +++ b/spec/rubocop/cop/api/description_success_response_spec.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require 'rubocop_spec_helper' +require_relative '../../../../rubocop/cop/api/description_success_response' + +RSpec.describe RuboCop::Cop::API::DescriptionSuccessResponse, :config, feature_category: :api do + context 'when desc block includes success' do + it 'does not register an offense' do + expect_no_offenses(<<~RUBY) + desc 'Get a list of things' do + detail 'This endpoint was introduced in 18.2' + success Entities::Thing + tags %w[things] + end + RUBY + end + end + + context 'when desc block does not have a success' do + it 'registers an offense' do + expect_offense(<<~RUBY) + desc 'Get a list of things' do + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ API desc blocks must define a success response. https://docs.gitlab.com/development/api_styleguide/#methods-and-parameters-description. + tags %w[things] + end + RUBY + end + end +end -- GitLab From b4d59064f8901fa8b70904046041b8204c9814e8 Mon Sep 17 00:00:00 2001 From: Vlad Wolanyk Date: Fri, 17 Oct 2025 14:24:02 -0400 Subject: [PATCH 3/6] Improve grammer and copy Changelog: changed --- doc/development/api_styleguide.md | 13 +++++++++---- rubocop/cop/api/description_success_response.rb | 2 +- .../cop/api/description_success_response_spec.rb | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/doc/development/api_styleguide.md b/doc/development/api_styleguide.md index 5bc5b5fc9ec9bd..189d10fcd814d9 100644 --- a/doc/development/api_styleguide.md +++ b/doc/development/api_styleguide.md @@ -83,11 +83,16 @@ The `detail` should describe any additional details not covered by the `desc` su ### Defining endpoint success -Every endpoint must have a `success` value for each `desc` block. The value should accurately describe a success response for the endpoint. +Every endpoint must have a `success` value for each `desc` block. The value should accurately +describe a success response for the endpoint. -- If the response is one of `API::Entities` use the entity class for the success value ie `success Entities::System::BroadcastMessage` -- If it does not return an entity the value should include the status code and message ie `success code: 204, message: 'Record was deleted'` -- The `http_codes` option should not be used to document an endpoint's success response. +Do not use the `http_codes` option to document the success response. Instead, format the response +based on the endpoint response: + +- If the endpoint responds with an object, include the `Grape::Entity` class. + For example, `success Entities::System::BroadcastMessage` +- If the endpoint does not respond with an object, include a status code and message. +For example, `success code: 204, message: 'Record was deleted'` ### Choosing a tag diff --git a/rubocop/cop/api/description_success_response.rb b/rubocop/cop/api/description_success_response.rb index ca20480f2387f6..fcdb000bc99cf6 100644 --- a/rubocop/cop/api/description_success_response.rb +++ b/rubocop/cop/api/description_success_response.rb @@ -43,7 +43,7 @@ module API class DescriptionSuccessResponse < RuboCop::Cop::Base include CodeReuseHelpers - MSG = 'API desc blocks must define a success response. https://docs.gitlab.com/development/api_styleguide/#methods-and-parameters-description.' + MSG = 'API desc blocks must define a success response. https://docs.gitlab.com/development/api_styleguide/#defining-endpoint-success.' # @!method has_success_response?(node) def_node_matcher :has_success_response?, <<~PATTERN diff --git a/spec/rubocop/cop/api/description_success_response_spec.rb b/spec/rubocop/cop/api/description_success_response_spec.rb index 0a499791f1cba7..2e91041fa2752a 100644 --- a/spec/rubocop/cop/api/description_success_response_spec.rb +++ b/spec/rubocop/cop/api/description_success_response_spec.rb @@ -20,7 +20,7 @@ it 'registers an offense' do expect_offense(<<~RUBY) desc 'Get a list of things' do - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ API desc blocks must define a success response. https://docs.gitlab.com/development/api_styleguide/#methods-and-parameters-description. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ API desc blocks must define a success response. https://docs.gitlab.com/development/api_styleguide/#defining-endpoint-success. tags %w[things] end RUBY -- GitLab From f7d5305f1c622fea285899f4f746407a8287dfd4 Mon Sep 17 00:00:00 2001 From: Vlad Wolanyk Date: Tue, 21 Oct 2025 15:42:09 -0400 Subject: [PATCH 4/6] Update linter check Updates linter to accomodate desc blocks with only a success defined. Changelog: changed --- .../api/description_success_response.yml | 41 ------------------- .../cop/api/description_success_response.rb | 11 +---- .../api/description_success_response_spec.rb | 10 +++++ 3 files changed, 11 insertions(+), 51 deletions(-) diff --git a/.rubocop_todo/api/description_success_response.yml b/.rubocop_todo/api/description_success_response.yml index b40bb474908177..acd0757dab0d11 100644 --- a/.rubocop_todo/api/description_success_response.yml +++ b/.rubocop_todo/api/description_success_response.yml @@ -3,14 +3,8 @@ API/DescriptionSuccessResponse: Exclude: - 'ee/lib/api/admin/search/migrations.rb' - 'ee/lib/api/admin/search/zoekt.rb' - - 'ee/lib/api/ai/duo_workflows/workflows_internal.rb' - - 'ee/lib/api/analytics/code_review_analytics.rb' - - 'ee/lib/api/audit_events.rb' - 'ee/lib/api/clusters/agent_url_configurations.rb' - 'ee/lib/api/elasticsearch_indexed_namespaces.rb' - - 'ee/lib/api/gitlab_subscriptions/subscriptions.rb' - - 'ee/lib/api/group_approval_rules.rb' - - 'ee/lib/api/group_enterprise_users.rb' - 'ee/lib/api/group_security_settings.rb' - 'ee/lib/api/group_service_accounts.rb' - 'ee/lib/api/internal/ai/x_ray/scan.rb' @@ -21,36 +15,17 @@ API/DescriptionSuccessResponse: - 'ee/lib/api/project_google_cloud_integration.rb' - 'ee/lib/api/project_security_settings.rb' - 'ee/lib/api/protected_environments.rb' - - 'ee/lib/api/provider_identity.rb' - 'ee/lib/api/remote_development/internal/agents/agentw/agent_info.rb' - 'ee/lib/api/remote_development/internal/agents/agentw/authorize_user_access.rb' - 'ee/lib/api/remote_development/internal/agents/agentw/server_config.rb' - 'ee/lib/api/sbom/occurrences.rb' - 'ee/lib/api/scim/group_scim.rb' - - 'ee/lib/api/scim/instance_scim.rb' - - 'ee/lib/api/status_checks.rb' - 'ee/lib/api/virtual_registries/cleanup/policies.rb' - - 'ee/lib/api/vulnerabilities.rb' - - 'ee/lib/api/vulnerability_archive_exports.rb' - - 'ee/lib/api/vulnerability_exports.rb' - - 'ee/lib/api/vulnerability_issue_links.rb' - 'ee/lib/ee/api/group_milestones.rb' - - 'ee/lib/ee/api/groups.rb' - 'ee/lib/ee/api/internal/kubernetes.rb' - - 'ee/lib/ee/api/issues.rb' - - 'ee/lib/ee/api/members.rb' - - 'ee/lib/ee/api/merge_request_approvals.rb' - - 'ee/lib/ee/api/namespaces.rb' - 'ee/lib/ee/api/project_milestones.rb' - - 'ee/lib/ee/api/projects.rb' - - 'ee/lib/ee/api/todos.rb' - - 'ee/lib/gitlab_subscriptions/api/internal/members.rb' - - 'ee/lib/gitlab_subscriptions/api/internal/subscriptions.rb' - - 'ee/lib/gitlab_subscriptions/api/internal/users.rb' - 'lib/api/access_requests.rb' - 'lib/api/admin/token.rb' - - 'lib/api/appearance.rb' - - 'lib/api/avatar.rb' - 'lib/api/badges.rb' - 'lib/api/ci/job_artifacts.rb' - 'lib/api/ci/pipelines.rb' @@ -58,18 +33,14 @@ API/DescriptionSuccessResponse: - 'lib/api/ci/secure_files.rb' - 'lib/api/clusters/agent_tokens.rb' - 'lib/api/clusters/agents.rb' - - 'lib/api/custom_attributes_endpoints.rb' - 'lib/api/deploy_keys.rb' - 'lib/api/deploy_tokens.rb' - 'lib/api/deployments.rb' - - 'lib/api/discussions.rb' - 'lib/api/environments.rb' - 'lib/api/feature_flags_user_lists.rb' - 'lib/api/features.rb' - - 'lib/api/files.rb' - 'lib/api/go_proxy.rb' - 'lib/api/group_import.rb' - - 'lib/api/group_milestones.rb' - 'lib/api/group_placeholder_reassignments.rb' - 'lib/api/groups.rb' - 'lib/api/integrations.rb' @@ -77,8 +48,6 @@ API/DescriptionSuccessResponse: - 'lib/api/internal/kubernetes.rb' - 'lib/api/internal/lfs.rb' - 'lib/api/internal/pages.rb' - - 'lib/api/issues.rb' - - 'lib/api/labels.rb' - 'lib/api/members.rb' - 'lib/api/merge_request_approvals.rb' - 'lib/api/merge_requests.rb' @@ -88,24 +57,14 @@ API/DescriptionSuccessResponse: - 'lib/api/ml/mlflow/runs.rb' - 'lib/api/ml/mlflow_artifacts/artifacts.rb' - 'lib/api/ml/mlflow_artifacts/entrypoint.rb' - - 'lib/api/notes.rb' - - 'lib/api/pages_domains.rb' - - 'lib/api/project_events.rb' - 'lib/api/project_import.rb' - 'lib/api/project_milestones.rb' - - 'lib/api/projects.rb' - 'lib/api/releases.rb' - - 'lib/api/repositories.rb' - - 'lib/api/resource_state_events.rb' - 'lib/api/rpm_project_packages.rb' - 'lib/api/rubygem_packages.rb' - 'lib/api/search.rb' - - 'lib/api/settings.rb' - 'lib/api/snippets.rb' - - 'lib/api/statistics.rb' - - 'lib/api/subscriptions.rb' - 'lib/api/supply_chain/attestations.rb' - - 'lib/api/todos.rb' - 'lib/api/topics.rb' - 'lib/api/unleash.rb' - 'lib/api/users.rb' diff --git a/rubocop/cop/api/description_success_response.rb b/rubocop/cop/api/description_success_response.rb index fcdb000bc99cf6..98d240d2a945b8 100644 --- a/rubocop/cop/api/description_success_response.rb +++ b/rubocop/cop/api/description_success_response.rb @@ -45,18 +45,9 @@ class DescriptionSuccessResponse < RuboCop::Cop::Base MSG = 'API desc blocks must define a success response. https://docs.gitlab.com/development/api_styleguide/#defining-endpoint-success.' - # @!method has_success_response?(node) - def_node_matcher :has_success_response?, <<~PATTERN - (block - (send nil? :desc ...) - (args) - (begin <(send nil? :success ...) ...>) - ) - PATTERN - def on_block(node) return unless node.method?(:desc) - return if has_success_response?(node) + return if node.body&.each_node(:send)&.any? { |n| n.method?(:success) } add_offense(node) end diff --git a/spec/rubocop/cop/api/description_success_response_spec.rb b/spec/rubocop/cop/api/description_success_response_spec.rb index 2e91041fa2752a..ef52f2da2310fa 100644 --- a/spec/rubocop/cop/api/description_success_response_spec.rb +++ b/spec/rubocop/cop/api/description_success_response_spec.rb @@ -14,6 +14,16 @@ end RUBY end + + context 'when desc block only includes success' do + it 'does not register an offense' do + expect_no_offenses(<<~RUBY) + desc 'Get a list of things' do + success Entities::Thing + end + RUBY + end + end end context 'when desc block does not have a success' do -- GitLab From b1f08722b5eeb94cbc385fc02c7038e8595f0379 Mon Sep 17 00:00:00 2001 From: Vlad Wolanyk Date: Tue, 21 Oct 2025 16:58:10 -0400 Subject: [PATCH 5/6] Use back tick syntax --- rubocop/cop/api/description_success_response.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rubocop/cop/api/description_success_response.rb b/rubocop/cop/api/description_success_response.rb index 98d240d2a945b8..0f617882a802c1 100644 --- a/rubocop/cop/api/description_success_response.rb +++ b/rubocop/cop/api/description_success_response.rb @@ -45,9 +45,12 @@ class DescriptionSuccessResponse < RuboCop::Cop::Base MSG = 'API desc blocks must define a success response. https://docs.gitlab.com/development/api_styleguide/#defining-endpoint-success.' + # @!method has_success_response?(node) + def_node_matcher :has_success_response?, '`(send nil? :success ...)' + def on_block(node) return unless node.method?(:desc) - return if node.body&.each_node(:send)&.any? { |n| n.method?(:success) } + return if has_success_response?(node) add_offense(node) end -- GitLab From e764f88c5b5de0d829498a644308543834fcc02e Mon Sep 17 00:00:00 2001 From: Vlad Wolanyk Date: Wed, 22 Oct 2025 10:01:33 -0400 Subject: [PATCH 6/6] Disable linter in fixture --- gems/gitlab-grape-openapi/spec/fixtures/test_audit_events.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gems/gitlab-grape-openapi/spec/fixtures/test_audit_events.rb b/gems/gitlab-grape-openapi/spec/fixtures/test_audit_events.rb index 7eacb30d41c565..9c7fc88aaca9e4 100644 --- a/gems/gitlab-grape-openapi/spec/fixtures/test_audit_events.rb +++ b/gems/gitlab-grape-openapi/spec/fixtures/test_audit_events.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +# rubocop:disable API/DescriptionSuccessResponse -- Needed to test edge cases + require 'grape' module API @@ -29,3 +31,4 @@ class TestAuditEvents < Grape::API end end end +# rubocop:enable API/DescriptionSuccessResponse -- GitLab