diff options
60 files changed, 406 insertions, 208 deletions
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS index 786a379731e..13389dd508b 100644 --- a/.gitlab/CODEOWNERS +++ b/.gitlab/CODEOWNERS @@ -351,10 +351,25 @@ Dangerfile @gl-quality/eng-prod /spec/frontend/batch_comments/ @viktomas @jboyson @iamphill @thomasrandolph ^[Product Intelligence] -/ee/lib/gitlab/usage_data_counters/ @gitlab-org/growth/product-intelligence/engineers -/ee/lib/ee/gitlab/usage_data.rb @gitlab-org/growth/product-intelligence/engineers -/lib/gitlab/usage_data.rb @gitlab-org/growth/product_intelligence/engineers -/lib/gitlab/usage_data_counters/ @gitlab-org/growth/product-intelligence/engineers +/ee/lib/gitlab/usage_data_counters/ @gitlab-org/analytics-section/product-intelligence/engineers +/ee/lib/ee/gitlab/usage_data.rb @gitlab-org/analytics-section/product-intelligence/engineers +/lib/gitlab/usage_data.rb @gitlab-org/analytics-section/product-intelligence/engineers +/lib/gitlab/usage_data_counters/ @gitlab-org/analytics-section/product-intelligence/engineers +/lib/gitlab/usage/ @gitlab-org/analytics-section/product-intelligence/engineers +/ee/lib/ee/gitlab/usage_data_counters/ @gitlab-org/analytics-section/product-intelligence/engineers +/ee/lib/ee/gitlab/usage/ @gitlab-org/analytics-section/product-intelligence/engineers +/config/metrics/ @gitlab-org/analytics-section/product-intelligence/engineers +/ee/config/metrics/ @gitlab-org/analytics-section/product-intelligence/engineers +/app/workers/gitlab_service_ping_worker.rb @gitlab-org/analytics-section/product-intelligence/engineers +/spec/workers/gitlab_service_ping_worker_spec.rb @gitlab-org/analytics-section/product-intelligence/engineers +/ee/spec/lib/gitlab/usage_data_counters/ @gitlab-org/analytics-section/product-intelligence/engineers +/ee/spec/lib/ee/gitlab/usage_data_spec.rb @gitlab-org/analytics-section/product-intelligence/engineers +/spec/lib/gitlab/usage_data_spec.rb @gitlab-org/analytics-section/product-intelligence/engineers +/spec/lib/gitlab/usage_data_counters/ @gitlab-org/analytics-section/product-intelligence/engineers +/spec/lib/gitlab/usage/ @gitlab-org/analytics-section/product-intelligence/engineers +/ee/spec/lib/ee/gitlab/usage_data_counters/ @gitlab-org/analytics-section/product-intelligence/engineers +/ee/spec/lib/ee/gitlab/usage/ @gitlab-org/analytics-section/product-intelligence/engineers +/ee/spec/config/metrics/ @gitlab-org/analytics-section/product-intelligence/engineers ^[Growth Experiments] /app/experiments/ @gitlab-org/growth/experiment-devs diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml index fdc53ac6218..d7bd42aa016 100644 --- a/.gitlab/ci/frontend.gitlab-ci.yml +++ b/.gitlab/ci/frontend.gitlab-ci.yml @@ -398,5 +398,5 @@ compile-storybook as-if-foss: - .as-if-foss - .frontend:rules:default-frontend-jobs-as-if-foss needs: - - !reference [.compile-storybook-base, needs] + - job: "graphql-schema-dump as-if-foss" - job: "rspec-all frontend_fixture as-if-foss" diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml index 553debc0fdb..d1ba727d232 100644 --- a/.gitlab/ci/rules.gitlab-ci.yml +++ b/.gitlab/ci/rules.gitlab-ci.yml @@ -278,7 +278,7 @@ - "Dockerfile.assets" - "config/**/*.js" - "vendor/assets/**/*" - - "{app/assets,app/components,app/helpers,app/presenters,app/views,locale,public,spec/frontend,symbol}/**/*" + - "{app/assets,app/components,app/helpers,app/presenters,app/views,locale,public,spec/frontend,storybook,symbol}/**/*" .controllers-patterns: &controllers-patterns - "{,ee/,jh/}{app/controllers}/**/*" @@ -393,7 +393,7 @@ - "Rakefile" - "tests.yml" - "config.ru" - - "{,ee/,jh/}{app,bin,config,db,generator_templates,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*" + - "{,ee/,jh/}{app,bin,config,db,generator_templates,haml_lint,lib,locale,public,scripts,storybook,symbol,vendor}/**/*" - "doc/api/graphql/reference/*" # Files in this folder are auto-generated # CI changes - ".gitlab-ci.yml" @@ -450,7 +450,7 @@ - "Rakefile" - "tests.yml" - "config.ru" - - "{,ee/,jh/}{app,bin,config,db,generator_templates,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*" + - "{,ee/,jh/}{app,bin,config,db,generator_templates,haml_lint,lib,locale,public,scripts,storybook,symbol,vendor}/**/*" - "doc/api/graphql/reference/*" # Files in this folder are auto-generated # CI changes - ".gitlab-ci.yml" @@ -487,7 +487,7 @@ - "Rakefile" - "tests.yml" - "config.ru" - - "{,ee/,jh/}{app,bin,config,db,generator_templates,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*" + - "{,ee/,jh/}{app,bin,config,db,generator_templates,haml_lint,lib,locale,public,scripts,storybook,symbol,vendor}/**/*" - "doc/api/graphql/reference/*" # Files in this folder are auto-generated - "data/whats_new/*.yml" # CI changes @@ -877,6 +877,8 @@ - <<: *if-merge-request-labels-run-all-rspec - <<: *if-merge-request changes: *startup-css-patterns + - <<: *if-merge-request + changes: *frontend-patterns-for-as-if-foss .frontend:rules:frontend_fixture-as-if-foss: rules: diff --git a/.rubocop_todo/layout/space_inside_parens.yml b/.rubocop_todo/layout/space_inside_parens.yml index 5dc3513f4f8..cf33828b20f 100644 --- a/.rubocop_todo/layout/space_inside_parens.yml +++ b/.rubocop_todo/layout/space_inside_parens.yml @@ -198,31 +198,6 @@ Layout/SpaceInsideParens: - 'spec/policies/clusters/agent_policy_spec.rb' - 'spec/presenters/ci/build_presenter_spec.rb' - 'spec/presenters/packages/conan/package_presenter_spec.rb' - - 'spec/requests/api/boards_spec.rb' - - 'spec/requests/api/ci/runner/jobs_artifacts_spec.rb' - - 'spec/requests/api/ci/runner/jobs_request_post_spec.rb' - - 'spec/requests/api/ci/runners_reset_registration_token_spec.rb' - - 'spec/requests/api/ci/runners_spec.rb' - - 'spec/requests/api/dependency_proxy_spec.rb' - - 'spec/requests/api/deployments_spec.rb' - - 'spec/requests/api/files_spec.rb' - - 'spec/requests/api/go_proxy_spec.rb' - - 'spec/requests/api/graphql/boards/board_list_issues_query_spec.rb' - - 'spec/requests/api/graphql/ci/jobs_spec.rb' - - 'spec/requests/api/graphql/ci/pipelines_spec.rb' - - 'spec/requests/api/graphql/mutations/award_emojis/remove_spec.rb' - - 'spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb' - - 'spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb' - - 'spec/requests/api/group_boards_spec.rb' - - 'spec/requests/api/issues/issues_spec.rb' - - 'spec/requests/api/issues/post_projects_issues_spec.rb' - - 'spec/requests/api/labels_spec.rb' - - 'spec/requests/api/merge_requests_spec.rb' - - 'spec/requests/api/pages/pages_spec.rb' - - 'spec/requests/api/project_milestones_spec.rb' - - 'spec/requests/api/project_snippets_spec.rb' - - 'spec/requests/api/snippets_spec.rb' - - 'spec/requests/api/submodules_spec.rb' - 'spec/requests/jwt_controller_spec.rb' - 'spec/requests/projects/merge_requests/diffs_spec.rb' - 'spec/requests/projects/merge_requests_spec.rb' diff --git a/app/assets/javascripts/graphql_shared/issuable_client.js b/app/assets/javascripts/graphql_shared/issuable_client.js index 04a6e555bea..38c7af8cf95 100644 --- a/app/assets/javascripts/graphql_shared/issuable_client.js +++ b/app/assets/javascripts/graphql_shared/issuable_client.js @@ -57,7 +57,9 @@ export const config = { return incoming; } return existing.map((existingWidget) => { - const incomingWidget = incoming.find((w) => w.type === existingWidget.type); + const incomingWidget = incoming.find( + (w) => w.type && w.type === existingWidget.type, + ); return incomingWidget || existingWidget; }); }, diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb index 67eeb43d5a2..5ffd525c170 100644 --- a/app/controllers/graphql_controller.rb +++ b/app/controllers/graphql_controller.rb @@ -190,7 +190,8 @@ class GraphqlController < ApplicationController current_user: current_user, is_sessionless_user: api_user, request: request, - scope_validator: ::Gitlab::Auth::ScopeValidator.new(api_user, request_authenticator) + scope_validator: ::Gitlab::Auth::ScopeValidator.new(api_user, request_authenticator), + remove_deprecated: Gitlab::Utils.to_boolean(params[:remove_deprecated], default: false) } end diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 83422c6d8cd..b78017a26e8 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -34,14 +34,14 @@ class RegistrationsController < Devise::RegistrationsController def create set_user_state - token = set_custom_confirmation_token + set_custom_confirmation_token super do |new_user| accept_pending_invitations if new_user.persisted? persist_accepted_terms_if_required(new_user) set_role_required(new_user) - send_custom_confirmation_instructions(new_user, token) + send_custom_confirmation_instructions track_weak_password_error(new_user, self.class.name, 'create') if pending_approval? @@ -128,7 +128,7 @@ class RegistrationsController < Devise::RegistrationsController # after user confirms and comes back, he will be redirected store_location_for(:redirect, users_sign_up_welcome_path(glm_tracking_params)) - return identity_verification_redirect_path if custom_confirmation_enabled?(resource) + return identity_verification_redirect_path if custom_confirmation_enabled? users_almost_there_path(email: resource.email) end @@ -244,7 +244,7 @@ class RegistrationsController < Devise::RegistrationsController # overridden by EE module end - def custom_confirmation_enabled?(resource) + def custom_confirmation_enabled? # overridden by EE module end @@ -252,7 +252,7 @@ class RegistrationsController < Devise::RegistrationsController # overridden by EE module end - def send_custom_confirmation_instructions(user, token) + def send_custom_confirmation_instructions # overridden by EE module end end diff --git a/app/graphql/types/base_argument.rb b/app/graphql/types/base_argument.rb index 2c899e9edaa..4086015dad6 100644 --- a/app/graphql/types/base_argument.rb +++ b/app/graphql/types/base_argument.rb @@ -4,10 +4,10 @@ module Types class BaseArgument < GraphQL::Schema::Argument include GitlabStyleDeprecations - attr_reader :deprecation, :doc_reference + attr_reader :doc_reference def initialize(*args, **kwargs, &block) - @deprecation = gitlab_deprecation(kwargs) + init_gitlab_deprecation(kwargs) @doc_reference = kwargs.delete(:see) # our custom addition `nullable` which allows us to declare diff --git a/app/graphql/types/base_enum.rb b/app/graphql/types/base_enum.rb index 0224aeddac6..11877b79e59 100644 --- a/app/graphql/types/base_enum.rb +++ b/app/graphql/types/base_enum.rb @@ -6,10 +6,8 @@ module Types class CustomValue < GraphQL::Schema::EnumValue include ::GitlabStyleDeprecations - attr_reader :deprecation - def initialize(name, desc = nil, **kwargs) - @deprecation = gitlab_deprecation(kwargs) + init_gitlab_deprecation(kwargs) super(name, desc, **kwargs) end diff --git a/app/graphql/types/base_field.rb b/app/graphql/types/base_field.rb index 6f64e5b5053..36ba3399754 100644 --- a/app/graphql/types/base_field.rb +++ b/app/graphql/types/base_field.rb @@ -8,16 +8,16 @@ module Types DEFAULT_COMPLEXITY = 1 - attr_reader :deprecation, :doc_reference + attr_reader :doc_reference def initialize(**kwargs, &block) + init_gitlab_deprecation(kwargs) @calls_gitaly = !!kwargs.delete(:calls_gitaly) @doc_reference = kwargs.delete(:see) @constant_complexity = kwargs[:complexity].is_a?(Integer) && kwargs[:complexity] > 0 @requires_argument = !!kwargs.delete(:requires_argument) @authorize = Array.wrap(kwargs.delete(:authorize)) kwargs[:complexity] = field_complexity(kwargs[:resolver_class], kwargs[:complexity]) - @deprecation = gitlab_deprecation(kwargs) after_connection_extensions = kwargs.delete(:late_extensions) || [] super(**kwargs, &block) diff --git a/app/graphql/types/concerns/gitlab_style_deprecations.rb b/app/graphql/types/concerns/gitlab_style_deprecations.rb index e404f1fcad9..859a27cac4c 100644 --- a/app/graphql/types/concerns/gitlab_style_deprecations.rb +++ b/app/graphql/types/concerns/gitlab_style_deprecations.rb @@ -1,14 +1,22 @@ # frozen_string_literal: true -# Concern for handling deprecation arguments. +# Concern for handling GraphQL deprecations. # https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-schema-items module GitlabStyleDeprecations extend ActiveSupport::Concern + included do + attr_accessor :deprecation + end + + def visible?(ctx) + super && ctx[:remove_deprecated] == true ? deprecation.nil? : true + end + private - # Mutate the arguments, returns the deprecation - def gitlab_deprecation(kwargs) + # Set deprecation, mutate the arguments + def init_gitlab_deprecation(kwargs) if kwargs[:deprecation_reason].present? raise ArgumentError, 'Use `deprecated` property instead of `deprecation_reason`. ' \ 'See https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-schema-items' @@ -17,14 +25,12 @@ module GitlabStyleDeprecations # GitLab allows items to be marked as "alpha", which leverages GraphQL deprecations. deprecation_args = kwargs.extract!(:alpha, :deprecated) - deprecation = ::Gitlab::Graphql::Deprecation.parse(**deprecation_args) + self.deprecation = ::Gitlab::Graphql::Deprecation.parse(**deprecation_args) return unless deprecation raise ArgumentError, "Bad deprecation. #{deprecation.errors.full_messages.to_sentence}" unless deprecation.valid? kwargs[:deprecation_reason] = deprecation.deprecation_reason kwargs[:description] = deprecation.edit_description(kwargs[:description]) - - deprecation end end diff --git a/app/models/project.rb b/app/models/project.rb index 8ecfdeb98f5..a9144fa7c2a 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1706,7 +1706,11 @@ class Project < ApplicationRecord end def has_active_integrations?(hooks_scope = :push_hooks) - integrations.public_send(hooks_scope).any? # rubocop:disable GitlabSecurity/PublicSend + @has_active_integrations ||= {} # rubocop: disable Gitlab/PredicateMemoization + + return @has_active_integrations[hooks_scope] if @has_active_integrations.key?(hooks_scope) + + @has_active_integrations[hooks_scope] = integrations.public_send(hooks_scope).any? # rubocop:disable GitlabSecurity/PublicSend end def feature_usage diff --git a/app/views/notify/unknown_sign_in_email.html.haml b/app/views/notify/unknown_sign_in_email.html.haml index b1c79274e26..64bf4e7b4e8 100644 --- a/app/views/notify/unknown_sign_in_email.html.haml +++ b/app/views/notify/unknown_sign_in_email.html.haml @@ -9,7 +9,7 @@ %tr %td{ style: "#{default_font}vertical-align:middle;color:#ffffff;text-align:center;" } %span - = _("Your %{host} account was signed in to from a new location") % { host: Gitlab.config.gitlab.host } + = _("Someone signed in to your %{host} account from a new location") % { host: Gitlab.config.gitlab.host } %tr.spacer %td{ style: spacer_style } diff --git a/config/open_api.yml b/config/open_api.yml index 29b2b622aaf..cd0b64ba1fd 100644 --- a/config/open_api.yml +++ b/config/open_api.yml @@ -32,3 +32,5 @@ metadata: description: Operations related to deploy freeze periods - name: release_links description: Operations related to release assets (links) + - name: cluster_agents + description: Operations related to the GitLab agent for Kubernetes diff --git a/doc/api/graphql/index.md b/doc/api/graphql/index.md index 151d8750ad9..99d2bf76a49 100644 --- a/doc/api/graphql/index.md +++ b/doc/api/graphql/index.md @@ -102,6 +102,8 @@ Items are marked as deprecated in: NOTE: If you use the GraphQL API, we recommend you remove the deprecated schema from your GraphQL API calls as soon as possible to avoid experiencing breaking changes. +To verify your API calls against the schema without the deprecated schema items, you can add a +`?remove_deprecated=true` query parameter. You should only use this parameter for verification purposes. The deprecation message provides an alternative for the deprecated schema item, if applicable. diff --git a/doc/api/vulnerability_exports.md b/doc/api/vulnerability_exports.md index 14966d2e925..bdc5d2c29e7 100644 --- a/doc/api/vulnerability_exports.md +++ b/doc/api/vulnerability_exports.md @@ -198,18 +198,11 @@ The response is `404 Not Found` if the vulnerability export is not finished yet Example response: ```csv -Group Name,Project Name,Tool,Scanner Name,Status,Vulnerability,Details,Additional Info,Severity,CVE,CWE,Other Identifiers -Gitlab.org,Defend,container_scanning,Trivy,detected,CVE-2017-16997 in glibc,,CVE-2017-16997 in glibc,critical,CVE-2017-16997 -Gitlab.org,Defend,container_scanning,Trivy,detected,CVE-2017-18269 in glibc,,CVE-2017-18269 in glibc,critical,CVE-2017-18269 -Gitlab.org,Defend,container_scanning,Trivy,detected,CVE-2018-1000001 in glibc,,CVE-2018-1000001 in glibc,high,CVE-2018-1000001 -Gitlab.org,Defend,container_scanning,Trivy,detected,CVE-2016-10228 in glibc,,CVE-2016-10228 in glibc,medium,CVE-2016-10228 -Gitlab.org,Defend,container_scanning,Trivy,detected,CVE-2010-4052 in glibc,,CVE-2010-4052 in glibc,low,CVE-2010-4052 -Gitlab.org,Defend,container_scanning,Trivy,detected,CVE-2018-18520 in elfutils,,CVE-2018-18520 in elfutils,low,CVE-2018-18520 -Gitlab.org,Defend,container_scanning,Trivy,detected,CVE-2018-16869 in nettle,,CVE-2018-16869 in nettle,unknown,CVE-2018-16869,CWE-1 -Gitlab.org,Defend,dependency_scanning,Gemnasium,detected,Regular Expression Denial of Service in debug,,Regular Expression Denial of Service in debug,unknown,CVE-2021-1234,CWE-2,"""yarn.lock:debug:gemnasium:37283ed4-0380-40d7-ada7-2d994afcc62a""" -Gitlab.org,Defend,dependency_scanning,Gemnasium,detected,Authentication bypass via incorrect DOM traversal and canonicalization in saml2-js,,Authentication bypass via incorrect DOM traversal and canonicalization in saml2-js,unknown,,,"""yarn.lock:saml2-js:gemnasium:9952e574-7b5b-46fa-a270-aeb694198a98""" -Gitlab.org,Defend,sast,Find Security Bugs,detected,Predictable pseudorandom number generator,,Predictable pseudorandom number generator,medium,,,"""818bf5dacb291e15d9e6dc3c5ac32178:PREDICTABLE_RANDOM:src/main/java/com/gitlab/security_products/tests/App.java:47""" -Gitlab.org,Defend,sast,Find Security Bugs,detected,Cipher with no integrity,,Cipher with no integrity,medium,,,"""e6449b89335daf53c0db4c0219bc1634:CIPHER_INTEGRITY:src/main/java/com/gitlab/security_products/tests/App.java:29""" -Gitlab.org,Defend,sast,Find Security Bugs,detected,Predictable pseudorandom number generator,,Predictable pseudorandom number generator,medium,,,"""e8ff1d01f74cd372f78da8f5247d3e73:PREDICTABLE_RANDOM:src/main/java/com/gitlab/security_products/tests/App.java:41""" -Gitlab.org,Defend,sast,Find Security Bugs,detected,ECB mode is insecure,,ECB mode is insecure,medium,,,"""ea0f905fc76f2739d5f10a1fd1e37a10:ECB_MODE:src/main/java/com/gitlab/security_products/tests/App.java:29""" +Group Name,Project Name,Tool,Scanner Name,Status,Vulnerability,Details,Additional Info,Severity,CVE,CWE,Other Identifiers,Detected At,Location,Activity, +Gitlab.org,Defend,container_scanning,Trivy,detected,CVE-2019-14697 in musl-utils-1.1.20-r4,"musl libc through 1.1.23 has an x87 floating-point stack adjustment imbalance, related to the math/i386/ directory. In some cases, use of this library could introduce out-of-bounds writes that are not present in an application's source code.",CVE-2019-14697 in musl-utils-1.1.20-r4,critical,CVE-2019-14697,,"",2022-10-07 13:34:41 UTC,"{""image""=>""python:3.4-alpine"", ""dependency""=>{""package""=>{""name""=>""musl-utils""}, ""version""=>""1.1.20-r4""}, ""operating_system""=>""alpine 3.9.2""}",true, +Gitlab.org,Defend,container_scanning,Trivy,detected,CVE-2019-19242 in sqlite-libs-3.26.0-r3,"SQLite 3.30.1 mishandles pExpr->y.pTab, as demonstrated by the TK_COLUMN case in sqlite3ExprCodeTarget in expr.c.",CVE-2019-19242 in sqlite-libs-3.26.0-r3,medium,CVE-2019-19242,,"",2022-10-07 13:34:41 UTC,"{""image""=>""python:3.4-alpine"", ""dependency""=>{""package""=>{""name""=>""sqlite-libs""}, ""version""=>""3.26.0-r3""}, ""operating_system""=>""alpine 3.9.2""}",true, +Gitlab.org,Defend,container_scanning,Trivy,detected,CVE-2020-28928 in musl-1.1.20-r4,"In musl libc through 1.2.1, wcsnrtombs mishandles particular combinations of destination buffer size and source character limit, as demonstrated by an invalid write access (buffer overflow).",CVE-2020-28928 in musl-1.1.20-r4,medium,CVE-2020-28928,,"",2022-10-07 13:34:41 UTC,"{""image""=>""python:3.4-alpine"", ""dependency""=>{""package""=>{""name""=>""musl""}, ""version""=>""1.1.20-r4""}, ""operating_system""=>""alpine 3.9.2""}",true, +Gitlab.org,Defend,dependency_scanning,Gemnasium,detected,Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection') in rack,Carefully crafted requests can cause shell escape sequences to be written to the terminal via Rack's Lint middleware and CommonLogger middleware. These escape sequences can be leveraged to possibly execute commands in the victim's terminal.,Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection') in rack,unknown,Gemfile.lock:rack:gemnasium:60b5a27f-4e4d-4ab4-8ae7-74b4b212e177,,Gemnasium-60b5a27f-4e4d-4ab4-8ae7-74b4b212e177; GHSA-wq4h-7r42-5hrr,2022-10-14 13:16:00 UTC,"{""file""=>""Gemfile.lock"", ""dependency""=>{""package""=>{""name""=>""rack""}, ""version""=>""2.2.3""}}",false, +Gitlab.org,Defend,dependency_scanning,Gemnasium,detected,Denial of Service Vulnerability in Rack Multipart Parsing in rack,"Carefully crafted multipart POST requests can cause Rack's multipart parser to take much longer than expected, leading to a possible denial of service vulnerability. Impacted code will use Rack's multipart parser to parse multipart posts.",Denial of Service Vulnerability in Rack Multipart Parsing in rack,unknown,Gemfile.lock:rack:gemnasium:20daa17a-47b5-4f79-80c2-cd8f2db9805c,,Gemnasium-20daa17a-47b5-4f79-80c2-cd8f2db9805c; GHSA-hxqx-xwvh-44m2,2022-10-14 13:16:00 UTC,"{""file""=>""Gemfile.lock"", ""dependency""=>{""package""=>{""name""=>""rack""}, ""version""=>""2.2.3""}}",false, +Gitlab.org,Defend,sast,Brakeman,detected,Possible SQL injection,,Possible SQL injection,medium,e52f23a259cd489168b4313317ac94a3f13bffde57b9635171c1a44a9f329e9a,,"""Brakeman Warning Code 0""",2022-10-13 15:16:36 UTC,"{""file""=>""main.rb"", ""class""=>""User"", ""method""=>""index"", ""start_line""=>3}",false ``` diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md index 1f67457ab54..47ad2655710 100644 --- a/doc/ci/yaml/index.md +++ b/doc/ci/yaml/index.md @@ -3255,7 +3255,8 @@ Use `rules:if` clauses to specify when to add a job to a pipeline: - If no `if` statements are true, do not add the job to the pipeline. `if` clauses are evaluated based on the values of [predefined CI/CD variables](../variables/predefined_variables.md) -or [custom CI/CD variables](../variables/index.md#custom-cicd-variables). +or [custom CI/CD variables](../variables/index.md#custom-cicd-variables), with +[some exceptions](../variables/where_variables_can_be_used.md#gitlab-ciyml-file). **Keyword type**: Job-specific and pipeline-specific. You can use it as part of a job to configure the job behavior, or with [`workflow`](#workflow) to configure the pipeline behavior. diff --git a/doc/development/documentation/topic_types/index.md b/doc/development/documentation/topic_types/index.md index 8403fd26517..d88a5448d53 100644 --- a/doc/development/documentation/topic_types/index.md +++ b/doc/development/documentation/topic_types/index.md @@ -20,11 +20,10 @@ The acronym refers to the first letter of each topic type. In general, each page in the GitLab documentation contains multiple topics. Each topic on a page should be recognizable as a specific topic type. -## Other topic types +In addition to the four primary topic types, we also have a page type for +[Tutorials](tutorial.md) and [Get started](#get-started). -In addition to the four primary topic types, we have a few other types. - -### Related topics +## Related topics If inline links are not sufficient, you can create a topic called **Related topics** and include an unordered list of related topics. This topic should be above the Troubleshooting section. @@ -36,57 +35,7 @@ and include an unordered list of related topics. This topic should be above the - [Trigger a pipeline manually](link-to-topic). ``` -### Tutorials - -A tutorial is page that contains an end-to-end walkthrough of a complex workflow or scenario. -In general, you might consider using a tutorial when: - -- The workflow requires a number of sequential steps where each step consists - of sub-steps. -- The steps cover a variety of GitLab features or third-party tools. - -Tutorials are learning aids that complement our core documentation. -They do not introduce new features. -Always use the primary [topic types](#documentation-topic-types-ctrt) to document new features. - -Tutorials should be in this format: - -```markdown -# Title (starts with "Tutorial:" followed by an active verb, like "Tutorial: Create a website") - -A paragraph that explains what the tutorial does, and the expected outcome. - -To create a website: - -1. [Do the first task](#do-the-first-task) -1. [Do the second task](#do-the-second-task) - -Prerequisites (optional): - -- Thing 1 -- Thing 2 -- Thing 3 - -## Do the first task - -To do step 1: - -1. First step. -1. Another step. -1. Another step. - -## Do the second task - -Before you begin, make sure you have [done the first task](#do-the-first-task). - -To do step 2: - -1. First step. -1. Another step. -1. Another step. -``` - -### Get started +## Get started A get started page is a set of steps to help a user get set up quickly to use a single GitLab feature or tool. @@ -110,7 +59,7 @@ consider using subsections for each distinct task. In the left nav, use `Get started` as the text. On the page itself, spell out the full name. For example, `Get started with application security`. -### Topics and resources +## Topics and resources Some pages are solely a list of links to other documentation. diff --git a/doc/development/documentation/topic_types/tutorial.md b/doc/development/documentation/topic_types/tutorial.md new file mode 100644 index 00000000000..0164b525528 --- /dev/null +++ b/doc/development/documentation/topic_types/tutorial.md @@ -0,0 +1,79 @@ +--- +stage: none +group: Style Guide +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + +# Tutorial topic type + +A tutorial is page that contains an end-to-end walkthrough of a complex workflow or scenario. +In general, you might consider using a tutorial when: + +- The workflow requires a number of sequential steps where each step consists + of sub-steps. +- The steps cover a variety of GitLab features or third-party tools. + +Tutorials are learning aids that complement our core documentation. +They do not introduce new features. +Always use the primary [topic types](index.md) to document new features. + +Tutorials should be in this format: + +```markdown +# Title (starts with "Tutorial:" followed by an active verb, like "Tutorial: Create a website") + +A paragraph that explains what the tutorial does, and the expected outcome. + +To create a website: + +1. [Do the first task](#do-the-first-task) +1. [Do the second task](#do-the-second-task) + +Prerequisites (optional): + +- Thing 1 +- Thing 2 +- Thing 3 + +## Do the first task + +To do step 1: + +1. First step. +1. Another step. +1. Another step. + +## Do the second task + +Before you begin, make sure you have [done the first task](#do-the-first-task). + +To do step 2: + +1. First step. +1. Another step. +1. Another step. +``` + +## Tutorial headings + +Start with `Tutorial:` followed by an active verb, like `Tutorial: Create a website`. + +## Screenshots + +You can include screenshots in a tutorial to illustrate important steps in the process. +In the core product documentation, you should [use screenshots sparingly](../styleguide/index.md#images). +However, in tutorials, screenshots can help users understand where they are in a complex process. + +Try to balance the number of screenshots in the tutorial so they don't disrupt +the narrative flow. For example, do not put one large screenshot in the middle of the tutorial. +Instead, put multiple, smaller screenshots throughout. + +## Tutorial voice + +Use a friendlier tone than you would for other topic types. For example, +you can: + +- Add encouraging or congratulatory phrases after tasks. +- Use future tense from time to time, especially when you're introducing + steps. For example, `Next, you will associate your issues with your epics`. +- Be more conversational. For example, `This task might take a while to complete`. diff --git a/doc/user/application_security/vulnerability_report/index.md b/doc/user/application_security/vulnerability_report/index.md index 59851fd192c..159445406f0 100644 --- a/doc/user/application_security/vulnerability_report/index.md +++ b/doc/user/application_security/vulnerability_report/index.md @@ -216,6 +216,9 @@ Fields included are: - [CVE](https://cve.mitre.org/) (Common Vulnerabilities and Exposures) - [CWE](https://cwe.mitre.org/) (Common Weakness Enumeration) - Other identifiers +- Detected At +- Location +- Activity NOTE: Full details are available through our diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md index 4605642399a..66e877e6590 100644 --- a/doc/user/project/integrations/webhooks.md +++ b/doc/user/project/integrations/webhooks.md @@ -115,6 +115,14 @@ a test request to re-enable a [disabled webhook](#re-enable-disabled-webhooks). For example, to test `push events`, your project should have at least one commit. The webhook uses this commit in the webhook. +NOTE: +Testing is not supported for some types of events for project and groups webhooks. +Read more in [issue 379201](https://gitlab.com/gitlab-org/gitlab/-/issues/379201). + +Prerequisite: + +- To test group webhooks, you must have administrator access for your instance. + To test a webhook: 1. In your project or group, on the left sidebar, select **Settings > Webhooks**. @@ -237,6 +245,10 @@ Webhook requests to your endpoint include the following headers: GitLab records the history of each webhook request. You can view requests made in the last 2 days in the **Recent events** table. +Prerequisite: + +- To troubleshoot group webhooks, you must have administrator access for your instance. + To view the table: 1. In your project or group, on the left sidebar, select **Settings > Webhooks**. diff --git a/lib/api/api.rb b/lib/api/api.rb index 851f4e83494..38c20e80d14 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -171,6 +171,8 @@ module API namespace do mount ::API::AccessRequests mount ::API::Appearance + mount ::API::Clusters::Agents + mount ::API::Clusters::AgentTokens mount ::API::DeployKeys mount ::API::DeployTokens mount ::API::Deployments @@ -212,8 +214,6 @@ module API mount ::API::Ci::SecureFiles mount ::API::Ci::Triggers mount ::API::Ci::Variables - mount ::API::Clusters::Agents - mount ::API::Clusters::AgentTokens mount ::API::CommitStatuses mount ::API::Commits mount ::API::ComposerPackages diff --git a/lib/api/clusters/agent_tokens.rb b/lib/api/clusters/agent_tokens.rb index 1f9c8700d7a..02d3fcdf5ea 100644 --- a/lib/api/clusters/agent_tokens.rb +++ b/lib/api/clusters/agent_tokens.rb @@ -18,9 +18,10 @@ module API end resource ':id/cluster_agents/:agent_id' do resource :tokens do - desc 'List agent tokens' do - detail 'This feature was introduced in GitLab 15.0.' + desc 'List tokens for an agent' do + detail 'This feature was introduced in GitLab 15.0. Returns a list of tokens for an agent.' success Entities::Clusters::AgentTokenBasic + tags %w[cluster_agents] end params do use :pagination @@ -32,8 +33,9 @@ module API end desc 'Get a single agent token' do - detail 'This feature was introduced in GitLab 15.0.' + detail 'This feature was introduced in GitLab 15.0. Gets a single agent token.' success Entities::Clusters::AgentToken + tags %w[cluster_agents] end params do requires :token_id, type: Integer, desc: 'The ID of the agent token' @@ -47,8 +49,9 @@ module API end desc 'Create an agent token' do - detail 'This feature was introduced in GitLab 15.0.' + detail 'This feature was introduced in GitLab 15.0. Creates a new token for an agent.' success Entities::Clusters::AgentTokenWithToken + tags %w[cluster_agents] end params do requires :name, type: String, desc: 'The name for the token' @@ -71,7 +74,8 @@ module API end desc 'Revoke an agent token' do - detail 'This feature was introduced in GitLab 15.0.' + detail 'This feature was introduced in GitLab 15.0. Revokes an agent token.' + tags %w[cluster_agents] end params do requires :token_id, type: Integer, desc: 'The ID of the agent token' diff --git a/lib/api/clusters/agents.rb b/lib/api/clusters/agents.rb index 2affd9680b6..b93ad2a946b 100644 --- a/lib/api/clusters/agents.rb +++ b/lib/api/clusters/agents.rb @@ -14,9 +14,10 @@ module API requires :id, type: String, desc: 'The ID of a project' end resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do - desc 'List agents' do - detail 'This feature was introduced in GitLab 14.10.' + desc 'List the agents for a project' do + detail 'This feature was introduced in GitLab 14.10. Returns the list of agents registered for the project.' success Entities::Clusters::Agent + tags %w[cluster_agents] end params do use :pagination @@ -29,9 +30,10 @@ module API present paginate(agents), with: Entities::Clusters::Agent end - desc 'Get single agent' do - detail 'This feature was introduced in GitLab 14.10.' + desc 'Get details about an agent' do + detail 'This feature was introduced in GitLab 14.10. Gets a single agent details.' success Entities::Clusters::Agent + tags %w[cluster_agents] end params do requires :agent_id, type: Integer, desc: 'The ID of an agent' @@ -42,9 +44,10 @@ module API present agent, with: Entities::Clusters::Agent end - desc 'Add an agent to a project' do - detail 'This feature was introduced in GitLab 14.10.' + desc 'Register an agent with a project' do + detail 'This feature was introduced in GitLab 14.10. Registers an agent to the project.' success Entities::Clusters::Agent + tags %w[cluster_agents] end params do requires :name, type: String, desc: 'The name of the agent' @@ -61,8 +64,9 @@ module API present result[:cluster_agent], with: Entities::Clusters::Agent end - desc 'Delete an agent' do - detail 'This feature was introduced in GitLab 14.10.' + desc 'Delete a registered agent' do + detail 'This feature was introduced in GitLab 14.10. Deletes an existing agent registration.' + tags %w[cluster_agents] end params do requires :agent_id, type: Integer, desc: 'The ID of an agent' diff --git a/lib/api/entities/entity_helpers.rb b/lib/api/entities/entity_helpers.rb index 3a68044ad35..6fb04bb8ad6 100644 --- a/lib/api/entities/entity_helpers.rb +++ b/lib/api/entities/entity_helpers.rb @@ -11,8 +11,8 @@ module API ->(obj, opts) { Ability.allowed?(opts[:user], "destroy_#{attr}".to_sym, yield(obj)) } end - def expose_restricted(attr, &block) - expose attr, if: can_read(attr, &block) + def expose_restricted(attr, documentation: {}, &block) + expose attr, documentation: documentation, if: can_read(attr, &block) end end end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index f428b753f21..e86ce08a1ce 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -38095,6 +38095,9 @@ msgstr "" msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again." msgstr "" +msgid "Someone signed in to your %{host} account from a new location" +msgstr "" + msgid "Someone, hopefully you, has requested to reset the password for your GitLab account on %{link_to_gitlab}." msgstr "" @@ -46227,6 +46230,9 @@ msgstr "" msgid "You are not allowed to create this tag as it is protected." msgstr "" +msgid "You are not allowed to download code from this project." +msgstr "" + msgid "You are not allowed to log in using password" msgstr "" @@ -46849,9 +46855,6 @@ msgstr "" msgid "Your %{group} membership will now expire in %{days}." msgstr "" -msgid "Your %{host} account was signed in to from a new location" -msgstr "" - msgid "Your %{spammable_entity_type} has been recognized as spam and has been discarded." msgstr "" diff --git a/qa/Gemfile b/qa/Gemfile index d71de41f89e..7134ad162ba 100644 --- a/qa/Gemfile +++ b/qa/Gemfile @@ -2,7 +2,7 @@ source 'https://rubygems.org' -gem 'gitlab-qa', '~> 8', '>= 8.10.0', require: 'gitlab/qa' +gem 'gitlab-qa', '~> 8', '>= 8.10.1', require: 'gitlab/qa' gem 'activesupport', '~> 6.1.4.7' # This should stay in sync with the root's Gemfile gem 'allure-rspec', '~> 2.18.0' gem 'capybara', '~> 3.37.1' diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock index 9e52677d3bf..eb01db74a08 100644 --- a/qa/Gemfile.lock +++ b/qa/Gemfile.lock @@ -100,7 +100,7 @@ GEM gitlab (4.18.0) httparty (~> 0.18) terminal-table (>= 1.5.1) - gitlab-qa (8.10.0) + gitlab-qa (8.10.1) activesupport (~> 6.1) gitlab (~> 4.18.0) http (~> 5.0) @@ -312,7 +312,7 @@ DEPENDENCIES faraday-retry (~> 2.0) fog-core (= 2.1.0) fog-google (~> 1.19) - gitlab-qa (~> 8, >= 8.10.0) + gitlab-qa (~> 8, >= 8.10.1) influxdb-client (~> 2.8) knapsack (~> 4.0) nokogiri (~> 1.13, >= 1.13.9) diff --git a/spec/controllers/graphql_controller_spec.rb b/spec/controllers/graphql_controller_spec.rb index fc561b6b191..fe8b0291733 100644 --- a/spec/controllers/graphql_controller_spec.rb +++ b/spec/controllers/graphql_controller_spec.rb @@ -414,4 +414,114 @@ RSpec.describe GraphqlController do expect(log_payload.dig(:exception_object)).to eq(exception) end end + + describe 'removal of deprecated items' do + let(:mock_schema) do + Class.new(GraphQL::Schema) do + lazy_resolve ::Gitlab::Graphql::Lazy, :force + + query(Class.new(::Types::BaseObject) do + graphql_name 'Query' + + field :foo, GraphQL::Types::Boolean, + deprecated: { milestone: '0.1', reason: :renamed } + + field :bar, (Class.new(::Types::BaseEnum) do + graphql_name 'BarEnum' + + value 'FOOBAR', value: 'foobar', deprecated: { milestone: '0.1', reason: :renamed } + end) + + field :baz, GraphQL::Types::Boolean do + argument :arg, String, required: false, deprecated: { milestone: '0.1', reason: :renamed } + end + + def foo + false + end + + def bar + 'foobar' + end + + def baz(arg:) + false + end + end) + end + end + + before do + allow(GitlabSchema).to receive(:execute).and_wrap_original do |method, *args| + mock_schema.execute(*args) + end + end + + context 'without `remove_deprecated` param' do + let(:params) { { query: '{ foo bar baz(arg: "test") }' } } + + subject { post :execute, params: params } + + it "sets context's `remove_deprecated` value to false" do + subject + + expect(assigns(:context)[:remove_deprecated]).to be false + end + + it 'returns deprecated items in response' do + subject + + expect(json_response).to include('data' => { 'foo' => false, 'bar' => 'FOOBAR', 'baz' => false }) + end + end + + context 'with `remove_deprecated` param' do + let(:params) { { remove_deprecated: 'true' } } + + subject { post :execute, params: params } + + it "sets context's `remove_deprecated` value to true" do + subject + + expect(assigns(:context)[:remove_deprecated]).to be true + end + + it 'does not allow deprecated field' do + params[:query] = '{ foo }' + + subject + + expect(json_response).not_to include('data' => { 'foo' => false }) + expect(json_response).to include( + 'errors' => include(a_hash_including('message' => /Field 'foo' doesn't exist on type 'Query'/)) + ) + end + + it 'does not allow deprecated enum value' do + params[:query] = '{ bar }' + + subject + + expect(json_response).not_to include('data' => { 'bar' => 'FOOBAR' }) + expect(json_response).to include( + 'errors' => include( + a_hash_including( + 'message' => /`Query.bar` returned `"foobar"` at `bar`, but this isn't a valid value for `BarEnum`/ + ) + ) + ) + end + + it 'does not allow deprecated argument' do + params[:query] = '{ baz(arg: "test") }' + + subject + + expect(json_response).not_to include('data' => { 'bar' => 'FOOBAR' }) + expect(json_response).to include( + 'errors' => include(a_hash_including('message' => /Field 'baz' doesn't accept argument 'arg'/)) + ) + end + end + end end diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb index 66fafa002b7..3cd4394c732 100644 --- a/spec/features/merge_request/user_sees_merge_widget_spec.rb +++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb @@ -400,9 +400,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do it 'updates the MR widget', :sidekiq_might_not_need_inline do click_button 'Merge' - page.within('.mr-widget-body') do - expect(page).to have_content('An error occurred while merging') - end + expect(page).to have_content('An error occurred while merging') end end diff --git a/spec/graphql/mutations/concerns/mutations/resolves_group_spec.rb b/spec/graphql/mutations/concerns/mutations/resolves_group_spec.rb index 6bed3a752ed..3198419fb81 100644 --- a/spec/graphql/mutations/concerns/mutations/resolves_group_spec.rb +++ b/spec/graphql/mutations/concerns/mutations/resolves_group_spec.rb @@ -9,7 +9,7 @@ RSpec.describe Mutations::ResolvesGroup do end end - let(:context) { double } + let(:context) { {} } subject(:mutation) { mutation_class.new(object: nil, context: context, field: nil) } diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 359fc4db01f..2fffbe578de 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -5799,7 +5799,7 @@ RSpec.describe Project, factory_default: :keep do end describe '#has_active_integrations?' do - let_it_be(:project) { create(:project) } + let_it_be_with_refind(:project) { create(:project) } it { expect(project.has_active_integrations?).to eq(false) } @@ -5809,6 +5809,20 @@ RSpec.describe Project, factory_default: :keep do expect(project.has_active_integrations?(:merge_request_hooks)).to eq(false) expect(project.has_active_integrations?).to eq(true) end + + it 'caches matching integrations' do + create(:custom_issue_tracker_integration, push_events: true, merge_requests_events: false, project: project) + + expect(project.has_active_integrations?(:merge_request_hooks)).to eq(false) + expect(project.has_active_integrations?).to eq(true) + + count = ActiveRecord::QueryRecorder.new do + expect(project.has_active_integrations?(:merge_request_hooks)).to eq(false) + expect(project.has_active_integrations?).to eq(true) + end.count + + expect(count).to eq(0) + end end describe '#badges' do diff --git a/spec/requests/api/boards_spec.rb b/spec/requests/api/boards_spec.rb index 817e1324c7c..4d7256a1f03 100644 --- a/spec/requests/api/boards_spec.rb +++ b/spec/requests/api/boards_spec.rb @@ -7,7 +7,7 @@ RSpec.describe API::Boards do let_it_be(:non_member) { create(:user) } let_it_be(:guest) { create(:user) } let_it_be(:admin) { create(:user, :admin) } - let_it_be(:board_parent, reload: true) { create(:project, :public, creator_id: user.id, namespace: user.namespace ) } + let_it_be(:board_parent, reload: true) { create(:project, :public, creator_id: user.id, namespace: user.namespace) } let_it_be(:dev_label) do create(:label, title: 'Development', color: '#FFAABB', project: board_parent) @@ -97,7 +97,7 @@ RSpec.describe API::Boards do describe "POST /groups/:id/boards/:board_id/lists" do let_it_be(:group) { create(:group) } - let_it_be(:board_parent) { create(:group, parent: group ) } + let_it_be(:board_parent) { create(:group, parent: group) } let(:url) { "/groups/#{board_parent.id}/boards/#{board.id}/lists" } let_it_be(:board) { create(:board, group: board_parent) } diff --git a/spec/requests/api/ci/runner/jobs_artifacts_spec.rb b/spec/requests/api/ci/runner/jobs_artifacts_spec.rb index cd8c3dd2806..aaaa128b7a2 100644 --- a/spec/requests/api/ci/runner/jobs_artifacts_spec.rb +++ b/spec/requests/api/ci/runner/jobs_artifacts_spec.rb @@ -238,7 +238,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do context 'authorization token is invalid' do it 'responds with forbidden' do - authorize_artifacts(token: 'invalid', filesize: 100 ) + authorize_artifacts(token: 'invalid', filesize: 100) expect(response).to have_gitlab_http_status(:forbidden) end diff --git a/spec/requests/api/ci/runner/jobs_request_post_spec.rb b/spec/requests/api/ci/runner/jobs_request_post_spec.rb index d4f734e7bdd..1cb4cc93ea5 100644 --- a/spec/requests/api/ci/runner/jobs_request_post_spec.rb +++ b/spec/requests/api/ci/runner/jobs_request_post_spec.rb @@ -462,7 +462,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do request_job info: { 'config' => { 'gpus' => 'all', 'ignored' => 'hello' } } expect(response).to have_gitlab_http_status(:created) - expect(runner.reload.config).to eq( { 'gpus' => 'all' } ) + expect(runner.reload.config).to eq({ 'gpus' => 'all' }) end it "sets the runner's ip_address" do diff --git a/spec/requests/api/ci/runners_reset_registration_token_spec.rb b/spec/requests/api/ci/runners_reset_registration_token_spec.rb index e1dc347f8dd..b8e4370fd46 100644 --- a/spec/requests/api/ci/runners_reset_registration_token_spec.rb +++ b/spec/requests/api/ci/runners_reset_registration_token_spec.rb @@ -118,7 +118,7 @@ RSpec.describe API::Ci::Runners do end include_context 'when authorized', 'group' do - let_it_be(:user) { create_default(:group_member, :owner, user: create(:user), group: group ).user } + let_it_be(:user) { create_default(:group_member, :owner, user: create(:user), group: group).user } def get_token group.reload.runners_token diff --git a/spec/requests/api/ci/runners_spec.rb b/spec/requests/api/ci/runners_spec.rb index 69f26d3f257..dd9894f2972 100644 --- a/spec/requests/api/ci/runners_spec.rb +++ b/spec/requests/api/ci/runners_spec.rb @@ -399,7 +399,7 @@ RSpec.describe API::Ci::Runners do it 'unrelated runner attribute on an existing runner with too many tags' do # This test ensures that it is possible to update any attribute on a runner that currently fails the # validation that ensures that there aren't too many tags associated with a runner - existing_invalid_shared_runner = build(:ci_runner, :instance, tag_list: (1..::Ci::Runner::TAG_LIST_MAX_LENGTH + 1).map { |i| "tag#{i}" } ) + existing_invalid_shared_runner = build(:ci_runner, :instance, tag_list: (1..::Ci::Runner::TAG_LIST_MAX_LENGTH + 1).map { |i| "tag#{i}" }) existing_invalid_shared_runner.save!(validate: false) active = existing_invalid_shared_runner.active diff --git a/spec/requests/api/dependency_proxy_spec.rb b/spec/requests/api/dependency_proxy_spec.rb index a8617fcb0bf..7af4ed08cb8 100644 --- a/spec/requests/api/dependency_proxy_spec.rb +++ b/spec/requests/api/dependency_proxy_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe API::DependencyProxy, api: true do let_it_be(:user) { create(:user) } - let_it_be(:blob) { create(:dependency_proxy_blob ) } + let_it_be(:blob) { create(:dependency_proxy_blob) } let_it_be(:group, reload: true) { blob.group } before do diff --git a/spec/requests/api/deployments_spec.rb b/spec/requests/api/deployments_spec.rb index 24e0e5d3180..6d4e2cf31a3 100644 --- a/spec/requests/api/deployments_spec.rb +++ b/spec/requests/api/deployments_spec.rb @@ -325,7 +325,7 @@ RSpec.describe API::Deployments do context 'as non member' do it 'returns a 404 status code' do post( - api( "/projects/#{project.id}/deployments", non_member), + api("/projects/#{project.id}/deployments", non_member), params: { environment: 'production', sha: '123', diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb index e95a626b4aa..241ad75dcf8 100644 --- a/spec/requests/api/files_spec.rb +++ b/spec/requests/api/files_spec.rb @@ -11,7 +11,7 @@ RSpec.describe API::Files do let_it_be(:inherited_reporter) { create(:user) } let_it_be(:inherited_developer) { create(:user) } - let!(:project) { create(:project, :repository, namespace: user.namespace ) } + let!(:project) { create(:project, :repository, namespace: user.namespace) } let(:guest) { create(:user) { |u| project.add_guest(u) } } let(:file_path) { 'files%2Fruby%2Fpopen%2Erb' } let(:file_name) { 'popen.rb' } @@ -935,7 +935,7 @@ RSpec.describe API::Files do end context 'and the repo is empty' do - let!(:project) { create(:project_empty_repo, namespace: user.namespace ) } + let!(:project) { create(:project_empty_repo, namespace: user.namespace) } it_behaves_like 'creates a new file in the project repo' do let(:current_user) { user } diff --git a/spec/requests/api/go_proxy_spec.rb b/spec/requests/api/go_proxy_spec.rb index 7c44fddc303..fd74d06f383 100644 --- a/spec/requests/api/go_proxy_spec.rb +++ b/spec/requests/api/go_proxy_spec.rb @@ -16,12 +16,12 @@ RSpec.describe API::GoProxy do let_it_be(:modules) do commits = [ - create(:go_module_commit, :files, project: project, tag: 'v1.0.0', files: { 'README.md' => 'Hi' } ), - create(:go_module_commit, :module, project: project, tag: 'v1.0.1' ), - create(:go_module_commit, :package, project: project, tag: 'v1.0.2', path: 'pkg' ), - create(:go_module_commit, :module, project: project, tag: 'v1.0.3', name: 'mod' ), - create(:go_module_commit, :files, project: project, files: { 'y.go' => "package a\n" } ), - create(:go_module_commit, :module, project: project, name: 'v2' ), + create(:go_module_commit, :files, project: project, tag: 'v1.0.0', files: { 'README.md' => 'Hi' }), + create(:go_module_commit, :module, project: project, tag: 'v1.0.1'), + create(:go_module_commit, :package, project: project, tag: 'v1.0.2', path: 'pkg'), + create(:go_module_commit, :module, project: project, tag: 'v1.0.3', name: 'mod'), + create(:go_module_commit, :files, project: project, files: { 'y.go' => "package a\n" }), + create(:go_module_commit, :module, project: project, name: 'v2'), create(:go_module_commit, :files, project: project, tag: 'v2.0.0', files: { 'v2/x.go' => "package a\n" }) ] @@ -288,10 +288,10 @@ RSpec.describe API::GoProxy do let_it_be(:base) { "#{Settings.build_gitlab_go_url}/#{project.full_path}" } let_it_be(:modules) do - create(:go_module_commit, :files, project: project, files: { 'a.go' => "package\a" } ) + create(:go_module_commit, :files, project: project, files: { 'a.go' => "package\a" }) create(:go_module_commit, :files, project: project, tag: 'v1.0.0', files: { 'go.mod' => "module not/a/real/module\n" }) - create(:go_module_commit, :files, project: project, files: { 'v2/a.go' => "package a\n" } ) - create(:go_module_commit, :files, project: project, tag: 'v2.0.0', files: { 'v2/go.mod' => "module #{base}\n" } ) + create(:go_module_commit, :files, project: project, files: { 'v2/a.go' => "package a\n" }) + create(:go_module_commit, :files, project: project, tag: 'v2.0.0', files: { 'v2/go.mod' => "module #{base}\n" }) end describe 'GET /projects/:id/packages/go/*module_name/@v/list' do diff --git a/spec/requests/api/graphql/boards/board_list_issues_query_spec.rb b/spec/requests/api/graphql/boards/board_list_issues_query_spec.rb index 484ddc3469b..a9acced1efa 100644 --- a/spec/requests/api/graphql/boards/board_list_issues_query_spec.rb +++ b/spec/requests/api/graphql/boards/board_list_issues_query_spec.rb @@ -7,7 +7,7 @@ RSpec.describe 'get board lists' do let_it_be(:user) { create(:user) } let_it_be(:unauth_user) { create(:user) } - let_it_be(:project) { create(:project, creator_id: user.id, namespace: user.namespace ) } + let_it_be(:project) { create(:project, creator_id: user.id, namespace: user.namespace) } let_it_be(:group) { create(:group, :private) } let_it_be(:project_label) { create(:label, project: project, name: 'Development') } let_it_be(:project_label2) { create(:label, project: project, name: 'Testing') } diff --git a/spec/requests/api/graphql/ci/jobs_spec.rb b/spec/requests/api/graphql/ci/jobs_spec.rb index 47e3221c567..a161c5c98ed 100644 --- a/spec/requests/api/graphql/ci/jobs_spec.rb +++ b/spec/requests/api/graphql/ci/jobs_spec.rb @@ -109,7 +109,7 @@ RSpec.describe 'Query.project.pipeline' do 'name' => 'docker 1 2', 'needs' => { 'nodes' => [] }, 'previousStageJobsOrNeeds' => { 'nodes' => [ - a_hash_including( 'name' => 'my test job' ) + a_hash_including('name' => 'my test job') ] } ), a_hash_including( @@ -129,7 +129,7 @@ RSpec.describe 'Query.project.pipeline' do 'name' => 'rspec 2 2', 'needs' => { 'nodes' => [a_hash_including('name' => 'my test job')] }, 'previousStageJobsOrNeeds' => { 'nodes' => [ - a_hash_including('name' => 'my test job' ) + a_hash_including('name' => 'my test job') ] } ) ) diff --git a/spec/requests/api/graphql/ci/pipelines_spec.rb b/spec/requests/api/graphql/ci/pipelines_spec.rb index f471a152603..948704e8770 100644 --- a/spec/requests/api/graphql/ci/pipelines_spec.rb +++ b/spec/requests/api/graphql/ci/pipelines_spec.rb @@ -419,7 +419,7 @@ RSpec.describe 'Query.project(fullPath).pipelines' do end before do - create(:ci_sources_pipeline, source_pipeline: upstream_pipeline, pipeline: pipeline ) + create(:ci_sources_pipeline, source_pipeline: upstream_pipeline, pipeline: pipeline) post_graphql(query, current_user: user) end @@ -441,10 +441,10 @@ RSpec.describe 'Query.project(fullPath).pipelines' do pipeline_2 = create(:ci_pipeline, project: project, user: user) upstream_pipeline_2 = create(:ci_pipeline, project: upstream_project, user: user) - create(:ci_sources_pipeline, source_pipeline: upstream_pipeline_2, pipeline: pipeline_2 ) + create(:ci_sources_pipeline, source_pipeline: upstream_pipeline_2, pipeline: pipeline_2) pipeline_3 = create(:ci_pipeline, project: project, user: user) upstream_pipeline_3 = create(:ci_pipeline, project: upstream_project, user: user) - create(:ci_sources_pipeline, source_pipeline: upstream_pipeline_3, pipeline: pipeline_3 ) + create(:ci_sources_pipeline, source_pipeline: upstream_pipeline_3, pipeline: pipeline_3) expect do post_graphql(query, current_user: second_user) diff --git a/spec/requests/api/graphql/mutations/award_emojis/remove_spec.rb b/spec/requests/api/graphql/mutations/award_emojis/remove_spec.rb index 7cd39f93ae7..e81621209fb 100644 --- a/spec/requests/api/graphql/mutations/award_emojis/remove_spec.rb +++ b/spec/requests/api/graphql/mutations/award_emojis/remove_spec.rb @@ -20,7 +20,7 @@ RSpec.describe 'Removing an AwardEmoji' do end def create_award_emoji(user) - create(:award_emoji, name: emoji_name, awardable: awardable, user: user ) + create(:award_emoji, name: emoji_name, awardable: awardable, user: user) end shared_examples 'a mutation that does not destroy an AwardEmoji' do diff --git a/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb b/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb index 7ddffa1ab0a..b151da72b55 100644 --- a/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb +++ b/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb @@ -32,7 +32,7 @@ RSpec.describe 'Toggling an AwardEmoji' do end def create_award_emoji(user) - create(:award_emoji, name: emoji_name, awardable: awardable, user: user ) + create(:award_emoji, name: emoji_name, awardable: awardable, user: user) end context 'when the user has permission' do diff --git a/spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb b/spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb index 6818ba33e74..54e63df96a6 100644 --- a/spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb @@ -87,7 +87,7 @@ RSpec.describe 'RunnersRegistrationTokenReset' do include_context('when unauthorized', 'group') include_context 'when authorized', 'group' do - let_it_be(:user) { create_default(:group_member, :owner, user: create(:user), group: group ).user } + let_it_be(:user) { create_default(:group_member, :owner, user: create(:user), group: group).user } def get_token group.reload.runners_token diff --git a/spec/requests/api/group_boards_spec.rb b/spec/requests/api/group_boards_spec.rb index 6ce8b766807..cc110aa4017 100644 --- a/spec/requests/api/group_boards_spec.rb +++ b/spec/requests/api/group_boards_spec.rb @@ -13,7 +13,7 @@ RSpec.describe API::GroupBoards do board_parent.add_owner(user) end - let_it_be(:project) { create(:project, :public, namespace: board_parent ) } + let_it_be(:project) { create(:project, :public, namespace: board_parent) } let_it_be(:dev_label) do create(:group_label, title: 'Development', color: '#FFAABB', group: board_parent) diff --git a/spec/requests/api/issues/issues_spec.rb b/spec/requests/api/issues/issues_spec.rb index f5c73846173..0e20b2133db 100644 --- a/spec/requests/api/issues/issues_spec.rb +++ b/spec/requests/api/issues/issues_spec.rb @@ -92,7 +92,7 @@ RSpec.describe API::Issues do describe 'GET /issues/:id' do context 'when unauthorized' do it 'returns unauthorized' do - get api("/issues/#{issue.id}" ) + get api("/issues/#{issue.id}") expect(response).to have_gitlab_http_status(:unauthorized) end @@ -101,7 +101,7 @@ RSpec.describe API::Issues do context 'when authorized' do context 'as a normal user' do it 'returns forbidden' do - get api("/issues/#{issue.id}", user ) + get api("/issues/#{issue.id}", user) expect(response).to have_gitlab_http_status(:forbidden) end diff --git a/spec/requests/api/issues/post_projects_issues_spec.rb b/spec/requests/api/issues/post_projects_issues_spec.rb index 3883eb01391..deaf7be96ab 100644 --- a/spec/requests/api/issues/post_projects_issues_spec.rb +++ b/spec/requests/api/issues/post_projects_issues_spec.rb @@ -473,8 +473,8 @@ RSpec.describe API::Issues do end describe '/projects/:id/issues/:issue_iid/move' do - let!(:target_project) { create(:project, creator_id: user.id, namespace: user.namespace ) } - let!(:target_project2) { create(:project, creator_id: non_member.id, namespace: non_member.namespace ) } + let!(:target_project) { create(:project, creator_id: user.id, namespace: user.namespace) } + let!(:target_project2) { create(:project, creator_id: non_member.id, namespace: non_member.namespace) } it 'moves an issue' do post api("/projects/#{project.id}/issues/#{issue.iid}/move", user), diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb index c1217292d5c..97ab90c9776 100644 --- a/spec/requests/api/labels_spec.rb +++ b/spec/requests/api/labels_spec.rb @@ -234,7 +234,7 @@ RSpec.describe API::Labels do before do create(:labeled_issue, project: project, labels: [group_label], author: user) create(:labeled_issue, project: project, labels: [label1], author: user, state: :closed) - create(:labeled_merge_request, labels: [priority_label], author: user, source_project: project ) + create(:labeled_merge_request, labels: [priority_label], author: user, source_project: project) end it 'includes counts in the response' do diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index d593e369d27..b04cc26d1ff 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -3022,7 +3022,7 @@ RSpec.describe API::MergeRequests do describe "PUT /projects/:id/merge_requests/:merge_request_iid" do context 'updates force_remove_source_branch properly' do it 'sets to false' do - merge_request.update!(merge_params: { 'force_remove_source_branch' => true } ) + merge_request.update!(merge_params: { 'force_remove_source_branch' => true }) expect(merge_request.force_remove_source_branch?).to be_truthy @@ -3034,7 +3034,7 @@ RSpec.describe API::MergeRequests do end it 'sets to true' do - merge_request.update!(merge_params: { 'force_remove_source_branch' => false } ) + merge_request.update!(merge_params: { 'force_remove_source_branch' => false }) expect(merge_request.force_remove_source_branch?).to be false diff --git a/spec/requests/api/ml/mlflow_spec.rb b/spec/requests/api/ml/mlflow_spec.rb index c588c99c1bf..9448f009742 100644 --- a/spec/requests/api/ml/mlflow_spec.rb +++ b/spec/requests/api/ml/mlflow_spec.rb @@ -253,7 +253,7 @@ RSpec.describe API::Ml::Mlflow do it 'creates the experiment', :aggregate_failures do expect(response).to have_gitlab_http_status(:ok) - expect(json_response).to include('experiment_id' ) + expect(json_response).to include('experiment_id') end describe 'Error States' do diff --git a/spec/requests/api/pages/pages_spec.rb b/spec/requests/api/pages/pages_spec.rb index 7d44ff533aa..4a94bf90205 100644 --- a/spec/requests/api/pages/pages_spec.rb +++ b/spec/requests/api/pages/pages_spec.rb @@ -36,7 +36,7 @@ RSpec.describe API::Pages do end it 'removes the pages' do - delete api("/projects/#{project.id}/pages", admin ) + delete api("/projects/#{project.id}/pages", admin) expect(project.reload.pages_metadatum.deployed?).to be(false) end diff --git a/spec/requests/api/personal_access_tokens_spec.rb b/spec/requests/api/personal_access_tokens_spec.rb index 31c4e8803e3..f656fdff12e 100644 --- a/spec/requests/api/personal_access_tokens_spec.rb +++ b/spec/requests/api/personal_access_tokens_spec.rb @@ -87,7 +87,7 @@ RSpec.describe API::PersonalAccessTokens do end context 'filter with created parameter' do - let_it_be(:token1) { create(:personal_access_token, created_at: DateTime.new(2022, 01, 01, 12, 30, 25) ) } + let_it_be(:token1) { create(:personal_access_token, created_at: DateTime.new(2022, 01, 01, 12, 30, 25)) } context 'test created_before' do where(:created_at, :status, :result_count, :result) do @@ -121,7 +121,7 @@ RSpec.describe API::PersonalAccessTokens do end context 'filter with last_used parameter' do - let_it_be(:token1) { create(:personal_access_token, last_used_at: DateTime.new(2022, 01, 01, 12, 30, 25) ) } + let_it_be(:token1) { create(:personal_access_token, last_used_at: DateTime.new(2022, 01, 01, 12, 30, 25)) } let_it_be(:never_used_token) { create(:personal_access_token) } context 'test last_used_before' do @@ -209,13 +209,13 @@ RSpec.describe API::PersonalAccessTokens do expect(response).to have_gitlab_http_status(status) - expect(json_response.map { |pat| pat['id'] } ).to include(*result) if status == :ok + expect(json_response.map { |pat| pat['id'] }).to include(*result) if status == :ok end end end context 'filter last_used_before and last_used_after combined is valid' do - let_it_be(:token1) { create(:personal_access_token, last_used_at: DateTime.new(2022, 01, 02) ) } + let_it_be(:token1) { create(:personal_access_token, last_used_at: DateTime.new(2022, 01, 02)) } where(:last_used_before, :last_used_after, :status, :result) do '2022-01-02' | '2022-01-02' | :ok | lazy { [token1.id] } @@ -232,7 +232,7 @@ RSpec.describe API::PersonalAccessTokens do expect(response).to have_gitlab_http_status(status) - expect(json_response.map { |pat| pat['id'] } ).to include(*result) if status == :ok + expect(json_response.map { |pat| pat['id'] }).to include(*result) if status == :ok end end end @@ -304,7 +304,7 @@ RSpec.describe API::PersonalAccessTokens do # Here it is only tested whether PATs to which the user has no access right are excluded from the filter function. context 'filter with created parameter' do let_it_be(:token1) do - create(:personal_access_token, created_at: DateTime.new(2022, 01, 02, 12, 30, 25), user: current_user ) + create(:personal_access_token, created_at: DateTime.new(2022, 01, 02, 12, 30, 25), user: current_user) end let_it_be(:token2) { create(:personal_access_token, created_at: DateTime.new(2022, 01, 02, 12, 30, 25)) } @@ -332,7 +332,7 @@ RSpec.describe API::PersonalAccessTokens do create(:personal_access_token, last_used_at: DateTime.new(2022, 01, 01, 12, 30, 25), user: current_user) end - let_it_be(:token2) { create(:personal_access_token, last_used_at: DateTime.new(2022, 01, 01, 12, 30, 25) ) } + let_it_be(:token2) { create(:personal_access_token, last_used_at: DateTime.new(2022, 01, 01, 12, 30, 25)) } let_it_be(:never_used_token) { create(:personal_access_token) } let_it_be(:status) { :ok } diff --git a/spec/requests/api/project_milestones_spec.rb b/spec/requests/api/project_milestones_spec.rb index b23fb86a9de..8294ca143d3 100644 --- a/spec/requests/api/project_milestones_spec.rb +++ b/spec/requests/api/project_milestones_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe API::ProjectMilestones do let_it_be(:user) { create(:user) } - let_it_be_with_reload(:project) { create(:project, namespace: user.namespace ) } + let_it_be_with_reload(:project) { create(:project, namespace: user.namespace) } let_it_be(:closed_milestone) { create(:closed_milestone, project: project, title: 'version1', description: 'closed milestone') } let_it_be(:milestone) { create(:milestone, project: project, title: 'version2', description: 'open milestone') } let_it_be(:route) { "/projects/#{project.id}/milestones" } diff --git a/spec/requests/api/project_snippets_spec.rb b/spec/requests/api/project_snippets_spec.rb index 6e2dd6e76a9..1d255f7c1d8 100644 --- a/spec/requests/api/project_snippets_spec.rb +++ b/spec/requests/api/project_snippets_spec.rb @@ -89,7 +89,7 @@ RSpec.describe API::ProjectSnippets do expect(json_response['title']).to eq(snippet.title) expect(json_response['description']).to eq(snippet.description) expect(json_response['file_name']).to eq(snippet.file_name_on_repo) - expect(json_response['files']).to eq(snippet.blobs.map { |blob| snippet_blob_file(blob) } ) + expect(json_response['files']).to eq(snippet.blobs.map { |blob| snippet_blob_file(blob) }) expect(json_response['ssh_url_to_repo']).to eq(snippet.ssh_url_to_repo) expect(json_response['http_url_to_repo']).to eq(snippet.http_url_to_repo) end diff --git a/spec/requests/api/snippets_spec.rb b/spec/requests/api/snippets_spec.rb index 031bcb612f4..9408d1cc248 100644 --- a/spec/requests/api/snippets_spec.rb +++ b/spec/requests/api/snippets_spec.rb @@ -28,7 +28,7 @@ RSpec.describe API::Snippets, factory_default: :keep do expect(response).to have_gitlab_http_status(:ok) expect(response).to include_pagination_headers expect(json_response).to be_an Array - expect(json_response.map { |snippet| snippet['id'] } ).to contain_exactly( + expect(json_response.map { |snippet| snippet['id'] }).to contain_exactly( public_snippet.id, internal_snippet.id, private_snippet.id) @@ -75,7 +75,7 @@ RSpec.describe API::Snippets, factory_default: :keep do it 'returns snippets available for user in given time range' do get api(path, personal_access_token: user_token) - expect(json_response.map { |snippet| snippet['id'] } ).to contain_exactly( + expect(json_response.map { |snippet| snippet['id'] }).to contain_exactly( private_snippet_in_time_range1.id, private_snippet_in_time_range2.id) end @@ -99,10 +99,10 @@ RSpec.describe API::Snippets, factory_default: :keep do expect(response).to have_gitlab_http_status(:ok) expect(response).to include_pagination_headers expect(json_response).to be_an Array - expect(json_response.map { |snippet| snippet['id'] } ).to contain_exactly( + expect(json_response.map { |snippet| snippet['id'] }).to contain_exactly( public_snippet.id, public_snippet_other.id) - expect(json_response.map { |snippet| snippet['web_url'] } ).to contain_exactly( + expect(json_response.map { |snippet| snippet['web_url'] }).to contain_exactly( "http://localhost/-/snippets/#{public_snippet.id}", "http://localhost/-/snippets/#{public_snippet_other.id}") expect(json_response[0]['files'].first).to eq snippet_blob_file(public_snippet_other.blobs.first) @@ -126,7 +126,7 @@ RSpec.describe API::Snippets, factory_default: :keep do it 'returns public snippets available to user in given time range' do get api(path, personal_access_token: user_token) - expect(json_response.map { |snippet| snippet['id'] } ).to contain_exactly( + expect(json_response.map { |snippet| snippet['id'] }).to contain_exactly( public_snippet_in_time_range.id) end end diff --git a/spec/requests/api/submodules_spec.rb b/spec/requests/api/submodules_spec.rb index 6b141d6d036..9840476ca27 100644 --- a/spec/requests/api/submodules_spec.rb +++ b/spec/requests/api/submodules_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe API::Submodules do let(:user) { create(:user) } - let!(:project) { create(:project, :repository, namespace: user.namespace ) } + let!(:project) { create(:project, :repository, namespace: user.namespace) } let(:guest) { create(:user) { |u| project.add_guest(u) } } let(:submodule) { 'six' } let(:commit_sha) { 'e25eda1fece24ac7a03624ed1320f82396f35bd8' } diff --git a/spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb b/spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb index 2d7da9f9f00..67576a18c80 100644 --- a/spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb +++ b/spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb @@ -86,4 +86,25 @@ RSpec.shared_examples 'Gitlab-style deprecations' do eq("`alpha` and `deprecated` arguments cannot be passed at the same time") ) end + + describe 'visible?' do + let(:ctx) { {} } + + it 'defaults to true' do + expect(subject).to be_visible(ctx) + end + + context 'when subject is deprecated' do + let(:arguments) { { deprecated: { milestone: '1.10', reason: :renamed } } } + + it 'defaults to true' do + expect(subject(arguments)).to be_visible(ctx) + end + + it 'returns false if `remove_deprecated` is true in context' do + ctx = { remove_deprecated: true } + expect(subject(arguments)).not_to be_visible(ctx) + end + end + end end |