From c3524d16b2ef6a13fd6b398aaeae9af5462f1e33 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 7 Oct 2021 15:12:00 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- app/controllers/graphql_controller.rb | 8 + .../resolvers/board_list_issues_resolver.rb | 5 +- app/graphql/types/base_field.rb | 3 + app/graphql/types/board_list_type.rb | 1 + app/models/user_highest_role.rb | 8 +- app/services/ci/register_job_service.rb | 64 +- .../development/variable_inside_variable.yml | 2 +- config/initializers/postgres_partitioning.rb | 3 +- .../variables/where_variables_can_be_used.md | 3 +- doc/development/database/keyset_pagination.md | 2 +- .../database/multiple_databases.md | 86 ++ doc/user/award_emojis.md | 9 - doc/user/gitlab_com/index.md | 2 +- doc/user/project/labels.md | 8 +- doc/user/todos.md | 4 - lib/gitlab/application_context.rb | 5 +- lib/gitlab/feature_categories.rb | 38 + .../board/issues_connection_extension.rb | 15 + .../graphql/connection_collection_methods.rb | 2 +- .../import_export/group/import_export.yml | 1 - .../metrics/requests_rack_middleware.rb | 2 +- lib/gitlab/metrics/web_transaction.rb | 11 +- .../in_operator_optimization/query_builder.rb | 11 +- lib/gitlab/pagination/keyset/iterator.rb | 4 +- lib/gitlab/pagination/keyset/paginator.rb | 4 +- .../keyset/unsupported_scope_order.rb | 19 + .../kubernetes/kubernetes_integration_spec.rb | 2 +- spec/controllers/graphql_controller_spec.rb | 8 + spec/factories/ci/pipelines.rb | 5 +- .../board_list_issues_resolver_spec.rb | 5 +- spec/graphql/types/base_field_spec.rb | 11 + spec/graphql/types/board_list_type_spec.rb | 8 + spec/lib/gitlab/database/partitioning_spec.rb | 6 + spec/lib/gitlab/feature_categories_spec.rb | 74 + .../metrics/requests_rack_middleware_spec.rb | 2 +- .../gitlab/metrics/web_transaction_spec.rb | 15 +- .../boards/board_list_issues_query_spec.rb | 16 +- spec/services/ci/register_job_service_spec.rb | 44 +- .../cross-database-modification-allowlist.yml | 1340 +++++++++++++++++ .../support/database/cross-join-allowlist.yml | 2 - .../prevent_cross_database_modification.rb | 21 +- spec/support/database/prevent_cross_joins.rb | 4 + .../graphql/connection_shared_examples.rb | 2 +- workhorse/internal/upstream/routes.go | 8 +- workhorse/internal/upstream/upstream_test.go | 8 + 45 files changed, 1781 insertions(+), 120 deletions(-) create mode 100644 lib/gitlab/feature_categories.rb create mode 100644 lib/gitlab/graphql/board/issues_connection_extension.rb create mode 100644 lib/gitlab/pagination/keyset/unsupported_scope_order.rb create mode 100644 spec/lib/gitlab/feature_categories_spec.rb create mode 100644 spec/support/database/cross-database-modification-allowlist.yml diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb index 515fbd7b482..0722a712b5c 100644 --- a/app/controllers/graphql_controller.rb +++ b/app/controllers/graphql_controller.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class GraphqlController < ApplicationController + extend ::Gitlab::Utils::Override + # Unauthenticated users have access to the API for public data skip_before_action :authenticate_user! @@ -35,6 +37,7 @@ class GraphqlController < ApplicationController # callback execution order here around_action :sessionless_bypass_admin_mode!, if: :sessionless_user? + # The default feature category is overridden to read from request feature_category :not_owned def execute @@ -64,6 +67,11 @@ class GraphqlController < ApplicationController render_error(exception.message, status: :unprocessable_entity) end + override :feature_category + def feature_category + ::Gitlab::FeatureCategories.default.from_request(request) || super + end + private def disallow_mutations_for_get diff --git a/app/graphql/resolvers/board_list_issues_resolver.rb b/app/graphql/resolvers/board_list_issues_resolver.rb index 7c85dd8fb9b..d70acdf7ca0 100644 --- a/app/graphql/resolvers/board_list_issues_resolver.rb +++ b/app/graphql/resolvers/board_list_issues_resolver.rb @@ -18,11 +18,8 @@ module Resolvers filter_params = filters.merge(board_id: list.board.id, id: list.id) service = ::Boards::Issues::ListService.new(list.board.resource_parent, context[:current_user], filter_params) - pagination_connections = Gitlab::Graphql::Pagination::Keyset::Connection.new(service.execute) - ::Boards::Issues::ListService.initialize_relative_positions(list.board, current_user, pagination_connections.items) - - pagination_connections + service.execute end # https://gitlab.com/gitlab-org/gitlab/-/issues/235681 diff --git a/app/graphql/types/base_field.rb b/app/graphql/types/base_field.rb index 9c27f0f8138..d2dd8b27c4a 100644 --- a/app/graphql/types/base_field.rb +++ b/app/graphql/types/base_field.rb @@ -21,6 +21,7 @@ module Types @feature_flag = kwargs[:feature_flag] kwargs = check_feature_flag(kwargs) @deprecation = gitlab_deprecation(kwargs) + after_connection_extensions = kwargs.delete(:late_extensions) || [] super(**kwargs, &block) @@ -28,6 +29,8 @@ module Types extension ::Gitlab::Graphql::CallsGitaly::FieldExtension if Gitlab.dev_or_test_env? extension ::Gitlab::Graphql::Present::FieldExtension extension ::Gitlab::Graphql::Authorize::ConnectionFilterExtension + + after_connection_extensions.each { extension _1 } if after_connection_extensions.any? end def may_call_gitaly? diff --git a/app/graphql/types/board_list_type.rb b/app/graphql/types/board_list_type.rb index 762e03973d9..deb4da5f785 100644 --- a/app/graphql/types/board_list_type.rb +++ b/app/graphql/types/board_list_type.rb @@ -27,6 +27,7 @@ module Types field :issues, ::Types::IssueType.connection_type, null: true, description: 'Board issues.', + late_extensions: [Gitlab::Graphql::Board::IssuesConnectionExtension], resolver: ::Resolvers::BoardListIssuesResolver def issues_count diff --git a/app/models/user_highest_role.rb b/app/models/user_highest_role.rb index 4853fc3d248..dd5c85a5a87 100644 --- a/app/models/user_highest_role.rb +++ b/app/models/user_highest_role.rb @@ -3,7 +3,13 @@ class UserHighestRole < ApplicationRecord belongs_to :user, optional: false - validates :highest_access_level, allow_nil: true, inclusion: { in: Gitlab::Access.all_values } + validates :highest_access_level, allow_nil: true, inclusion: { in: ->(_) { self.allowed_values } } scope :with_highest_access_level, -> (highest_access_level) { where(highest_access_level: highest_access_level) } + + def self.allowed_values + Gitlab::Access.all_values + end end + +UserHighestRole.prepend_mod diff --git a/app/services/ci/register_job_service.rb b/app/services/ci/register_job_service.rb index c46ddd22558..5dd586e9f22 100644 --- a/app/services/ci/register_job_service.rb +++ b/app/services/ci/register_job_service.rb @@ -103,42 +103,40 @@ module Ci # rubocop: disable CodeReuse/ActiveRecord def each_build(params, &blk) - ::Gitlab::Database.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/339429') do - queue = ::Ci::Queue::BuildQueueService.new(runner) + queue = ::Ci::Queue::BuildQueueService.new(runner) - builds = begin - if runner.instance_type? - queue.builds_for_shared_runner - elsif runner.group_type? - queue.builds_for_group_runner - else - queue.builds_for_project_runner - end + builds = begin + if runner.instance_type? + queue.builds_for_shared_runner + elsif runner.group_type? + queue.builds_for_group_runner + else + queue.builds_for_project_runner end - - if runner.ref_protected? - builds = queue.builds_for_protected_runner(builds) - end - - # pick builds that does not have other tags than runner's one - builds = queue.builds_matching_tag_ids(builds, runner.tags.ids) - - # pick builds that have at least one tag - unless runner.run_untagged? - builds = queue.builds_with_any_tags(builds) - end - - # pick builds that older than specified age - if params.key?(:job_age) - builds = queue.builds_queued_before(builds, params[:job_age].seconds.ago) - end - - build_ids = retrieve_queue(-> { queue.execute(builds) }) - - @metrics.observe_queue_size(-> { build_ids.size }, @runner.runner_type) - - build_ids.each { |build_id| yield Ci::Build.find(build_id) } end + + if runner.ref_protected? + builds = queue.builds_for_protected_runner(builds) + end + + # pick builds that does not have other tags than runner's one + builds = queue.builds_matching_tag_ids(builds, runner.tags.ids) + + # pick builds that have at least one tag + unless runner.run_untagged? + builds = queue.builds_with_any_tags(builds) + end + + # pick builds that older than specified age + if params.key?(:job_age) + builds = queue.builds_queued_before(builds, params[:job_age].seconds.ago) + end + + build_ids = retrieve_queue(-> { queue.execute(builds) }) + + @metrics.observe_queue_size(-> { build_ids.size }, @runner.runner_type) + + build_ids.each { |build_id| yield Ci::Build.find(build_id) } end # rubocop: enable CodeReuse/ActiveRecord diff --git a/config/feature_flags/development/variable_inside_variable.yml b/config/feature_flags/development/variable_inside_variable.yml index 2060958590f..fee4897b3f0 100644 --- a/config/feature_flags/development/variable_inside_variable.yml +++ b/config/feature_flags/development/variable_inside_variable.yml @@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/297382 milestone: '13.11' type: development group: group::runner -default_enabled: false +default_enabled: true diff --git a/config/initializers/postgres_partitioning.rb b/config/initializers/postgres_partitioning.rb index f2e2fba1559..49f382547d6 100644 --- a/config/initializers/postgres_partitioning.rb +++ b/config/initializers/postgres_partitioning.rb @@ -2,8 +2,7 @@ Gitlab::Database::Partitioning.register_models([ AuditEvent, - WebHookLog, - LooseForeignKeys::DeletedRecord + WebHookLog ]) if Gitlab.ee? diff --git a/doc/ci/variables/where_variables_can_be_used.md b/doc/ci/variables/where_variables_can_be_used.md index 0f9339657fe..8c5b7feed70 100644 --- a/doc/ci/variables/where_variables_can_be_used.md +++ b/doc/ci/variables/where_variables_can_be_used.md @@ -65,9 +65,10 @@ because the expansion is done in GitLab before any runner gets the job. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48627) in GitLab 13.10. [Deployed behind the `variable_inside_variable` feature flag](../../user/feature_flags.md), disabled by default. > - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/297382) in GitLab 14.3. +> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/297382) in GitLab 14.4. FLAG: -On self-managed GitLab, by default this feature is disabled. To enable the feature per project or for your entire instance, ask an administrator to [enable the `variable_inside_variable` flag](../../administration/feature_flags.md). +On self-managed GitLab, by default this feature is available. To hide the feature, ask an administrator to [disable the feature flag](../../administration/feature_flags.md) named `variable_inside_variable`. On GitLab.com, this feature is available. GitLab expands job variable values recursively before sending them to the runner. For example: diff --git a/doc/development/database/keyset_pagination.md b/doc/development/database/keyset_pagination.md index fd62c36b753..4f0b353a37f 100644 --- a/doc/development/database/keyset_pagination.md +++ b/doc/development/database/keyset_pagination.md @@ -169,7 +169,7 @@ Consider the following scope: scope = Issue.where(project_id: 10).order(Gitlab::Database.nulls_last_order('relative_position', 'DESC')) # SELECT "issues".* FROM "issues" WHERE "issues"."project_id" = 10 ORDER BY relative_position DESC NULLS LAST -scope.keyset_paginate # raises: Gitlab::Pagination::Keyset::Paginator::UnsupportedScopeOrder: The order on the scope does not support keyset pagination +scope.keyset_paginate # raises: Gitlab::Pagination::Keyset::UnsupportedScopeOrder: The order on the scope does not support keyset pagination ``` The `keyset_paginate` method raises an error because the order value on the query is a custom SQL string and not an [`Arel`](https://www.rubydoc.info/gems/arel) AST node. The keyset library cannot automatically infer configuration values from these kinds of queries. diff --git a/doc/development/database/multiple_databases.md b/doc/development/database/multiple_databases.md index 38cca2eb592..d00103c94ba 100644 --- a/doc/development/database/multiple_databases.md +++ b/doc/development/database/multiple_databases.md @@ -425,6 +425,92 @@ to fix the cross-join. If the cross-join is being used in a migration, we do not need to fix the code. See for more details. +### Removing cross-database transactions + +When dealing with multiple databases, it's important to pay close attention to data modification +that affects more than one database. +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/339811) GitLab 14.4, an automated check +prevents cross-database modifications. + +When at least two different databases are modified during a transaction initiated on any database +server, the application triggers a cross-database modification error (only in test environment). + +Example: + +```ruby +# Open transaction on Main DB +ApplicationRecord.transaction do + ci_build.update!(updated_at: Time.current) # UPDATE on CI DB + ci_build.project.update!(updated_at: Time.current) # UPDATE on Main DB +end +# raises error: Cross-database data modification of 'main, ci' were detected within +# a transaction modifying the 'ci_build, projects' tables +``` + +The code example above updates the timestamp for two records within a transaction. With the +ongoing work on the CI database decomposition, we cannot ensure the schematics of a database +transaction. +If the second update query fails, the first update query will not be +rolled back because the `ci_build` record is located on a different database server. For +more information, look at the +[transaction guidelines](transaction_guidelines.md#dangerous-example-third-party-api-calls) +page. + +#### Fixing cross-database errors + +##### Removing the transaction block + +Without an open transaction, the cross-database modification check cannot raise an error. +By making this change, we sacrifice consistency. In case of an application failure after the +first `UPDATE` query, the second `UPDATE` query will never execute. + +The same code without the `transaction` block: + +```ruby +ci_build.update!(updated_at: Time.current) # CI DB +ci_build.project.update!(updated_at: Time.current) # Main DB +``` + +##### Async processing + +If we need more guarantee that an operation finishes the work consistently we can execute it +within a background job. A background job is scheduled asynchronously and retried several times +in case of an error. There is still a very small chance of introducing inconsistency. + +Example: + +```ruby +current_time = Time.current + +MyAsyncConsistencyJob.perform_async(cu_build.id) + +ci_build.update!(updated_at: current_time) +ci_build.project.update!(updated_at: current_time) +``` + +The `MyAsyncConsistencyJob` would also attempt to update the timestamp if they differ. + +##### Aiming for perfect consistency + +At this point, we don't have the tooling (we might not even need it) to ensure similar consistency +characteristics as we had with one database. If you think that the code you're working on requires +these properties, then you can disable the cross-database modification check by wrapping to +offending database queries with a block and create a follow-up issue mentioning the sharding group +(`gitlab-org/sharding-group`). + +```ruby +Gitlab::Database.allow_cross_joins_across_databases(url: 'gitlab issue URL') do + ApplicationRecord.transaction do + ci_build.update!(updated_at: Time.current) # UPDATE on CI DB + ci_build.project.update!(updated_at: Time.current) # UPDATE on Main DB + end +end +``` + +Don't hesitate to reach out to the +[sharding group](https://about.gitlab.com/handbook/engineering/development/enablement/sharding) +for advice. + ## `config/database.yml` GitLab will support running multiple databases in the future, for example to [separate tables for the continuous integration features](https://gitlab.com/groups/gitlab-org/-/epics/6167) from the main database. In order to prepare for this change, we [validate the structure of the configuration](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67877) in `database.yml` to ensure that only known databases are used. diff --git a/doc/user/award_emojis.md b/doc/user/award_emojis.md index de250bc5fb4..88651688779 100644 --- a/doc/user/award_emojis.md +++ b/doc/user/award_emojis.md @@ -6,11 +6,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Award emoji **(FREE)** -> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/1825) in GitLab 8.2. -> - GitLab 9.0 [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9570) the usage of native emoji if the platform -> supports them and falls back to images or CSS sprites. This change greatly -> improved award emoji performance overall. - When you're collaborating online, you get fewer opportunities for high-fives and thumbs-ups. Emoji can be awarded to [issues](project/issues/index.md), [merge requests](project/merge_requests/index.md), [snippets](snippets.md), and anywhere you can have a thread. @@ -24,8 +19,6 @@ For information on the relevant API, see [Award Emoji API](../api/award_emoji.md ## Sort issues and merge requests on vote count -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/2781) in GitLab 8.5. - You can quickly sort issues and merge requests by the number of votes they have received. The sort options can be found in the dropdown menu as "Most popular" and "Least popular". @@ -38,8 +31,6 @@ downvotes. ## Award emoji for comments -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4291) in GitLab 8.9. - Award emoji can also be applied to individual comments when you want to celebrate an accomplishment or agree with an opinion. diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md index 23765de8f46..6db059bd82b 100644 --- a/doc/user/gitlab_com/index.md +++ b/doc/user/gitlab_com/index.md @@ -139,7 +139,7 @@ the related documentation. | [Max pipelines per schedule](../../administration/instance_limits.md#limit-the-number-of-pipelines-created-by-a-pipeline-schedule-per-day) | `24` for Free tier, `288` for all paid tiers | Unlimited | | [Scheduled Job Archival](../../user/admin_area/settings/continuous_integration.md#archive-jobs) | 3 months | Never | | Max test cases per [unit test report](../../ci/unit_test_reports.md) | `500_000` | Unlimited | -| [Max registered runners](../../administration/instance_limits.md#number-of-registered-runners-per-scope) | `50` per-project and per-group for Free tier,
`1_000` per-group for all paid tiers / `1_000` per-project for all paid tiers | `1_000` per-group / `1_000` per-project | +| [Max registered runners](../../administration/instance_limits.md#number-of-registered-runners-per-scope) | Free tier: `50` per-group / `50` per-project
All paid tiers: `1_000` per-group / `1_000` per-project | `1_000` per-group / `1_000` per-project | ## Account and limit settings diff --git a/doc/user/project/labels.md b/doc/user/project/labels.md index 27688c9082a..e9cbe012110 100644 --- a/doc/user/project/labels.md +++ b/doc/user/project/labels.md @@ -156,8 +156,6 @@ to the project: ## Scoped labels **(PREMIUM)** -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9175) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.10. - Scoped labels allow teams to use the label feature to annotate issues, merge requests and epics with mutually exclusive labels. This can enable more complicated workflows by preventing certain labels from being used together. @@ -241,14 +239,14 @@ to label notifications for the project only, or the whole group. ## Label priority -> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/14189) in GitLab 8.9. -> - Priority sorting is based on the highest priority label only. [This discussion](https://gitlab.com/gitlab-org/gitlab/-/issues/14523) considers changing this. - Labels can have relative priorities, which are used in the **Label priority** and **Priority** sort orders of issues and merge request list pages. Prioritization for both group and project labels happens at the project level, and cannot be done from the group label list. +NOTE: +Priority sorting is based on the highest priority label only. [This discussion](https://gitlab.com/gitlab-org/gitlab/-/issues/14523) considers changing this. + From the project label list page, star a label to indicate that it has a priority. ![Labels prioritized](img/labels_prioritized_v13_5.png) diff --git a/doc/user/todos.md b/doc/user/todos.md index f0601db0300..9a985664ed1 100644 --- a/doc/user/todos.md +++ b/doc/user/todos.md @@ -7,8 +7,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w # To-Do List **(FREE)** -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/2817) in GitLab 8.5. - Your *To-Do List* is a chronological list of items waiting for your input. The items are known as *to-do items*. @@ -67,8 +65,6 @@ You can manually add an item to your To-Do List. ## Create a to-do item by directly addressing someone -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7926) in GitLab 9.0. - You can create a to-do item by directly addressing someone at the start of a line. For example, in the following comment: diff --git a/lib/gitlab/application_context.rb b/lib/gitlab/application_context.rb index 760f1352256..aa33f56582b 100644 --- a/lib/gitlab/application_context.rb +++ b/lib/gitlab/application_context.rb @@ -124,7 +124,10 @@ module Gitlab strong_memoize(:runner_project) do next unless runner&.project_type? - projects = runner.projects.take(2) # rubocop: disable CodeReuse/ActiveRecord + projects = ::Gitlab::Database.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/342147') do + runner.projects.take(2) # rubocop: disable CodeReuse/ActiveRecord + end + projects.first if projects.one? end end diff --git a/lib/gitlab/feature_categories.rb b/lib/gitlab/feature_categories.rb new file mode 100644 index 00000000000..d06f3b14fed --- /dev/null +++ b/lib/gitlab/feature_categories.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +module Gitlab + class FeatureCategories + FEATURE_CATEGORY_DEFAULT = 'unknown' + + attr_reader :categories + + def self.default + @default ||= self.load_from_yaml + end + + def self.load_from_yaml + categories = YAML.load_file(Rails.root.join('config', 'feature_categories.yml')) + + new(categories) + end + + def initialize(categories) + @categories = categories.to_set + end + + # If valid, returns a feature category from the given request. + def from_request(request) + category = request.headers["HTTP_X_GITLAB_FEATURE_CATEGORY"].presence + + return unless category && valid?(category) + + return unless ::Gitlab::RequestForgeryProtection.verified?(request.env) + + category + end + + def valid?(category) + categories.include?(category.to_s) + end + end +end diff --git a/lib/gitlab/graphql/board/issues_connection_extension.rb b/lib/gitlab/graphql/board/issues_connection_extension.rb new file mode 100644 index 00000000000..9dcd8c92592 --- /dev/null +++ b/lib/gitlab/graphql/board/issues_connection_extension.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true +module Gitlab + module Graphql + module Board + class IssuesConnectionExtension < GraphQL::Schema::Field::ConnectionExtension + def after_resolve(value:, object:, context:, **rest) + ::Boards::Issues::ListService + .initialize_relative_positions(object.list.board, context[:current_user], value.nodes) + + value + end + end + end + end +end diff --git a/lib/gitlab/graphql/connection_collection_methods.rb b/lib/gitlab/graphql/connection_collection_methods.rb index 0e2c4a98bb6..2818a9d4e88 100644 --- a/lib/gitlab/graphql/connection_collection_methods.rb +++ b/lib/gitlab/graphql/connection_collection_methods.rb @@ -6,7 +6,7 @@ module Gitlab extend ActiveSupport::Concern included do - delegate :to_a, :size, :include?, :empty?, to: :nodes + delegate :to_a, :size, :map, :include?, :empty?, to: :nodes end end end diff --git a/lib/gitlab/import_export/group/import_export.yml b/lib/gitlab/import_export/group/import_export.yml index c2a1c60e927..f7ab1677001 100644 --- a/lib/gitlab/import_export/group/import_export.yml +++ b/lib/gitlab/import_export/group/import_export.yml @@ -10,7 +10,6 @@ tree: - labels: - :priorities - boards: - - :milestone - lists: - label: - :priorities diff --git a/lib/gitlab/metrics/requests_rack_middleware.rb b/lib/gitlab/metrics/requests_rack_middleware.rb index 324d05b6a84..3a0e34d5615 100644 --- a/lib/gitlab/metrics/requests_rack_middleware.rb +++ b/lib/gitlab/metrics/requests_rack_middleware.rb @@ -15,7 +15,7 @@ module Gitlab HEALTH_ENDPOINT = %r{^/-/(liveness|readiness|health|metrics)/?$}.freeze - FEATURE_CATEGORY_DEFAULT = 'unknown' + FEATURE_CATEGORY_DEFAULT = ::Gitlab::FeatureCategories::FEATURE_CATEGORY_DEFAULT ENDPOINT_MISSING = 'unknown' # These were the top 5 categories at a point in time, chosen as a diff --git a/lib/gitlab/metrics/web_transaction.rb b/lib/gitlab/metrics/web_transaction.rb index 3ebfcc43b0b..544c142f7bb 100644 --- a/lib/gitlab/metrics/web_transaction.rb +++ b/lib/gitlab/metrics/web_transaction.rb @@ -57,10 +57,6 @@ module Gitlab action = "#{controller.action_name}" - # Try to get the feature category, but don't fail when the controller is - # not an ApplicationController. - feature_category = controller.class.try(:feature_category_for_action, action).to_s - # Devise exposes a method called "request_format" that does the below. # However, this method is not available to all controllers (e.g. certain # Doorkeeper controllers). As such we use the underlying code directly. @@ -91,9 +87,6 @@ module Gitlab if route path = endpoint_paths_cache[route.request_method][route.path] - grape_class = endpoint.options[:for] - feature_category = grape_class.try(:feature_category_for_app, endpoint).to_s - { controller: 'Grape', action: "#{route.request_method} #{path}", feature_category: feature_category } end end @@ -109,6 +102,10 @@ module Gitlab def endpoint_instrumentable_path(raw_path) raw_path.sub('(.:format)', '').sub('/:version', '') end + + def feature_category + ::Gitlab::ApplicationContext.current_context_attribute(:feature_category) || ::Gitlab::FeatureCategories::FEATURE_CATEGORY_DEFAULT + end end end end diff --git a/lib/gitlab/pagination/keyset/in_operator_optimization/query_builder.rb b/lib/gitlab/pagination/keyset/in_operator_optimization/query_builder.rb index c4cf6dfbf88..53faf8469f2 100644 --- a/lib/gitlab/pagination/keyset/in_operator_optimization/query_builder.rb +++ b/lib/gitlab/pagination/keyset/in_operator_optimization/query_builder.rb @@ -6,8 +6,6 @@ module Gitlab module InOperatorOptimization # rubocop: disable CodeReuse/ActiveRecord class QueryBuilder - UnsupportedScopeOrder = Class.new(StandardError) - RECURSIVE_CTE_NAME = 'recursive_keyset_cte' # This class optimizes slow database queries (PostgreSQL specific) where the @@ -44,14 +42,7 @@ module Gitlab def initialize(scope:, array_scope:, array_mapping_scope:, finder_query: nil, values: {}) @scope, success = Gitlab::Pagination::Keyset::SimpleOrderBuilder.build(scope) - unless success - error_message = <<~MSG - The order on the scope does not support keyset pagination. You might need to define a custom Order object.\n - See https://docs.gitlab.com/ee/development/database/keyset_pagination.html#complex-order-configuration\n - Or the Gitlab::Pagination::Keyset::Order class for examples - MSG - raise(UnsupportedScopeOrder, error_message) - end + raise(UnsupportedScopeOrder) unless success @order = Gitlab::Pagination::Keyset::Order.extract_keyset_order_object(scope) @array_scope = array_scope diff --git a/lib/gitlab/pagination/keyset/iterator.rb b/lib/gitlab/pagination/keyset/iterator.rb index f54ade6ca66..bcd17fd0d34 100644 --- a/lib/gitlab/pagination/keyset/iterator.rb +++ b/lib/gitlab/pagination/keyset/iterator.rb @@ -4,11 +4,9 @@ module Gitlab module Pagination module Keyset class Iterator - UnsupportedScopeOrder = Class.new(StandardError) - def initialize(scope:, cursor: {}, use_union_optimization: true, in_operator_optimization_options: nil) @scope, success = Gitlab::Pagination::Keyset::SimpleOrderBuilder.build(scope) - raise(UnsupportedScopeOrder, 'The order on the scope does not support keyset pagination') unless success + raise(UnsupportedScopeOrder) unless success @cursor = cursor @order = Gitlab::Pagination::Keyset::Order.extract_keyset_order_object(scope) diff --git a/lib/gitlab/pagination/keyset/paginator.rb b/lib/gitlab/pagination/keyset/paginator.rb index 1c71549d86a..1ff4589d8e1 100644 --- a/lib/gitlab/pagination/keyset/paginator.rb +++ b/lib/gitlab/pagination/keyset/paginator.rb @@ -19,8 +19,6 @@ module Gitlab FORWARD_DIRECTION = 'n' BACKWARD_DIRECTION = 'p' - UnsupportedScopeOrder = Class.new(StandardError) - # scope - ActiveRecord::Relation object with order by clause # cursor - Encoded cursor attributes as String. Empty value will requests the first page. # per_page - Number of items per page. @@ -167,7 +165,7 @@ module Gitlab def build_scope(scope) keyset_aware_scope, success = Gitlab::Pagination::Keyset::SimpleOrderBuilder.build(scope) - raise(UnsupportedScopeOrder, 'The order on the scope does not support keyset pagination') unless success + raise(UnsupportedScopeOrder) unless success keyset_aware_scope end diff --git a/lib/gitlab/pagination/keyset/unsupported_scope_order.rb b/lib/gitlab/pagination/keyset/unsupported_scope_order.rb new file mode 100644 index 00000000000..1571c00e130 --- /dev/null +++ b/lib/gitlab/pagination/keyset/unsupported_scope_order.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Gitlab + module Pagination + module Keyset + class UnsupportedScopeOrder < StandardError + DEFAULT_ERROR_MESSAGE = <<~MSG + The order on the scope does not support keyset pagination. You might need to define a custom Order object.\n + See https://docs.gitlab.com/ee/development/database/keyset_pagination.html#complex-order-configuration\n + Or the Gitlab::Pagination::Keyset::Order class for examples + MSG + + def message + DEFAULT_ERROR_MESSAGE + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb index ba41285ebca..b928eae62e6 100644 --- a/qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb +++ b/qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb @@ -2,7 +2,7 @@ module QA RSpec.describe 'Configure', except: { job: 'review-qa-*' } do - describe 'Kubernetes Cluster Integration', :requires_admin, :skip_live_env, :smoke do + describe 'Kubernetes Cluster Integration', :orchestrated, :requires_admin, :skip_live_env do context 'Project Clusters' do let!(:cluster) { Service::KubernetesCluster.new(provider_class: Service::ClusterProvider::K3s).create! } let(:project) do diff --git a/spec/controllers/graphql_controller_spec.rb b/spec/controllers/graphql_controller_spec.rb index aed97a01a72..6e7bcfdaa08 100644 --- a/spec/controllers/graphql_controller_spec.rb +++ b/spec/controllers/graphql_controller_spec.rb @@ -38,6 +38,14 @@ RSpec.describe GraphqlController do sign_in(user) end + it 'sets feature category in ApplicationContext from request' do + request.headers["HTTP_X_GITLAB_FEATURE_CATEGORY"] = "web_ide" + + post :execute + + expect(::Gitlab::ApplicationContext.current_context_attribute(:feature_category)).to eq('web_ide') + end + it 'returns 200 when user can access API' do post :execute diff --git a/spec/factories/ci/pipelines.rb b/spec/factories/ci/pipelines.rb index 7548167efae..ae3404a41a2 100644 --- a/spec/factories/ci/pipelines.rb +++ b/spec/factories/ci/pipelines.rb @@ -18,6 +18,10 @@ FactoryBot.define do transient { child_of { nil } } transient { upstream_of { nil } } + before(:create) do |pipeline, evaluator| + pipeline.ensure_project_iid! + end + after(:build) do |pipeline, evaluator| if evaluator.child_of pipeline.project = evaluator.child_of.project @@ -48,7 +52,6 @@ FactoryBot.define do transient { ci_ref_presence { true } } before(:create) do |pipeline, evaluator| - pipeline.ensure_project_iid! pipeline.ensure_ci_ref! if evaluator.ci_ref_presence && pipeline.ci_ref_id.nil? end diff --git a/spec/graphql/resolvers/board_list_issues_resolver_spec.rb b/spec/graphql/resolvers/board_list_issues_resolver_spec.rb index b9ba2634c8f..53d2c8a853c 100644 --- a/spec/graphql/resolvers/board_list_issues_resolver_spec.rb +++ b/spec/graphql/resolvers/board_list_issues_resolver_spec.rb @@ -31,12 +31,11 @@ RSpec.describe Resolvers::BoardListIssuesResolver do end.to raise_error(Gitlab::Graphql::Errors::ArgumentError) end - it 'returns issues in the correct order with non-nil relative positions', :aggregate_failures do + it 'returns the issues in the correct order' do # by relative_position and then ID result = resolve_board_list_issues expect(result.map(&:id)).to eq [issue1.id, issue3.id, issue2.id, issue4.id] - expect(result.map(&:relative_position)).not_to include(nil) end it 'finds only issues matching filters' do @@ -119,6 +118,6 @@ RSpec.describe Resolvers::BoardListIssuesResolver do end def resolve_board_list_issues(args: {}, current_user: user) - resolve(described_class, obj: list, args: args, ctx: { current_user: current_user }).items + resolve(described_class, obj: list, args: args, ctx: { current_user: current_user }) end end diff --git a/spec/graphql/types/base_field_spec.rb b/spec/graphql/types/base_field_spec.rb index 82efd618e38..31d07f701e8 100644 --- a/spec/graphql/types/base_field_spec.rb +++ b/spec/graphql/types/base_field_spec.rb @@ -154,6 +154,17 @@ RSpec.describe Types::BaseField do end end + describe '#resolve' do + context "late_extensions is given" do + it 'registers the late extensions after the regular extensions' do + extension_class = Class.new(GraphQL::Schema::Field::ConnectionExtension) + field = described_class.new(name: 'test', type: GraphQL::Types::String.connection_type, null: true, late_extensions: [extension_class]) + + expect(field.extensions.last.class).to be(extension_class) + end + end + end + describe '#description' do context 'feature flag given' do let(:field) { described_class.new(name: 'test', type: GraphQL::Types::String, feature_flag: flag, null: false, description: 'Test description.') } diff --git a/spec/graphql/types/board_list_type_spec.rb b/spec/graphql/types/board_list_type_spec.rb index 7976936fc1f..4149dd1de50 100644 --- a/spec/graphql/types/board_list_type_spec.rb +++ b/spec/graphql/types/board_list_type_spec.rb @@ -10,4 +10,12 @@ RSpec.describe GitlabSchema.types['BoardList'] do expect(described_class).to include_graphql_fields(*expected_fields) end + + describe 'issues field' do + subject { described_class.fields['issues'] } + + it 'has a correct extension' do + is_expected.to have_graphql_extension(Gitlab::Graphql::Board::IssuesConnectionExtension) + end + end end diff --git a/spec/lib/gitlab/database/partitioning_spec.rb b/spec/lib/gitlab/database/partitioning_spec.rb index e539a8d0917..486af9413e8 100644 --- a/spec/lib/gitlab/database/partitioning_spec.rb +++ b/spec/lib/gitlab/database/partitioning_spec.rb @@ -45,4 +45,10 @@ RSpec.describe Gitlab::Database::Partitioning do described_class.drop_detached_partitions end end + + context 'ensure that the registered models have partitioning strategy' do + it 'fails when partitioning_strategy is not specified for the model' do + expect(described_class.registered_models).to all(respond_to(:partitioning_strategy)) + end + end end diff --git a/spec/lib/gitlab/feature_categories_spec.rb b/spec/lib/gitlab/feature_categories_spec.rb new file mode 100644 index 00000000000..daced154a69 --- /dev/null +++ b/spec/lib/gitlab/feature_categories_spec.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +require 'fast_spec_helper' + +RSpec.describe Gitlab::FeatureCategories do + let(:fake_categories) { %w(foo bar) } + + subject { described_class.new(fake_categories) } + + describe "#valid?" do + it "returns true if category is known", :aggregate_failures do + expect(subject.valid?('foo')).to be(true) + expect(subject.valid?('zzz')).to be(false) + end + end + + describe "#from_request" do + let(:request_env) { {} } + let(:verified) { true } + + def fake_request(request_feature_category) + double('request', env: request_env, headers: { "HTTP_X_GITLAB_FEATURE_CATEGORY" => request_feature_category }) + end + + before do + allow(::Gitlab::RequestForgeryProtection).to receive(:verified?).with(request_env).and_return(verified) + end + + it "returns category from request when valid, otherwise returns nil", :aggregate_failures do + expect(subject.from_request(fake_request("foo"))).to be("foo") + expect(subject.from_request(fake_request("zzz"))).to be_nil + end + + context "when request is not verified" do + let(:verified) { false } + + it "returns nil" do + expect(subject.from_request(fake_request("foo"))).to be_nil + end + end + end + + describe "#categories" do + it "returns a set of the given categories" do + expect(subject.categories).to be_a(Set) + expect(subject.categories).to contain_exactly(*fake_categories) + end + end + + describe ".load_from_yaml" do + subject { described_class.load_from_yaml } + + it "creates FeatureCategories from feature_categories.yml file" do + contents = YAML.load_file(Rails.root.join('config', 'feature_categories.yml')) + + expect(subject.categories).to contain_exactly(*contents) + end + end + + describe ".default" do + it "returns a memoization of load_from_yaml", :aggregate_failures do + # FeatureCategories.default could have been referenced in another spec, so we need to clean it up here + described_class.instance_variable_set(:@default, nil) + + expect(described_class).to receive(:load_from_yaml).once.and_call_original + + 2.times { described_class.default } + + # Uses reference equality to verify memoization + expect(described_class.default).to equal(described_class.default) + expect(described_class.default).to be_a(described_class) + end + end +end diff --git a/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb b/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb index 0a829d00855..192c0c7d02f 100644 --- a/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb +++ b/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb @@ -348,7 +348,7 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do end it 'has every label in config/feature_categories.yml' do - defaults = [described_class::FEATURE_CATEGORY_DEFAULT, 'not_owned'] + defaults = [::Gitlab::FeatureCategories::FEATURE_CATEGORY_DEFAULT, 'not_owned'] feature_categories = YAML.load_file(Rails.root.join('config', 'feature_categories.yml')).map(&:strip) + defaults expect(described_class::FEATURE_CATEGORIES_TO_INITIALIZE).to all(be_in(feature_categories)) diff --git a/spec/lib/gitlab/metrics/web_transaction_spec.rb b/spec/lib/gitlab/metrics/web_transaction_spec.rb index 5261d04c879..9e22dccb2a2 100644 --- a/spec/lib/gitlab/metrics/web_transaction_spec.rb +++ b/spec/lib/gitlab/metrics/web_transaction_spec.rb @@ -32,7 +32,7 @@ RSpec.describe Gitlab::Metrics::WebTransaction do it 'measures with correct labels and value' do value = 1 - expect(prometheus_metric).to receive(metric_method).with({ controller: 'TestController', action: 'show', feature_category: '' }, value) + expect(prometheus_metric).to receive(metric_method).with({ controller: 'TestController', action: 'show', feature_category: ::Gitlab::FeatureCategories::FEATURE_CATEGORY_DEFAULT }, value) transaction.send(metric_method, :bau, value) end @@ -105,6 +105,9 @@ RSpec.describe Gitlab::Metrics::WebTransaction do namespace: "/projects") env['api.endpoint'] = endpoint + + # This is needed since we're not actually making a request, which would trigger the controller pushing to the context + ::Gitlab::ApplicationContext.push(feature_category: 'projects') end it 'provides labels with the method and path of the route in the grape endpoint' do @@ -129,7 +132,7 @@ RSpec.describe Gitlab::Metrics::WebTransaction do include_context 'ActionController request' it 'tags a transaction with the name and action of a controller' do - expect(transaction.labels).to eq({ controller: 'TestController', action: 'show', feature_category: '' }) + expect(transaction.labels).to eq({ controller: 'TestController', action: 'show', feature_category: ::Gitlab::FeatureCategories::FEATURE_CATEGORY_DEFAULT }) end it 'contains only the labels defined for transactions' do @@ -140,7 +143,7 @@ RSpec.describe Gitlab::Metrics::WebTransaction do let(:request) { double(:request, format: double(:format, ref: :json)) } it 'appends the mime type to the transaction action' do - expect(transaction.labels).to eq({ controller: 'TestController', action: 'show.json', feature_category: '' }) + expect(transaction.labels).to eq({ controller: 'TestController', action: 'show.json', feature_category: ::Gitlab::FeatureCategories::FEATURE_CATEGORY_DEFAULT }) end end @@ -148,13 +151,15 @@ RSpec.describe Gitlab::Metrics::WebTransaction do let(:request) { double(:request, format: double(:format, ref: 'http://example.com')) } it 'does not append the MIME type to the transaction action' do - expect(transaction.labels).to eq({ controller: 'TestController', action: 'show', feature_category: '' }) + expect(transaction.labels).to eq({ controller: 'TestController', action: 'show', feature_category: ::Gitlab::FeatureCategories::FEATURE_CATEGORY_DEFAULT }) end end context 'when the feature category is known' do it 'includes it in the feature category label' do - expect(controller_class).to receive(:feature_category_for_action).with('show').and_return(:source_code_management) + # This is needed since we're not actually making a request, which would trigger the controller pushing to the context + ::Gitlab::ApplicationContext.push(feature_category: 'source_code_management') + expect(transaction.labels).to eq({ controller: 'TestController', action: 'show', feature_category: "source_code_management" }) end end 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 008241b8055..241c658441b 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 @@ -30,7 +30,7 @@ RSpec.describe 'get board lists' do nodes { lists { nodes { - issues(filters: {labelName: "#{label2.title}"}) { + issues(filters: {labelName: "#{label2.title}"}, first: 3) { count nodes { #{all_graphql_fields_for('issues'.classify)} @@ -44,6 +44,10 @@ RSpec.describe 'get board lists' do ) end + def issue_id + issues_data.map { |i| i['id'] } + end + def issue_titles issues_data.map { |i| i['title'] } end @@ -60,6 +64,7 @@ RSpec.describe 'get board lists' do let!(:issue3) { create(:issue, project: issue_project, labels: [label, label2], relative_position: nil) } let!(:issue4) { create(:issue, project: issue_project, labels: [label], relative_position: 9) } let!(:issue5) { create(:issue, project: issue_project, labels: [label2], relative_position: 432) } + let!(:issue6) { create(:issue, project: issue_project, labels: [label, label2], relative_position: nil) } context 'when the user does not have access to the board' do it 'returns nil' do @@ -72,14 +77,19 @@ RSpec.describe 'get board lists' do context 'when user can read the board' do before do board_parent.add_reporter(user) + post_graphql(query("id: \"#{global_id_of(label_list)}\""), current_user: user) end it 'can access the issues', :aggregate_failures do - post_graphql(query("id: \"#{global_id_of(label_list)}\""), current_user: user) - + # ties for relative positions are broken by id in ascending order by default expect(issue_titles).to eq([issue2.title, issue1.title, issue3.title]) expect(issue_relative_positions).not_to include(nil) end + + it 'does not set the relative positions of the issues not being returned', :aggregate_failures do + expect(issue_id).not_to include(issue6.id) + expect(issue3.relative_position).to be_nil + end end end diff --git a/spec/services/ci/register_job_service_spec.rb b/spec/services/ci/register_job_service_spec.rb index 73ff15ec393..d1a7b2a822b 100644 --- a/spec/services/ci/register_job_service_spec.rb +++ b/spec/services/ci/register_job_service_spec.rb @@ -87,19 +87,25 @@ module Ci end context 'for specific runner' do - context 'with FF disabled' do + context 'with tables decoupling disabled' do before do stub_feature_flags( ci_pending_builds_project_runners_decoupling: false, ci_queueing_builds_enabled_checks: false) end + around do |example| + allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/332952') do + example.run + end + end + it 'does not pick a build' do expect(execute(specific_runner)).to be_nil end end - context 'with FF enabled' do + context 'with tables decoupling enabled' do before do stub_feature_flags( ci_pending_builds_project_runners_decoupling: true, @@ -266,17 +272,23 @@ module Ci context 'and uses project runner' do let(:build) { execute(specific_runner) } - context 'with FF disabled' do + context 'with tables decoupling disabled' do before do stub_feature_flags( ci_pending_builds_project_runners_decoupling: false, ci_queueing_builds_enabled_checks: false) end + around do |example| + allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/332952') do + example.run + end + end + it { expect(build).to be_nil } end - context 'with FF enabled' do + context 'with tables decoupling enabled' do before do stub_feature_flags( ci_pending_builds_project_runners_decoupling: true, @@ -791,6 +803,12 @@ module Ci stub_feature_flags(ci_queueing_denormalize_shared_runners_information: false) end + around do |example| + allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/332952') do + example.run + end + end + include_examples 'handles runner assignment' end @@ -807,6 +825,12 @@ module Ci stub_feature_flags(ci_queueing_denormalize_tags_information: false) end + around do |example| + allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/332952') do + example.run + end + end + include_examples 'handles runner assignment' end @@ -815,6 +839,12 @@ module Ci stub_feature_flags(ci_queueing_denormalize_namespace_traversal_ids: false) end + around do |example| + allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/332952') do + example.run + end + end + include_examples 'handles runner assignment' end end @@ -824,6 +854,12 @@ module Ci stub_feature_flags(ci_pending_builds_queue_source: false) end + around do |example| + allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/332952') do + example.run + end + end + include_examples 'handles runner assignment' end end diff --git a/spec/support/database/cross-database-modification-allowlist.yml b/spec/support/database/cross-database-modification-allowlist.yml new file mode 100644 index 00000000000..87126bdcdc8 --- /dev/null +++ b/spec/support/database/cross-database-modification-allowlist.yml @@ -0,0 +1,1340 @@ +- "./ee/spec/controllers/admin/geo/nodes_controller_spec.rb" +- "./ee/spec/controllers/admin/geo/projects_controller_spec.rb" +- "./ee/spec/controllers/admin/projects_controller_spec.rb" +- "./ee/spec/controllers/concerns/internal_redirect_spec.rb" +- "./ee/spec/controllers/ee/projects/jobs_controller_spec.rb" +- "./ee/spec/controllers/oauth/geo_auth_controller_spec.rb" +- "./ee/spec/controllers/projects/approver_groups_controller_spec.rb" +- "./ee/spec/controllers/projects/approvers_controller_spec.rb" +- "./ee/spec/controllers/projects/merge_requests_controller_spec.rb" +- "./ee/spec/controllers/projects/merge_requests/creations_controller_spec.rb" +- "./ee/spec/controllers/projects/settings/access_tokens_controller_spec.rb" +- "./ee/spec/controllers/projects/subscriptions_controller_spec.rb" +- "./ee/spec/features/account_recovery_regular_check_spec.rb" +- "./ee/spec/features/admin/admin_audit_logs_spec.rb" +- "./ee/spec/features/admin/admin_credentials_inventory_spec.rb" +- "./ee/spec/features/admin/admin_dashboard_spec.rb" +- "./ee/spec/features/admin/admin_dev_ops_report_spec.rb" +- "./ee/spec/features/admin/admin_merge_requests_approvals_spec.rb" +- "./ee/spec/features/admin/admin_reset_pipeline_minutes_spec.rb" +- "./ee/spec/features/admin/admin_sends_notification_spec.rb" +- "./ee/spec/features/admin/admin_settings_spec.rb" +- "./ee/spec/features/admin/admin_show_new_user_signups_cap_alert_spec.rb" +- "./ee/spec/features/admin/admin_users_spec.rb" +- "./ee/spec/features/admin/geo/admin_geo_nodes_spec.rb" +- "./ee/spec/features/admin/geo/admin_geo_projects_spec.rb" +- "./ee/spec/features/admin/geo/admin_geo_replication_nav_spec.rb" +- "./ee/spec/features/admin/geo/admin_geo_sidebar_spec.rb" +- "./ee/spec/features/admin/geo/admin_geo_uploads_spec.rb" +- "./ee/spec/features/admin/groups/admin_changes_plan_spec.rb" +- "./ee/spec/features/admin/licenses/admin_uploads_license_spec.rb" +- "./ee/spec/features/admin/licenses/show_user_count_threshold_spec.rb" +- "./ee/spec/features/admin/subscriptions/admin_views_subscription_spec.rb" +- "./ee/spec/features/analytics/code_analytics_spec.rb" +- "./ee/spec/features/billings/billing_plans_spec.rb" +- "./ee/spec/features/billings/extend_reactivate_trial_spec.rb" +- "./ee/spec/features/billings/qrtly_reconciliation_alert_spec.rb" +- "./ee/spec/features/boards/boards_licensed_features_spec.rb" +- "./ee/spec/features/boards/boards_spec.rb" +- "./ee/spec/features/boards/group_boards/board_deletion_spec.rb" +- "./ee/spec/features/boards/group_boards/multiple_boards_spec.rb" +- "./ee/spec/features/boards/new_issue_spec.rb" +- "./ee/spec/features/boards/scoped_issue_board_spec.rb" +- "./ee/spec/features/boards/sidebar_spec.rb" +- "./ee/spec/features/boards/swimlanes/epics_swimlanes_drag_drop_spec.rb" +- "./ee/spec/features/boards/swimlanes/epics_swimlanes_filtering_spec.rb" +- "./ee/spec/features/boards/swimlanes/epics_swimlanes_sidebar_labels_spec.rb" +- "./ee/spec/features/boards/swimlanes/epics_swimlanes_sidebar_spec.rb" +- "./ee/spec/features/boards/swimlanes/epics_swimlanes_spec.rb" +- "./ee/spec/features/boards/user_adds_lists_to_board_spec.rb" +- "./ee/spec/features/boards/user_visits_board_spec.rb" +- "./ee/spec/features/burndown_charts_spec.rb" +- "./ee/spec/features/burnup_charts_spec.rb" +- "./ee/spec/features/ci/ci_minutes_spec.rb" +- "./ee/spec/features/ci_shared_runner_warnings_spec.rb" +- "./ee/spec/features/clusters/create_agent_spec.rb" +- "./ee/spec/features/dashboards/activity_spec.rb" +- "./ee/spec/features/dashboards/groups_spec.rb" +- "./ee/spec/features/dashboards/issues_spec.rb" +- "./ee/spec/features/dashboards/merge_requests_spec.rb" +- "./ee/spec/features/dashboards/operations_spec.rb" +- "./ee/spec/features/dashboards/projects_spec.rb" +- "./ee/spec/features/dashboards/todos_spec.rb" +- "./ee/spec/features/discussion_comments/epic_quick_actions_spec.rb" +- "./ee/spec/features/discussion_comments/epic_spec.rb" +- "./ee/spec/features/epic_boards/epic_boards_sidebar_spec.rb" +- "./ee/spec/features/epic_boards/epic_boards_spec.rb" +- "./ee/spec/features/epic_boards/multiple_epic_boards_spec.rb" +- "./ee/spec/features/epic_boards/new_epic_spec.rb" +- "./ee/spec/features/epics/delete_epic_spec.rb" +- "./ee/spec/features/epics/epic_issues_spec.rb" +- "./ee/spec/features/epics/epic_labels_spec.rb" +- "./ee/spec/features/epics/epic_show_spec.rb" +- "./ee/spec/features/epics/epics_list_spec.rb" +- "./ee/spec/features/epics/filtered_search/visual_tokens_spec.rb" +- "./ee/spec/features/epics/gfm_autocomplete_spec.rb" +- "./ee/spec/features/epics/issue_promotion_spec.rb" +- "./ee/spec/features/epics/referencing_epics_spec.rb" +- "./ee/spec/features/epics/shortcuts_epic_spec.rb" +- "./ee/spec/features/epics/todo_spec.rb" +- "./ee/spec/features/epics/update_epic_spec.rb" +- "./ee/spec/features/epics/user_uses_quick_actions_spec.rb" +- "./ee/spec/features/geo_node_spec.rb" +- "./ee/spec/features/groups/analytics/ci_cd_analytics_spec.rb" +- "./ee/spec/features/groups/analytics/cycle_analytics/charts_spec.rb" +- "./ee/spec/features/groups/analytics/cycle_analytics/filters_and_data_spec.rb" +- "./ee/spec/features/groups/analytics/cycle_analytics/multiple_value_streams_spec.rb" +- "./ee/spec/features/groups/audit_events_spec.rb" +- "./ee/spec/features/groups/billing_spec.rb" +- "./ee/spec/features/groups/contribution_analytics_spec.rb" +- "./ee/spec/features/groups/group_overview_spec.rb" +- "./ee/spec/features/groups/group_roadmap_spec.rb" +- "./ee/spec/features/groups/group_settings_spec.rb" +- "./ee/spec/features/groups/groups_security_credentials_spec.rb" +- "./ee/spec/features/groups/hooks/user_tests_hooks_spec.rb" +- "./ee/spec/features/groups/insights_spec.rb" +- "./ee/spec/features/groups/issues_spec.rb" +- "./ee/spec/features/groups/iterations/iterations_list_spec.rb" +- "./ee/spec/features/groups/iteration_spec.rb" +- "./ee/spec/features/groups/iterations/user_creates_iteration_in_cadence_spec.rb" +- "./ee/spec/features/groups/iterations/user_edits_iteration_cadence_spec.rb" +- "./ee/spec/features/groups/iterations/user_edits_iteration_spec.rb" +- "./ee/spec/features/groups/iterations/user_views_iteration_cadence_spec.rb" +- "./ee/spec/features/groups/iterations/user_views_iteration_spec.rb" +- "./ee/spec/features/groups/ldap_group_links_spec.rb" +- "./ee/spec/features/groups/ldap_settings_spec.rb" +- "./ee/spec/features/groups/members/leave_group_spec.rb" +- "./ee/spec/features/groups/members/list_members_spec.rb" +- "./ee/spec/features/groups/members/override_ldap_memberships_spec.rb" +- "./ee/spec/features/groups/new_spec.rb" +- "./ee/spec/features/groups/push_rules_spec.rb" +- "./ee/spec/features/groups/saml_providers_spec.rb" +- "./ee/spec/features/groups/scim_token_spec.rb" +- "./ee/spec/features/groups/seat_usage/seat_usage_spec.rb" +- "./ee/spec/features/groups/security/compliance_dashboards_spec.rb" +- "./ee/spec/features/groups/settings/user_configures_insights_spec.rb" +- "./ee/spec/features/groups/settings/user_searches_in_settings_spec.rb" +- "./ee/spec/features/groups/sso_spec.rb" +- "./ee/spec/features/groups/wikis_spec.rb" +- "./ee/spec/features/groups/wiki/user_views_wiki_empty_spec.rb" +- "./ee/spec/features/ide/user_commits_changes_spec.rb" +- "./ee/spec/features/ide/user_opens_ide_spec.rb" +- "./ee/spec/features/integrations/jira/jira_issues_list_spec.rb" +- "./ee/spec/features/issues/blocking_issues_spec.rb" +- "./ee/spec/features/issues/epic_in_issue_sidebar_spec.rb" +- "./ee/spec/features/issues/filtered_search/filter_issues_by_iteration_spec.rb" +- "./ee/spec/features/issues/filtered_search/filter_issues_epic_spec.rb" +- "./ee/spec/features/issues/filtered_search/filter_issues_weight_spec.rb" +- "./ee/spec/features/issues/form_spec.rb" +- "./ee/spec/features/issues/gfm_autocomplete_ee_spec.rb" +- "./ee/spec/features/issues/issue_actions_spec.rb" +- "./ee/spec/features/issues/issue_sidebar_spec.rb" +- "./ee/spec/features/issues/move_issue_resource_weight_events_spec.rb" +- "./ee/spec/features/issues/related_issues_spec.rb" +- "./ee/spec/features/issues/resource_weight_events_spec.rb" +- "./ee/spec/features/issues/user_bulk_edits_issues_spec.rb" +- "./ee/spec/features/issues/user_edits_issue_spec.rb" +- "./ee/spec/features/issues/user_uses_quick_actions_spec.rb" +- "./ee/spec/features/issues/user_views_issues_spec.rb" +- "./ee/spec/features/labels_hierarchy_spec.rb" +- "./ee/spec/features/markdown/metrics_spec.rb" +- "./ee/spec/features/merge_requests/user_filters_by_approvers_spec.rb" +- "./ee/spec/features/merge_requests/user_resets_approvers_spec.rb" +- "./ee/spec/features/merge_requests/user_views_all_merge_requests_spec.rb" +- "./ee/spec/features/merge_request/user_approves_with_password_spec.rb" +- "./ee/spec/features/merge_request/user_creates_merge_request_spec.rb" +- "./ee/spec/features/merge_request/user_creates_merge_request_with_blocking_mrs_spec.rb" +- "./ee/spec/features/merge_request/user_creates_multiple_assignees_mr_spec.rb" +- "./ee/spec/features/merge_request/user_creates_multiple_reviewers_mr_spec.rb" +- "./ee/spec/features/merge_request/user_edits_approval_rules_mr_spec.rb" +- "./ee/spec/features/merge_request/user_edits_merge_request_blocking_mrs_spec.rb" +- "./ee/spec/features/merge_request/user_edits_multiple_assignees_mr_spec.rb" +- "./ee/spec/features/merge_request/user_edits_multiple_reviewers_mr_spec.rb" +- "./ee/spec/features/merge_request/user_merges_immediately_spec.rb" +- "./ee/spec/features/merge_request/user_merges_with_push_rules_spec.rb" +- "./ee/spec/features/merge_request/user_sees_approval_widget_spec.rb" +- "./ee/spec/features/merge_request/user_sees_closing_issues_message_spec.rb" +- "./ee/spec/features/merge_request/user_sees_merge_widget_spec.rb" +- "./ee/spec/features/merge_request/user_sees_status_checks_widget_spec.rb" +- "./ee/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb" +- "./ee/spec/features/merge_request/user_sets_approval_rules_spec.rb" +- "./ee/spec/features/merge_request/user_sets_approvers_spec.rb" +- "./ee/spec/features/merge_request/user_uses_slash_commands_spec.rb" +- "./ee/spec/features/merge_request/user_views_blocked_merge_request_spec.rb" +- "./ee/spec/features/merge_trains/user_adds_merge_request_to_merge_train_spec.rb" +- "./ee/spec/features/merge_trains/user_adds_to_merge_train_when_pipeline_succeeds_spec.rb" +- "./ee/spec/features/oncall_schedules/user_creates_schedule_spec.rb" +- "./ee/spec/features/operations_nav_link_spec.rb" +- "./ee/spec/features/profiles/account_spec.rb" +- "./ee/spec/features/profiles/billing_spec.rb" +- "./ee/spec/features/projects/audit_events_spec.rb" +- "./ee/spec/features/projects/cluster_agents_spec.rb" +- "./ee/spec/features/projects/custom_projects_template_spec.rb" +- "./ee/spec/features/projects/environments/environments_spec.rb" +- "./ee/spec/features/projects/feature_flags/feature_flag_issues_spec.rb" +- "./ee/spec/features/projects/feature_flags/user_creates_feature_flag_spec.rb" +- "./ee/spec/features/projects/feature_flags/user_deletes_feature_flag_spec.rb" +- "./ee/spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb" +- "./ee/spec/features/projects/insights_spec.rb" +- "./ee/spec/features/projects/integrations/user_activates_jira_spec.rb" +- "./ee/spec/features/projects/issues/user_creates_issue_spec.rb" +- "./ee/spec/features/projects/iterations/iteration_cadences_list_spec.rb" +- "./ee/spec/features/projects/iterations/iterations_list_spec.rb" +- "./ee/spec/features/projects/iterations/user_views_iteration_spec.rb" +- "./ee/spec/features/projects/jobs_spec.rb" +- "./ee/spec/features/projects/kerberos_clone_instructions_spec.rb" +- "./ee/spec/features/projects/licenses/maintainer_views_policies_spec.rb" +- "./ee/spec/features/projects/members/member_is_removed_from_project_spec.rb" +- "./ee/spec/features/projects/merge_requests/user_approves_merge_request_spec.rb" +- "./ee/spec/features/projects/merge_requests/user_edits_merge_request_spec.rb" +- "./ee/spec/features/projects/mirror_spec.rb" +- "./ee/spec/features/projects/new_project_from_template_spec.rb" +- "./ee/spec/features/projects/new_project_spec.rb" +- "./ee/spec/features/projects/path_locks_spec.rb" +- "./ee/spec/features/projects/pipelines/pipeline_spec.rb" +- "./ee/spec/features/projects/push_rules_spec.rb" +- "./ee/spec/features/projects/quality/test_case_create_spec.rb" +- "./ee/spec/features/projects/quality/test_case_list_spec.rb" +- "./ee/spec/features/projects/quality/test_case_show_spec.rb" +- "./ee/spec/features/projects/releases/user_views_release_spec.rb" +- "./ee/spec/features/projects/requirements_management/requirements_list_spec.rb" +- "./ee/spec/features/projects/security/dast_scanner_profiles_spec.rb" +- "./ee/spec/features/projects/security/dast_site_profiles_spec.rb" +- "./ee/spec/features/projects/security/user_creates_on_demand_scan_spec.rb" +- "./ee/spec/features/projects/security/user_views_security_configuration_spec.rb" +- "./ee/spec/features/projects/services/prometheus_custom_metrics_spec.rb" +- "./ee/spec/features/projects/services/user_activates_github_spec.rb" +- "./ee/spec/features/projects/settings/disable_merge_trains_setting_spec.rb" +- "./ee/spec/features/projects/settings/ee/repository_mirrors_settings_spec.rb" +- "./ee/spec/features/projects/settings/ee/service_desk_setting_spec.rb" +- "./ee/spec/features/projects/settings/issues_settings_spec.rb" +- "./ee/spec/features/projects/settings/merge_request_approvals_settings_spec.rb" +- "./ee/spec/features/projects/settings/merge_requests_settings_spec.rb" +- "./ee/spec/features/projects/settings/pipeline_subscriptions_spec.rb" +- "./ee/spec/features/projects/settings/protected_environments_spec.rb" +- "./ee/spec/features/projects/settings/user_manages_merge_pipelines_spec.rb" +- "./ee/spec/features/projects/settings/user_manages_merge_trains_spec.rb" +- "./ee/spec/features/projects_spec.rb" +- "./ee/spec/features/projects/user_applies_custom_file_template_spec.rb" +- "./ee/spec/features/projects/view_blob_with_code_owners_spec.rb" +- "./ee/spec/features/projects/wiki/user_views_wiki_empty_spec.rb" +- "./ee/spec/features/promotion_spec.rb" +- "./ee/spec/features/protected_branches_spec.rb" +- "./ee/spec/features/protected_tags_spec.rb" +- "./ee/spec/features/registrations/combined_registration_spec.rb" +- "./ee/spec/features/registrations/trial_during_signup_flow_spec.rb" +- "./ee/spec/features/registrations/user_sees_new_onboarding_flow_spec.rb" +- "./ee/spec/features/registrations/welcome_spec.rb" +- "./ee/spec/features/search/elastic/global_search_spec.rb" +- "./ee/spec/features/search/elastic/group_search_spec.rb" +- "./ee/spec/features/search/elastic/project_search_spec.rb" +- "./ee/spec/features/search/elastic/snippet_search_spec.rb" +- "./ee/spec/features/search/user_searches_for_epics_spec.rb" +- "./ee/spec/features/subscriptions/groups/edit_spec.rb" +- "./ee/spec/features/trial_registrations/signup_spec.rb" +- "./ee/spec/features/trials/capture_lead_spec.rb" +- "./ee/spec/features/trials/select_namespace_spec.rb" +- "./ee/spec/features/trials/show_trial_banner_spec.rb" +- "./ee/spec/features/users/login_spec.rb" +- "./ee/spec/finders/geo/attachment_legacy_registry_finder_spec.rb" +- "./ee/spec/finders/geo/container_repository_registry_finder_spec.rb" +- "./ee/spec/finders/geo/lfs_object_registry_finder_spec.rb" +- "./ee/spec/finders/geo/merge_request_diff_registry_finder_spec.rb" +- "./ee/spec/finders/geo/package_file_registry_finder_spec.rb" +- "./ee/spec/finders/geo/pages_deployment_registry_finder_spec.rb" +- "./ee/spec/finders/geo/pipeline_artifact_registry_finder_spec.rb" +- "./ee/spec/finders/geo/project_registry_finder_spec.rb" +- "./ee/spec/finders/merge_requests/by_approvers_finder_spec.rb" +- "./ee/spec/frontend/fixtures/analytics/value_streams.rb" +- "./ee/spec/graphql/mutations/dast_on_demand_scans/create_spec.rb" +- "./ee/spec/graphql/mutations/dast/profiles/create_spec.rb" +- "./ee/spec/graphql/mutations/dast/profiles/run_spec.rb" +- "./ee/spec/graphql/mutations/dast/profiles/update_spec.rb" +- "./ee/spec/graphql/mutations/merge_requests/accept_spec.rb" +- "./ee/spec/graphql/resolvers/geo/group_wiki_repository_registries_resolver_spec.rb" +- "./ee/spec/graphql/resolvers/geo/lfs_object_registries_resolver_spec.rb" +- "./ee/spec/graphql/resolvers/geo/merge_request_diff_registries_resolver_spec.rb" +- "./ee/spec/graphql/resolvers/geo/package_file_registries_resolver_spec.rb" +- "./ee/spec/graphql/resolvers/geo/pages_deployment_registries_resolver_spec.rb" +- "./ee/spec/graphql/resolvers/geo/pipeline_artifact_registries_resolver_spec.rb" +- "./ee/spec/graphql/resolvers/geo/snippet_repository_registries_resolver_spec.rb" +- "./ee/spec/graphql/resolvers/geo/terraform_state_version_registries_resolver_spec.rb" +- "./ee/spec/graphql/resolvers/geo/upload_registries_resolver_spec.rb" +- "./ee/spec/helpers/application_helper_spec.rb" +- "./ee/spec/helpers/ee/geo_helper_spec.rb" +- "./ee/spec/lib/analytics/devops_adoption/snapshot_calculator_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/backfill_iteration_cadence_id_for_boards_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/backfill_version_data_from_gitaly_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/create_security_setting_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/fix_ruby_object_in_audit_events_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/migrate_approver_to_approval_rules_check_progress_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/migrate_approver_to_approval_rules_in_batch_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/migrate_approver_to_approval_rules_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/migrate_devops_segments_to_groups_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/migrate_security_scans_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/move_epic_issues_after_epics_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/populate_any_approval_rule_for_merge_requests_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/populate_any_approval_rule_for_projects_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/populate_latest_pipeline_ids_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/populate_namespace_statistics_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/populate_resolved_on_default_branch_column_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/populate_uuids_for_security_findings_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/populate_vulnerability_feedback_pipeline_id_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/populate_vulnerability_historical_statistics_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/prune_orphaned_geo_events_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/remove_duplicate_cs_findings_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/remove_duplicated_cs_findings_without_vulnerability_id_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/remove_inaccessible_epic_todos_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/remove_undefined_occurrence_confidence_level_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/remove_undefined_occurrence_severity_level_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/remove_undefined_vulnerability_confidence_level_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/remove_undefined_vulnerability_severity_level_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/update_location_fingerprint_for_container_scanning_findings_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/update_vulnerabilities_from_dismissal_feedback_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/update_vulnerabilities_to_dismissed_spec.rb" +- "./ee/spec/lib/ee/gitlab/background_migration/update_vulnerability_confidence_spec.rb" +- "./ee/spec/lib/ee/gitlab/database/connection_spec.rb" +- "./ee/spec/lib/ee/gitlab/database_spec.rb" +- "./ee/spec/lib/ee/gitlab/middleware/read_only_spec.rb" +- "./ee/spec/lib/ee/gitlab/usage_data_spec.rb" +- "./ee/spec/lib/gitlab/background_migration/fix_orphan_promoted_issues_spec.rb" +- "./ee/spec/lib/gitlab/background_migration/user_mentions/create_resource_user_mention_spec.rb" +- "./ee/spec/lib/gitlab/ci/templates/Jobs/dast_default_branch_gitlab_ci_yaml_spec.rb" +- "./ee/spec/lib/gitlab/geo/base_request_spec.rb" +- "./ee/spec/lib/gitlab/geo/database_tasks_spec.rb" +- "./ee/spec/lib/gitlab/geo/event_gap_tracking_spec.rb" +- "./ee/spec/lib/gitlab/geo/geo_tasks_spec.rb" +- "./ee/spec/lib/gitlab/geo/jwt_request_decoder_spec.rb" +- "./ee/spec/lib/gitlab/geo/log_cursor/events/design_repository_updated_event_spec.rb" +- "./ee/spec/lib/gitlab/geo/log_cursor/events/job_artifact_deleted_event_spec.rb" +- "./ee/spec/lib/gitlab/geo/log_cursor/events/repository_created_event_spec.rb" +- "./ee/spec/lib/gitlab/geo/log_cursor/events/repository_updated_event_spec.rb" +- "./ee/spec/lib/gitlab/geo/oauth/login_state_spec.rb" +- "./ee/spec/lib/gitlab/geo/oauth/logout_token_spec.rb" +- "./ee/spec/lib/gitlab/geo/oauth/session_spec.rb" +- "./ee/spec/lib/gitlab/geo/registry_batcher_spec.rb" +- "./ee/spec/lib/gitlab/geo/replicable_model_spec.rb" +- "./ee/spec/lib/gitlab/geo/replication/blob_downloader_spec.rb" +- "./ee/spec/lib/gitlab/geo/replication/file_transfer_spec.rb" +- "./ee/spec/lib/gitlab/geo/replicator_spec.rb" +- "./ee/spec/lib/gitlab/git_access_spec.rb" +- "./ee/spec/lib/pseudonymizer/dumper_spec.rb" +- "./ee/spec/lib/system_check/geo/geo_database_configured_check_spec.rb" +- "./ee/spec/lib/system_check/geo/http_connection_check_spec.rb" +- "./ee/spec/lib/system_check/rake_task/geo_task_spec.rb" +- "./ee/spec/mailers/notify_spec.rb" +- "./ee/spec/migrations/20190926180443_schedule_epic_issues_after_epics_move_spec.rb" +- "./ee/spec/migrations/add_non_null_constraint_for_escalation_rule_on_pending_alert_escalations_spec.rb" +- "./ee/spec/migrations/add_unique_constraint_to_software_licenses_spec.rb" +- "./ee/spec/migrations/backfill_namespace_statistics_with_wiki_size_spec.rb" +- "./ee/spec/migrations/backfill_operations_feature_flags_iid_spec.rb" +- "./ee/spec/migrations/backfill_software_licenses_spdx_identifiers_spec.rb" +- "./ee/spec/migrations/backfill_version_author_and_created_at_spec.rb" +- "./ee/spec/migrations/cleanup_deploy_access_levels_for_removed_groups_spec.rb" +- "./ee/spec/migrations/create_elastic_reindexing_subtasks_spec.rb" +- "./ee/spec/migrations/fix_any_approver_rule_for_projects_spec.rb" +- "./ee/spec/migrations/migrate_design_notes_mentions_to_db_spec.rb" +- "./ee/spec/migrations/migrate_epic_mentions_to_db_spec.rb" +- "./ee/spec/migrations/migrate_epic_notes_mentions_to_db_spec.rb" +- "./ee/spec/migrations/migrate_license_management_artifacts_to_license_scanning_spec.rb" +- "./ee/spec/migrations/migrate_saml_identities_to_scim_identities_spec.rb" +- "./ee/spec/migrations/migrate_scim_identities_to_saml_for_new_users_spec.rb" +- "./ee/spec/migrations/migrate_vulnerability_dismissal_feedback_spec.rb" +- "./ee/spec/migrations/migrate_vulnerability_dismissals_spec.rb" +- "./ee/spec/migrations/nullify_feature_flag_plaintext_tokens_spec.rb" +- "./ee/spec/migrations/populate_vulnerability_historical_statistics_for_year_spec.rb" +- "./ee/spec/migrations/remove_creations_in_gitlab_subscription_histories_spec.rb" +- "./ee/spec/migrations/remove_cycle_analytics_total_stage_data_spec.rb" +- "./ee/spec/migrations/remove_duplicated_cs_findings_spec.rb" +- "./ee/spec/migrations/remove_duplicated_cs_findings_without_vulnerability_id_spec.rb" +- "./ee/spec/migrations/remove_schedule_and_status_null_constraints_from_pending_escalations_alert_spec.rb" +- "./ee/spec/migrations/schedule_fix_orphan_promoted_issues_spec.rb" +- "./ee/spec/migrations/schedule_fix_ruby_object_in_audit_events_spec.rb" +- "./ee/spec/migrations/schedule_merge_request_any_approval_rule_migration_spec.rb" +- "./ee/spec/migrations/schedule_populate_dismissed_state_for_vulnerabilities_spec.rb" +- "./ee/spec/migrations/schedule_populate_resolved_on_default_branch_column_spec.rb" +- "./ee/spec/migrations/schedule_populate_vulnerability_historical_statistics_spec.rb" +- "./ee/spec/migrations/schedule_project_any_approval_rule_migration_spec.rb" +- "./ee/spec/migrations/schedule_remove_inaccessible_epic_todos_spec.rb" +- "./ee/spec/migrations/schedule_sync_blocking_issues_count_spec.rb" +- "./ee/spec/migrations/schedule_uuid_population_for_security_findings2_spec.rb" +- "./ee/spec/migrations/set_report_type_for_vulnerabilities_spec.rb" +- "./ee/spec/migrations/set_resolved_state_on_vulnerabilities_spec.rb" +- "./ee/spec/migrations/update_cs_vulnerability_confidence_column_spec.rb" +- "./ee/spec/migrations/update_gitlab_subscriptions_start_at_post_eoa_spec.rb" +- "./ee/spec/migrations/update_location_fingerprint_column_for_cs_spec.rb" +- "./ee/spec/migrations/update_occurrence_severity_column_spec.rb" +- "./ee/spec/migrations/update_undefined_confidence_from_occurrences_spec.rb" +- "./ee/spec/migrations/update_undefined_confidence_from_vulnerabilities_spec.rb" +- "./ee/spec/migrations/update_vulnerability_severity_column_spec.rb" +- "./ee/spec/models/analytics/cycle_analytics/group_level_spec.rb" +- "./ee/spec/models/approval_merge_request_rule_spec.rb" +- "./ee/spec/models/approval_project_rule_spec.rb" +- "./ee/spec/models/approval_state_spec.rb" +- "./ee/spec/models/approval_wrapped_code_owner_rule_spec.rb" +- "./ee/spec/models/approval_wrapped_rule_spec.rb" +- "./ee/spec/models/approver_group_spec.rb" +- "./ee/spec/models/ci/bridge_spec.rb" +- "./ee/spec/models/ci/build_spec.rb" +- "./ee/spec/models/ci/minutes/additional_pack_spec.rb" +- "./ee/spec/models/ci/pipeline_spec.rb" +- "./ee/spec/models/ci/subscriptions/project_spec.rb" +- "./ee/spec/models/concerns/approval_rule_like_spec.rb" +- "./ee/spec/models/concerns/approver_migrate_hook_spec.rb" +- "./ee/spec/models/dora/daily_metrics_spec.rb" +- "./ee/spec/models/ee/ci/job_artifact_spec.rb" +- "./ee/spec/models/ee/ci/pipeline_artifact_spec.rb" +- "./ee/spec/models/ee/ci/runner_spec.rb" +- "./ee/spec/models/ee/merge_request_diff_spec.rb" +- "./ee/spec/models/ee/pages_deployment_spec.rb" +- "./ee/spec/models/ee/terraform/state_version_spec.rb" +- "./ee/spec/models/geo/container_repository_registry_spec.rb" +- "./ee/spec/models/geo/deleted_project_spec.rb" +- "./ee/spec/models/geo/design_registry_spec.rb" +- "./ee/spec/models/geo/job_artifact_registry_spec.rb" +- "./ee/spec/models/geo_node_namespace_link_spec.rb" +- "./ee/spec/models/geo_node_spec.rb" +- "./ee/spec/models/geo_node_status_spec.rb" +- "./ee/spec/models/geo/package_file_registry_spec.rb" +- "./ee/spec/models/geo/project_registry_spec.rb" +- "./ee/spec/models/group_member_spec.rb" +- "./ee/spec/models/group_wiki_repository_spec.rb" +- "./ee/spec/models/merge_request_spec.rb" +- "./ee/spec/models/packages/package_file_spec.rb" +- "./ee/spec/models/project_spec.rb" +- "./ee/spec/models/requirements_management/requirement_spec.rb" +- "./ee/spec/models/snippet_repository_spec.rb" +- "./ee/spec/models/upload_spec.rb" +- "./ee/spec/models/visible_approvable_spec.rb" +- "./ee/spec/policies/ci/build_policy_spec.rb" +- "./ee/spec/presenters/approval_rule_presenter_spec.rb" +- "./ee/spec/presenters/merge_request_presenter_spec.rb" +- "./ee/spec/replicators/geo/pipeline_artifact_replicator_spec.rb" +- "./ee/spec/replicators/geo/terraform_state_version_replicator_spec.rb" +- "./ee/spec/requests/api/ci/pipelines_spec.rb" +- "./ee/spec/requests/api/geo_nodes_spec.rb" +- "./ee/spec/requests/api/geo_replication_spec.rb" +- "./ee/spec/requests/api/graphql/mutations/dast_on_demand_scans/create_spec.rb" +- "./ee/spec/requests/api/graphql/mutations/dast/profiles/create_spec.rb" +- "./ee/spec/requests/api/graphql/mutations/dast/profiles/run_spec.rb" +- "./ee/spec/requests/api/graphql/mutations/dast/profiles/update_spec.rb" +- "./ee/spec/requests/api/graphql/project/pipeline/dast_profile_spec.rb" +- "./ee/spec/requests/api/merge_request_approval_rules_spec.rb" +- "./ee/spec/requests/api/merge_requests_spec.rb" +- "./ee/spec/requests/api/project_approval_rules_spec.rb" +- "./ee/spec/requests/api/project_approval_settings_spec.rb" +- "./ee/spec/requests/api/project_approvals_spec.rb" +- "./ee/spec/requests/api/project_snapshots_spec.rb" +- "./ee/spec/requests/api/status_checks_spec.rb" +- "./ee/spec/requests/api/vulnerability_findings_spec.rb" +- "./ee/spec/requests/projects/merge_requests_controller_spec.rb" +- "./ee/spec/routing/admin_routing_spec.rb" +- "./ee/spec/serializers/dashboard_operations_project_entity_spec.rb" +- "./ee/spec/serializers/ee/evidences/release_entity_spec.rb" +- "./ee/spec/serializers/ee/user_serializer_spec.rb" +- "./ee/spec/serializers/evidences/evidence_entity_spec.rb" +- "./ee/spec/serializers/merge_request_widget_entity_spec.rb" +- "./ee/spec/serializers/pipeline_serializer_spec.rb" +- "./ee/spec/services/approval_rules/create_service_spec.rb" +- "./ee/spec/services/approval_rules/finalize_service_spec.rb" +- "./ee/spec/services/approval_rules/merge_request_rule_destroy_service_spec.rb" +- "./ee/spec/services/approval_rules/params_filtering_service_spec.rb" +- "./ee/spec/services/approval_rules/project_rule_destroy_service_spec.rb" +- "./ee/spec/services/approval_rules/update_service_spec.rb" +- "./ee/spec/services/app_sec/dast/profiles/create_service_spec.rb" +- "./ee/spec/services/app_sec/dast/profiles/update_service_spec.rb" +- "./ee/spec/services/app_sec/dast/scans/create_service_spec.rb" +- "./ee/spec/services/app_sec/dast/scans/run_service_spec.rb" +- "./ee/spec/services/ci/compare_license_scanning_reports_service_spec.rb" +- "./ee/spec/services/ci/compare_metrics_reports_service_spec.rb" +- "./ee/spec/services/ci/create_pipeline_service/dast_configuration_spec.rb" +- "./ee/spec/services/ci/destroy_pipeline_service_spec.rb" +- "./ee/spec/services/ci/minutes/track_live_consumption_service_spec.rb" +- "./ee/spec/services/ci/minutes/update_build_minutes_service_spec.rb" +- "./ee/spec/services/ci/register_job_service_spec.rb" +- "./ee/spec/services/ci/retry_build_service_spec.rb" +- "./ee/spec/services/ci/run_dast_scan_service_spec.rb" +- "./ee/spec/services/ci/subscribe_bridge_service_spec.rb" +- "./ee/spec/services/ci/sync_reports_to_approval_rules_service_spec.rb" +- "./ee/spec/services/ci/trigger_downstream_subscription_service_spec.rb" +- "./ee/spec/services/dast_on_demand_scans/create_service_spec.rb" +- "./ee/spec/services/deployments/auto_rollback_service_spec.rb" +- "./ee/spec/services/ee/ci/job_artifacts/destroy_all_expired_service_spec.rb" +- "./ee/spec/services/ee/ci/job_artifacts/destroy_batch_service_spec.rb" +- "./ee/spec/services/ee/integrations/test/project_service_spec.rb" +- "./ee/spec/services/ee/issuable/destroy_service_spec.rb" +- "./ee/spec/services/ee/merge_requests/refresh_service_spec.rb" +- "./ee/spec/services/ee/merge_requests/update_service_spec.rb" +- "./ee/spec/services/ee/notification_service_spec.rb" +- "./ee/spec/services/ee/post_receive_service_spec.rb" +- "./ee/spec/services/ee/releases/create_evidence_service_spec.rb" +- "./ee/spec/services/ee/users/destroy_service_spec.rb" +- "./ee/spec/services/external_status_checks/create_service_spec.rb" +- "./ee/spec/services/external_status_checks/destroy_service_spec.rb" +- "./ee/spec/services/external_status_checks/update_service_spec.rb" +- "./ee/spec/services/geo/container_repository_sync_service_spec.rb" +- "./ee/spec/services/geo/hashed_storage_migrated_event_store_spec.rb" +- "./ee/spec/services/geo/hashed_storage_migration_service_spec.rb" +- "./ee/spec/services/geo/node_create_service_spec.rb" +- "./ee/spec/services/geo/node_status_request_service_spec.rb" +- "./ee/spec/services/geo/node_update_service_spec.rb" +- "./ee/spec/services/geo/project_housekeeping_service_spec.rb" +- "./ee/spec/services/geo/registry_consistency_service_spec.rb" +- "./ee/spec/services/geo/repositories_changed_event_store_spec.rb" +- "./ee/spec/services/geo/repository_updated_event_store_spec.rb" +- "./ee/spec/services/geo/repository_verification_reset_spec.rb" +- "./ee/spec/services/geo/repository_verification_secondary_service_spec.rb" +- "./ee/spec/services/merge_requests/merge_service_spec.rb" +- "./ee/spec/services/merge_requests/reset_approvals_service_spec.rb" +- "./ee/spec/services/merge_requests/sync_report_approver_approval_rules_spec.rb" +- "./ee/spec/services/projects/transfer_service_spec.rb" +- "./ee/spec/services/security/security_orchestration_policies/rule_schedule_service_spec.rb" +- "./ee/spec/services/todo_service_spec.rb" +- "./ee/spec/services/vulnerability_feedback/create_service_spec.rb" +- "./ee/spec/services/wiki_pages/create_service_spec.rb" +- "./ee/spec/services/wiki_pages/destroy_service_spec.rb" +- "./ee/spec/services/wiki_pages/update_service_spec.rb" +- "./ee/spec/support/shared_examples/fixtures/analytics_value_streams_shared_examples.rb" +- "./ee/spec/support/shared_examples/graphql/geo/geo_registries_resolver_shared_examples.rb" +- "./ee/spec/support/shared_examples/graphql/mutations/dast_on_demand_scans_shared_examples.rb" +- "./ee/spec/support/shared_examples/graphql/mutations/dast_on_demand_scan_with_user_abilities_shared_examples.rb" +- "./ee/spec/support/shared_examples/lib/gitlab/geo/geo_log_cursor_event_shared_examples.rb" +- "./ee/spec/support/shared_examples/lib/gitlab/geo/geo_logs_event_source_info_shared_examples.rb" +- "./ee/spec/support/shared_examples/models/concerns/blob_replicator_strategy_shared_examples.rb" +- "./ee/spec/support/shared_examples/models/concerns/replicable_model_shared_examples.rb" +- "./ee/spec/support/shared_examples/models/concerns/verifiable_replicator_shared_examples.rb" +- "./ee/spec/support/shared_examples/policies/protected_environments_shared_examples.rb" +- "./ee/spec/support/shared_examples/requests/api/project_approval_rules_api_shared_examples.rb" +- "./ee/spec/support/shared_examples/services/audit_event_logging_shared_examples.rb" +- "./ee/spec/support/shared_examples/services/build_execute_shared_examples.rb" +- "./ee/spec/support/shared_examples/services/dast_on_demand_scans_shared_examples.rb" +- "./ee/spec/support/shared_examples/services/geo_event_store_shared_examples.rb" +- "./ee/spec/tasks/geo_rake_spec.rb" +- "./ee/spec/tasks/gitlab/geo_rake_spec.rb" +- "./ee/spec/workers/geo/file_download_dispatch_worker_spec.rb" +- "./ee/spec/workers/geo/metrics_update_worker_spec.rb" +- "./ee/spec/workers/geo/prune_event_log_worker_spec.rb" +- "./ee/spec/workers/geo/registry_sync_worker_spec.rb" +- "./ee/spec/workers/geo/repository_cleanup_worker_spec.rb" +- "./ee/spec/workers/geo/repository_sync_worker_spec.rb" +- "./ee/spec/workers/geo/repository_verification/secondary/scheduler_worker_spec.rb" +- "./ee/spec/workers/geo/repository_verification/secondary/single_worker_spec.rb" +- "./ee/spec/workers/geo/verification_worker_spec.rb" +- "./ee/spec/workers/refresh_license_compliance_checks_worker_spec.rb" +- "./spec/controllers/abuse_reports_controller_spec.rb" +- "./spec/controllers/admin/spam_logs_controller_spec.rb" +- "./spec/controllers/admin/users_controller_spec.rb" +- "./spec/controllers/omniauth_callbacks_controller_spec.rb" +- "./spec/controllers/projects/issues_controller_spec.rb" +- "./spec/controllers/projects/jobs_controller_spec.rb" +- "./spec/controllers/projects/merge_requests/content_controller_spec.rb" +- "./spec/controllers/projects/merge_requests_controller_spec.rb" +- "./spec/controllers/projects/pipelines_controller_spec.rb" +- "./spec/controllers/projects/pipelines/tests_controller_spec.rb" +- "./spec/controllers/projects/settings/access_tokens_controller_spec.rb" +- "./spec/controllers/projects/tags_controller_spec.rb" +- "./spec/controllers/sent_notifications_controller_spec.rb" +- "./spec/factories_spec.rb" +- "./spec/features/action_cable_logging_spec.rb" +- "./spec/features/admin/admin_abuse_reports_spec.rb" +- "./spec/features/admin/admin_appearance_spec.rb" +- "./spec/features/admin/admin_broadcast_messages_spec.rb" +- "./spec/features/admin/admin_builds_spec.rb" +- "./spec/features/admin/admin_dev_ops_report_spec.rb" +- "./spec/features/admin/admin_disables_git_access_protocol_spec.rb" +- "./spec/features/admin/admin_disables_two_factor_spec.rb" +- "./spec/features/admin/admin_groups_spec.rb" +- "./spec/features/admin/admin_hooks_spec.rb" +- "./spec/features/admin/admin_labels_spec.rb" +- "./spec/features/admin/admin_mode/login_spec.rb" +- "./spec/features/admin/admin_mode/logout_spec.rb" +- "./spec/features/admin/admin_mode_spec.rb" +- "./spec/features/admin/admin_mode/workers_spec.rb" +- "./spec/features/admin/admin_projects_spec.rb" +- "./spec/features/admin/admin_runners_spec.rb" +- "./spec/features/admin/admin_search_settings_spec.rb" +- "./spec/features/admin/admin_serverless_domains_spec.rb" +- "./spec/features/admin/admin_settings_spec.rb" +- "./spec/features/admin/admin_users_impersonation_tokens_spec.rb" +- "./spec/features/admin/admin_uses_repository_checks_spec.rb" +- "./spec/features/admin/clusters/eks_spec.rb" +- "./spec/features/admin/dashboard_spec.rb" +- "./spec/features/admin/integrations/user_activates_mattermost_slash_command_spec.rb" +- "./spec/features/admin/users/user_spec.rb" +- "./spec/features/admin/users/users_spec.rb" +- "./spec/features/alert_management/alert_details_spec.rb" +- "./spec/features/alert_management/alert_management_list_spec.rb" +- "./spec/features/alert_management_spec.rb" +- "./spec/features/alert_management/user_filters_alerts_by_status_spec.rb" +- "./spec/features/alert_management/user_searches_alerts_spec.rb" +- "./spec/features/alert_management/user_updates_alert_status_spec.rb" +- "./spec/features/alerts_settings/user_views_alerts_settings_spec.rb" +- "./spec/features/atom/dashboard_spec.rb" +- "./spec/features/boards/boards_spec.rb" +- "./spec/features/boards/focus_mode_spec.rb" +- "./spec/features/boards/issue_ordering_spec.rb" +- "./spec/features/boards/keyboard_shortcut_spec.rb" +- "./spec/features/boards/multiple_boards_spec.rb" +- "./spec/features/boards/new_issue_spec.rb" +- "./spec/features/boards/reload_boards_on_browser_back_spec.rb" +- "./spec/features/boards/sidebar_due_date_spec.rb" +- "./spec/features/boards/sidebar_labels_in_namespaces_spec.rb" +- "./spec/features/boards/sidebar_labels_spec.rb" +- "./spec/features/boards/sidebar_milestones_spec.rb" +- "./spec/features/boards/sidebar_spec.rb" +- "./spec/features/boards/user_adds_lists_to_board_spec.rb" +- "./spec/features/boards/user_visits_board_spec.rb" +- "./spec/features/broadcast_messages_spec.rb" +- "./spec/features/calendar_spec.rb" +- "./spec/features/callouts/registration_enabled_spec.rb" +- "./spec/features/clusters/cluster_detail_page_spec.rb" +- "./spec/features/clusters/cluster_health_dashboard_spec.rb" +- "./spec/features/commit_spec.rb" +- "./spec/features/commits_spec.rb" +- "./spec/features/commits/user_uses_quick_actions_spec.rb" +- "./spec/features/contextual_sidebar_spec.rb" +- "./spec/features/cycle_analytics_spec.rb" +- "./spec/features/dashboard/activity_spec.rb" +- "./spec/features/dashboard/archived_projects_spec.rb" +- "./spec/features/dashboard/datetime_on_tooltips_spec.rb" +- "./spec/features/dashboard/group_dashboard_with_external_authorization_service_spec.rb" +- "./spec/features/dashboard/groups_list_spec.rb" +- "./spec/features/dashboard/group_spec.rb" +- "./spec/features/dashboard/issues_filter_spec.rb" +- "./spec/features/dashboard/issues_spec.rb" +- "./spec/features/dashboard/label_filter_spec.rb" +- "./spec/features/dashboard/merge_requests_spec.rb" +- "./spec/features/dashboard/milestones_spec.rb" +- "./spec/features/dashboard/project_member_activity_index_spec.rb" +- "./spec/features/dashboard/projects_spec.rb" +- "./spec/features/dashboard/root_spec.rb" +- "./spec/features/dashboard/shortcuts_spec.rb" +- "./spec/features/dashboard/snippets_spec.rb" +- "./spec/features/dashboard/todos/todos_filtering_spec.rb" +- "./spec/features/dashboard/todos/todos_spec.rb" +- "./spec/features/dashboard/user_filters_projects_spec.rb" +- "./spec/features/discussion_comments/commit_spec.rb" +- "./spec/features/discussion_comments/issue_spec.rb" +- "./spec/features/discussion_comments/merge_request_spec.rb" +- "./spec/features/discussion_comments/snippets_spec.rb" +- "./spec/features/error_pages_spec.rb" +- "./spec/features/error_tracking/user_filters_errors_by_status_spec.rb" +- "./spec/features/error_tracking/user_searches_sentry_errors_spec.rb" +- "./spec/features/error_tracking/user_sees_error_details_spec.rb" +- "./spec/features/error_tracking/user_sees_error_index_spec.rb" +- "./spec/features/expand_collapse_diffs_spec.rb" +- "./spec/features/explore/groups_list_spec.rb" +- "./spec/features/explore/groups_spec.rb" +- "./spec/features/explore/user_explores_projects_spec.rb" +- "./spec/features/file_uploads/attachment_spec.rb" +- "./spec/features/file_uploads/ci_artifact_spec.rb" +- "./spec/features/file_uploads/git_lfs_spec.rb" +- "./spec/features/file_uploads/graphql_add_design_spec.rb" +- "./spec/features/file_uploads/group_import_spec.rb" +- "./spec/features/file_uploads/maven_package_spec.rb" +- "./spec/features/file_uploads/multipart_invalid_uploads_spec.rb" +- "./spec/features/file_uploads/nuget_package_spec.rb" +- "./spec/features/file_uploads/project_import_spec.rb" +- "./spec/features/file_uploads/rubygem_package_spec.rb" +- "./spec/features/file_uploads/user_avatar_spec.rb" +- "./spec/features/frequently_visited_projects_and_groups_spec.rb" +- "./spec/features/gitlab_experiments_spec.rb" +- "./spec/features/global_search_spec.rb" +- "./spec/features/groups/activity_spec.rb" +- "./spec/features/groups/board_sidebar_spec.rb" +- "./spec/features/groups/board_spec.rb" +- "./spec/features/groups/clusters/eks_spec.rb" +- "./spec/features/groups/clusters/user_spec.rb" +- "./spec/features/groups/container_registry_spec.rb" +- "./spec/features/groups/dependency_proxy_spec.rb" +- "./spec/features/groups/empty_states_spec.rb" +- "./spec/features/groups/import_export/connect_instance_spec.rb" +- "./spec/features/groups/import_export/export_file_spec.rb" +- "./spec/features/groups/import_export/import_file_spec.rb" +- "./spec/features/groups/integrations/user_activates_mattermost_slash_command_spec.rb" +- "./spec/features/groups/issues_spec.rb" +- "./spec/features/groups/labels/index_spec.rb" +- "./spec/features/groups/labels/search_labels_spec.rb" +- "./spec/features/groups/labels/sort_labels_spec.rb" +- "./spec/features/groups/labels/subscription_spec.rb" +- "./spec/features/groups/members/filter_members_spec.rb" +- "./spec/features/groups/members/leave_group_spec.rb" +- "./spec/features/groups/members/list_members_spec.rb" +- "./spec/features/groups/members/manage_groups_spec.rb" +- "./spec/features/groups/members/manage_members_spec.rb" +- "./spec/features/groups/members/master_adds_member_with_expiration_date_spec.rb" +- "./spec/features/groups/members/master_manages_access_requests_spec.rb" +- "./spec/features/groups/members/search_members_spec.rb" +- "./spec/features/groups/members/sort_members_spec.rb" +- "./spec/features/groups/members/tabs_spec.rb" +- "./spec/features/groups/merge_requests_spec.rb" +- "./spec/features/groups/milestones/gfm_autocomplete_spec.rb" +- "./spec/features/groups/milestone_spec.rb" +- "./spec/features/groups/milestones_sorting_spec.rb" +- "./spec/features/groups/packages_spec.rb" +- "./spec/features/groups/settings/group_badges_spec.rb" +- "./spec/features/groups/settings/packages_and_registries_spec.rb" +- "./spec/features/groups/settings/repository_spec.rb" +- "./spec/features/groups/settings/user_searches_in_settings_spec.rb" +- "./spec/features/groups/show_spec.rb" +- "./spec/features/groups_spec.rb" +- "./spec/features/groups/user_browse_projects_group_page_spec.rb" +- "./spec/features/groups/user_sees_users_dropdowns_in_issuables_list_spec.rb" +- "./spec/features/help_pages_spec.rb" +- "./spec/features/ide_spec.rb" +- "./spec/features/ide/user_commits_changes_spec.rb" +- "./spec/features/ide/user_opens_merge_request_spec.rb" +- "./spec/features/import/manifest_import_spec.rb" +- "./spec/features/incidents/incident_details_spec.rb" +- "./spec/features/incidents/incidents_list_spec.rb" +- "./spec/features/incidents/user_creates_new_incident_spec.rb" +- "./spec/features/incidents/user_filters_incidents_by_status_spec.rb" +- "./spec/features/incidents/user_searches_incidents_spec.rb" +- "./spec/features/incidents/user_views_incident_spec.rb" +- "./spec/features/issuables/issuable_list_spec.rb" +- "./spec/features/issuables/markdown_references/internal_references_spec.rb" +- "./spec/features/issuables/markdown_references/jira_spec.rb" +- "./spec/features/issuables/sorting_list_spec.rb" +- "./spec/features/issuables/user_sees_sidebar_spec.rb" +- "./spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb" +- "./spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb" +- "./spec/features/issues/csv_spec.rb" +- "./spec/features/issues/discussion_lock_spec.rb" +- "./spec/features/issues/filtered_search/dropdown_assignee_spec.rb" +- "./spec/features/issues/filtered_search/dropdown_author_spec.rb" +- "./spec/features/issues/filtered_search/dropdown_base_spec.rb" +- "./spec/features/issues/filtered_search/dropdown_emoji_spec.rb" +- "./spec/features/issues/filtered_search/dropdown_hint_spec.rb" +- "./spec/features/issues/filtered_search/dropdown_label_spec.rb" +- "./spec/features/issues/filtered_search/dropdown_milestone_spec.rb" +- "./spec/features/issues/filtered_search/dropdown_release_spec.rb" +- "./spec/features/issues/filtered_search/filter_issues_spec.rb" +- "./spec/features/issues/filtered_search/recent_searches_spec.rb" +- "./spec/features/issues/filtered_search/search_bar_spec.rb" +- "./spec/features/issues/filtered_search/visual_tokens_spec.rb" +- "./spec/features/issues/form_spec.rb" +- "./spec/features/issues/gfm_autocomplete_spec.rb" +- "./spec/features/issues/group_label_sidebar_spec.rb" +- "./spec/features/issues/incident_issue_spec.rb" +- "./spec/features/issues/issue_detail_spec.rb" +- "./spec/features/issues/issue_header_spec.rb" +- "./spec/features/issues/issue_sidebar_spec.rb" +- "./spec/features/issues/keyboard_shortcut_spec.rb" +- "./spec/features/issues/markdown_toolbar_spec.rb" +- "./spec/features/issues/move_spec.rb" +- "./spec/features/issues/note_polling_spec.rb" +- "./spec/features/issues/notes_on_issues_spec.rb" +- "./spec/features/issues/related_issues_spec.rb" +- "./spec/features/issues/resource_label_events_spec.rb" +- "./spec/features/issues/service_desk_spec.rb" +- "./spec/features/issues/spam_issues_spec.rb" +- "./spec/features/issues/todo_spec.rb" +- "./spec/features/issues/user_bulk_edits_issues_labels_spec.rb" +- "./spec/features/issues/user_bulk_edits_issues_spec.rb" +- "./spec/features/issues/user_comments_on_issue_spec.rb" +- "./spec/features/issues/user_creates_branch_and_merge_request_spec.rb" +- "./spec/features/issues/user_creates_confidential_merge_request_spec.rb" +- "./spec/features/issues/user_creates_issue_by_email_spec.rb" +- "./spec/features/issues/user_creates_issue_spec.rb" +- "./spec/features/issues/user_edits_issue_spec.rb" +- "./spec/features/issues/user_filters_issues_spec.rb" +- "./spec/features/issues/user_interacts_with_awards_spec.rb" +- "./spec/features/issues/user_invites_from_a_comment_spec.rb" +- "./spec/features/issues/user_resets_their_incoming_email_token_spec.rb" +- "./spec/features/issues/user_sees_empty_state_spec.rb" +- "./spec/features/issues/user_sees_live_update_spec.rb" +- "./spec/features/issues/user_sees_sidebar_updates_in_realtime_spec.rb" +- "./spec/features/issues/user_sorts_issue_comments_spec.rb" +- "./spec/features/issues/user_sorts_issues_spec.rb" +- "./spec/features/issues/user_toggles_subscription_spec.rb" +- "./spec/features/issues/user_uses_quick_actions_spec.rb" +- "./spec/features/issues/user_views_issue_spec.rb" +- "./spec/features/issues/user_views_issues_spec.rb" +- "./spec/features/jira_connect/branches_spec.rb" +- "./spec/features/labels_hierarchy_spec.rb" +- "./spec/features/markdown/copy_as_gfm_spec.rb" +- "./spec/features/markdown/gitlab_flavored_markdown_spec.rb" +- "./spec/features/markdown/keyboard_shortcuts_spec.rb" +- "./spec/features/markdown/math_spec.rb" +- "./spec/features/markdown/mermaid_spec.rb" +- "./spec/features/markdown/metrics_spec.rb" +- "./spec/features/merge_request/batch_comments_spec.rb" +- "./spec/features/merge_request/close_reopen_report_toggle_spec.rb" +- "./spec/features/merge_request/maintainer_edits_fork_spec.rb" +- "./spec/features/merge_request/merge_request_discussion_lock_spec.rb" +- "./spec/features/merge_requests/filters_generic_behavior_spec.rb" +- "./spec/features/merge_requests/user_exports_as_csv_spec.rb" +- "./spec/features/merge_requests/user_filters_by_approvals_spec.rb" +- "./spec/features/merge_requests/user_filters_by_assignees_spec.rb" +- "./spec/features/merge_requests/user_filters_by_deployments_spec.rb" +- "./spec/features/merge_requests/user_filters_by_draft_spec.rb" +- "./spec/features/merge_requests/user_filters_by_labels_spec.rb" +- "./spec/features/merge_requests/user_filters_by_milestones_spec.rb" +- "./spec/features/merge_requests/user_filters_by_multiple_criteria_spec.rb" +- "./spec/features/merge_requests/user_filters_by_target_branch_spec.rb" +- "./spec/features/merge_requests/user_mass_updates_spec.rb" +- "./spec/features/merge_request/user_accepts_merge_request_spec.rb" +- "./spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb" +- "./spec/features/merge_request/user_approves_spec.rb" +- "./spec/features/merge_request/user_assigns_themselves_spec.rb" +- "./spec/features/merge_request/user_awards_emoji_spec.rb" +- "./spec/features/merge_request/user_clicks_merge_request_tabs_spec.rb" +- "./spec/features/merge_request/user_comments_on_commit_spec.rb" +- "./spec/features/merge_request/user_comments_on_diff_spec.rb" +- "./spec/features/merge_request/user_comments_on_merge_request_spec.rb" +- "./spec/features/merge_request/user_creates_image_diff_notes_spec.rb" +- "./spec/features/merge_request/user_creates_merge_request_spec.rb" +- "./spec/features/merge_request/user_creates_mr_spec.rb" +- "./spec/features/merge_request/user_customizes_merge_commit_message_spec.rb" +- "./spec/features/merge_request/user_edits_assignees_sidebar_spec.rb" +- "./spec/features/merge_request/user_edits_merge_request_spec.rb" +- "./spec/features/merge_request/user_edits_mr_spec.rb" +- "./spec/features/merge_request/user_edits_reviewers_sidebar_spec.rb" +- "./spec/features/merge_request/user_expands_diff_spec.rb" +- "./spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb" +- "./spec/features/merge_request/user_invites_from_a_comment_spec.rb" +- "./spec/features/merge_request/user_jumps_to_discussion_spec.rb" +- "./spec/features/merge_request/user_locks_discussion_spec.rb" +- "./spec/features/merge_request/user_manages_subscription_spec.rb" +- "./spec/features/merge_request/user_marks_merge_request_as_draft_spec.rb" +- "./spec/features/merge_request/user_merges_immediately_spec.rb" +- "./spec/features/merge_request/user_merges_merge_request_spec.rb" +- "./spec/features/merge_request/user_merges_only_if_pipeline_succeeds_spec.rb" +- "./spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb" +- "./spec/features/merge_request/user_posts_diff_notes_spec.rb" +- "./spec/features/merge_request/user_posts_notes_spec.rb" +- "./spec/features/merge_request/user_rebases_merge_request_spec.rb" +- "./spec/features/merge_request/user_resolves_conflicts_spec.rb" +- "./spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb" +- "./spec/features/merge_request/user_resolves_outdated_diff_discussions_spec.rb" +- "./spec/features/merge_request/user_resolves_wip_mr_spec.rb" +- "./spec/features/merge_request/user_reverts_merge_request_spec.rb" +- "./spec/features/merge_request/user_reviews_image_spec.rb" +- "./spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb" +- "./spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb" +- "./spec/features/merge_request/user_sees_check_out_branch_modal_spec.rb" +- "./spec/features/merge_request/user_sees_cherry_pick_modal_spec.rb" +- "./spec/features/merge_request/user_sees_closing_issues_message_spec.rb" +- "./spec/features/merge_request/user_sees_deleted_target_branch_spec.rb" +- "./spec/features/merge_request/user_sees_deployment_widget_spec.rb" +- "./spec/features/merge_request/user_sees_diff_spec.rb" +- "./spec/features/merge_request/user_sees_discussions_spec.rb" +- "./spec/features/merge_request/user_sees_merge_button_depending_on_unresolved_discussions_spec.rb" +- "./spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb" +- "./spec/features/merge_request/user_sees_merge_widget_spec.rb" +- "./spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb" +- "./spec/features/merge_request/user_sees_mr_from_deleted_forked_project_spec.rb" +- "./spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb" +- "./spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb" +- "./spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb" +- "./spec/features/merge_request/user_sees_pipelines_spec.rb" +- "./spec/features/merge_request/user_sees_suggest_pipeline_spec.rb" +- "./spec/features/merge_request/user_sees_system_notes_spec.rb" +- "./spec/features/merge_request/user_sees_versions_spec.rb" +- "./spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb" +- "./spec/features/merge_request/user_squashes_merge_request_spec.rb" +- "./spec/features/merge_request/user_suggests_changes_on_diff_spec.rb" +- "./spec/features/merge_request/user_toggles_whitespace_changes_spec.rb" +- "./spec/features/merge_request/user_uses_quick_actions_spec.rb" +- "./spec/features/merge_request/user_views_auto_expanding_diff_spec.rb" +- "./spec/features/merge_request/user_views_diffs_commit_spec.rb" +- "./spec/features/merge_request/user_views_diffs_file_by_file_spec.rb" +- "./spec/features/merge_request/user_views_diffs_spec.rb" +- "./spec/features/merge_request/user_views_open_merge_request_spec.rb" +- "./spec/features/merge_request/user_views_user_status_on_merge_request_spec.rb" +- "./spec/features/milestone_spec.rb" +- "./spec/features/milestones/user_creates_milestone_spec.rb" +- "./spec/features/milestones/user_deletes_milestone_spec.rb" +- "./spec/features/milestones/user_edits_milestone_spec.rb" +- "./spec/features/milestones/user_views_milestone_spec.rb" +- "./spec/features/milestones/user_views_milestones_spec.rb" +- "./spec/features/nav/top_nav_responsive_spec.rb" +- "./spec/features/oauth_login_spec.rb" +- "./spec/features/participants_autocomplete_spec.rb" +- "./spec/features/populate_new_pipeline_vars_with_params_spec.rb" +- "./spec/features/profiles/account_spec.rb" +- "./spec/features/profiles/active_sessions_spec.rb" +- "./spec/features/profiles/keys_spec.rb" +- "./spec/features/profiles/oauth_applications_spec.rb" +- "./spec/features/profile_spec.rb" +- "./spec/features/profiles/personal_access_tokens_spec.rb" +- "./spec/features/profiles/user_changes_notified_of_own_activity_spec.rb" +- "./spec/features/profiles/user_edit_preferences_spec.rb" +- "./spec/features/profiles/user_edit_profile_spec.rb" +- "./spec/features/profiles/user_search_settings_spec.rb" +- "./spec/features/profiles/user_visits_notifications_tab_spec.rb" +- "./spec/features/profiles/user_visits_profile_preferences_page_spec.rb" +- "./spec/features/profiles/user_visits_profile_spec.rb" +- "./spec/features/project_group_variables_spec.rb" +- "./spec/features/projects/activity/user_sees_activity_spec.rb" +- "./spec/features/projects/activity/user_sees_design_activity_spec.rb" +- "./spec/features/projects/activity/user_sees_design_comment_spec.rb" +- "./spec/features/projects/activity/user_sees_private_activity_spec.rb" +- "./spec/features/projects/artifacts/file_spec.rb" +- "./spec/features/projects/artifacts/raw_spec.rb" +- "./spec/features/projects/artifacts/user_browses_artifacts_spec.rb" +- "./spec/features/projects/badges/list_spec.rb" +- "./spec/features/projects/badges/pipeline_badge_spec.rb" +- "./spec/features/projects/blobs/balsamiq_spec.rb" +- "./spec/features/projects/blobs/blob_line_permalink_updater_spec.rb" +- "./spec/features/projects/blobs/blob_show_spec.rb" +- "./spec/features/projects/blobs/edit_spec.rb" +- "./spec/features/projects/blobs/shortcuts_blob_spec.rb" +- "./spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb" +- "./spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb" +- "./spec/features/projects/blobs/user_views_pipeline_editor_button_spec.rb" +- "./spec/features/projects/branches/new_branch_ref_dropdown_spec.rb" +- "./spec/features/projects/branches_spec.rb" +- "./spec/features/projects/branches/user_creates_branch_spec.rb" +- "./spec/features/projects/branches/user_deletes_branch_spec.rb" +- "./spec/features/projects/branches/user_views_branches_spec.rb" +- "./spec/features/projects/ci/editor_spec.rb" +- "./spec/features/projects/clusters/eks_spec.rb" +- "./spec/features/projects/clusters/gcp_spec.rb" +- "./spec/features/projects/clusters_spec.rb" +- "./spec/features/projects/clusters/user_spec.rb" +- "./spec/features/projects/commit/builds_spec.rb" +- "./spec/features/projects/commit/cherry_pick_spec.rb" +- "./spec/features/projects/commit/comments/user_adds_comment_spec.rb" +- "./spec/features/projects/commit/comments/user_deletes_comments_spec.rb" +- "./spec/features/projects/commit/comments/user_edits_comments_spec.rb" +- "./spec/features/projects/commit/diff_notes_spec.rb" +- "./spec/features/projects/commit/mini_pipeline_graph_spec.rb" +- "./spec/features/projects/commits/user_browses_commits_spec.rb" +- "./spec/features/projects/commit/user_comments_on_commit_spec.rb" +- "./spec/features/projects/commit/user_reverts_commit_spec.rb" +- "./spec/features/projects/commit/user_views_user_status_on_commit_spec.rb" +- "./spec/features/projects/compare_spec.rb" +- "./spec/features/projects/container_registry_spec.rb" +- "./spec/features/projects/deploy_keys_spec.rb" +- "./spec/features/projects/diffs/diff_show_spec.rb" +- "./spec/features/projects/environments/environment_metrics_spec.rb" +- "./spec/features/projects/environments/environment_spec.rb" +- "./spec/features/projects/environments/environments_spec.rb" +- "./spec/features/projects/environments_pod_logs_spec.rb" +- "./spec/features/projects/feature_flags/user_creates_feature_flag_spec.rb" +- "./spec/features/projects/feature_flags/user_deletes_feature_flag_spec.rb" +- "./spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb" +- "./spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb" +- "./spec/features/projects/feature_flag_user_lists/user_deletes_feature_flag_user_list_spec.rb" +- "./spec/features/projects/feature_flag_user_lists/user_edits_feature_flag_user_list_spec.rb" +- "./spec/features/projects/feature_flag_user_lists/user_sees_feature_flag_user_list_details_spec.rb" +- "./spec/features/projects/features_visibility_spec.rb" +- "./spec/features/projects/files/dockerfile_dropdown_spec.rb" +- "./spec/features/projects/files/edit_file_soft_wrap_spec.rb" +- "./spec/features/projects/files/files_sort_submodules_with_folders_spec.rb" +- "./spec/features/projects/files/find_file_keyboard_spec.rb" +- "./spec/features/projects/files/gitignore_dropdown_spec.rb" +- "./spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb" +- "./spec/features/projects/files/project_owner_creates_license_file_spec.rb" +- "./spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb" +- "./spec/features/projects/files/template_selector_menu_spec.rb" +- "./spec/features/projects/files/template_type_dropdown_spec.rb" +- "./spec/features/projects/files/undo_template_spec.rb" +- "./spec/features/projects/files/user_browses_a_tree_with_a_folder_containing_only_a_folder_spec.rb" +- "./spec/features/projects/files/user_browses_files_spec.rb" +- "./spec/features/projects/files/user_browses_lfs_files_spec.rb" +- "./spec/features/projects/files/user_creates_directory_spec.rb" +- "./spec/features/projects/files/user_creates_files_spec.rb" +- "./spec/features/projects/files/user_deletes_files_spec.rb" +- "./spec/features/projects/files/user_edits_files_spec.rb" +- "./spec/features/projects/files/user_find_file_spec.rb" +- "./spec/features/projects/files/user_reads_pipeline_status_spec.rb" +- "./spec/features/projects/files/user_replaces_files_spec.rb" +- "./spec/features/projects/files/user_uploads_files_spec.rb" +- "./spec/features/projects/fork_spec.rb" +- "./spec/features/projects/gfm_autocomplete_load_spec.rb" +- "./spec/features/projects/graph_spec.rb" +- "./spec/features/projects/import_export/export_file_spec.rb" +- "./spec/features/projects/import_export/import_file_spec.rb" +- "./spec/features/projects/infrastructure_registry_spec.rb" +- "./spec/features/projects/integrations/user_activates_asana_spec.rb" +- "./spec/features/projects/integrations/user_activates_assembla_spec.rb" +- "./spec/features/projects/integrations/user_activates_atlassian_bamboo_ci_spec.rb" +- "./spec/features/projects/integrations/user_activates_flowdock_spec.rb" +- "./spec/features/projects/integrations/user_activates_jira_spec.rb" +- "./spec/features/projects/integrations/user_activates_pivotaltracker_spec.rb" +- "./spec/features/projects/integrations/user_uses_inherited_settings_spec.rb" +- "./spec/features/projects/issuable_templates_spec.rb" +- "./spec/features/projects/issues/design_management/user_paginates_designs_spec.rb" +- "./spec/features/projects/issues/design_management/user_permissions_upload_spec.rb" +- "./spec/features/projects/issues/design_management/user_uploads_designs_spec.rb" +- "./spec/features/projects/issues/design_management/user_views_design_spec.rb" +- "./spec/features/projects/issues/design_management/user_views_designs_spec.rb" +- "./spec/features/projects/issues/design_management/user_views_designs_with_svg_xss_spec.rb" +- "./spec/features/projects/issues/email_participants_spec.rb" +- "./spec/features/projects/jobs/permissions_spec.rb" +- "./spec/features/projects/jobs_spec.rb" +- "./spec/features/projects/jobs/user_browses_job_spec.rb" +- "./spec/features/projects/jobs/user_browses_jobs_spec.rb" +- "./spec/features/projects/labels/issues_sorted_by_priority_spec.rb" +- "./spec/features/projects/labels/search_labels_spec.rb" +- "./spec/features/projects/labels/sort_labels_spec.rb" +- "./spec/features/projects/labels/subscription_spec.rb" +- "./spec/features/projects/labels/update_prioritization_spec.rb" +- "./spec/features/projects/labels/user_removes_labels_spec.rb" +- "./spec/features/projects/members/anonymous_user_sees_members_spec.rb" +- "./spec/features/projects/members/group_member_cannot_leave_group_project_spec.rb" +- "./spec/features/projects/members/group_members_spec.rb" +- "./spec/features/projects/members/group_requester_cannot_request_access_to_project_spec.rb" +- "./spec/features/projects/members/groups_with_access_list_spec.rb" +- "./spec/features/projects/members/invite_group_spec.rb" +- "./spec/features/projects/members/list_spec.rb" +- "./spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb" +- "./spec/features/projects/members/master_manages_access_requests_spec.rb" +- "./spec/features/projects/members/sorting_spec.rb" +- "./spec/features/projects/members/tabs_spec.rb" +- "./spec/features/projects/members/user_requests_access_spec.rb" +- "./spec/features/projects/merge_request_button_spec.rb" +- "./spec/features/projects/milestones/gfm_autocomplete_spec.rb" +- "./spec/features/projects/milestones/milestones_sorting_spec.rb" +- "./spec/features/projects/milestones/new_spec.rb" +- "./spec/features/projects/milestones/user_interacts_with_labels_spec.rb" +- "./spec/features/projects/network_graph_spec.rb" +- "./spec/features/projects/new_project_from_template_spec.rb" +- "./spec/features/projects/new_project_spec.rb" +- "./spec/features/projects/packages_spec.rb" +- "./spec/features/projects/pages/user_adds_domain_spec.rb" +- "./spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb" +- "./spec/features/projects/pages/user_edits_settings_spec.rb" +- "./spec/features/projects/pipeline_schedules_spec.rb" +- "./spec/features/projects/pipelines/pipeline_spec.rb" +- "./spec/features/projects/pipelines/pipelines_spec.rb" +- "./spec/features/projects/product_analytics/graphs_spec.rb" +- "./spec/features/projects/releases/user_creates_release_spec.rb" +- "./spec/features/projects/releases/user_views_edit_release_spec.rb" +- "./spec/features/projects/releases/user_views_release_spec.rb" +- "./spec/features/projects/releases/user_views_releases_spec.rb" +- "./spec/features/projects/remote_mirror_spec.rb" +- "./spec/features/projects/serverless/functions_spec.rb" +- "./spec/features/projects/services/disable_triggers_spec.rb" +- "./spec/features/projects/services/prometheus_external_alerts_spec.rb" +- "./spec/features/projects/services/user_activates_emails_on_push_spec.rb" +- "./spec/features/projects/services/user_activates_irker_spec.rb" +- "./spec/features/projects/services/user_activates_issue_tracker_spec.rb" +- "./spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb" +- "./spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb" +- "./spec/features/projects/services/user_activates_packagist_spec.rb" +- "./spec/features/projects/services/user_activates_prometheus_spec.rb" +- "./spec/features/projects/services/user_activates_pushover_spec.rb" +- "./spec/features/projects/services/user_activates_slack_notifications_spec.rb" +- "./spec/features/projects/services/user_activates_slack_slash_command_spec.rb" +- "./spec/features/projects/services/user_views_services_spec.rb" +- "./spec/features/projects/settings/access_tokens_spec.rb" +- "./spec/features/projects/settings/lfs_settings_spec.rb" +- "./spec/features/projects/settings/monitor_settings_spec.rb" +- "./spec/features/projects/settings/packages_settings_spec.rb" +- "./spec/features/projects/settings/project_badges_spec.rb" +- "./spec/features/projects/settings/project_settings_spec.rb" +- "./spec/features/projects/settings/registry_settings_spec.rb" +- "./spec/features/projects/settings/repository_settings_spec.rb" +- "./spec/features/projects/settings/service_desk_setting_spec.rb" +- "./spec/features/projects/settings/user_changes_default_branch_spec.rb" +- "./spec/features/projects/settings/user_interacts_with_deploy_keys_spec.rb" +- "./spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb" +- "./spec/features/projects/settings/user_manages_project_members_spec.rb" +- "./spec/features/projects/settings/user_searches_in_settings_spec.rb" +- "./spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb" +- "./spec/features/projects/settings/user_tags_project_spec.rb" +- "./spec/features/projects/settings/user_transfers_a_project_spec.rb" +- "./spec/features/projects/settings/visibility_settings_spec.rb" +- "./spec/features/projects/settings/webhooks_settings_spec.rb" +- "./spec/features/projects/show/schema_markup_spec.rb" +- "./spec/features/projects/show/user_interacts_with_auto_devops_banner_spec.rb" +- "./spec/features/projects/show/user_interacts_with_stars_spec.rb" +- "./spec/features/projects/show/user_manages_notifications_spec.rb" +- "./spec/features/projects/show/user_sees_collaboration_links_spec.rb" +- "./spec/features/projects/show/user_sees_last_commit_ci_status_spec.rb" +- "./spec/features/projects/show/user_sees_readme_spec.rb" +- "./spec/features/projects/show/user_uploads_files_spec.rb" +- "./spec/features/projects/snippets/create_snippet_spec.rb" +- "./spec/features/projects/snippets/show_spec.rb" +- "./spec/features/projects/snippets/user_comments_on_snippet_spec.rb" +- "./spec/features/projects/snippets/user_deletes_snippet_spec.rb" +- "./spec/features/projects/snippets/user_updates_snippet_spec.rb" +- "./spec/features/projects_spec.rb" +- "./spec/features/projects/sub_group_issuables_spec.rb" +- "./spec/features/projects/tags/user_edits_tags_spec.rb" +- "./spec/features/projects/terraform_spec.rb" +- "./spec/features/projects/tree/create_directory_spec.rb" +- "./spec/features/projects/tree/create_file_spec.rb" +- "./spec/features/projects/tree/tree_show_spec.rb" +- "./spec/features/projects/tree/upload_file_spec.rb" +- "./spec/features/projects/user_changes_project_visibility_spec.rb" +- "./spec/features/projects/user_creates_project_spec.rb" +- "./spec/features/projects/user_sees_sidebar_spec.rb" +- "./spec/features/projects/user_sees_user_popover_spec.rb" +- "./spec/features/projects/user_uses_shortcuts_spec.rb" +- "./spec/features/projects/user_views_empty_project_spec.rb" +- "./spec/features/projects/view_on_env_spec.rb" +- "./spec/features/projects/wikis_spec.rb" +- "./spec/features/projects/wiki/user_views_wiki_empty_spec.rb" +- "./spec/features/project_variables_spec.rb" +- "./spec/features/promotion_spec.rb" +- "./spec/features/protected_branches_spec.rb" +- "./spec/features/protected_tags_spec.rb" +- "./spec/features/reportable_note/commit_spec.rb" +- "./spec/features/reportable_note/issue_spec.rb" +- "./spec/features/reportable_note/merge_request_spec.rb" +- "./spec/features/reportable_note/snippets_spec.rb" +- "./spec/features/runners_spec.rb" +- "./spec/features/search/user_searches_for_code_spec.rb" +- "./spec/features/search/user_searches_for_commits_spec.rb" +- "./spec/features/search/user_searches_for_issues_spec.rb" +- "./spec/features/search/user_searches_for_merge_requests_spec.rb" +- "./spec/features/search/user_searches_for_milestones_spec.rb" +- "./spec/features/search/user_searches_for_projects_spec.rb" +- "./spec/features/search/user_searches_for_users_spec.rb" +- "./spec/features/search/user_searches_for_wiki_pages_spec.rb" +- "./spec/features/search/user_uses_header_search_field_spec.rb" +- "./spec/features/search/user_uses_search_filters_spec.rb" +- "./spec/features/signed_commits_spec.rb" +- "./spec/features/snippets/embedded_snippet_spec.rb" +- "./spec/features/snippets/internal_snippet_spec.rb" +- "./spec/features/snippets/notes_on_personal_snippets_spec.rb" +- "./spec/features/snippets/private_snippets_spec.rb" +- "./spec/features/snippets/public_snippets_spec.rb" +- "./spec/features/snippets/show_spec.rb" +- "./spec/features/snippets/user_creates_snippet_spec.rb" +- "./spec/features/snippets/user_deletes_snippet_spec.rb" +- "./spec/features/snippets/user_edits_snippet_spec.rb" +- "./spec/features/tags/developer_creates_tag_spec.rb" +- "./spec/features/tags/developer_deletes_tag_spec.rb" +- "./spec/features/tags/developer_updates_tag_spec.rb" +- "./spec/features/task_lists_spec.rb" +- "./spec/features/triggers_spec.rb" +- "./spec/features/u2f_spec.rb" +- "./spec/features/uploads/user_uploads_avatar_to_profile_spec.rb" +- "./spec/features/uploads/user_uploads_file_to_note_spec.rb" +- "./spec/features/user_can_display_performance_bar_spec.rb" +- "./spec/features/user_opens_link_to_comment_spec.rb" +- "./spec/features/user_sees_revert_modal_spec.rb" +- "./spec/features/users/login_spec.rb" +- "./spec/features/users/logout_spec.rb" +- "./spec/features/users/overview_spec.rb" +- "./spec/features/users/signup_spec.rb" +- "./spec/features/users/snippets_spec.rb" +- "./spec/features/users/terms_spec.rb" +- "./spec/features/users/user_browses_projects_on_user_page_spec.rb" +- "./spec/features/webauthn_spec.rb" +- "./spec/features/whats_new_spec.rb" +- "./spec/finders/ci/pipeline_schedules_finder_spec.rb" +- "./spec/finders/ci/pipelines_finder_spec.rb" +- "./spec/finders/ci/pipelines_for_merge_request_finder_spec.rb" +- "./spec/finders/projects_finder_spec.rb" +- "./spec/finders/releases/evidence_pipeline_finder_spec.rb" +- "./spec/frontend/fixtures/analytics.rb" +- "./spec/frontend/fixtures/jobs.rb" +- "./spec/frontend/fixtures/pipeline_schedules.rb" +- "./spec/frontend/fixtures/pipelines.rb" +- "./spec/graphql/mutations/design_management/upload_spec.rb" +- "./spec/graphql/mutations/merge_requests/accept_spec.rb" +- "./spec/graphql/resolvers/ci/test_report_summary_resolver_spec.rb" +- "./spec/helpers/issuables_helper_spec.rb" +- "./spec/initializers/active_record_locking_spec.rb" +- "./spec/initializers/database_config_spec.rb" +- "./spec/lib/gitlab/auth_spec.rb" +- "./spec/lib/gitlab/ci/badge/pipeline/status_spec.rb" +- "./spec/lib/gitlab/ci/build/policy/changes_spec.rb" +- "./spec/lib/gitlab/ci/charts_spec.rb" +- "./spec/lib/gitlab/ci/config_spec.rb" +- "./spec/lib/gitlab/ci/pipeline/chain/create_spec.rb" +- "./spec/lib/gitlab/ci/pipeline/chain/seed_block_spec.rb" +- "./spec/lib/gitlab/ci/pipeline/seed/build_spec.rb" +- "./spec/lib/gitlab/ci/pipeline/seed/stage_spec.rb" +- "./spec/lib/gitlab/ci/status/stage/common_spec.rb" +- "./spec/lib/gitlab/ci/status/stage/factory_spec.rb" +- "./spec/lib/gitlab/ci/status/stage/play_manual_spec.rb" +- "./spec/lib/gitlab/ci/templates/5_minute_production_app_ci_yaml_spec.rb" +- "./spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb" +- "./spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb" +- "./spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb" +- "./spec/lib/gitlab/ci/templates/managed_cluster_applications_gitlab_ci_yaml_spec.rb" +- "./spec/lib/gitlab/database/bulk_update_spec.rb" +- "./spec/lib/gitlab/database/connection_spec.rb" +- "./spec/lib/gitlab/database/load_balancing/host_spec.rb" +- "./spec/lib/gitlab/database/load_balancing_spec.rb" +- "./spec/lib/gitlab/database/postgresql_adapter/force_disconnectable_mixin_spec.rb" +- "./spec/lib/gitlab/database/postgresql_adapter/type_map_cache_spec.rb" +- "./spec/lib/gitlab/database/schema_migrations/context_spec.rb" +- "./spec/lib/gitlab/database/with_lock_retries_outside_transaction_spec.rb" +- "./spec/lib/gitlab/database/with_lock_retries_spec.rb" +- "./spec/lib/gitlab/data_builder/pipeline_spec.rb" +- "./spec/lib/gitlab/email/handler/create_issue_handler_spec.rb" +- "./spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb" +- "./spec/lib/gitlab/email/handler/create_note_handler_spec.rb" +- "./spec/lib/gitlab/email/handler/create_note_on_issuable_handler_spec.rb" +- "./spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb" +- "./spec/lib/gitlab/usage_data_spec.rb" +- "./spec/lib/peek/views/active_record_spec.rb" +- "./spec/mailers/emails/pipelines_spec.rb" +- "./spec/migrations/20210205174154_remove_bad_dependency_proxy_manifests_spec.rb" +- "./spec/migrations/20210722150102_operations_feature_flags_correct_flexible_rollout_values_spec.rb" +- "./spec/migrations/backfill_escalation_policies_for_oncall_schedules_spec.rb" +- "./spec/migrations/insert_ci_daily_pipeline_schedule_triggers_plan_limits_spec.rb" +- "./spec/migrations/remove_duplicate_dast_site_tokens_with_same_token_spec.rb" +- "./spec/models/ci/bridge_spec.rb" +- "./spec/models/ci/build_need_spec.rb" +- "./spec/models/ci/build_spec.rb" +- "./spec/models/ci/build_trace_chunk_spec.rb" +- "./spec/models/ci/commit_with_pipeline_spec.rb" +- "./spec/models/ci/group_spec.rb" +- "./spec/models/ci/group_variable_spec.rb" +- "./spec/models/ci/instance_variable_spec.rb" +- "./spec/models/ci/job_artifact_spec.rb" +- "./spec/models/ci/job_variable_spec.rb" +- "./spec/models/ci/legacy_stage_spec.rb" +- "./spec/models/ci/pipeline_schedule_spec.rb" +- "./spec/models/ci/pipeline_spec.rb" +- "./spec/models/ci/runner_namespace_spec.rb" +- "./spec/models/ci/runner_project_spec.rb" +- "./spec/models/ci/runner_spec.rb" +- "./spec/models/ci/running_build_spec.rb" +- "./spec/models/ci/stage_spec.rb" +- "./spec/models/ci/variable_spec.rb" +- "./spec/models/clusters/applications/jupyter_spec.rb" +- "./spec/models/clusters/applications/runner_spec.rb" +- "./spec/models/commit_collection_spec.rb" +- "./spec/models/commit_status_spec.rb" +- "./spec/models/concerns/batch_destroy_dependent_associations_spec.rb" +- "./spec/models/concerns/bulk_insertable_associations_spec.rb" +- "./spec/models/concerns/cron_schedulable_spec.rb" +- "./spec/models/concerns/has_environment_scope_spec.rb" +- "./spec/models/concerns/schedulable_spec.rb" +- "./spec/models/concerns/token_authenticatable_spec.rb" +- "./spec/models/design_management/version_spec.rb" +- "./spec/models/environment_status_spec.rb" +- "./spec/models/hooks/system_hook_spec.rb" +- "./spec/models/issue_spec.rb" +- "./spec/models/members/project_member_spec.rb" +- "./spec/models/merge_request_spec.rb" +- "./spec/models/plan_spec.rb" +- "./spec/models/project_feature_usage_spec.rb" +- "./spec/models/project_spec.rb" +- "./spec/models/spam_log_spec.rb" +- "./spec/models/user_spec.rb" +- "./spec/models/user_status_spec.rb" +- "./spec/policies/ci/build_policy_spec.rb" +- "./spec/policies/ci/pipeline_policy_spec.rb" +- "./spec/presenters/ci/stage_presenter_spec.rb" +- "./spec/requests/api/admin/ci/variables_spec.rb" +- "./spec/requests/api/admin/plan_limits_spec.rb" +- "./spec/requests/api/ci/jobs_spec.rb" +- "./spec/requests/api/ci/pipeline_schedules_spec.rb" +- "./spec/requests/api/ci/pipelines_spec.rb" +- "./spec/requests/api/ci/runner/runners_post_spec.rb" +- "./spec/requests/api/ci/runners_spec.rb" +- "./spec/requests/api/commits_spec.rb" +- "./spec/requests/api/commit_statuses_spec.rb" +- "./spec/requests/api/graphql/ci/runner_spec.rb" +- "./spec/requests/api/graphql/mutations/ci/pipeline_destroy_spec.rb" +- "./spec/requests/api/graphql/project/merge_request_spec.rb" +- "./spec/requests/api/graphql/project_query_spec.rb" +- "./spec/requests/api/issues/issues_spec.rb" +- "./spec/requests/api/merge_requests_spec.rb" +- "./spec/requests/api/projects_spec.rb" +- "./spec/requests/api/resource_access_tokens_spec.rb" +- "./spec/requests/api/users_spec.rb" +- "./spec/requests/lfs_http_spec.rb" +- "./spec/requests/projects/cycle_analytics_events_spec.rb" +- "./spec/serializers/ci/downloadable_artifact_entity_spec.rb" +- "./spec/serializers/ci/downloadable_artifact_serializer_spec.rb" +- "./spec/serializers/ci/pipeline_entity_spec.rb" +- "./spec/serializers/merge_request_poll_cached_widget_entity_spec.rb" +- "./spec/serializers/merge_request_poll_widget_entity_spec.rb" +- "./spec/serializers/merge_request_widget_entity_spec.rb" +- "./spec/serializers/pipeline_details_entity_spec.rb" +- "./spec/serializers/pipeline_serializer_spec.rb" +- "./spec/serializers/stage_entity_spec.rb" +- "./spec/serializers/stage_serializer_spec.rb" +- "./spec/serializers/test_report_entity_spec.rb" +- "./spec/serializers/test_report_summary_entity_spec.rb" +- "./spec/serializers/test_suite_entity_spec.rb" +- "./spec/serializers/test_suite_summary_entity_spec.rb" +- "./spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb" +- "./spec/services/ci/compare_accessibility_reports_service_spec.rb" +- "./spec/services/ci/compare_codequality_reports_service_spec.rb" +- "./spec/services/ci/compare_reports_base_service_spec.rb" +- "./spec/services/ci/compare_test_reports_service_spec.rb" +- "./spec/services/ci/create_pipeline_service/environment_spec.rb" +- "./spec/services/ci/create_pipeline_service_spec.rb" +- "./spec/services/ci/destroy_pipeline_service_spec.rb" +- "./spec/services/ci/disable_user_pipeline_schedules_service_spec.rb" +- "./spec/services/ci/ensure_stage_service_spec.rb" +- "./spec/services/ci/expire_pipeline_cache_service_spec.rb" +- "./spec/services/ci/generate_codequality_mr_diff_report_service_spec.rb" +- "./spec/services/ci/generate_coverage_reports_service_spec.rb" +- "./spec/services/ci/job_artifacts/destroy_all_expired_service_spec.rb" +- "./spec/services/ci/job_artifacts/destroy_associations_service_spec.rb" +- "./spec/services/ci/job_artifacts/destroy_batch_service_spec.rb" +- "./spec/services/ci/pipeline_artifacts/coverage_report_service_spec.rb" +- "./spec/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service_spec.rb" +- "./spec/services/ci/pipeline_bridge_status_service_spec.rb" +- "./spec/services/ci/pipeline_processing/shared_processing_service.rb" +- "./spec/services/ci/pipelines/add_job_service_spec.rb" +- "./spec/services/ci/pipeline_schedule_service_spec.rb" +- "./spec/services/ci/pipeline_trigger_service_spec.rb" +- "./spec/services/ci/register_job_service_spec.rb" +- "./spec/services/ci/retry_build_service_spec.rb" +- "./spec/services/ci/test_failure_history_service_spec.rb" +- "./spec/services/ci/update_instance_variables_service_spec.rb" +- "./spec/services/deployments/update_environment_service_spec.rb" +- "./spec/services/design_management/save_designs_service_spec.rb" +- "./spec/services/environments/stop_service_spec.rb" +- "./spec/services/groups/transfer_service_spec.rb" +- "./spec/services/integrations/test/project_service_spec.rb" +- "./spec/services/issuable/destroy_service_spec.rb" +- "./spec/services/issue_links/list_service_spec.rb" +- "./spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb" +- "./spec/services/merge_requests/mergeability_check_service_spec.rb" +- "./spec/services/merge_requests/post_merge_service_spec.rb" +- "./spec/services/merge_requests/refresh_service_spec.rb" +- "./spec/services/pages/migrate_from_legacy_storage_service_spec.rb" +- "./spec/services/projects/destroy_service_spec.rb" +- "./spec/services/projects/transfer_service_spec.rb" +- "./spec/services/projects/update_service_spec.rb" +- "./spec/services/releases/create_service_spec.rb" +- "./spec/services/resource_access_tokens/revoke_service_spec.rb" +- "./spec/services/todo_service_spec.rb" +- "./spec/services/users/activity_service_spec.rb" +- "./spec/services/users/destroy_service_spec.rb" +- "./spec/services/users/reject_service_spec.rb" +- "./spec/support/shared_contexts/email_shared_context.rb" +- "./spec/support/shared_examples/controllers/access_tokens_controller_shared_examples.rb" +- "./spec/support/shared_examples/features/master_manages_access_requests_shared_example.rb" +- "./spec/support/shared_examples/integrations/test_examples.rb" +- "./spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb" +- "./spec/support/shared_examples/models/cluster_application_status_shared_examples.rb" +- "./spec/support/shared_examples/models/cluster_application_version_shared_examples.rb" +- "./spec/support/shared_examples/models/concerns/cron_schedulable_shared_examples.rb" +- "./spec/support/shared_examples/models/concerns/limitable_shared_examples.rb" +- "./spec/support/shared_examples/models/update_highest_role_shared_examples.rb" +- "./spec/support/shared_examples/models/update_project_statistics_shared_examples.rb" +- "./spec/support/shared_examples/models/with_uploads_shared_examples.rb" +- "./spec/support/shared_examples/requests/api/status_shared_examples.rb" +- "./spec/support/shared_examples/requests/lfs_http_shared_examples.rb" +- "./spec/support/shared_examples/services/destroy_label_links_shared_examples.rb" +- "./spec/support/shared_examples/services/issuable/destroy_service_shared_examples.rb" +- "./spec/support/shared_examples/services/notification_service_shared_examples.rb" +- "./spec/support/shared_examples/services/wiki_pages/create_service_shared_examples.rb" +- "./spec/support/shared_examples/services/wiki_pages/destroy_service_shared_examples.rb" +- "./spec/support/shared_examples/services/wiki_pages/update_service_shared_examples.rb" +- "./spec/support/shared_examples/workers/idempotency_shared_examples.rb" +- "./spec/views/projects/artifacts/_artifact.html.haml_spec.rb" +- "./spec/views/projects/commits/_commit.html.haml_spec.rb" +- "./spec/views/projects/jobs/_build.html.haml_spec.rb" +- "./spec/views/projects/jobs/_generic_commit_status.html.haml_spec.rb" +- "./spec/views/projects/merge_requests/creations/_new_submit.html.haml_spec.rb" +- "./spec/views/projects/pipeline_schedules/_pipeline_schedule.html.haml_spec.rb" +- "./spec/views/shared/runners/_runner_details.html.haml_spec.rb" +- "./spec/workers/authorized_project_update/user_refresh_from_replica_worker_spec.rb" +- "./spec/workers/ci/pipeline_artifacts/create_quality_report_worker_spec.rb" +- "./spec/workers/container_expiration_policy_worker_spec.rb" +- "./spec/workers/merge_requests/create_pipeline_worker_spec.rb" +- "./spec/workers/pipeline_metrics_worker_spec.rb" +- "./spec/workers/pipeline_schedule_worker_spec.rb" +- "./spec/workers/releases/create_evidence_worker_spec.rb" +- "./spec/workers/remove_expired_members_worker_spec.rb" +- "./spec/workers/repository_cleanup_worker_spec.rb" +- "./spec/workers/stage_update_worker_spec.rb" +- "./spec/workers/stuck_merge_jobs_worker_spec.rb" diff --git a/spec/support/database/cross-join-allowlist.yml b/spec/support/database/cross-join-allowlist.yml index 53cc565181c..de4d2f8156a 100644 --- a/spec/support/database/cross-join-allowlist.yml +++ b/spec/support/database/cross-join-allowlist.yml @@ -81,7 +81,6 @@ - "./spec/presenters/ci/build_runner_presenter_spec.rb" - "./spec/presenters/ci/pipeline_presenter_spec.rb" - "./spec/presenters/packages/detail/package_presenter_spec.rb" -- "./spec/requests/api/ci/runner/jobs_request_post_spec.rb" - "./spec/requests/api/ci/runner/runners_post_spec.rb" - "./spec/requests/api/ci/runners_spec.rb" - "./spec/requests/api/commit_statuses_spec.rb" @@ -105,7 +104,6 @@ - "./spec/services/ci/job_artifacts/destroy_all_expired_service_spec.rb" - "./spec/services/ci/job_artifacts/destroy_associations_service_spec.rb" - "./spec/services/ci/job_artifacts/destroy_batch_service_spec.rb" -- "./spec/services/ci/register_job_service_spec.rb" - "./spec/services/deployments/older_deployments_drop_service_spec.rb" - "./spec/services/environments/stop_service_spec.rb" - "./spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb" diff --git a/spec/support/database/prevent_cross_database_modification.rb b/spec/support/database/prevent_cross_database_modification.rb index b4c968e3c41..744e082de64 100644 --- a/spec/support/database/prevent_cross_database_modification.rb +++ b/spec/support/database/prevent_cross_database_modification.rb @@ -33,8 +33,10 @@ module Database end def cleanup_with_cross_database_modification_prevented - ActiveSupport::Notifications.unsubscribe(PreventCrossDatabaseModification.cross_database_context[:subscriber]) - PreventCrossDatabaseModification.cross_database_context[:enabled] = false + if PreventCrossDatabaseModification.cross_database_context + ActiveSupport::Notifications.unsubscribe(PreventCrossDatabaseModification.cross_database_context[:subscriber]) + PreventCrossDatabaseModification.cross_database_context[:enabled] = false + end end end @@ -55,8 +57,11 @@ module Database end def self.prevent_cross_database_modification!(connection, sql) + return unless cross_database_context return unless cross_database_context[:enabled] + return if connection.pool.instance_of?(ActiveRecord::ConnectionAdapters::NullPool) + database = connection.pool.db_config.name if sql.start_with?('SAVEPOINT') @@ -87,7 +92,7 @@ module Database if schemas.many? raise Database::PreventCrossDatabaseModification::CrossDatabaseModificationAcrossUnsupportedTablesError, "Cross-database data modification of '#{schemas.to_a.join(", ")}' were detected within " \ - "a transaction modifying the '#{all_tables.to_a.join(", ")}'" + "a transaction modifying the '#{all_tables.to_a.join(", ")}' tables" end end end @@ -96,16 +101,20 @@ end Gitlab::Database.singleton_class.prepend( Database::PreventCrossDatabaseModification::GitlabDatabaseMixin) +CROSS_DB_MODIFICATION_ALLOW_LIST = Set.new(YAML.load_file(File.join(__dir__, 'cross-database-modification-allowlist.yml'))).freeze + RSpec.configure do |config| config.include(::Database::PreventCrossDatabaseModification::SpecHelpers) # Using before and after blocks because the around block causes problems with the let_it_be # record creations. It makes an extra savepoint which breaks the transaction count logic. - config.before(:each, :prevent_cross_database_modification) do - with_cross_database_modification_prevented + config.before do |example_file| + if CROSS_DB_MODIFICATION_ALLOW_LIST.exclude?(example_file.file_path) + with_cross_database_modification_prevented + end end - config.after(:each, :prevent_cross_database_modification) do + config.after do |example_file| cleanup_with_cross_database_modification_prevented end end diff --git a/spec/support/database/prevent_cross_joins.rb b/spec/support/database/prevent_cross_joins.rb index c21f92d3baf..1bedee77570 100644 --- a/spec/support/database/prevent_cross_joins.rb +++ b/spec/support/database/prevent_cross_joins.rb @@ -64,6 +64,10 @@ module Database ensure ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber end + + def allow_cross_joins_across_databases(url:, &block) + ::Gitlab::Database.allow_cross_joins_across_databases(url: url, &block) + end end module GitlabDatabaseMixin diff --git a/spec/support/shared_examples/graphql/connection_shared_examples.rb b/spec/support/shared_examples/graphql/connection_shared_examples.rb index 4cba5b5a69d..895bab1f51a 100644 --- a/spec/support/shared_examples/graphql/connection_shared_examples.rb +++ b/spec/support/shared_examples/graphql/connection_shared_examples.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true RSpec.shared_examples 'a connection with collection methods' do - %i[to_a size include? empty?].each do |method_name| + %i[to_a size map include? empty?].each do |method_name| it "responds to #{method_name}" do expect(connection).to respond_to(method_name) end diff --git a/workhorse/internal/upstream/routes.go b/workhorse/internal/upstream/routes.go index 8c85c5144e5..07bbd57421e 100644 --- a/workhorse/internal/upstream/routes.go +++ b/workhorse/internal/upstream/routes.go @@ -56,6 +56,7 @@ const ( apiPattern = `^/api/` ciAPIPattern = `^/ci/api/` gitProjectPattern = `^/.+\.git/` + geoGitProjectPattern = `^/[^-].+\.git/` // Prevent matching routes like /-/push_from_secondary projectPattern = `^/([^/]+/){1,}[^/]+/` apiProjectPattern = apiPattern + `v4/projects/[^/]+/` // API: Projects can be encoded via group%2Fsubgroup%2Fproject snippetUploadPattern = `^/uploads/personal_snippet` @@ -348,10 +349,9 @@ func configureRoutes(u *upstream) { // pulls are performed against a different source of truth. Ideally, we'd // proxy/redirect pulls as well, when the secondary is not up-to-date. // - u.route("GET", gitProjectPattern+`info/refs\z`, git.GetInfoRefsHandler(api)), - u.route("POST", gitProjectPattern+`git-upload-pack\z`, contentEncodingHandler(git.UploadPack(api)), withMatcher(isContentType("application/x-git-upload-pack-request"))), - u.route("POST", gitProjectPattern+`git-receive-pack\z`, contentEncodingHandler(git.ReceivePack(api)), withMatcher(isContentType("application/x-git-receive-pack-request"))), - u.route("PUT", gitProjectPattern+`gitlab-lfs/objects/([0-9a-f]{64})/([0-9]+)\z`, lfs.PutStore(api, signingProxy, preparers.lfs), withMatcher(isContentType("application/octet-stream"))), + u.route("GET", geoGitProjectPattern+`info/refs\z`, git.GetInfoRefsHandler(api)), + u.route("POST", geoGitProjectPattern+`git-upload-pack\z`, contentEncodingHandler(git.UploadPack(api)), withMatcher(isContentType("application/x-git-upload-pack-request"))), + u.route("GET", geoGitProjectPattern+`gitlab-lfs/objects/([0-9a-f]{64})\z`, defaultUpstream), // Serve health checks from this Geo secondary u.route("", "^/-/(readiness|liveness)$", static.DeployPage(probeUpstream)), diff --git a/workhorse/internal/upstream/upstream_test.go b/workhorse/internal/upstream/upstream_test.go index efc85dd6c2e..3c942767384 100644 --- a/workhorse/internal/upstream/upstream_test.go +++ b/workhorse/internal/upstream/upstream_test.go @@ -99,6 +99,8 @@ func TestGeoProxyFeatureEnabledOnGeoSecondarySite(t *testing.T) { defer wsDeferredClose() testCases := []testCase{ + {"push from secondary is forwarded", "/-/push_from_secondary/foo/bar.git/info/refs", "Geo primary received request to path /-/push_from_secondary/foo/bar.git/info/refs"}, + {"LFS files are served locally", "/group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6", "Local Rails server received request to path /group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6"}, {"jobs request is forwarded", "/api/v4/jobs/request", "Geo primary received request to path /api/v4/jobs/request"}, {"health check is served locally", "/-/health", "Local Rails server received request to path /-/health"}, {"unknown route is forwarded", "/anything", "Geo primary received request to path /anything"}, @@ -117,6 +119,7 @@ func TestGeoProxyFeatureDisabledOnNonGeoSecondarySite(t *testing.T) { defer wsDeferredClose() testCases := []testCase{ + {"LFS files are served locally", "/group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6", "Local Rails server received request to path /group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6"}, {"jobs request is served locally", "/api/v4/jobs/request", "Local Rails server received request to path /api/v4/jobs/request"}, {"health check is served locally", "/-/health", "Local Rails server received request to path /-/health"}, {"unknown route is served locally", "/anything", "Local Rails server received request to path /anything"}, @@ -134,6 +137,7 @@ func TestGeoProxyFeatureEnabledOnNonGeoSecondarySite(t *testing.T) { defer wsDeferredClose() testCases := []testCase{ + {"LFS files are served locally", "/group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6", "Local Rails server received request to path /group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6"}, {"jobs request is served locally", "/api/v4/jobs/request", "Local Rails server received request to path /api/v4/jobs/request"}, {"health check is served locally", "/-/health", "Local Rails server received request to path /-/health"}, {"unknown route is served locally", "/anything", "Local Rails server received request to path /anything"}, @@ -151,6 +155,7 @@ func TestGeoProxyFeatureEnabledButWithAPIError(t *testing.T) { defer wsDeferredClose() testCases := []testCase{ + {"LFS files are served locally", "/group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6", "Local Rails server received request to path /group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6"}, {"jobs request is served locally", "/api/v4/jobs/request", "Local Rails server received request to path /api/v4/jobs/request"}, {"health check is served locally", "/-/health", "Local Rails server received request to path /-/health"}, {"unknown route is served locally", "/anything", "Local Rails server received request to path /anything"}, @@ -174,12 +179,15 @@ func TestGeoProxyFeatureEnablingAndDisabling(t *testing.T) { defer wsDeferredClose() testCasesLocal := []testCase{ + {"LFS files are served locally", "/group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6", "Local Rails server received request to path /group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6"}, {"jobs request is served locally", "/api/v4/jobs/request", "Local Rails server received request to path /api/v4/jobs/request"}, {"health check is served locally", "/-/health", "Local Rails server received request to path /-/health"}, {"unknown route is served locally", "/anything", "Local Rails server received request to path /anything"}, } testCasesProxied := []testCase{ + {"push from secondary is forwarded", "/-/push_from_secondary/foo/bar.git/info/refs", "Geo primary received request to path /-/push_from_secondary/foo/bar.git/info/refs"}, + {"LFS files are served locally", "/group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6", "Local Rails server received request to path /group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6"}, {"jobs request is forwarded", "/api/v4/jobs/request", "Geo primary received request to path /api/v4/jobs/request"}, {"health check is served locally", "/-/health", "Local Rails server received request to path /-/health"}, {"unknown route is forwarded", "/anything", "Geo primary received request to path /anything"},