diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index dddf6334e78..f6d9954363f 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -5c143379d62a9489c5c24e42fb177bb5b7f09318 +c832720d9ad3948e6cf2c371f01c85e9dd9a3a5a diff --git a/app/assets/javascripts/badges/components/badge_form.vue b/app/assets/javascripts/badges/components/badge_form.vue index c95c90d5daf..5bc29750635 100644 --- a/app/assets/javascripts/badges/components/badge_form.vue +++ b/app/assets/javascripts/badges/components/badge_form.vue @@ -6,7 +6,6 @@ import SafeHtml from '~/vue_shared/directives/safe_html'; import { createAlert, VARIANT_INFO } from '~/flash'; import { s__, sprintf } from '~/locale'; import createEmptyBadge from '../empty_badge'; -import { PLACEHOLDERS } from '../constants'; import Badge from './badge.vue'; const badgePreviewDelayInMilliseconds = 1500; @@ -51,9 +50,9 @@ export default { return this.badgeInAddForm; }, helpText() { - const placeholders = PLACEHOLDERS.map((placeholder) => `%{${placeholder}}`).join( - ', ', - ); + const placeholders = ['project_path', 'project_id', 'default_branch', 'commit_sha'] + .map((placeholder) => `%{${placeholder}}`) + .join(', '); return sprintf( s__('Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}'), { diff --git a/app/assets/javascripts/badges/constants.js b/app/assets/javascripts/badges/constants.js index 6819a20fe8f..8fbe3db5ef1 100644 --- a/app/assets/javascripts/badges/constants.js +++ b/app/assets/javascripts/badges/constants.js @@ -1,9 +1,2 @@ export const GROUP_BADGE = 'group'; export const PROJECT_BADGE = 'project'; -export const PLACEHOLDERS = [ - 'project_path', - 'project_name', - 'project_id', - 'default_branch', - 'commit_sha', -]; diff --git a/app/assets/javascripts/graphql_shared/mutations/alert_status_update.mutation.graphql b/app/assets/javascripts/graphql_shared/mutations/alert_status_update.mutation.graphql index ba1e607bc10..11c57780cf5 100644 --- a/app/assets/javascripts/graphql_shared/mutations/alert_status_update.mutation.graphql +++ b/app/assets/javascripts/graphql_shared/mutations/alert_status_update.mutation.graphql @@ -3,6 +3,7 @@ mutation updateAlertStatus($projectPath: ID!, $status: AlertManagementStatus!, $iid: String!) { updateAlertStatus(input: { iid: $iid, status: $status, projectPath: $projectPath }) { errors + # eslint-disable-next-line @graphql-eslint/require-id-when-available alert { iid status diff --git a/app/assets/javascripts/graphql_shared/queries/alert_details.query.graphql b/app/assets/javascripts/graphql_shared/queries/alert_details.query.graphql index 8debc6113d1..b235fd51413 100644 --- a/app/assets/javascripts/graphql_shared/queries/alert_details.query.graphql +++ b/app/assets/javascripts/graphql_shared/queries/alert_details.query.graphql @@ -4,6 +4,7 @@ query alertDetails($fullPath: ID!, $alertId: String) { project(fullPath: $fullPath) { id alertManagementAlerts(iid: $alertId) { + # eslint-disable-next-line @graphql-eslint/require-id-when-available nodes { ...AlertDetailItem } diff --git a/app/assets/javascripts/graphql_shared/queries/get_alerts.query.graphql b/app/assets/javascripts/graphql_shared/queries/get_alerts.query.graphql index 9ffa0bad9ad..afdd0cb0a7a 100644 --- a/app/assets/javascripts/graphql_shared/queries/get_alerts.query.graphql +++ b/app/assets/javascripts/graphql_shared/queries/get_alerts.query.graphql @@ -26,6 +26,7 @@ query getAlerts( before: $prevPageCursor domain: $domain ) { + # eslint-disable-next-line @graphql-eslint/require-id-when-available nodes { ...AlertListItem assignees { diff --git a/app/assets/javascripts/issues/show/components/incidents/graphql/queries/get_alert.graphql b/app/assets/javascripts/issues/show/components/incidents/graphql/queries/get_alert.graphql index d88633f2ae9..1f1b55a5dbf 100644 --- a/app/assets/javascripts/issues/show/components/incidents/graphql/queries/get_alert.graphql +++ b/app/assets/javascripts/issues/show/components/incidents/graphql/queries/get_alert.graphql @@ -3,6 +3,7 @@ query getAlert($iid: String!, $fullPath: ID!) { id issue(iid: $iid) { id + # eslint-disable-next-line @graphql-eslint/require-id-when-available alertManagementAlert { iid title diff --git a/app/assets/javascripts/merge_requests/components/target_project_dropdown.vue b/app/assets/javascripts/merge_requests/components/target_project_dropdown.vue new file mode 100644 index 00000000000..cd2e25793f4 --- /dev/null +++ b/app/assets/javascripts/merge_requests/components/target_project_dropdown.vue @@ -0,0 +1,87 @@ + + + diff --git a/app/assets/javascripts/pages/projects/merge_requests/creations/new/compare.js b/app/assets/javascripts/pages/projects/merge_requests/creations/new/compare.js index 2d26d3922bf..653f903c6d1 100644 --- a/app/assets/javascripts/pages/projects/merge_requests/creations/new/compare.js +++ b/app/assets/javascripts/pages/projects/merge_requests/creations/new/compare.js @@ -26,7 +26,10 @@ const updateCommitList = (url, $emptyState, $loadingIndicator, $commitList, para export default (mrNewCompareNode) => { const { sourceBranchUrl, targetBranchUrl } = mrNewCompareNode.dataset; - initTargetProjectDropdown(); + + if (!window.gon?.features?.mrCompareDropdowns) { + initTargetProjectDropdown(); + } const updateSourceBranchCommitList = () => updateCommitList( diff --git a/app/assets/javascripts/pages/projects/merge_requests/creations/new/index.js b/app/assets/javascripts/pages/projects/merge_requests/creations/new/index.js index 9aecd154483..b3868653d6a 100644 --- a/app/assets/javascripts/pages/projects/merge_requests/creations/new/index.js +++ b/app/assets/javascripts/pages/projects/merge_requests/creations/new/index.js @@ -1,10 +1,37 @@ +import $ from 'jquery'; +import Vue from 'vue'; import initPipelines from '~/commit/pipelines/pipelines_bundle'; import MergeRequest from '~/merge_request'; +import TargetProjectDropdown from '~/merge_requests/components/target_project_dropdown.vue'; import initCompare from './compare'; const mrNewCompareNode = document.querySelector('.js-merge-request-new-compare'); if (mrNewCompareNode) { initCompare(mrNewCompareNode); + + const el = document.getElementById('js-target-project-dropdown'); + const { targetProjectsPath, currentProject } = el.dataset; + + // eslint-disable-next-line no-new + new Vue({ + el, + name: 'TargetProjectDropdown', + provide: { + targetProjectsPath, + currentProject: JSON.parse(currentProject), + }, + render(h) { + return h(TargetProjectDropdown, { + on: { + 'project-selected': function projectSelectedFunction(refsUrl) { + const $targetBranchDropdown = $('.js-target-branch'); + $targetBranchDropdown.data('refsUrl', refsUrl); + $targetBranchDropdown.data('deprecatedJQueryDropdown').clearMenu(); + }, + }, + }); + }, + }); } else { const mrNewSubmitNode = document.querySelector('.js-merge-request-new-submit'); // eslint-disable-next-line no-new diff --git a/app/assets/javascripts/sidebar/queries/get_alert_assignees.query.graphql b/app/assets/javascripts/sidebar/queries/get_alert_assignees.query.graphql index bb6c7181e5c..78c1f9e13cd 100644 --- a/app/assets/javascripts/sidebar/queries/get_alert_assignees.query.graphql +++ b/app/assets/javascripts/sidebar/queries/get_alert_assignees.query.graphql @@ -8,6 +8,7 @@ query alertAssignees( ) { workspace: project(fullPath: $fullPath) { id + # eslint-disable-next-line @graphql-eslint/require-id-when-available issuable: alertManagementAlert(domain: $domain, iid: $iid) { iid assignees { diff --git a/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_set_assignees.mutation.graphql b/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_set_assignees.mutation.graphql index 33091f1ba5e..577bea8c342 100644 --- a/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_set_assignees.mutation.graphql +++ b/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_set_assignees.mutation.graphql @@ -7,6 +7,7 @@ mutation alertSetAssignees($fullPath: ID!, $assigneeUsernames: [String!]!, $iid: input: { iid: $iid, assigneeUsernames: $assigneeUsernames, projectPath: $fullPath } ) { errors + # eslint-disable-next-line @graphql-eslint/require-id-when-available issuable: alert { iid assignees { diff --git a/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_todo_create.mutation.graphql b/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_todo_create.mutation.graphql index c860bf0915c..2af1940c723 100644 --- a/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_todo_create.mutation.graphql +++ b/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_todo_create.mutation.graphql @@ -4,6 +4,7 @@ mutation alertTodoCreate($projectPath: ID!, $iid: String!) { alertTodoCreate(input: { iid: $iid, projectPath: $projectPath }) { errors + # eslint-disable-next-line @graphql-eslint/require-id-when-available alert { ...AlertDetailItem assignees { diff --git a/app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_sidebar_details.query.graphql b/app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_sidebar_details.query.graphql index 0ea209ffd39..9683233d191 100644 --- a/app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_sidebar_details.query.graphql +++ b/app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_sidebar_details.query.graphql @@ -5,6 +5,7 @@ query alertDetailsAssignees($fullPath: ID!, $alertId: String) { project(fullPath: $fullPath) { id alertManagementAlerts(iid: $alertId) { + # eslint-disable-next-line @graphql-eslint/require-id-when-available nodes { ...AlertDetailItem assignees { diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index b016d0a1068..6b662359a67 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -382,3 +382,9 @@ $comparison-empty-state-height: 62px; .survey-slide-up-enter-active { @include gl-transition-slow; } + +.mr-compare-dropdown { + .gl-button-text { + @include gl-w-full; + } +} diff --git a/app/controllers/concerns/observability/content_security_policy.rb b/app/controllers/concerns/observability/content_security_policy.rb index 2721907f218..eccd1e1e3ef 100644 --- a/app/controllers/concerns/observability/content_security_policy.rb +++ b/app/controllers/concerns/observability/content_security_policy.rb @@ -11,8 +11,12 @@ module Observability default_frame_src = p.directives['frame-src'] || p.directives['default-src'] # When ObservabilityUI is not authenticated, it needs to be able - # to redirect to the GL sign-in page, hence 'self' - frame_src_values = Array.wrap(default_frame_src) | [Gitlab::Observability.observability_url, "'self'"] + # to redirect to the GL sign-in page, hence '/users/sign_in' and '/oauth/authorize' + frame_src_values = Array.wrap(default_frame_src) | [Gitlab::Observability.observability_url, + Gitlab::Utils.append_path(Gitlab.config.gitlab.url, +'/users/sign_in'), + Gitlab::Utils.append_path(Gitlab.config.gitlab.url, +'/oauth/authorize')] p.frame_src(*frame_src_values) end diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index f3f0ddd968a..0d6f289f5f5 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -169,6 +169,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController # available in the logs for this request. Gitlab::ApplicationContext.push(user: user) log_audit_event(user, with: oauth['provider']) + Gitlab::Tracking.event(self.class.name, "#{oauth['provider']}_sso", user: user) if new_user set_remember_me(user) diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 22ad590edbe..631e697dd2f 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -7,6 +7,7 @@ class Projects::IssuesController < Projects::ApplicationController include IssuableCollections include IssuesCalendar include RecordUserLastActivity + include ::Observability::ContentSecurityPolicy ISSUES_EXCEPT_ACTIONS = %i[index calendar new create bulk_update import_csv export_csv service_desk].freeze SET_ISSUABLES_INDEX_ONLY_ACTIONS = %i[index calendar service_desk].freeze diff --git a/app/controllers/projects/merge_requests/creations_controller.rb b/app/controllers/projects/merge_requests/creations_controller.rb index 93e2298ca98..cba0056ccd5 100644 --- a/app/controllers/projects/merge_requests/creations_controller.rb +++ b/app/controllers/projects/merge_requests/creations_controller.rb @@ -4,6 +4,7 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap include DiffForPath include DiffHelper include RendersCommits + include ::Observability::ContentSecurityPolicy skip_before_action :merge_request before_action :authorize_create_merge_request_from! @@ -19,6 +20,10 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap :branch_to ] + before_action do + push_frontend_feature_flag(:mr_compare_dropdowns, project) + end + def new define_new_vars end @@ -89,6 +94,14 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap render layout: false end + def target_projects + projects = MergeRequestTargetProjectFinder + .new(current_user: current_user, source_project: @project, project_feature: :repository) + .execute(include_routes: true).limit(20).search(params[:search]) + + render json: ProjectSerializer.new.represent(projects) + end + private def build_merge_request diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index a366c815e95..be56ccf62b5 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -11,6 +11,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo include SourcegraphDecorator include DiffHelper include Gitlab::Cache::Helpers + include ::Observability::ContentSecurityPolicy prepend_before_action(only: [:index]) { authenticate_sessionless_user!(:rss) } skip_before_action :merge_request, only: [:index, :bulk_update, :export_csv] diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 8161afcedb5..1a13b8ca6e5 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -111,8 +111,11 @@ class RegistrationsController < Devise::RegistrationsController super end + # overridden by EE module def after_request_hook(user) - # overridden by EE module + return unless user.persisted? + + Gitlab::Tracking.event(self.class.name, 'successfully_submitted_form', user: user) end def after_sign_up_path_for(user) @@ -226,12 +229,14 @@ class RegistrationsController < Devise::RegistrationsController Gitlab::Recaptcha.load_configurations! end + # overridden by EE module def set_resource_fields return unless set_blocked_pending_approval? resource.state = User::BLOCKED_PENDING_APPROVAL_STATE end + # overridden by EE module def set_blocked_pending_approval? Gitlab::CurrentSettings.require_admin_approval_after_user_signup end diff --git a/app/graphql/types/alert_management/alert_type.rb b/app/graphql/types/alert_management/alert_type.rb index cf594505683..a13453f9194 100644 --- a/app/graphql/types/alert_management/alert_type.rb +++ b/app/graphql/types/alert_management/alert_type.rb @@ -13,6 +13,11 @@ module Types authorize :read_alert_management_alert + field :id, + GraphQL::Types::ID, + null: false, + description: 'ID of the alert.' + field :iid, GraphQL::Types::ID, null: false, diff --git a/app/models/badge.rb b/app/models/badge.rb index c3338b0412d..4339d419b48 100644 --- a/app/models/badge.rb +++ b/app/models/badge.rb @@ -8,7 +8,6 @@ class Badge < ApplicationRecord # the placeholder is found. PLACEHOLDERS = { 'project_path' => :full_path, - 'project_name' => :name, 'project_id' => :id, 'default_branch' => :default_branch, 'commit_sha' => ->(project) { project.commit&.sha } diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 632fd0fd24d..05207fb1ca0 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -1352,8 +1352,7 @@ module Ci return unless bridge_waiting? return unless current_user.can?(:update_pipeline, source_bridge.pipeline) - source_bridge.pending! - Ci::ResetSkippedJobsService.new(project, current_user).execute(source_bridge) # rubocop:disable CodeReuse/ServiceClass + Ci::EnqueueJobService.new(source_bridge, current_user: current_user).execute(&:pending!) # rubocop:disable CodeReuse/ServiceClass end # EE-only diff --git a/app/models/concerns/has_user_type.rb b/app/models/concerns/has_user_type.rb index 8e371f2a9c1..1af655277b8 100644 --- a/app/models/concerns/has_user_type.rb +++ b/app/models/concerns/has_user_type.rb @@ -25,7 +25,6 @@ module HasUserType scope :humans, -> { where(user_type: :human) } scope :bots, -> { where(user_type: BOT_USER_TYPES) } scope :without_bots, -> { humans.or(where.not(user_type: BOT_USER_TYPES)) } - scope :bots_without_project_bot, -> { where(user_type: BOT_USER_TYPES - ['project_bot']) } scope :non_internal, -> { humans.or(where(user_type: NON_INTERNAL_USER_TYPES)) } scope :without_ghosts, -> { humans.or(where.not(user_type: :ghost)) } scope :without_project_bot, -> { humans.or(where.not(user_type: :project_bot)) } diff --git a/app/serializers/project_entity.rb b/app/serializers/project_entity.rb index 77e2115fbe2..cbdc19a83ce 100644 --- a/app/serializers/project_entity.rb +++ b/app/serializers/project_entity.rb @@ -13,4 +13,8 @@ class ProjectEntity < Grape::Entity expose :full_name, documentation: { type: 'string', example: 'GitLab Org / GitLab' } do |project| project.full_name end + + expose :refs_url do |project| + refs_project_path(project) + end end diff --git a/app/services/ci/enqueue_job_service.rb b/app/services/ci/enqueue_job_service.rb new file mode 100644 index 00000000000..9e3bea3fd28 --- /dev/null +++ b/app/services/ci/enqueue_job_service.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Ci + class EnqueueJobService + attr_accessor :job, :current_user, :variables + + def initialize(job, current_user:, variables: nil) + @job = job + @current_user = current_user + @variables = variables + end + + def execute(&transition) + job.user = current_user + job.job_variables_attributes = variables if variables + + transition ||= ->(job) { job.enqueue! } + Gitlab::OptimisticLocking.retry_lock(job, name: 'ci_enqueue_job', &transition) + + ResetSkippedJobsService.new(job.project, current_user).execute(job) + + job + end + end +end diff --git a/app/services/ci/play_bridge_service.rb b/app/services/ci/play_bridge_service.rb index 897f54ee712..ffcd2b05b31 100644 --- a/app/services/ci/play_bridge_service.rb +++ b/app/services/ci/play_bridge_service.rb @@ -5,12 +5,7 @@ module Ci def execute(bridge) check_access!(bridge) - bridge.tap do |bridge| - bridge.user = current_user - bridge.enqueue! - - ResetSkippedJobsService.new(project, current_user).execute(bridge) - end + Ci::EnqueueJobService.new(bridge, current_user: current_user).execute end private diff --git a/app/services/ci/play_build_service.rb b/app/services/ci/play_build_service.rb index 4f474cf506c..8d2225aba71 100644 --- a/app/services/ci/play_build_service.rb +++ b/app/services/ci/play_build_service.rb @@ -5,17 +5,7 @@ module Ci def execute(build, job_variables_attributes = nil) check_access!(build, job_variables_attributes) - if build.can_enqueue? - build.user = current_user - build.job_variables_attributes = job_variables_attributes || [] - build.enqueue! - - ResetSkippedJobsService.new(project, current_user).execute(build) - - build - else - retry_build(build) - end + Ci::EnqueueJobService.new(build, current_user: current_user, variables: job_variables_attributes || []).execute rescue StateMachines::InvalidTransition retry_build(build.reset) end diff --git a/app/views/projects/merge_requests/creations/_new_compare.html.haml b/app/views/projects/merge_requests/creations/_new_compare.html.haml index 17b1e5a757c..86f151f8288 100644 --- a/app/views/projects/merge_requests/creations/_new_compare.html.haml +++ b/app/views/projects/merge_requests/creations/_new_compare.html.haml @@ -40,17 +40,20 @@ %h2.gl-font-size-h2 = _('Target branch') .clearfix - - projects = target_projects(@project) .merge-request-select.dropdown - = f.hidden_field :target_project_id - = dropdown_toggle f.object.target_project.full_path, { toggle: "dropdown", 'field-name': "#{f.object_name}[target_project_id]", disabled: @merge_request.persisted?, default_text: _("Select target project") }, { toggle_class: "js-compare-dropdown js-target-project" } - .dropdown-menu.dropdown-menu-selectable.dropdown-target-project - = dropdown_title(_("Select target project")) - = dropdown_filter(_("Search projects")) - = dropdown_content do - = render 'projects/merge_requests/dropdowns/project', - projects: projects, - selected: f.object.target_project_id + - if Feature.enabled?(:mr_compare_dropdowns, @project) + #js-target-project-dropdown{ data: { target_projects_path: project_new_merge_request_json_target_projects_path(@project), current_project: { value: f.object.target_project_id.to_s, text: f.object.target_project.full_path }.to_json } } + - else + - projects = target_projects(@project) + = f.hidden_field :target_project_id + = dropdown_toggle f.object.target_project.full_path, { toggle: "dropdown", 'field-name': "#{f.object_name}[target_project_id]", disabled: @merge_request.persisted?, default_text: _("Select target project") }, { toggle_class: "js-compare-dropdown js-target-project" } + .dropdown-menu.dropdown-menu-selectable.dropdown-target-project + = dropdown_title(_("Select target project")) + = dropdown_filter(_("Search projects")) + = dropdown_content do + = render 'projects/merge_requests/dropdowns/project', + projects: projects, + selected: f.object.target_project_id .merge-request-select.dropdown = f.hidden_field :target_branch = dropdown_toggle f.object.target_branch.presence || _("Select target branch"), { toggle: "dropdown", 'field-name': "#{f.object_name}[target_branch]", 'refs-url': refs_project_path(f.object.target_project), selected: f.object.target_branch, default_text: _("Select target branch") }, { toggle_class: "js-compare-dropdown js-target-branch monospace" } diff --git a/config/feature_flags/development/mr_compare_dropdowns.yml b/config/feature_flags/development/mr_compare_dropdowns.yml new file mode 100644 index 00000000000..bffab02389b --- /dev/null +++ b/config/feature_flags/development/mr_compare_dropdowns.yml @@ -0,0 +1,8 @@ +--- +name: mr_compare_dropdowns +introduced_by_url: +rollout_issue_url: +milestone: '15.7' +type: development +group: group::code review +default_enabled: false diff --git a/config/feature_flags/ops/report_heap_dumps.yml b/config/feature_flags/ops/report_heap_dumps.yml new file mode 100644 index 00000000000..12b126a8f80 --- /dev/null +++ b/config/feature_flags/ops/report_heap_dumps.yml @@ -0,0 +1,8 @@ +--- +name: report_heap_dumps +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106406 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/385175 +milestone: '15.7' +type: ops +group: group::application performance +default_enabled: false diff --git a/config/initializers/diagnostic_reports.rb b/config/initializers/diagnostic_reports.rb index 64ddc98c9fb..14bac060c25 100644 --- a/config/initializers/diagnostic_reports.rb +++ b/config/initializers/diagnostic_reports.rb @@ -8,8 +8,6 @@ Gitlab::Cluster::LifecycleEvents.on_worker_start do Gitlab::Memory::ReportsDaemon.instance.start end -return unless Gitlab::Utils.to_boolean(ENV['GITLAB_MEMWD_DUMP_HEAP']) - Gitlab::Cluster::LifecycleEvents.on_worker_stop do Gitlab::Memory::Reporter.new.run_report( Gitlab::Memory::Reports::HeapDump.new diff --git a/config/routes/merge_requests.rb b/config/routes/merge_requests.rb index b0bab1717a6..cd776b2a2a7 100644 --- a/config/routes/merge_requests.rb +++ b/config/routes/merge_requests.rb @@ -78,6 +78,7 @@ scope path: 'merge_requests', controller: 'merge_requests/creations' do scope constraints: ->(req) { req.format == :json }, as: :json do get :diffs get :pipelines + get :target_projects end scope action: :new do diff --git a/db/migrate/20221202202351_remove_index_i_ci_job_token_project_scope_links_on_source_and_target_project.rb b/db/migrate/20221202202351_remove_index_i_ci_job_token_project_scope_links_on_source_and_target_project.rb new file mode 100644 index 00000000000..81a636739b4 --- /dev/null +++ b/db/migrate/20221202202351_remove_index_i_ci_job_token_project_scope_links_on_source_and_target_project.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true +class RemoveIndexICiJobTokenProjectScopeLinksOnSourceAndTargetProject < Gitlab::Database::Migration[2.0] + disable_ddl_transaction! + + TABLE_NAME = 'ci_job_token_project_scope_links' + OLD_INDEX_NAME = 'i_ci_job_token_project_scope_links_on_source_and_target_project' + NEW_INDEX_NAME = 'ci_job_token_scope_links_source_and_target_project_direction' + NEW_INDEX_COL = %w[source_project_id target_project_id direction] + + def up + add_concurrent_index( + TABLE_NAME, + NEW_INDEX_COL, + name: NEW_INDEX_NAME, + unique: true + ) + remove_concurrent_index_by_name(TABLE_NAME, OLD_INDEX_NAME) + end + + def down + # noop: as we can have duplicate records once the unique index is removed + end +end diff --git a/db/schema_migrations/20221202202351 b/db/schema_migrations/20221202202351 new file mode 100644 index 00000000000..942bc0577d6 --- /dev/null +++ b/db/schema_migrations/20221202202351 @@ -0,0 +1 @@ +8e9641a603bd9540d0004fb76b407a5cb4392c8cc41c084cd746f354b9a8d417 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index d90ff32528e..2465f70c59d 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -27999,6 +27999,8 @@ CREATE INDEX ca_aggregations_last_incremental_run_at ON analytics_cycle_analytic CREATE INDEX ci_builds_gitlab_monitor_metrics ON ci_builds USING btree (status, created_at, project_id) WHERE ((type)::text = 'Ci::Build'::text); +CREATE UNIQUE INDEX ci_job_token_scope_links_source_and_target_project_direction ON ci_job_token_project_scope_links USING btree (source_project_id, target_project_id, direction); + CREATE INDEX ci_pipeline_artifacts_on_expire_at_for_removal ON ci_pipeline_artifacts USING btree (expire_at) WHERE ((locked = 0) AND (expire_at IS NOT NULL)); CREATE INDEX code_owner_approval_required ON protected_branches USING btree (project_id, code_owner_approval_required) WHERE (code_owner_approval_required = true); @@ -28029,8 +28031,6 @@ CREATE INDEX finding_links_on_vulnerability_occurrence_id ON vulnerability_findi CREATE INDEX i_batched_background_migration_job_transition_logs_on_job_id ON ONLY batched_background_migration_job_transition_logs USING btree (batched_background_migration_job_id); -CREATE UNIQUE INDEX i_ci_job_token_project_scope_links_on_source_and_target_project ON ci_job_token_project_scope_links USING btree (source_project_id, target_project_id); - CREATE INDEX i_compliance_frameworks_on_id_and_created_at ON compliance_management_frameworks USING btree (id, created_at, pipeline_configuration_full_path); CREATE UNIQUE INDEX i_pm_licenses_on_spdx_identifier ON pm_licenses USING btree (spdx_identifier); diff --git a/doc/administration/geo/replication/configuration.md b/doc/administration/geo/replication/configuration.md index 55c5d3784c2..d625b2a0324 100644 --- a/doc/administration/geo/replication/configuration.md +++ b/doc/administration/geo/replication/configuration.md @@ -264,7 +264,7 @@ Install the correct certificate based on your certificate type: - **Multi-domain certificate** that includes both primary and secondary site domains: Install the certificate at `/etc/gitlab/ssl` on all **Rails, Sidekiq, and Gitaly** nodes in the **secondary** site. - **Single-domain certificate** where the certificates are specific to each Geo site domain: Generate a valid certificate for your **secondary** site's domain and install it at `/etc/gitlab/ssl` per [these instructions](https://docs.gitlab.com/omnibus/settings/ssl.html#install-custom-public-certificates) on all **Rails, Sidekiq, and Gitaly** nodes in the **secondary** site. -#### Connecting to external services that use customer certificates +#### Connecting to external services that use custom certificates A copy of the self-signed certificate for the external service needs to be added to the trust store on all the **primary** site's nodes that require access to the service. diff --git a/doc/administration/logs/index.md b/doc/administration/logs/index.md index efe91e944b7..9893c6935a3 100644 --- a/doc/administration/logs/index.md +++ b/doc/administration/logs/index.md @@ -161,11 +161,13 @@ seconds: - `gitaly_calls`: Total number of calls made to Gitaly - `redis_calls`: Total number of calls made to Redis - `redis_cross_slot_calls`: Total number of cross-slot calls made to Redis +- `redis_allowed_cross_slot_calls`: Total number of allowed cross-slot calls made to Redis - `redis_duration_s`: Total time to retrieve data from Redis - `redis_read_bytes`: Total bytes read from Redis - `redis_write_bytes`: Total bytes written to Redis - `redis__calls`: Total number of calls made to a Redis instance - `redis__cross_slot_calls`: Total number of cross-slot calls made to a Redis instance +- `redis__allowed_cross_slot_calls`: Total number of allowed cross-slot calls made to a Redis instance - `redis__duration_s`: Total time to retrieve data from a Redis instance - `redis__read_bytes`: Total bytes read from a Redis instance - `redis__write_bytes`: Total bytes written to a Redis instance diff --git a/doc/administration/maintenance_mode/index.md b/doc/administration/maintenance_mode/index.md index 9adb8ce2cd9..0b4488075d0 100644 --- a/doc/administration/maintenance_mode/index.md +++ b/doc/administration/maintenance_mode/index.md @@ -84,7 +84,7 @@ them to disable Maintenance Mode after it's been enabled. All users can sign in and out of the GitLab instance but no new users can be created. -If there are [LDAP syncs](../auth/ldap/index.md) scheduled for that time, they fail since user creation is disabled. Similarly, [user creations based on SAML](../../integration/saml.md#general-setup) fail. +If there are [LDAP syncs](../auth/ldap/index.md) scheduled for that time, they fail since user creation is disabled. Similarly, [user creations based on SAML](../../integration/saml.md#configure-saml-support-in-gitlab) fail. ### Git actions diff --git a/doc/administration/sidekiq/index.md b/doc/administration/sidekiq/index.md index b40a1f0ba1d..7b3ecdd0890 100644 --- a/doc/administration/sidekiq/index.md +++ b/doc/administration/sidekiq/index.md @@ -379,7 +379,7 @@ To enable LDAP with the synchronization worker for Sidekiq: ## Configure SAML Groups for SAML Group Sync -If you use [SAML Group Sync](../../user/group/saml_sso/group_sync.md), you must configure [SAML Groups](../../integration/saml.md#saml-groups) on all your Sidekiq nodes. +If you use [SAML Group Sync](../../user/group/saml_sso/group_sync.md), you must configure [SAML Groups](../../integration/saml.md#configure-users-based-on-saml-group-membership) on all your Sidekiq nodes. ## Disable Rugged diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index bd0bd2e6288..4a22fccb895 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -10195,6 +10195,7 @@ Describes an alert from the project's Alert Management. | `environment` | [`Environment`](#environment) | Environment for the alert. | | `eventCount` | [`Int`](#int) | Number of events of this alert. | | `hosts` | [`[String!]`](#string) | List of hosts the alert came from. | +| `id` | [`ID!`](#id) | ID of the alert. | | `iid` | [`ID!`](#id) | Internal ID of the alert. | | `issue` | [`Issue`](#issue) | Issue attached to the alert. | | `issueIid` **{warning-solid}** | [`ID`](#id) | **Deprecated** in 13.10. Use issue field. | diff --git a/doc/api/group_badges.md b/doc/api/group_badges.md index a44a9d538e9..cc99c137a47 100644 --- a/doc/api/group_badges.md +++ b/doc/api/group_badges.md @@ -15,7 +15,6 @@ Badges support placeholders that are replaced in real time in both the link and - **%{project_path}**: replaced by the project path. -- **%{project_name}**: replaced by the project name. - **%{project_id}**: replaced by the project ID. - **%{default_branch}**: replaced by the project default branch. - **%{commit_sha}**: replaced by the last project's commit SHA. diff --git a/doc/api/project_badges.md b/doc/api/project_badges.md index 7f0e1caa2c1..d83aa370808 100644 --- a/doc/api/project_badges.md +++ b/doc/api/project_badges.md @@ -13,7 +13,6 @@ Badges support placeholders that are replaced in real-time in both the link and - **%{project_path}**: Replaced by the project path. -- **%{project_name}**: Replaced by the project name. - **%{project_id}**: Replaced by the project ID. - **%{default_branch}**: Replaced by the project default branch. - **%{commit_sha}**: Replaced by the last project's commit SHA. diff --git a/doc/ci/runners/saas/macos_saas_runner.md b/doc/ci/runners/saas/macos_saas_runner.md index cd40aac25bc..270f85e65e2 100644 --- a/doc/ci/runners/saas/macos_saas_runner.md +++ b/doc/ci/runners/saas/macos_saas_runner.md @@ -18,9 +18,11 @@ Jobs handled by macOS shared runners on GitLab.com **time out after 3 hours**, r ## Access request process -While in beta, to run CI jobs on the macOS runners, GitLab SaaS customer namespaces must be explicitly added to the macOS `allow-list`. +While in beta, to run CI jobs on the macOS runners, you must specify the GitLab SaaS customer personal or group [namespaces](../../../user/namespace/index.md) in the macOS `allow-list`. These are the namespaces that use the macOS runners. -After you have been added, you can use the macOS runners for any projects in your namespace. +When you specify a personal or group namespace, the top level group is not added unless you specify it. + +After you add your namespace, you can use the macOS runners for any projects under the namespace you included. To request access, open an [access request](https://gitlab.com/gitlab-com/runner-saas-macos-limited-availability/-/issues/new). The expected turnaround for activation is two business days. diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md index 81419acb51f..e9a088bbe25 100644 --- a/doc/integration/omniauth.md +++ b/doc/integration/omniauth.md @@ -280,7 +280,7 @@ for the OpenID Connect provider and the Twitter OAuth provider. This method of enabling automatic linking works for all providers [except SAML](https://gitlab.com/gitlab-org/gitlab/-/issues/338293). -To enable automatic linking for SAML, see the [SAML setup instructions](saml.md#general-setup). +To enable automatic linking for SAML, see the [SAML setup instructions](saml.md#configure-saml-support-in-gitlab). ## Create an external providers list diff --git a/doc/integration/saml.md b/doc/integration/saml.md index bba872a9ae9..1983f3a180e 100644 --- a/doc/integration/saml.md +++ b/doc/integration/saml.md @@ -5,34 +5,21 @@ info: To determine the technical writer assigned to the Stage/Group associated w type: reference --- -# SAML OmniAuth Provider **(FREE SELF)** +# SAML SSO for self-managed GitLab instances **(FREE SELF)** -This page describes instance-wide SAML for self-managed GitLab instances. For -SAML on GitLab.com, see [SAML SSO for GitLab.com groups](../user/group/saml_sso/index.md). +This page describes instance-wide SAML 2.0 for self-managed GitLab instances. For +SAML 2.0 on GitLab.com, see [SAML SSO for GitLab.com groups](../user/group/saml_sso/index.md). You should also reference the [OmniAuth documentation](omniauth.md) for general settings that apply to all OmniAuth providers. -## Glossary of common terms - -| Term | Description | -|--------------------------------|-------------| -| Identity provider (IdP) | The service which manages your user identities, such as Okta or OneLogin. | -| Service provider (SP) | GitLab can be configured as a SAML 2.0 SP. | -| Assertion | A piece of information about a user's identity, such as their name or role. Also known as claims or attributes. | -| Single Sign-On (SSO) | Name of authentication scheme. | -| Assertion consumer service URL | The callback on GitLab where users are redirected after successfully authenticating with the identity provider. | -| Issuer | How GitLab identifies itself to the identity provider. Also known as a "Relying party trust identifier". | -| Certificate fingerprint | Used to confirm that communications over SAML are secure by checking that the server is signing communications with the correct certificate. Also known as a certificate thumbprint. | - -## General Setup +If required, you can find a [glossary of common terms](#glossary-of-common-terms). GitLab can be configured to act as a SAML 2.0 Service Provider (SP). This allows -GitLab to consume assertions from a SAML 2.0 Identity Provider (IdP), such as +GitLab to consume assertions from a SAML 2.0 identity provider (IdP), such as Okta to authenticate users. -First configure SAML 2.0 support in GitLab, then register the GitLab application -in your SAML IdP: +## Configure SAML support in GitLab 1. Make sure GitLab is configured with HTTPS. See [Using HTTPS](../install/installation.md#using-https) for instructions. @@ -73,7 +60,7 @@ in your SAML IdP: block_auto_created_users: false ``` -1. You can also automatically link SAML users with existing GitLab users if their +1. Optional. You can automatically link SAML users with existing GitLab users if their email addresses match by adding the following setting: For Omnibus package: @@ -88,8 +75,16 @@ in your SAML IdP: auto_link_saml_user: true ``` -1. Ensure that the SAML [`NameID`](../user/group/saml_sso/index.md#nameid) and email address are fixed for each user, -as described in the section on [Security](#security). Otherwise, your users are able to sign in as other authorized users. + Alternatively, a user can manually link their SAML identity to an existing GitLab + account by following the steps in + [Enable OmniAuth for an existing user](omniauth.md#enable-omniauth-for-an-existing-user). + +1. Ensure that the SAML [`NameID`](../user/group/saml_sso/index.md#nameid) and email + address are fixed for each user. These attributes define the SAML user. If users + can change these attributes, they can impersonate others. + + Refer to the documentation for your SAML identity provider for information on + how to fix these attributes. 1. Add the provider configuration: @@ -138,7 +133,7 @@ as described in the section on [Security](#security). Otherwise, your users are be a SHA1 fingerprint; check [the OmniAuth SAML documentation](https://github.com/omniauth/omniauth-saml) for more details on these options. - See the [notes on configuring your identity provider](#notes-on-configuring-your-identity-provider) for more information. + See the [notes on configuring a SAML 2.0 app on your IdP](#configure-saml-on-your-idp) for more information. 1. Change the value of `issuer` to a unique name, which identifies the application to the IdP. @@ -147,6 +142,8 @@ as described in the section on [Security](#security). Otherwise, your users are - If you installed via Omnibus, [reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure). - If you installed from source, [restart GitLab](../administration/restart_gitlab.md#installations-from-source). +### Register GitLab in your SAML IdP + 1. Register the GitLab SP in your SAML 2.0 IdP, using the application name specified in `issuer`. @@ -159,17 +156,31 @@ https://gitlab.example.com/users/auth/saml/metadata ``` At a minimum the IdP *must* provide a claim containing the user's email address using `email` or `mail`. -See [the assertions list](#assertions) for other available claims. +See [configuring assertions](#configure-assertions) for other available claims. On the sign in page there should now be a SAML button below the regular sign in form. Select the icon to begin the authentication process. If everything goes well the user is returned to GitLab and signed in. -### Use multiple SAML identity providers +### Configure SAML on your IdP + +When configuring a SAML app on the IdP, you need at least: + +- Assertion consumer service URL +- Issuer +- [`NameID`](../user/group/saml_sso/index.md#nameid) +- [Email address claim](#configure-assertions) + +For example configurations, see the [notes on specific providers](#set-up-identity-providers). + +Your identity provider may require additional configuration. +See [additional information on configuring a SAML app](#additional-configuration-for-saml-apps-on-your-idp) on your IdP for more information. + +### Configure GitLab to use multiple SAML IdPs > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14361) in GitLab 14.6. -You can configure GitLab to use multiple SAML identity providers if: +You can configure GitLab to use multiple SAML 2.0 identity providers if: - Each provider has a unique name set that matches a name set in `args`. At least one provider **must** have the name `saml` to mitigate a [known issue](https://gitlab.com/gitlab-org/gitlab/-/issues/366450) in GitLab 14.6 and newer. @@ -234,54 +245,99 @@ omniauth: } ``` -### Notes on configuring your identity provider +## Set up identity providers -When configuring a SAML app on the IdP, you need at least: +GitLab support of SAML means that you can sign in to GitLab with a wide range of identity providers. +Your identity provider may have additional documentation. Some identity providers include +documentation on how to use SAML to sign in to GitLab. -- Assertion consumer service URL -- Issuer -- [`NameID`](../user/group/saml_sso/index.md#nameid) -- [Email address claim](#assertions) +Examples: -Your identity provider may require additional configuration, such as the following: +- [ADFS (Active Directory Federation Services)](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-relying-party-trust) +- [Auth0](https://auth0.com/docs/authenticate/protocols/saml/saml-sso-integrations/configure-auth0-saml-identity-provider) -| Field | Value | Notes | -|-------|-------|-------| -| SAML profile | Web browser SSO profile | GitLab uses SAML to sign users in through their browser. No requests are made directly to the identity provider. | -| SAML request binding | HTTP Redirect | GitLab (the service provider) redirects users to your identity provider with a base64 encoded `SAMLRequest` HTTP parameter. | -| SAML response binding | HTTP POST | Specifies how the SAML token is sent by your identity provider. Includes the `SAMLResponse`, which a user's browser submits back to GitLab. | -| Sign SAML response | Required | Prevents tampering. | -| X.509 certificate in response | Required | Signs the response and checks against the provided fingerprint. | -| Fingerprint algorithm | SHA-1 | GitLab uses a SHA-1 hash of the certificate to sign the SAML Response. | -| Signature algorithm | SHA-1/SHA-256/SHA-384/SHA-512 | Determines how a response is signed. Also known as the digest method, this can be specified in the SAML response. | -| Encrypt SAML assertion | Optional | Uses TLS between your identity provider, the user's browser, and GitLab. | -| Sign SAML assertion | Optional | Validates the integrity of a SAML assertion. When active, signs the whole response. | -| Check SAML request signature | Optional | Checks the signature on the SAML response. | -| Default RelayState | Optional | Specifies the URL users should end up on after successfully signing in through SAML at your identity provider. | -| NameID format | Persistent | See [NameID format details](../user/group/saml_sso/index.md#nameid-format). | -| Additional URLs | Optional | May include the issuer (or identifier) or the assertion consumer service URL in other fields on some providers. | +GitLab provides the following setup notes for guidance only. +If you have any questions on configuring the SAML app, please contact your provider's support. -For example configurations, see the [notes on specific providers](#providers). +### Set up Okta -### Assertions +1. In the Okta administrator section choose **Applications**. +1. When the app screen comes up you see another button to **Create App Integration** and + choose SAML 2.0 on the next screen. +1. Optionally, you can add a logo + (you can choose it from ). You must + crop and resize it. +1. Next, fill in the SAML general configuration with + the assertion consumer service URL as "Single sign-on URL" and + the issuer as "Audience URI" along with the [NameID](../user/group/saml_sso/index.md#nameid) + and [assertions](#configure-assertions). +1. The last part of the configuration is the feedback section where you can + just say you're a customer and creating an app for internal use. +1. When you have your app you can see a few tabs on the top of the app's + profile. Select the SAML 2.0 configuration instructions button. +1. On the screen that comes up take note of the + **Identity Provider Single Sign-On URL** which you can use for the + `idp_sso_target_url` on your GitLab configuration file. +1. **Before you leave Okta, make sure you add your user and groups if any.** -| Field | Supported keys | -|-----------------|----------------| -| Email (required)| `email`, `mail` | -| Full Name | `name` | +### Set up Google Workspace + +The following guidance is based on this Google Workspace article, on how to [Set up your own custom SAML application](https://support.google.com/a/answer/6087519?hl=en): + +Make sure you have access to a Google Workspace [Super Admin](https://support.google.com/a/answer/2405986#super_admin) account. + Use the information below and follow the instructions in the linked Google Workspace article. + +| | Typical value | Description | +|------------------|--------------------------------------------------|----------------------------------------------------------| +| Name of SAML App | GitLab | Other names OK. | +| ACS URL | `https:///users/auth/saml/callback` | ACS is short for Assertion Consumer Service. | +| GITLAB_DOMAIN | `gitlab.example.com` | Set to the domain of your GitLab instance. | +| Entity ID | `https://gitlab.example.com` | A value unique to your SAML app, set it to the `issuer` in your GitLab configuration. | +| Name ID format | EMAIL | Required value. Also known as `name_identifier_format` | +| Name ID | Primary email address | Make sure someone receives content sent to that address | +| First name | `first_name` | Required value to communicate with GitLab. | +| Last name | `last_name` | Required value to communicate with GitLab. | + +You also must setup the following SAML attribute mappings: + +| Google Directory attributes | App attributes | +|-----------------------------------|----------------| +| Basic information > Email | `email` | +| Basic Information > First name | `first_name` | +| Basic Information > Last name | `last_name` | + +You may also use some of this information when you [configure GitLab](#configure-saml-support-in-gitlab). + +When configuring the Google Workspace SAML app, be sure to record the following information: + +| | Value | Description | +|-------------|--------------|-----------------------------------------------------------------------------------| +| SSO URL | Depends | Google Identity Provider details. Set to the GitLab `idp_sso_target_url` setting. | +| Certificate | Downloadable | Run `openssl x509 -in -noout -fingerprint` to generate the SHA1 fingerprint that can be used in the `idp_cert_fingerprint` setting. | + +While the Google Workspace Administrator provides IdP metadata, Entity ID, and SHA-256 +fingerprint, they are not required. GitLab does not need that information to +connect to the Google Workspace SAML app. + +### Configure assertions + +| Field | Supported default keys | +|-----------------|------------------------| +| Email (required)| `email`, `mail` | +| Full Name | `name` | | First Name | `first_name`, `firstname`, `firstName` | -| Last Name | `last_name`, `lastname`, `lastName` | +| Last Name | `last_name`, `lastname`, `lastName` | -See [`attribute_statements`](#attribute_statements) for examples on how custom +See [`attribute_statements`](#map-saml-response-attribute-names) for examples on how custom assertions are configured. This section also describes how to configure custom username attributes. Please refer to [the OmniAuth SAML gem](https://github.com/omniauth/omniauth-saml/blob/master/lib/omniauth/strategies/saml.rb) for a full list of supported assertions. -## SAML Groups +## Configure users based on SAML group membership -You can require users to be members of a certain group, or assign users [external](../user/admin_area/external_users.md), administrator or [auditor](../user/permissions.md#auditor-users) roles based on group membership. +You can require users to be members of a certain group, or assign users [external](../user/admin_area/external_users.md), administrator or [auditor](../administration/auditor_users.md) access levels based on group membership. These groups are checked on each SAML login and user attributes updated as necessary. This feature **does not** allow you to automatically add users to GitLab [Groups](../user/group/index.md). @@ -296,7 +352,7 @@ and whether you've installed [GitLab Enterprise Edition (EE)](https://about.gitl | [Admin](#administrator-groups) | **(FREE SELF)** | Yes | | [Auditor](#auditor-groups) | **(PREMIUM SELF)** | Yes | -### Requirements +### Prerequisites First tell GitLab where to look for group information. For this, you must make sure that your IdP server sends a specific `AttributeStatement` along @@ -394,7 +450,7 @@ The requirements are the same as the previous settings: - The IdP must pass Group information to GitLab. - GitLab should know where to look for the groups in the SAML response, as well as which - groups include users with the [Auditor role](../user/permissions.md#auditor-users). + groups include users with the [Auditor access level](../administration/auditor_users.md). ```yaml { name: 'saml', @@ -410,11 +466,11 @@ The requirements are the same as the previous settings: } } ``` -## Group Sync +## Automatically manage SAML Group Sync For information on automatically managing GitLab group membership, see [SAML Group Sync](../user/group/saml_sso/group_sync.md). -## Bypass two factor authentication +## Bypass two-factor authentication If you want some SAML authentication methods to count as 2FA on a per session basis, you can register them in the `upstream_two_factor_authn_contexts` list. @@ -488,9 +544,57 @@ In addition to the changes in GitLab, make sure that your IdP is returning the 1. Save the file and [restart GitLab](../administration/restart_gitlab.md#installations-from-source) for the changes to take effect -## Customization +## Validate response signatures -### `auto_sign_in_with_provider` +We require Identity Providers to sign SAML responses to ensure that the assertions are +not tampered with. + +This prevents user impersonation and prevents privilege escalation when specific group +membership is required. Typically this: + +- Is configured using `idp_cert_fingerprint`. +- Includes the full certificate in the response, although if your Identity Provider + doesn't support this, you can directly configure GitLab using the `idp_cert` option. + +Example configuration with `idp_cert_fingerprint`: + +```yaml +args: { + assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback', + idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8', + idp_sso_target_url: 'https://login.example.com/idp', + issuer: 'https://gitlab.example.com', + name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent', +} +``` + +Example configuration with `idp_cert`: + +```yaml +args: { + assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback', + idp_cert: '-----BEGIN CERTIFICATE----- + + -----END CERTIFICATE-----', + idp_sso_target_url: 'https://login.example.com/idp', + issuer: 'https://gitlab.example.com', + name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent', +} +``` + +If the response signature validation is configured incorrectly, you can see error messages +such as: + +- A key validation error. +- Digest mismatch. +- Fingerprint mismatch. + +Refer to the [troubleshooting section](#troubleshooting) for more information on +solving these errors. + +## Customize SAML settings + +### Redirect users to SAML server for authentication You can add this setting to your GitLab configuration to automatically redirect you to your SAML server for authentication. This removes the requirement to select a button @@ -516,7 +620,7 @@ SAML users has administrator access. You may also bypass the auto sign-in feature by browsing to `https://gitlab.example.com/users/sign_in?auto_sign_in=false`. -### `attribute_statements` **(FREE SELF)** +### Map SAML response attribute names **(FREE SELF)** NOTE: This setting should be used only to map attributes that are part of the OmniAuth @@ -566,7 +670,7 @@ args: { This also sets the `username` attribute in your SAML Response to the username in GitLab. -### `allowed_clock_drift` +### Allow for clock drift The clock of the Identity Provider may drift slightly ahead of your system clocks. To allow for a small amount of clock drift, you can use `allowed_clock_drift` in @@ -585,7 +689,7 @@ args: { } ``` -### `uid_attribute` +### Designate a unique attribute for the `uid` By default, the `uid` is set as the `name_id` in the SAML response. If you'd like to designate a unique attribute for the `uid`, you can set the `uid_attribute`. In the example below, the value of `uid` attribute in the SAML response is set as the `uid_attribute`. @@ -600,59 +704,13 @@ args: { } ``` -Make sure you read the [Security](#security) section before changing this value. +Ensure that attributes define the SAML user, such as +[`NameID`](../user/group/saml_sso/index.md#nameid) and email address, are fixed +for each user before changing this value. -## Response signature validation (required) +## Assertion encryption (optional) -We require Identity Providers to sign SAML responses to ensure that the assertions are -not tampered with. - -This prevents user impersonation and prevents privilege escalation when specific group -membership is required. Typically this: - -- Is configured using `idp_cert_fingerprint`. -- Includes the full certificate in the response, although if your Identity Provider - doesn't support this, you can directly configure GitLab using the `idp_cert` option. - -Example configuration with `idp_cert_fingerprint`: - -```yaml -args: { - assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback', - idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8', - idp_sso_target_url: 'https://login.example.com/idp', - issuer: 'https://gitlab.example.com', - name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent', -} -``` - -Example configuration with `idp_cert`: - -```yaml -args: { - assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback', - idp_cert: '-----BEGIN CERTIFICATE----- - - -----END CERTIFICATE-----', - idp_sso_target_url: 'https://login.example.com/idp', - issuer: 'https://gitlab.example.com', - name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent', -} -``` - -If the response signature validation is configured incorrectly, you can see error messages -such as: - -- A key validation error. -- Digest mismatch. -- Fingerprint mismatch. - -Refer to the [troubleshooting section](#troubleshooting) for more information on -debugging these errors. - -## Assertion Encryption (optional) - -GitLab requires the use of TLS encryption with SAML, but in some cases there can be a +GitLab requires the use of TLS encryption with SAML 2.0, but in some cases there can be a need for additional encryption of the assertions. This may be the case, for example, if you terminate TLS encryption early at a load @@ -679,7 +737,7 @@ Your Identity Provider encrypts the assertion with the public certificate of Git NOTE: This integration uses the `certificate` and `private_key` settings for both assertion encryption and request signing. -## Request signing (optional) +## Sign SAML authentication requests (optional) Another optional configuration is to sign SAML authentication requests. GitLab SAML Requests use the SAML redirect binding, so this isn't necessary (unlike the @@ -713,18 +771,7 @@ args: { GitLab signs the request with the provided private key. GitLab includes the configured public x500 certificate in the metadata for your Identity Provider to validate the signature of the received request with. For more information on this option, see the [Ruby SAML gem documentation](https://github.com/onelogin/ruby-saml/tree/v1.7.0). The Ruby SAML gem is used by the [OmniAuth SAML gem](https://github.com/omniauth/omniauth-saml) to implement the client side of the SAML authentication. -## Security - -Avoid user control of the following attributes: - -- [`NameID`](../user/group/saml_sso/index.md#nameid) -- `Email` when used with `omniauth_auto_link_saml_user` - -These attributes define the SAML user. If users can change these attributes, they can impersonate others. - -Refer to the documentation for your SAML Identity Provider for information on how to fix these attributes. - -## Passwords for users created via SAML +## Password generation for users created through SAML The [Generated passwords for users created through integrated authentication](../security/passwords_for_integrated_authentication_methods.md) guide provides an overview of how GitLab generates and sets passwords for users created via SAML. @@ -738,7 +785,7 @@ Users authenticated with SSO or SAML must not use a password for Git operations A user can manually link their SAML identity to an existing GitLab account by following the steps in [Enable OmniAuth for an existing user](omniauth.md#enable-omniauth-for-an-existing-user). -## Configuring Group SAML on a self-managed GitLab instance **(PREMIUM SELF)** +## Group SAML on a self-managed GitLab instance **(PREMIUM SELF)** For information on the GitLab.com implementation, please see the [SAML SSO for GitLab.com groups page](../user/group/saml_sso). @@ -746,10 +793,10 @@ Group SAML SSO helps if you have to allow access via multiple SAML identity prov To proceed with configuring Group SAML SSO instead, enable the `group_saml` OmniAuth provider. This can be done from: -- `gitlab.rb` for [Omnibus GitLab installations](#omnibus-installations). -- `gitlab/config/gitlab.yml` for [source installations](#source-installations). +- `gitlab.rb` for Omnibus GitLab installations. +- `gitlab/config/gitlab.yml` for source installations. -### Limitations +### Self-managed instance group SAML limitations Group SAML on a self-managed instance is limited when compared to the recommended [instance-wide SAML](../user/group/saml_sso/index.md). The recommended solution allows you to take advantage of: @@ -760,7 +807,7 @@ Group SAML on a self-managed instance is limited when compared to the recommende - [Administrator groups](#administrator-groups). - [Auditor groups](#auditor-groups). -### Omnibus installations +For Omnibus installations: 1. Make sure GitLab is [configured with HTTPS](../install/installation.md#using-https). @@ -771,7 +818,7 @@ Group SAML on a self-managed instance is limited when compared to the recommende gitlab_rails['omniauth_providers'] = [{ name: 'group_saml' }] ``` -### Source installations +For installations from source: 1. Make sure GitLab is [configured with HTTPS](../install/installation.md#using-https). @@ -784,78 +831,39 @@ Group SAML on a self-managed instance is limited when compared to the recommende - { name: 'group_saml' } ``` -## Providers +## Additional configuration for SAML apps on your IdP -GitLab support of SAML means that you can sign in to GitLab with a wide range of identity providers. -Your identity provider may have additional documentation. Some identity providers include -documentation on how to use SAML to sign in to GitLab. +When configuring a SAML app on the IdP, your identity provider may require additional configuration, such as the following: -Examples: +| Field | Value | Notes | +|-------|-------|-------| +| SAML profile | Web browser SSO profile | GitLab uses SAML to sign users in through their browser. No requests are made directly to the identity provider. | +| SAML request binding | HTTP Redirect | GitLab (the service provider) redirects users to your identity provider with a base64 encoded `SAMLRequest` HTTP parameter. | +| SAML response binding | HTTP POST | Specifies how the SAML token is sent by your identity provider. Includes the `SAMLResponse`, which a user's browser submits back to GitLab. | +| Sign SAML response | Required | Prevents tampering. | +| X.509 certificate in response | Required | Signs the response and checks against the provided fingerprint. | +| Fingerprint algorithm | SHA-1 | GitLab uses a SHA-1 hash of the certificate to sign the SAML Response. | +| Signature algorithm | SHA-1/SHA-256/SHA-384/SHA-512 | Determines how a response is signed. Also known as the digest method, this can be specified in the SAML response. | +| Encrypt SAML assertion | Optional | Uses TLS between your identity provider, the user's browser, and GitLab. | +| Sign SAML assertion | Optional | Validates the integrity of a SAML assertion. When active, signs the whole response. | +| Check SAML request signature | Optional | Checks the signature on the SAML response. | +| Default RelayState | Optional | Specifies the URL users should end up on after successfully signing in through SAML at your identity provider. | +| NameID format | Persistent | See [NameID format details](../user/group/saml_sso/index.md#nameid-format). | +| Additional URLs | Optional | May include the issuer (or identifier) or the assertion consumer service URL in other fields on some providers. | -- [ADFS (Active Directory Federation Services)](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-relying-party-trust) -- [Auth0](https://auth0.com/docs/authenticate/protocols/saml/saml-sso-integrations/configure-auth0-saml-identity-provider) +For example configurations, see the [notes on specific providers](#set-up-identity-providers). -GitLab provides the following setup notes for guidance only. -If you have any questions on configuring the SAML app, please contact your provider's support. +## Glossary of common terms -### Okta setup notes - -1. In the Okta administrator section choose **Applications**. -1. When the app screen comes up you see another button to **Create App Integration** and - choose SAML 2.0 on the next screen. -1. Optionally, you can add a logo - (you can choose it from ). You must - crop and resize it. -1. Next, fill in the SAML general configuration with - the assertion consumer service URL as "Single sign-on URL" and - the issuer as "Audience URI" along with the [NameID](../user/group/saml_sso/index.md#nameid) and [assertions](#assertions). -1. The last part of the configuration is the feedback section where you can - just say you're a customer and creating an app for internal use. -1. When you have your app you can see a few tabs on the top of the app's - profile. Select the SAML 2.0 configuration instructions button. -1. On the screen that comes up take note of the - **Identity Provider Single Sign-On URL** which you can use for the - `idp_sso_target_url` on your GitLab configuration file. -1. **Before you leave Okta, make sure you add your user and groups if any.** - -### Google workspace setup notes - -The following guidance is based on this Google Workspace article, on how to [Set up your own custom SAML application](https://support.google.com/a/answer/6087519?hl=en): - -Make sure you have access to a Google Workspace [Super Admin](https://support.google.com/a/answer/2405986#super_admin) account. - Use the information below and follow the instructions in the linked Google Workspace article. - -| | Typical value | Description | -|------------------|--------------------------------------------------|----------------------------------------------------------| -| Name of SAML App | GitLab | Other names OK. | -| ACS URL | `https:///users/auth/saml/callback` | ACS is short for Assertion Consumer Service. | -| GITLAB_DOMAIN | `gitlab.example.com` | Set to the domain of your GitLab instance. | -| Entity ID | `https://gitlab.example.com` | A value unique to your SAML app, set it to the `issuer` in your GitLab configuration. | -| Name ID format | EMAIL | Required value. Also known as `name_identifier_format` | -| Name ID | Primary email address | Make sure someone receives content sent to that address | -| First name | `first_name` | Required value to communicate with GitLab. | -| Last name | `last_name` | Required value to communicate with GitLab. | - -You also must setup the following SAML attribute mappings: - -| Google Directory attributes | App attributes | -|-----------------------------------|----------------| -| Basic information > Email | `email` | -| Basic Information > First name | `first_name` | -| Basic Information > Last name | `last_name` | - -You may also use some of this information when you [configure GitLab](#general-setup). - -When configuring the Google Workspace SAML app, be sure to record the following information: - -| | Value | Description | -|-------------|--------------|-----------------------------------------------------------------------------------| -| SSO URL | Depends | Google Identity Provider details. Set to the GitLab `idp_sso_target_url` setting. | -| Certificate | Downloadable | Run `openssl x509 -in -noout -fingerprint` to generate the SHA1 fingerprint that can be used in the `idp_cert_fingerprint` setting. | - -While the Google Workspace Administrator provides IdP metadata, Entity ID, and SHA-256 -fingerprint, they are not required. GitLab does not need that information to -connect to the Google Workspace SAML app. +| Term | Description | +|--------------------------------|-------------| +| Identity provider (IdP) | The service which manages your user identities, such as Okta or OneLogin. | +| Service provider (SP) | GitLab can be configured as a SAML 2.0 SP. | +| Assertion | A piece of information about a user's identity, such as their name or role. Also known as claims or attributes. | +| Single Sign-On (SSO) | Name of authentication scheme. | +| Assertion consumer service URL | The callback on GitLab where users are redirected after successfully authenticating with the identity provider. | +| Issuer | How GitLab identifies itself to the identity provider. Also known as a "Relying party trust identifier". | +| Certificate fingerprint | Used to confirm that communications over SAML are secure by checking that the server is signing communications with the correct certificate. Also known as a certificate thumbprint. | ## Troubleshooting diff --git a/doc/subscriptions/gitlab_dedicated/index.md b/doc/subscriptions/gitlab_dedicated/index.md index 224ba954f1c..6bea3ba8ffd 100644 --- a/doc/subscriptions/gitlab_dedicated/index.md +++ b/doc/subscriptions/gitlab_dedicated/index.md @@ -14,14 +14,14 @@ GitLab Dedicated is a fully isolated, single-tenant SaaS service that is: - Hosted and managed by GitLab, Inc. - Deployed on AWS in a cloud region of your choice (see the [regions that are not supported](#aws-regions-not-supported)). -GitLab Dedicated removes the overhead of platform management to increase your operational efficiency, reduce risk, and enhance the speed and agility of your organization. Each GitLab Dedicated instance is highly available with disaster recovery and deployed into the cloud region of your choice. GitLab teams fully manage the maintenance and operations of each isolated instance, so customers can access our latest product improvements while meeting the most complex compliance standards. +GitLab Dedicated removes the overhead of platform management to increase your operational efficiency, reduce risk, and enhance the speed and agility of your organization. Each GitLab Dedicated instance is highly available with disaster recovery and deployed into the cloud region of your choice. GitLab teams fully manage the maintenance and operations of each isolated instance, so customers can access our latest product improvements while meeting the most complex compliance standards. It's the offering of choice for enterprises and organizations in highly regulated industries that have complex regulatory, compliance, and data residency requirements. ## Available features -- Authentication: Support for instance-level [SAML OmniAuth](../../integration/saml.md) functionality. GitLab Dedicated acts as the service provider, and you must provide the necessary [configuration](../../integration/saml.md#general-setup) in order for GitLab to communicate with your IdP. This is provided during onboarding. - - SAML [request signing](../../integration/saml.md#request-signing-optional), [group sync](../../user/group/saml_sso/group_sync.md#configure-saml-group-sync), and [SAML groups](../../integration/saml.md#saml-groups) are supported. +- Authentication: Support for instance-level [SAML OmniAuth](../../integration/saml.md) functionality. GitLab Dedicated acts as the service provider, and you must provide the necessary [configuration](../../integration/saml.md#configure-saml-support-in-gitlab) in order for GitLab to communicate with your IdP. This is provided during onboarding. + - SAML [request signing](../../integration/saml.md#sign-saml-authentication-requests-optional), [group sync](../../user/group/saml_sso/group_sync.md#configure-saml-group-sync), and [SAML groups](../../integration/saml.md#configure-users-based-on-saml-group-membership) are supported. - Networking: - Public connectivity with support for IP Allowlists. During onboarding, you can optionally specify a list of IP addresses that can access your GitLab Dedicated instance. Subsequently, when an IP not on the allowlist tries to access your instance the connection is refused. - Optional. Private connectivity via [AWS PrivateLink](https://aws.amazon.com/privatelink/). diff --git a/doc/user/admin_area/settings/continuous_integration.md b/doc/user/admin_area/settings/continuous_integration.md index 52798db870b..81e51aaef37 100644 --- a/doc/user/admin_area/settings/continuous_integration.md +++ b/doc/user/admin_area/settings/continuous_integration.md @@ -46,7 +46,10 @@ limit on the number of [CI/CD minutes](../../../ci/pipelines/cicd_minutes.md) yo ## Enable a specific runner for multiple projects -To enable a specific runner for one or more projects: +If you have already registered a [specific runner](../../../ci/runners/runners_scope.md#specific-runners) +you can assign that runner to other projects. + +To enable a specific runner for more than one project: 1. On the top bar, select **Main menu > Admin**. 1. From the left sidebar, select **Overview > Runners**. diff --git a/doc/user/analytics/index.md b/doc/user/analytics/index.md index 01fe466755c..38d92180c7d 100644 --- a/doc/user/analytics/index.md +++ b/doc/user/analytics/index.md @@ -12,7 +12,7 @@ Instance-level analytics make it possible to aggregate analytics across GitLab, so that users can view information across multiple projects and groups in one place. -[Learn more about instance-level analytics](../admin_area/analytics/index.md). +For more information, see [instance-level analytics](../admin_area/analytics/index.md). ## Group-level analytics diff --git a/doc/user/group/manage.md b/doc/user/group/manage.md index 163354fc37d..414b80d0f1d 100644 --- a/doc/user/group/manage.md +++ b/doc/user/group/manage.md @@ -172,7 +172,7 @@ Prerequisite: 1. On the left sidebar, select **Group information > Members**. 1. Select **Invite members**. 1. Fill in the fields. - - The role applies to all projects in the group. [Learn more about permissions](../permissions.md). + - The role applies to all projects in the group. For more information, see [permissions](../permissions.md). - On the **Access expiration date**, the user can no longer access projects in the group. 1. Select **Invite**. @@ -530,10 +530,10 @@ in a subgroup has access to the templates for that subgroup and any immediate parent groups. To learn how to create templates for issues and merge requests, see -[Description templates](../project/description_templates.md). +[description templates](../project/description_templates.md). Define project templates at a group level by setting a group as the template source. -[Learn more about group-level project templates](custom_project_templates.md). +For more information, see [group-level project templates](custom_project_templates.md). ### Enable group file template **(PREMIUM)** diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md index 1c5e7ff0115..15593655fac 100644 --- a/doc/user/group/saml_sso/index.md +++ b/doc/user/group/saml_sso/index.md @@ -72,7 +72,7 @@ must be specified as an attribute named `email` or `mail`. You can configure the following attributes with GitLab.com Group SAML: - `username` or `nickname`. We recommend you configure only one of these. -- The [attributes available](../../../integration/saml.md#assertions) to self-managed GitLab instances. +- The [attributes available](../../../integration/saml.md#configure-assertions) to self-managed GitLab instances. ### Metadata configuration @@ -98,7 +98,7 @@ After you set up your identity provider to work with GitLab, you must configure ![Group SAML Settings for GitLab.com](img/group_saml_settings_v13_12.png) NOTE: -The certificate [fingerprint algorithm](../../../integration/saml.md#notes-on-configuring-your-identity-provider) must be in SHA1. When configuring the identity provider (such as [Google Workspace](#google-workspace-setup-notes)), use a secure signature algorithm. +The certificate [fingerprint algorithm](../../../integration/saml.md#configure-saml-on-your-idp) must be in SHA1. When configuring the identity provider (such as [Google Workspace](#google-workspace-setup-notes)), use a secure signature algorithm. ### Additional configuration information @@ -184,7 +184,7 @@ The SAML standard means that you can use a wide range of identity providers with When [configuring your identity provider](#configure-your-identity-provider), consider the notes below for specific providers to help avoid common issues and as a guide for terminology used. -For providers not listed below, you can refer to the [instance SAML notes on configuring an identity provider](../../../integration/saml.md#notes-on-configuring-your-identity-provider) +For providers not listed below, you can refer to the [instance SAML notes on configuring an identity provider](../../../integration/saml.md#configure-saml-on-your-idp) for additional guidance on information your identity provider may require. GitLab provides the following information for guidance only. diff --git a/doc/user/group/saml_sso/troubleshooting.md b/doc/user/group/saml_sso/troubleshooting.md index 7dafd2c5075..048a8b461b4 100644 --- a/doc/user/group/saml_sso/troubleshooting.md +++ b/doc/user/group/saml_sso/troubleshooting.md @@ -52,7 +52,7 @@ You can use one of the following to troubleshoot SAML: - A [quick start guide to start a Docker container](../../../administration/troubleshooting/test_environments.md#saml) with a plug and play SAML 2.0 identity provider if you only require a SAML provider. - A local environment by - [enabling SAML for groups on a self-managed instance](../../../integration/saml.md#configuring-group-saml-on-a-self-managed-gitlab-instance). + [enabling SAML for groups on a self-managed instance](../../../integration/saml.md#group-saml-on-a-self-managed-gitlab-instance). ## Verify configuration @@ -138,7 +138,7 @@ Make sure this information is provided. Another issue that can result in this error is when the correct information is being sent by the identity provider, but the attributes don't match the names in the OmniAuth `info` hash. In this case, you must set `attribute_statements` in the SAML configuration to -[map the attribute names in your SAML Response to the corresponding OmniAuth `info` hash names](../../../integration/saml.md#attribute_statements). +[map the attribute names in your SAML Response to the corresponding OmniAuth `info` hash names](../../../integration/saml.md#map-saml-response-attribute-names). ## User sign in banner error messages @@ -221,7 +221,7 @@ If all users are receiving a `404` when attempting to sign in using SAML, confir [there is an active subscription](../../../subscriptions/gitlab_com/index.md#view-your-gitlab-saas-subscription) being used in this SAML SSO namespace. If you receive a `404` during setup when using "verify configuration", make sure you have used the correct -[SHA-1 generated fingerprint](../../../integration/saml.md#notes-on-configuring-your-identity-provider). +[SHA-1 generated fingerprint](../../../integration/saml.md#configure-saml-on-your-idp). If a user is trying to sign in for the first time and the GitLab single sign-on URL has not [been configured](index.md#configure-your-identity-provider), they may see a 404. As outlined in the [user access section](index.md#linking-saml-to-your-existing-gitlabcom-account), a group Owner needs to provide the URL to users. diff --git a/doc/user/permissions.md b/doc/user/permissions.md index 34fd4ea7094..5f56be66d54 100644 --- a/doc/user/permissions.md +++ b/doc/user/permissions.md @@ -12,13 +12,7 @@ The role determines which actions they can take in GitLab. If you add a user to both a project's group and the project itself, the higher role is used. -When a member leaves a team's project, all the assigned [issues](project/issues/index.md) and -[merge requests](project/merge_requests/index.md) are automatically unassigned. - -GitLab [administrators](../administration/index.md) receive all permissions. - -To add or import a user, you can follow the -[project members documentation](project/members/index.md). +GitLab [administrators](../administration/index.md) have all permissions. ## Roles @@ -33,11 +27,9 @@ The available roles are: A user assigned the Guest role has the least permissions, and the Owner has the most. -## Instance-wide user permissions - -By default, users can create top-level groups and change their -usernames. A GitLab administrator can configure the GitLab instance to -[modify this behavior](../administration/user_settings.md). +By default, all users can create top-level groups and change their +usernames. A GitLab administrator can [change this behavior](../administration/user_settings.md) +for the GitLab instance. ## Project members permissions @@ -337,18 +329,6 @@ This table shows granted privileges for jobs triggered by specific types of user 1. Only if the triggering user is not an external one. 1. Only if the triggering user is a member of the project. See also [Usage of private Docker images with `if-not-present` pull policy](http://docs.gitlabl.com/runner/security/index.html#usage-of-private-docker-images-with-if-not-present-pull-policy). -### Protected branches - -Additional restrictions can be applied on a per-branch basis with [protected branches](project/protected_branches.md). -Additionally, you can customize permissions to allow or prevent project Developers or Maintainers -from pushing to a protected branch. Read through the documentation on -[protected branches](project/protected_branches.md) to learn more. - -### Value stream analytics permissions - -Find the current permissions on the value stream analytics dashboard, as described in -[related documentation](analytics/value_stream_analytics.md#access-permissions-for-value-stream-analytics). - ### File Locking permissions **(PREMIUM)** The user that locks a file or directory is the only one that can edit and push their changes back to the repository where the locked objects are located. @@ -459,16 +439,6 @@ nested groups if you have membership in one of its parents. To learn more, read through the documentation on [subgroups memberships](group/subgroups/index.md#subgroup-membership). -## Auditor users **(PREMIUM SELF)** - -Auditor users are given read-only access to all projects, groups, and other -resources on the GitLab instance. - -An Auditor user should be able to access all projects and groups of a GitLab instance -with the permissions described on the documentation on [auditor users permissions](../administration/auditor_users.md#auditor-user-permissions-and-restrictions). - -[Read more about Auditor users.](../administration/auditor_users.md) - ## Users with minimal access **(PREMIUM)** > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40942) in GitLab 13.4. @@ -506,5 +476,9 @@ for more information. ## Related topics - [The GitLab principles behind permissions](https://about.gitlab.com/handbook/product/gitlab-the-product/#permissions-in-gitlab) -- [Project aliases](../user/project/import/index.md#project-aliases) +- [Members](project/members/index.md) +- Customize permissions on [protected branches](project/protected_branches.md) - [LDAP users permissions](group/access_and_permissions.md#manage-group-memberships-via-ldap) +- [Value stream analytics permissions](analytics/value_stream_analytics.md#access-permissions-for-value-stream-analytics) +- [Project aliases](../user/project/import/index.md#project-aliases) +- [Auditor users](../administration/auditor_users.md) diff --git a/doc/user/project/badges.md b/doc/user/project/badges.md index 2275d57772f..5d1d10fc37d 100644 --- a/doc/user/project/badges.md +++ b/doc/user/project/badges.md @@ -89,7 +89,6 @@ which are evaluated when displaying the badge. The following placeholders are available: - `%{project_path}`: Path of a project including the parent groups -- `%{project_name}`: Name of the project - `%{project_id}`: Database ID associated with a project - `%{default_branch}`: Default branch name configured for a project's repository - `%{commit_sha}`: ID of the most recent commit to the default branch of a diff --git a/doc/user/project/import/index.md b/doc/user/project/import/index.md index 1b5a658d209..5753b0a5b97 100644 --- a/doc/user/project/import/index.md +++ b/doc/user/project/import/index.md @@ -61,20 +61,43 @@ file with a URL host (`lfs.url`) different from the repository URL host, LFS fil ## Migrate from self-managed GitLab to GitLab.com +Depending on your requirements, there are several ways to migrate from self-managed GitLab to GitLab.com. + +### Migrate using GitLab Migration (recommended) + +Using [GitLab Migration](../../group/import/index.md), you can migrate top-level groups you are the Owner of, with all their subgroups and projects included. + +GitLab Migration maps users and their contributions correctly on GitLab.com provided: + +- Contributing users exist on GitLab.com at the time of the import. +- Those users have a public email on the source GitLab instance that matches their primary email on GitLab.com. + +If you use [SAML SSO for GitLab.com groups](../../group/saml_sso/index.md), +contributing users must have [linked their SAML identity to their GitLab.com account](../../group/saml_sso/index.md#linking-saml-to-your-existing-gitlabcom-account). + +When migrating to GitLab.com, you must create users manually unless [SCIM](../../group/saml_sso/scim_setup.md) is used. Creating users with the API is only +available to self-managed instances because it requires administrator access. + +### Migrate specific projects only + If you only need to migrate Git repositories, you can [import each project by URL](repo_by_url.md). -However, you can't import issues and merge requests this way. To retain all metadata like issues and +However, you can't import issues and merge requests this way. To retain metadata like issues and merge requests, use the [import/export feature](../settings/import_export.md) -to export projects from self-managed GitLab and import those projects into GitLab.com. All GitLab -user associations (such as comment author) are changed to the user importing the project. For more +to export projects from self-managed GitLab and import those projects into GitLab.com. + +GitLab maps user contributions correctly when an admin access token is used to perform the import. + +As a result, the import/export feature does not map user contributions correctly when you are importing projects from a self-managed instance to GitLab.com. + +Instead, all GitLab user associations (such as comment author) are changed to the user importing the project. For more information, see the prerequisites and important notes in these sections: - [Export a project and its data](../settings/import_export.md#export-a-project-and-its-data). - [Import the project](../settings/import_export.md#import-a-project-and-its-data). -NOTE: -When migrating to GitLab.com, you must create users manually unless [SCIM](../../../user/group/saml_sso/scim_setup.md) -will be used. Creating users with the API is limited to self-managed instances as it requires -administrator access. +To preserve contribution history, [migrate using GitLab Migration](#migrate-using-gitlab-migration-recommended). + +### Migrate using the API To migrate all data from self-managed to GitLab.com, you can leverage the [API](../../../api/index.md). Migrate the assets in this order: @@ -83,7 +106,7 @@ Migrate the assets in this order: 1. [Projects](../../../api/projects.md) 1. [Project variables](../../../api/project_level_variables.md) -Keep in mind the limitations of the [import/export feature](../settings/import_export.md#items-that-are-exported). +Keep in mind the limitations of the [import/export feature](../settings/import_export.md#items-that-are-exported). As with [Migrating specific projects using the import/export feature](#migrate-specific-projects-only) user associations (such as comment author) are changed to the user importing projects when migrating from self-managed to GitLab.com. You must still migrate your [Container Registry](../../packages/container_registry/index.md) over a series of Docker pulls and pushes. Re-run any CI pipelines to retrieve any build artifacts. diff --git a/doc/user/project/time_tracking.md b/doc/user/project/time_tracking.md index 71b8c911839..186ca0ba9f0 100644 --- a/doc/user/project/time_tracking.md +++ b/doc/user/project/time_tracking.md @@ -74,6 +74,25 @@ Prerequisites: - You must have at least the Reporter role for the project. +#### Using the user interface + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/101563) in GitLab 15.7. + +To add a time entry using the user interface: + +1. In the **Time tracking** section of the sidebar, select **Add time entry** (**{plus}**). A modal opens. +1. Enter: + + - The amount of time spent. + - Optional. When it was spent. + - Optional. A summary. + +1. Select **Save**. + +The **Spent** total in the sidebar is updated and you can view all entries in a [time tracking report](#view-a-time-tracking-report). + +#### Using a quick action + To enter time spent, use the `/spend` [quick action](quick_actions.md), followed by the time. For example, if you need @@ -90,15 +109,10 @@ Draft MR and respond to initial comments /spend 30m ``` -### Add time spent on a specific date +To log when time was spent, enter a date after the time, using the `YYYY-MM-DD` format. -Prerequisites: - -- You must have at least the Reporter role for the project. - -You can log time in the past by providing a date after the time. For example, to log 1 hour of time spent on 31 January 2021, -type `/spend 1h 2021-01-31`. +enter `/spend 1h 2021-01-31`. If you type a future date, no time is logged. diff --git a/doc/user/project/working_with_projects.md b/doc/user/project/working_with_projects.md index 006a33b8298..77a7c48658e 100644 --- a/doc/user/project/working_with_projects.md +++ b/doc/user/project/working_with_projects.md @@ -363,8 +363,11 @@ Prerequisite: ## Leave a project -If you leave a project, you are no longer a project -member and cannot contribute. +When you leave a project: + +- You are no longer a project member and cannot contribute. +- All the issues and merge requests that were assigned + to you are unassigned. To leave a project: diff --git a/doc/user/workspace/index.md b/doc/user/workspace/index.md index c18a21e875b..4a8b083e3a2 100644 --- a/doc/user/workspace/index.md +++ b/doc/user/workspace/index.md @@ -30,7 +30,7 @@ Our goal is to reach feature parity between SaaS and self-managed installations, - Hardware Controls. For functionality that does not apply to groups, Hardware Controls are only applicable to self-managed installations. There is one Hardware Controls section per installation. -To learn about the current state of workspace development, +For more information about the state of workspace development, see [epic 9265](https://gitlab.com/groups/gitlab-org/-/epics/9265). diff --git a/lib/gitlab/database/load_balancing/sidekiq_client_middleware.rb b/lib/gitlab/database/load_balancing/sidekiq_client_middleware.rb index 13afbd8fd37..619f11ae890 100644 --- a/lib/gitlab/database/load_balancing/sidekiq_client_middleware.rb +++ b/lib/gitlab/database/load_balancing/sidekiq_client_middleware.rb @@ -57,7 +57,7 @@ module Gitlab if uses_primary? load_balancer.primary_write_location else - load_balancer.host.database_replica_location + load_balancer.host&.database_replica_location || load_balancer.primary_write_location end end diff --git a/lib/gitlab/instrumentation/redis.rb b/lib/gitlab/instrumentation/redis.rb index da0061a4d99..a664656c467 100644 --- a/lib/gitlab/instrumentation/redis.rb +++ b/lib/gitlab/instrumentation/redis.rb @@ -39,7 +39,8 @@ module Gitlab end end - %i[get_request_count get_cross_slot_request_count query_time read_bytes write_bytes].each do |method| + %i[get_request_count get_cross_slot_request_count get_allowed_cross_slot_request_count query_time read_bytes + write_bytes].each do |method| define_method method do STORAGES.sum(&method) end diff --git a/lib/gitlab/instrumentation/redis_base.rb b/lib/gitlab/instrumentation/redis_base.rb index f88181820d8..de24132a28e 100644 --- a/lib/gitlab/instrumentation/redis_base.rb +++ b/lib/gitlab/instrumentation/redis_base.rb @@ -50,6 +50,11 @@ module Gitlab ::RequestStore[cross_slots_key] += amount end + def increment_allowed_cross_slot_request_count(amount = 1) + ::RequestStore[allowed_cross_slots_key] ||= 0 + ::RequestStore[allowed_cross_slots_key] += amount + end + def get_request_count ::RequestStore[request_count_key] || 0 end @@ -70,6 +75,10 @@ module Gitlab ::RequestStore[cross_slots_key] || 0 end + def get_allowed_cross_slot_request_count + ::RequestStore[allowed_cross_slots_key] || 0 + end + def query_time query_time = ::RequestStore[call_duration_key] || 0 query_time.round(::Gitlab::InstrumentationHelper::DURATION_PRECISION) @@ -85,6 +94,8 @@ module Gitlab raise RedisClusterValidator::CrossSlotError, "Redis command #{result[:command_name]} arguments hash to different slots. See https://docs.gitlab.com/ee/development/redis.html#multi-key-commands" end + increment_allowed_cross_slot_request_count if result[:allowed] + result[:valid] end @@ -144,6 +155,10 @@ module Gitlab strong_memoize(:cross_slots_key) { build_key(:redis_cross_slot_request_count) } end + def allowed_cross_slots_key + strong_memoize(:allowed_cross_slots_key) { build_key(:redis_allowed_cross_slot_request_count) } + end + def build_key(namespace) "#{storage_key}_#{namespace}" end diff --git a/lib/gitlab/instrumentation/redis_payload.rb b/lib/gitlab/instrumentation/redis_payload.rb index 3a9835410af..62a4d1a846f 100644 --- a/lib/gitlab/instrumentation/redis_payload.rb +++ b/lib/gitlab/instrumentation/redis_payload.rb @@ -21,6 +21,7 @@ module Gitlab { "#{key_prefix}_calls": -> { get_request_count }, "#{key_prefix}_cross_slot_calls": -> { get_cross_slot_request_count }, + "#{key_prefix}_allowed_cross_slot_calls": -> { get_allowed_cross_slot_request_count }, "#{key_prefix}_duration_s": -> { query_time }, "#{key_prefix}_read_bytes": -> { read_bytes }, "#{key_prefix}_write_bytes": -> { write_bytes } diff --git a/lib/gitlab/memory/reports/heap_dump.rb b/lib/gitlab/memory/reports/heap_dump.rb index 115f9efe753..95779407f12 100644 --- a/lib/gitlab/memory/reports/heap_dump.rb +++ b/lib/gitlab/memory/reports/heap_dump.rb @@ -18,16 +18,15 @@ module Gitlab 'heap_dump' end - # This will be enabled once https://gitlab.com/gitlab-org/gitlab/-/issues/370077 is done. def active? - false + Feature.enabled?(:report_heap_dumps, type: :ops) end - # This is a no-op currently and will be implemented at a later time in - # https://gitlab.com/gitlab-org/gitlab/-/issues/370077 def run(writer) return false unless self.class.enqueued? + ObjectSpace.dump_all(output: writer) + true end end diff --git a/lib/gitlab/memory/watchdog.rb b/lib/gitlab/memory/watchdog.rb index 2e0add73478..fdaaa183ca1 100644 --- a/lib/gitlab/memory/watchdog.rb +++ b/lib/gitlab/memory/watchdog.rb @@ -94,7 +94,7 @@ module Gitlab def strike_exceeded_callback(monitor_name, monitor_payload) event_reporter.strikes_exceeded(monitor_name, log_labels(monitor_payload)) - Gitlab::Memory::Reports::HeapDump.enqueue! if @configuration.write_heap_dumps? + Gitlab::Memory::Reports::HeapDump.enqueue! handler.call end diff --git a/lib/gitlab/memory/watchdog/configuration.rb b/lib/gitlab/memory/watchdog/configuration.rb index 980b6bf750b..5e2154af434 100644 --- a/lib/gitlab/memory/watchdog/configuration.rb +++ b/lib/gitlab/memory/watchdog/configuration.rb @@ -35,7 +35,7 @@ module Gitlab DEFAULT_SLEEP_TIME_SECONDS = 60 - attr_writer :event_reporter, :handler, :sleep_time_seconds, :write_heap_dumps + attr_writer :event_reporter, :handler, :sleep_time_seconds def monitors @monitor_stack ||= MonitorStack.new @@ -55,10 +55,6 @@ module Gitlab def sleep_time_seconds @sleep_time_seconds ||= DEFAULT_SLEEP_TIME_SECONDS end - - def write_heap_dumps? - !!@write_heap_dumps - end end end end diff --git a/lib/gitlab/memory/watchdog/configurator.rb b/lib/gitlab/memory/watchdog/configurator.rb index 2848d6c36e9..04c04cbde02 100644 --- a/lib/gitlab/memory/watchdog/configurator.rb +++ b/lib/gitlab/memory/watchdog/configurator.rb @@ -18,7 +18,6 @@ module Gitlab def configure_for_puma ->(config) do config.handler = Gitlab::Memory::Watchdog::PumaHandler.new - config.write_heap_dumps = write_heap_dumps? config.sleep_time_seconds = ENV.fetch('GITLAB_MEMWD_SLEEP_TIME_SEC', DEFAULT_SLEEP_INTERVAL_S).to_i config.monitors(&configure_monitors_for_puma) end @@ -27,7 +26,6 @@ module Gitlab def configure_for_sidekiq ->(config) do config.handler = Gitlab::Memory::Watchdog::TermProcessHandler.new - config.write_heap_dumps = write_heap_dumps? config.sleep_time_seconds = sidekiq_sleep_time config.monitors(&configure_monitors_for_sidekiq) config.event_reporter = SidekiqEventReporter.new @@ -36,10 +34,6 @@ module Gitlab private - def write_heap_dumps? - Gitlab::Utils.to_boolean(ENV['GITLAB_MEMWD_DUMP_HEAP'], default: false) - end - def configure_monitors_for_puma ->(stack) do max_strikes = ENV.fetch('GITLAB_MEMWD_MAX_STRIKES', DEFAULT_MAX_STRIKES).to_i diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 258d61624f2..54004b722f8 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -15805,6 +15805,9 @@ msgstr "" msgid "Error fetching refs" msgstr "" +msgid "Error fetching target projects. Please try again." +msgstr "" + msgid "Error fetching the dependency list. Please check your network connection and try again." msgstr "" diff --git a/spec/controllers/omniauth_callbacks_controller_spec.rb b/spec/controllers/omniauth_callbacks_controller_spec.rb index 0560ccb25dd..ab3f3fd397d 100644 --- a/spec/controllers/omniauth_callbacks_controller_spec.rb +++ b/spec/controllers/omniauth_callbacks_controller_spec.rb @@ -391,6 +391,32 @@ RSpec.describe OmniauthCallbacksController, type: :controller do end end end + + context 'with snowplow tracking', :snowplow do + let(:provider) { 'google_oauth2' } + let(:extern_uid) { 'my-uid' } + + context 'when sign_in' do + it 'does not track the event' do + post provider + expect_no_snowplow_event + end + end + + context 'when sign_up' do + let(:user) { double(email: generate(:email)) } + + it 'tracks the event' do + post provider + + expect_snowplow_event( + category: described_class.name, + action: "#{provider}_sso", + user: User.find_by(email: user.email) + ) + end + end + end end describe '#saml' do diff --git a/spec/controllers/projects/merge_requests/creations_controller_spec.rb b/spec/controllers/projects/merge_requests/creations_controller_spec.rb index a061a14c7b1..ace8c04b819 100644 --- a/spec/controllers/projects/merge_requests/creations_controller_spec.rb +++ b/spec/controllers/projects/merge_requests/creations_controller_spec.rb @@ -306,4 +306,18 @@ RSpec.describe Projects::MergeRequests::CreationsController do post :create, params: merge_request_params end end + + describe 'GET target_projects', feature_category: :code_review do + it 'returns target projects JSON' do + get :target_projects, params: { namespace_id: project.namespace.to_param, project_id: project } + + expect(json_response.size).to be(2) + + forked_project = json_response.first + expect(forked_project).to have_key('id') + expect(forked_project).to have_key('name') + expect(forked_project).to have_key('full_path') + expect(forked_project).to have_key('refs_url') + end + end end diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb index b34244b4c14..e0ed58f291e 100644 --- a/spec/controllers/registrations_controller_spec.rb +++ b/spec/controllers/registrations_controller_spec.rb @@ -36,7 +36,7 @@ RSpec.describe RegistrationsController do let(:session_params) { {} } - subject { post(:create, params: user_params, session: session_params) } + subject(:post_create) { post(:create, params: user_params, session: session_params) } context '`blocked_pending_approval` state' do context 'when the `require_admin_approval_after_user_signup` setting is turned on' do @@ -484,18 +484,19 @@ RSpec.describe RegistrationsController do render_views let_it_be(:new_user_params) { { new_user: base_user_params.merge({ password: "password" }) } } - subject { post(:create, params: new_user_params) } + subject(:post_create) { post(:create, params: new_user_params) } it 'renders the form with errors' do - expect { subject }.not_to change(User, :count) + expect { post_create }.not_to change(User, :count) expect(controller.current_user).to be_nil expect(response).to render_template(:new) expect(response.body).to include(_('Password must not contain commonly used combinations of words and letters')) end - it 'tracks the error' do - subject + it 'tracks a weak password error' do + post_create + expect_snowplow_event( category: 'Gitlab::Tracking::Helpers::WeakPasswordErrorEvent', action: 'track_weak_password_error', @@ -503,16 +504,36 @@ RSpec.describe RegistrationsController do method: 'create' ) end + + it 'does not track failed form submission' do + post_create + + expect_no_snowplow_event( + category: described_class.name, + action: 'successfully_submitted_form' + ) + end end context 'when the password is not weak' do it 'does not track a weak password error' do - subject + post_create + expect_no_snowplow_event( category: 'Gitlab::Tracking::Helpers::WeakPasswordErrorEvent', action: 'track_weak_password_error' ) end + + it 'tracks successful form submission' do + post_create + + expect_snowplow_event( + category: described_class.name, + action: 'successfully_submitted_form', + user: User.find_by(email: base_user_params[:email]) + ) + end end context 'with preferred language' do diff --git a/spec/features/merge_request/user_creates_merge_request_spec.rb b/spec/features/merge_request/user_creates_merge_request_spec.rb index abfe78d6bce..50629f11959 100644 --- a/spec/features/merge_request/user_creates_merge_request_spec.rb +++ b/spec/features/merge_request/user_creates_merge_request_spec.rb @@ -77,7 +77,7 @@ RSpec.describe 'User creates a merge request', :js, feature_category: :code_revi first('.dropdown-source-project a', text: forked_project.full_path) first('.js-target-project').click - first('.dropdown-target-project a', text: project.full_path) + first('.dropdown-target-project li', text: project.full_path) first('.js-source-branch').click diff --git a/spec/frontend/merge_requests/components/target_project_dropdown_spec.js b/spec/frontend/merge_requests/components/target_project_dropdown_spec.js new file mode 100644 index 00000000000..795fae2f8d8 --- /dev/null +++ b/spec/frontend/merge_requests/components/target_project_dropdown_spec.js @@ -0,0 +1,77 @@ +import { mount } from '@vue/test-utils'; +import MockAdapter from 'axios-mock-adapter'; +import waitForPromises from 'helpers/wait_for_promises'; +import axios from '~/lib/utils/axios_utils'; +import TargetProjectDropdown from '~/merge_requests/components/target_project_dropdown.vue'; + +let wrapper; +let mock; + +function factory() { + wrapper = mount(TargetProjectDropdown, { + provide: { + targetProjectsPath: '/gitlab-org/gitlab/target_projects', + currentProject: { value: 1, text: 'gitlab-org/gitlab' }, + }, + }); +} + +describe('Merge requests target project dropdown component', () => { + beforeEach(() => { + mock = new MockAdapter(axios); + mock.onGet('/gitlab-org/gitlab/target_projects').reply(200, [ + { + id: 10, + name: 'Gitlab Test', + full_path: '/root/gitlab-test', + full_name: 'Administrator / Gitlab Test', + refs_url: '/root/gitlab-test/refs', + }, + { + id: 1, + name: 'Gitlab Test', + full_path: '/gitlab-org/gitlab-test', + full_name: 'Gitlab Org / Gitlab Test', + refs_url: '/gitlab-org/gitlab-test/refs', + }, + ]); + }); + + afterEach(() => { + wrapper.destroy(); + mock.restore(); + }); + + it('creates hidden input with currentProject ID', () => { + factory(); + + expect(wrapper.find('[data-testid="target-project-input"]').attributes('value')).toBe('1'); + }); + + it('renders list of projects', async () => { + factory(); + + wrapper.find('[data-testid="base-dropdown-toggle"]').trigger('click'); + + await waitForPromises(); + + expect(wrapper.findAll('li').length).toBe(2); + expect(wrapper.findAll('li').at(0).text()).toBe('root/gitlab-test'); + expect(wrapper.findAll('li').at(1).text()).toBe('gitlab-org/gitlab-test'); + }); + + it('searches projects', async () => { + factory(); + + wrapper.find('[data-testid="base-dropdown-toggle"]').trigger('click'); + + await waitForPromises(); + + wrapper.find('[data-testid="listbox-search-input"]').setValue('test'); + + jest.advanceTimersByTime(500); + await waitForPromises(); + + expect(mock.history.get[1].params).toEqual({ search: 'test' }); + }); +}); diff --git a/spec/graphql/types/alert_management/alert_type_spec.rb b/spec/graphql/types/alert_management/alert_type_spec.rb index 69cbdb998eb..c1df24ccb5c 100644 --- a/spec/graphql/types/alert_management/alert_type_spec.rb +++ b/spec/graphql/types/alert_management/alert_type_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GitlabSchema.types['AlertManagementAlert'] do +RSpec.describe GitlabSchema.types['AlertManagementAlert'], feature_category: :incident_management do specify { expect(described_class.graphql_name).to eq('AlertManagementAlert') } specify { expect(described_class).to require_graphql_authorizations(:read_alert_management_alert) } @@ -11,6 +11,7 @@ RSpec.describe GitlabSchema.types['AlertManagementAlert'] do it 'exposes the expected fields' do expected_fields = %i[ + id iid issueIid issue diff --git a/spec/initializers/diagnostic_reports_spec.rb b/spec/initializers/diagnostic_reports_spec.rb index 20d0b2714f0..dc989efe809 100644 --- a/spec/initializers/diagnostic_reports_spec.rb +++ b/spec/initializers/diagnostic_reports_spec.rb @@ -2,16 +2,17 @@ require 'spec_helper' -RSpec.describe 'diagnostic reports' do +RSpec.describe 'diagnostic reports', :aggregate_failures, feature_category: :application_performance do subject(:load_initializer) do load Rails.root.join('config/initializers/diagnostic_reports.rb') end - shared_examples 'does not modify worker startup hooks' do + shared_examples 'does not modify worker hooks' do it do expect(Gitlab::Cluster::LifecycleEvents).not_to receive(:on_worker_start) expect(Gitlab::Cluster::LifecycleEvents).not_to receive(:on_worker_stop) expect(Gitlab::Memory::ReportsDaemon).not_to receive(:instance) + expect(Gitlab::Memory::Reporter).not_to receive(:new) load_initializer end @@ -32,6 +33,7 @@ RSpec.describe 'diagnostic reports' do it 'modifies worker startup hooks, starts Gitlab::Memory::ReportsDaemon' do expect(Gitlab::Cluster::LifecycleEvents).to receive(:on_worker_start).and_call_original + expect(Gitlab::Cluster::LifecycleEvents).to receive(:on_worker_stop) # stub this out to not mutate global state expect_next_instance_of(Gitlab::Memory::ReportsDaemon) do |daemon| expect(daemon).to receive(:start) end @@ -39,30 +41,15 @@ RSpec.describe 'diagnostic reports' do load_initializer end - context 'when GITLAB_MEMWD_DUMP_HEAP is set' do - before do - stub_env('GITLAB_MEMWD_DUMP_HEAP', '1') - end + it 'writes scheduled heap dumps in on_worker_stop' do + expect(Gitlab::Cluster::LifecycleEvents).to receive(:on_worker_start) + expect(Gitlab::Cluster::LifecycleEvents).to receive(:on_worker_stop).and_call_original + expect(Gitlab::Memory::Reporter).to receive(:new).and_return(reporter) + expect(reporter).to receive(:run_report).with(an_instance_of(Gitlab::Memory::Reports::HeapDump)) - it 'writes scheduled heap dumps in on_worker_stop' do - expect(Gitlab::Cluster::LifecycleEvents).to receive(:on_worker_start) - expect(Gitlab::Cluster::LifecycleEvents).to receive(:on_worker_stop).and_call_original - expect(Gitlab::Memory::Reporter).to receive(:new).and_return(reporter) - expect(reporter).to receive(:run_report).with(an_instance_of(Gitlab::Memory::Reports::HeapDump)) - - load_initializer - # This is necessary because this hook normally fires during worker shutdown. - Gitlab::Cluster::LifecycleEvents.do_worker_stop - end - end - - context 'when GITLAB_MEMWD_DUMP_HEAP is not set' do - it 'does not write heap dumps' do - expect(Gitlab::Cluster::LifecycleEvents).to receive(:on_worker_start) - expect(Gitlab::Cluster::LifecycleEvents).not_to receive(:on_worker_stop) - - load_initializer - end + load_initializer + # This is necessary because this hook normally fires during worker shutdown. + Gitlab::Cluster::LifecycleEvents.do_worker_stop end end @@ -71,7 +58,7 @@ RSpec.describe 'diagnostic reports' do allow(::Gitlab::Runtime).to receive(:puma?).and_return(false) end - include_examples 'does not modify worker startup hooks' + include_examples 'does not modify worker hooks' end end @@ -80,7 +67,7 @@ RSpec.describe 'diagnostic reports' do allow(::Gitlab::Runtime).to receive(:puma?).and_return(true) end - include_examples 'does not modify worker startup hooks' + include_examples 'does not modify worker hooks' end context 'when GITLAB_DIAGNOSTIC_REPORTS_ENABLED is set to false' do @@ -89,6 +76,6 @@ RSpec.describe 'diagnostic reports' do allow(::Gitlab::Runtime).to receive(:puma?).and_return(true) end - include_examples 'does not modify worker startup hooks' + include_examples 'does not modify worker hooks' end end diff --git a/spec/lib/gitlab/database/load_balancing/sidekiq_client_middleware_spec.rb b/spec/lib/gitlab/database/load_balancing/sidekiq_client_middleware_spec.rb index bd143c99d64..7eb20f77417 100644 --- a/spec/lib/gitlab/database/load_balancing/sidekiq_client_middleware_spec.rb +++ b/spec/lib/gitlab/database/load_balancing/sidekiq_client_middleware_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::Database::LoadBalancing::SidekiqClientMiddleware do +RSpec.describe Gitlab::Database::LoadBalancing::SidekiqClientMiddleware, feature_category: :database do let(:middleware) { described_class.new } let(:worker_class) { 'TestDataConsistencyWorker' } @@ -82,21 +82,41 @@ RSpec.describe Gitlab::Database::LoadBalancing::SidekiqClientMiddleware do allow(Gitlab::Database::LoadBalancing::Session.current).to receive(:use_primary?).and_return(false) end - it 'passes database_replica_location' do - expected_location = {} + context 'when replica hosts are available' do + it 'passes database_replica_location' do + expected_location = {} - Gitlab::Database::LoadBalancing.each_load_balancer do |lb| - expect(lb.host) - .to receive(:database_replica_location) - .and_return(location) + Gitlab::Database::LoadBalancing.each_load_balancer do |lb| + expect(lb.host) + .to receive(:database_replica_location) + .and_return(location) - expected_location[lb.name] = location + expected_location[lb.name] = location + end + + run_middleware + + expect(job['wal_locations']).to eq(expected_location) + expect(job['wal_location_source']).to eq(:replica) end + end - run_middleware + context 'when no replica hosts are available' do + it 'passes primary_write_location' do + expected_location = {} - expect(job['wal_locations']).to eq(expected_location) - expect(job['wal_location_source']).to eq(:replica) + Gitlab::Database::LoadBalancing.each_load_balancer do |lb| + expect(lb).to receive(:host).and_return(nil) + expect(lb).to receive(:primary_write_location).and_return(location) + + expected_location[lb.name] = location + end + + run_middleware + + expect(job['wal_locations']).to eq(expected_location) + expect(job['wal_location_source']).to eq(:replica) + end end include_examples 'job data consistency' diff --git a/spec/lib/gitlab/instrumentation/redis_base_spec.rb b/spec/lib/gitlab/instrumentation/redis_base_spec.rb index 9cf65a11bce..656e6ffba05 100644 --- a/spec/lib/gitlab/instrumentation/redis_base_spec.rb +++ b/spec/lib/gitlab/instrumentation/redis_base_spec.rb @@ -109,6 +109,25 @@ RSpec.describe Gitlab::Instrumentation::RedisBase, :request_store do end end + describe '.increment_allowed_cross_slot_request_count' do + context 'storage key overlapping' do + it 'keys do not overlap across storages' do + 3.times { instrumentation_class_a.increment_allowed_cross_slot_request_count } + 2.times { instrumentation_class_b.increment_allowed_cross_slot_request_count } + + expect(instrumentation_class_a.get_allowed_cross_slot_request_count).to eq(3) + expect(instrumentation_class_b.get_allowed_cross_slot_request_count).to eq(2) + end + + it 'increments by the given amount' do + instrumentation_class_a.increment_allowed_cross_slot_request_count(2) + instrumentation_class_a.increment_allowed_cross_slot_request_count(3) + + expect(instrumentation_class_a.get_allowed_cross_slot_request_count).to eq(5) + end + end + end + describe '.increment_read_bytes' do context 'storage key overlapping' do it 'keys do not overlap across storages' do diff --git a/spec/lib/gitlab/instrumentation/redis_interceptor_spec.rb b/spec/lib/gitlab/instrumentation/redis_interceptor_spec.rb index 120430accf1..187a6ff1739 100644 --- a/spec/lib/gitlab/instrumentation/redis_interceptor_spec.rb +++ b/spec/lib/gitlab/instrumentation/redis_interceptor_spec.rb @@ -83,12 +83,14 @@ RSpec.describe Gitlab::Instrumentation::RedisInterceptor, :clean_gitlab_redis_sh it 'counts disallowed cross-slot requests' do expect(instrumentation_class).to receive(:increment_cross_slot_request_count).and_call_original + expect(instrumentation_class).not_to receive(:increment_allowed_cross_slot_request_count).and_call_original Gitlab::Redis::SharedState.with { |redis| redis.call(:mget, 'foo', 'bar') } end it 'does not count allowed cross-slot requests' do expect(instrumentation_class).not_to receive(:increment_cross_slot_request_count).and_call_original + expect(instrumentation_class).to receive(:increment_allowed_cross_slot_request_count).and_call_original Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do Gitlab::Redis::SharedState.with { |redis| redis.call(:mget, 'foo', 'bar') } @@ -97,6 +99,7 @@ RSpec.describe Gitlab::Instrumentation::RedisInterceptor, :clean_gitlab_redis_sh it 'skips count for non-cross-slot requests' do expect(instrumentation_class).not_to receive(:increment_cross_slot_request_count).and_call_original + expect(instrumentation_class).not_to receive(:increment_allowed_cross_slot_request_count).and_call_original Gitlab::Redis::SharedState.with { |redis| redis.call(:mget, '{foo}bar', '{foo}baz') } end diff --git a/spec/lib/gitlab/instrumentation/redis_spec.rb b/spec/lib/gitlab/instrumentation/redis_spec.rb index 7b6f31c1a08..3e02eadba4b 100644 --- a/spec/lib/gitlab/instrumentation/redis_spec.rb +++ b/spec/lib/gitlab/instrumentation/redis_spec.rb @@ -24,6 +24,7 @@ RSpec.describe Gitlab::Instrumentation::Redis do it_behaves_like 'aggregation of redis storage data', :get_request_count it_behaves_like 'aggregation of redis storage data', :get_cross_slot_request_count + it_behaves_like 'aggregation of redis storage data', :get_allowed_cross_slot_request_count it_behaves_like 'aggregation of redis storage data', :query_time it_behaves_like 'aggregation of redis storage data', :read_bytes it_behaves_like 'aggregation of redis storage data', :write_bytes @@ -39,21 +40,26 @@ RSpec.describe Gitlab::Instrumentation::Redis do stub_rails_env('staging') # to avoid raising CrossSlotError Gitlab::Redis::Cache.with { |redis| redis.mset('cache-test', 321, 'cache-test-2', 321) } + Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do + Gitlab::Redis::Cache.with { |redis| redis.mget('cache-test', 'cache-test-2') } + end Gitlab::Redis::SharedState.with { |redis| redis.set('shared-state-test', 123) } end it 'returns payload filtering out zeroed values' do expected_payload = { # Aggregated results - redis_calls: 2, + redis_calls: 3, redis_cross_slot_calls: 1, + redis_allowed_cross_slot_calls: 1, redis_duration_s: be >= 0, redis_read_bytes: be >= 0, redis_write_bytes: be >= 0, # Cache results - redis_cache_calls: 1, + redis_cache_calls: 2, redis_cache_cross_slot_calls: 1, + redis_cache_allowed_cross_slot_calls: 1, redis_cache_duration_s: be >= 0, redis_cache_read_bytes: be >= 0, redis_cache_write_bytes: be >= 0, diff --git a/spec/lib/gitlab/instrumentation_helper_spec.rb b/spec/lib/gitlab/instrumentation_helper_spec.rb index b4738ed663c..7d78d25f18e 100644 --- a/spec/lib/gitlab/instrumentation_helper_spec.rb +++ b/spec/lib/gitlab/instrumentation_helper_spec.rb @@ -41,13 +41,17 @@ RSpec.describe Gitlab::InstrumentationHelper do it 'adds Redis data and omits Gitaly data' do stub_rails_env('staging') # to avoid raising CrossSlotError Gitlab::Redis::Cache.with { |redis| redis.mset('test-cache', 123, 'test-cache2', 123) } + Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do + Gitlab::Redis::Cache.with { |redis| redis.mget('cache-test', 'cache-test-2') } + end Gitlab::Redis::Queues.with { |redis| redis.set('test-queues', 321) } subject # Aggregated payload - expect(payload[:redis_calls]).to eq(2) + expect(payload[:redis_calls]).to eq(3) expect(payload[:redis_cross_slot_calls]).to eq(1) + expect(payload[:redis_allowed_cross_slot_calls]).to eq(1) expect(payload[:redis_duration_s]).to be >= 0 expect(payload[:redis_read_bytes]).to be >= 0 expect(payload[:redis_write_bytes]).to be >= 0 @@ -59,8 +63,9 @@ RSpec.describe Gitlab::InstrumentationHelper do expect(payload[:redis_queues_write_bytes]).to be >= 0 # Cache payload - expect(payload[:redis_cache_calls]).to eq(1) + expect(payload[:redis_cache_calls]).to eq(2) expect(payload[:redis_cache_cross_slot_calls]).to eq(1) + expect(payload[:redis_cache_allowed_cross_slot_calls]).to eq(1) expect(payload[:redis_cache_duration_s]).to be >= 0 expect(payload[:redis_cache_read_bytes]).to be >= 0 expect(payload[:redis_cache_write_bytes]).to be >= 0 diff --git a/spec/lib/gitlab/memory/reports/heap_dump_spec.rb b/spec/lib/gitlab/memory/reports/heap_dump_spec.rb index 1a24b083d6f..4e235a71bdb 100644 --- a/spec/lib/gitlab/memory/reports/heap_dump_spec.rb +++ b/spec/lib/gitlab/memory/reports/heap_dump_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::Memory::Reports::HeapDump do +RSpec.describe Gitlab::Memory::Reports::HeapDump, feature_category: :application_performance do # Copy this class so we do not mess with its state. let(:klass) { described_class.dup } @@ -16,8 +16,13 @@ RSpec.describe Gitlab::Memory::Reports::HeapDump do end describe '#active?' do - # This will be enabled once https://gitlab.com/gitlab-org/gitlab/-/issues/370077 is done. - it 'is false' do + it 'is true when report_heap_dumps is enabled' do + expect(report).to be_active + end + + it 'is false when report_heap_dumps is disabled' do + stub_feature_flags(report_heap_dumps: false) + expect(report).not_to be_active end end @@ -29,15 +34,22 @@ RSpec.describe Gitlab::Memory::Reports::HeapDump do context 'when no heap dump is enqueued' do it 'does nothing and returns false' do + expect(ObjectSpace).not_to receive(:dump_all) + expect(run).to be(false) end end - context 'when a heap dump is enqueued' do - it 'does nothing and returns true' do + context 'when a heap dump is enqueued', :aggregate_failures do + it 'dumps heap and returns true' do + expect(ObjectSpace).to receive(:dump_all).with(output: writer) do |output:| + output << 'heap contents' + end + klass.enqueue! expect(run).to be(true) + expect(writer.string).to eq('heap contents') end end end diff --git a/spec/lib/gitlab/memory/watchdog/configurator_spec.rb b/spec/lib/gitlab/memory/watchdog/configurator_spec.rb index 72661829bab..a901be84a21 100644 --- a/spec/lib/gitlab/memory/watchdog/configurator_spec.rb +++ b/spec/lib/gitlab/memory/watchdog/configurator_spec.rb @@ -25,12 +25,6 @@ RSpec.describe Gitlab::Memory::Watchdog::Configurator do expect(configuration.event_reporter.logger).to eq(logger) end - it 'does not enable writing heap dumps by default' do - configurator.call(configuration) - - expect(configuration.write_heap_dumps?).to be(false) - end - context 'when sleep_time_seconds is not passed through the environment' do let(:sleep_time_seconds) { sleep_time } @@ -54,42 +48,6 @@ RSpec.describe Gitlab::Memory::Watchdog::Configurator do expect(configuration.sleep_time_seconds).to eq(sleep_time_seconds) end end - - context 'when GITLAB_MEMWD_DUMP_HEAP is set' do - before do - stub_env('GITLAB_MEMWD_DUMP_HEAP', env_var) - end - - context 'with null value' do - let(:env_var) { nil } - - it 'does not enable writing heap dumps' do - configurator.call(configuration) - - expect(configuration.write_heap_dumps?).to be(false) - end - end - - context 'with falsey value' do - let(:env_var) { '0' } - - it 'does not enable writing heap dumps' do - configurator.call(configuration) - - expect(configuration.write_heap_dumps?).to be(false) - end - end - - context 'with truthy value' do - let(:env_var) { '1' } - - it 'enables writing heap dumps' do - configurator.call(configuration) - - expect(configuration.write_heap_dumps?).to be(true) - end - end - end end shared_examples 'as monitor configurator' do diff --git a/spec/lib/gitlab/memory/watchdog_spec.rb b/spec/lib/gitlab/memory/watchdog_spec.rb index fca31d590f5..92aa583a26d 100644 --- a/spec/lib/gitlab/memory/watchdog_spec.rb +++ b/spec/lib/gitlab/memory/watchdog_spec.rb @@ -2,13 +2,12 @@ require 'spec_helper' -RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures do +RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures, feature_category: :application_performance do context 'watchdog' do let(:configuration) { instance_double(described_class::Configuration) } let(:handler) { instance_double(described_class::NullHandler) } let(:reporter) { instance_double(described_class::EventReporter) } let(:sleep_time_seconds) { 60 } - let(:write_heap_dumps) { false } let(:threshold_violated) { false } let(:watchdog_iterations) { 1 } let(:name) { :monitor_name } @@ -50,7 +49,6 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures do config.handler = handler config.event_reporter = reporter config.sleep_time_seconds = sleep_time_seconds - config.write_heap_dumps = write_heap_dumps config.monitors.push monitor_class, threshold_violated, payload, max_strikes: max_strikes end @@ -123,16 +121,6 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures do watchdog.call end - - context 'and heap dumps are enabled' do - let(:write_heap_dumps) { true } - - it 'does not schedule a heap dump' do - expect(Gitlab::Memory::Reports::HeapDump).not_to receive(:enqueue!) - - watchdog.call - end - end end context 'when monitor exceeds the allowed number of strikes' do @@ -158,14 +146,10 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures do watchdog.call end - context 'and heap dumps are enabled' do - let(:write_heap_dumps) { true } + it 'schedules a heap dump' do + expect(Gitlab::Memory::Reports::HeapDump).to receive(:enqueue!) - it 'schedules a heap dump' do - expect(Gitlab::Memory::Reports::HeapDump).to receive(:enqueue!) - - watchdog.call - end + watchdog.call end context 'when enforce_memory_watchdog ops toggle is off' do diff --git a/spec/models/badge_spec.rb b/spec/models/badge_spec.rb index 3a5ffd44e3e..f3c95332ca0 100644 --- a/spec/models/badge_spec.rb +++ b/spec/models/badge_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe Badge do - let(:placeholder_url) { 'http://www.example.com/%{project_path}/%{project_id}/%{project_name}/%{default_branch}/%{commit_sha}' } + let(:placeholder_url) { 'http://www.example.com/%{project_path}/%{project_id}/%{default_branch}/%{commit_sha}' } describe 'validations' do # Requires the let variable url_sym @@ -64,7 +64,7 @@ RSpec.describe Badge do it 'uses the project information to populate the url placeholders' do stub_project_commit_info(project) - expect(badge.public_send("rendered_#{method}", project)).to eq "http://www.example.com/#{project.full_path}/#{project.id}/#{project.name}/master/whatever" + expect(badge.public_send("rendered_#{method}", project)).to eq "http://www.example.com/#{project.full_path}/#{project.id}/master/whatever" end it 'returns the url if the project used is nil' do diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index cdcfe80f455..b72693d9994 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -5310,6 +5310,20 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end end end + + context 'when the current user is not the bridge user' do + let(:current_user) { create(:user) } + + before do + project.add_maintainer(current_user) + end + + it 'changes bridge user to current user' do + expect { reset_bridge } + .to change { bridge.reload.user } + .from(owner).to(current_user) + end + end end context 'when the user does not have permissions for the processable' do @@ -5328,6 +5342,15 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do .and not_change { bridge_dependant_dag_job.reload.status } end end + + context 'when the current user is not the bridge user' do + let(:current_user) { create(:user) } + + it 'does not change bridge user' do + expect { reset_bridge } + .to not_change { bridge.reload.user } + end + end end end diff --git a/spec/models/concerns/has_user_type_spec.rb b/spec/models/concerns/has_user_type_spec.rb index b6e711e8325..462b28f99be 100644 --- a/spec/models/concerns/has_user_type_spec.rb +++ b/spec/models/concerns/has_user_type_spec.rb @@ -37,12 +37,6 @@ RSpec.describe User do end end - describe '.bots_without_project_bot' do - it 'includes all bots except project_bot' do - expect(described_class.bots_without_project_bot).to match_array(bots - [project_bot]) - end - end - describe '.non_internal' do it 'includes all non_internal users' do expect(described_class.non_internal).to match_array(non_internal) diff --git a/spec/requests/api/graphql/mutations/admin/sidekiq_queues/delete_jobs_spec.rb b/spec/requests/api/graphql/mutations/admin/sidekiq_queues/delete_jobs_spec.rb index f992e46879f..64ea6d32f5f 100644 --- a/spec/requests/api/graphql/mutations/admin/sidekiq_queues/delete_jobs_spec.rb +++ b/spec/requests/api/graphql/mutations/admin/sidekiq_queues/delete_jobs_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Deleting Sidekiq jobs', :clean_gitlab_redis_queues do +RSpec.describe 'Deleting Sidekiq jobs', :clean_gitlab_redis_queues, feature_category: :not_owned do include GraphqlHelpers let_it_be(:admin) { create(:admin) } diff --git a/spec/requests/api/graphql/mutations/alert_management/alerts/create_alert_issue_spec.rb b/spec/requests/api/graphql/mutations/alert_management/alerts/create_alert_issue_spec.rb index f637ca98353..fbe6d95dfff 100644 --- a/spec/requests/api/graphql/mutations/alert_management/alerts/create_alert_issue_spec.rb +++ b/spec/requests/api/graphql/mutations/alert_management/alerts/create_alert_issue_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Create an alert issue from an alert' do +RSpec.describe 'Create an alert issue from an alert', feature_category: :incident_management do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/alert_management/alerts/set_assignees_spec.rb b/spec/requests/api/graphql/mutations/alert_management/alerts/set_assignees_spec.rb index fcef7b4e3ec..935856814c4 100644 --- a/spec/requests/api/graphql/mutations/alert_management/alerts/set_assignees_spec.rb +++ b/spec/requests/api/graphql/mutations/alert_management/alerts/set_assignees_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Setting assignees of an alert' do +RSpec.describe 'Setting assignees of an alert', feature_category: :incident_management do include GraphqlHelpers let_it_be(:project) { create(:project) } diff --git a/spec/requests/api/graphql/mutations/alert_management/alerts/todo/create_spec.rb b/spec/requests/api/graphql/mutations/alert_management/alerts/todo/create_spec.rb index 48307964345..570324a3126 100644 --- a/spec/requests/api/graphql/mutations/alert_management/alerts/todo/create_spec.rb +++ b/spec/requests/api/graphql/mutations/alert_management/alerts/todo/create_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Creating a todo for the alert' do +RSpec.describe 'Creating a todo for the alert', feature_category: :incident_management do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/alert_management/alerts/update_alert_status_spec.rb b/spec/requests/api/graphql/mutations/alert_management/alerts/update_alert_status_spec.rb index 802d8d6c5a1..6537747850c 100644 --- a/spec/requests/api/graphql/mutations/alert_management/alerts/update_alert_status_spec.rb +++ b/spec/requests/api/graphql/mutations/alert_management/alerts/update_alert_status_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Setting the status of an alert' do +RSpec.describe 'Setting the status of an alert', feature_category: :incident_management do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/alert_management/http_integration/create_spec.rb b/spec/requests/api/graphql/mutations/alert_management/http_integration/create_spec.rb index ff93da2153f..187c88363c6 100644 --- a/spec/requests/api/graphql/mutations/alert_management/http_integration/create_spec.rb +++ b/spec/requests/api/graphql/mutations/alert_management/http_integration/create_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Creating a new HTTP Integration' do +RSpec.describe 'Creating a new HTTP Integration', feature_category: :integrations do include GraphqlHelpers let_it_be(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/alert_management/http_integration/destroy_spec.rb b/spec/requests/api/graphql/mutations/alert_management/http_integration/destroy_spec.rb index 1ecb5c76b57..1c77c71daba 100644 --- a/spec/requests/api/graphql/mutations/alert_management/http_integration/destroy_spec.rb +++ b/spec/requests/api/graphql/mutations/alert_management/http_integration/destroy_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Removing an HTTP Integration' do +RSpec.describe 'Removing an HTTP Integration', feature_category: :integrations do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/alert_management/http_integration/reset_token_spec.rb b/spec/requests/api/graphql/mutations/alert_management/http_integration/reset_token_spec.rb index badd9412589..427277dd540 100644 --- a/spec/requests/api/graphql/mutations/alert_management/http_integration/reset_token_spec.rb +++ b/spec/requests/api/graphql/mutations/alert_management/http_integration/reset_token_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Resetting a token on an existing HTTP Integration' do +RSpec.describe 'Resetting a token on an existing HTTP Integration', feature_category: :integrations do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/alert_management/http_integration/update_spec.rb b/spec/requests/api/graphql/mutations/alert_management/http_integration/update_spec.rb index 18cbb7d8b00..a9d189d564d 100644 --- a/spec/requests/api/graphql/mutations/alert_management/http_integration/update_spec.rb +++ b/spec/requests/api/graphql/mutations/alert_management/http_integration/update_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Updating an existing HTTP Integration' do +RSpec.describe 'Updating an existing HTTP Integration', feature_category: :integrations do include GraphqlHelpers let_it_be(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/create_spec.rb b/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/create_spec.rb index 4c359d9b357..3dee7f50af3 100644 --- a/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/create_spec.rb +++ b/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/create_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Creating a new Prometheus Integration' do +RSpec.describe 'Creating a new Prometheus Integration', feature_category: :incident_management do include GraphqlHelpers let_it_be(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb b/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb index 31053c50cac..15127843b95 100644 --- a/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb +++ b/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Resetting a token on an existing Prometheus Integration' do +RSpec.describe 'Resetting a token on an existing Prometheus Integration', feature_category: :incident_management do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/update_spec.rb b/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/update_spec.rb index ad26ec118d7..63e95f4513b 100644 --- a/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/update_spec.rb +++ b/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/update_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Updating an existing Prometheus Integration' do +RSpec.describe 'Updating an existing Prometheus Integration', feature_category: :incident_management do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb b/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb index 3879e58cecf..fdbff0f93cd 100644 --- a/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb +++ b/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Adding an AwardEmoji' do +RSpec.describe 'Adding an AwardEmoji', feature_category: :not_owned do include GraphqlHelpers let_it_be(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/award_emojis/remove_spec.rb b/spec/requests/api/graphql/mutations/award_emojis/remove_spec.rb index e81621209fb..e200bfc2d18 100644 --- a/spec/requests/api/graphql/mutations/award_emojis/remove_spec.rb +++ b/spec/requests/api/graphql/mutations/award_emojis/remove_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Removing an AwardEmoji' do +RSpec.describe 'Removing an AwardEmoji', feature_category: :not_owned do include GraphqlHelpers let(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb b/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb index b151da72b55..6dba2b58357 100644 --- a/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb +++ b/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Toggling an AwardEmoji' do +RSpec.describe 'Toggling an AwardEmoji', feature_category: :not_owned do include GraphqlHelpers let_it_be(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/boards/create_spec.rb b/spec/requests/api/graphql/mutations/boards/create_spec.rb index ca848c0c92f..10eb12f277f 100644 --- a/spec/requests/api/graphql/mutations/boards/create_spec.rb +++ b/spec/requests/api/graphql/mutations/boards/create_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Mutations::Boards::Create do +RSpec.describe Mutations::Boards::Create, feature_category: :team_planning do let_it_be(:parent) { create(:project) } let_it_be(:current_user, reload: true) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/boards/destroy_spec.rb b/spec/requests/api/graphql/mutations/boards/destroy_spec.rb index 7620da3e7e0..44924159137 100644 --- a/spec/requests/api/graphql/mutations/boards/destroy_spec.rb +++ b/spec/requests/api/graphql/mutations/boards/destroy_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Mutations::Boards::Destroy do +RSpec.describe Mutations::Boards::Destroy, feature_category: :team_planning do include GraphqlHelpers let_it_be(:current_user, reload: true) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/boards/issues/issue_move_list_spec.rb b/spec/requests/api/graphql/mutations/boards/issues/issue_move_list_spec.rb index 06093e9f7c2..df64caa1cfb 100644 --- a/spec/requests/api/graphql/mutations/boards/issues/issue_move_list_spec.rb +++ b/spec/requests/api/graphql/mutations/boards/issues/issue_move_list_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Reposition and move issue within board lists' do +RSpec.describe 'Reposition and move issue within board lists', feature_category: :team_planning do include GraphqlHelpers let_it_be(:group) { create(:group, :private) } diff --git a/spec/requests/api/graphql/mutations/boards/lists/create_spec.rb b/spec/requests/api/graphql/mutations/boards/lists/create_spec.rb index fec9a8c6307..f5381be2741 100644 --- a/spec/requests/api/graphql/mutations/boards/lists/create_spec.rb +++ b/spec/requests/api/graphql/mutations/boards/lists/create_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Create a label or backlog board list' do +RSpec.describe 'Create a label or backlog board list', feature_category: :team_planning do let_it_be(:group) { create(:group, :private) } let_it_be(:board) { create(:board, group: group) } diff --git a/spec/requests/api/graphql/mutations/boards/lists/destroy_spec.rb b/spec/requests/api/graphql/mutations/boards/lists/destroy_spec.rb index 83309ead352..b37b1a7b935 100644 --- a/spec/requests/api/graphql/mutations/boards/lists/destroy_spec.rb +++ b/spec/requests/api/graphql/mutations/boards/lists/destroy_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Mutations::Boards::Lists::Destroy do +RSpec.describe Mutations::Boards::Lists::Destroy, feature_category: :team_planning do include GraphqlHelpers let_it_be(:current_user, reload: true) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/boards/lists/update_spec.rb b/spec/requests/api/graphql/mutations/boards/lists/update_spec.rb index c7885879a9d..6a7edcd7349 100644 --- a/spec/requests/api/graphql/mutations/boards/lists/update_spec.rb +++ b/spec/requests/api/graphql/mutations/boards/lists/update_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Update of an existing board list' do +RSpec.describe 'Update of an existing board list', feature_category: :team_planning do include GraphqlHelpers let_it_be(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/branches/create_spec.rb b/spec/requests/api/graphql/mutations/branches/create_spec.rb index 9ee2f41e8fc..32512e2ee1b 100644 --- a/spec/requests/api/graphql/mutations/branches/create_spec.rb +++ b/spec/requests/api/graphql/mutations/branches/create_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Creation of a new branch' do +RSpec.describe 'Creation of a new branch', feature_category: :source_code_management do include GraphqlHelpers let_it_be(:group) { create(:group, :public) } diff --git a/spec/requests/api/graphql/mutations/ci/job/artifacts_destroy_spec.rb b/spec/requests/api/graphql/mutations/ci/job/artifacts_destroy_spec.rb index bdad80995ea..6cdf8788957 100644 --- a/spec/requests/api/graphql/mutations/ci/job/artifacts_destroy_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/job/artifacts_destroy_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'JobArtifactsDestroy' do +RSpec.describe 'JobArtifactsDestroy', feature_category: :build_artifacts do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/ci/job/destroy_spec.rb b/spec/requests/api/graphql/mutations/ci/job/destroy_spec.rb index 5855eb6bb51..88dfec41d36 100644 --- a/spec/requests/api/graphql/mutations/ci/job/destroy_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/job/destroy_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'JobArtifactsDestroy' do +RSpec.describe 'JobArtifactsDestroy', feature_category: :build_artifacts do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/ci/job_artifact/destroy_spec.rb b/spec/requests/api/graphql/mutations/ci/job_artifact/destroy_spec.rb index a5ec9ea343d..ac3592130b8 100644 --- a/spec/requests/api/graphql/mutations/ci/job_artifact/destroy_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/job_artifact/destroy_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'ArtifactDestroy' do +RSpec.describe 'ArtifactDestroy', feature_category: :build_artifacts do include GraphqlHelpers let(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/ci/job_cancel_spec.rb b/spec/requests/api/graphql/mutations/ci/job_cancel_spec.rb index ee0f0a9bccb..468a9e57f56 100644 --- a/spec/requests/api/graphql/mutations/ci/job_cancel_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/job_cancel_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe "JobCancel" do +RSpec.describe "JobCancel", feature_category: :continuous_integration do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/ci/job_play_spec.rb b/spec/requests/api/graphql/mutations/ci/job_play_spec.rb index 0874e225259..014a5e0f1c7 100644 --- a/spec/requests/api/graphql/mutations/ci/job_play_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/job_play_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'JobPlay' do +RSpec.describe 'JobPlay', feature_category: :continuous_integration do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/ci/job_retry_spec.rb b/spec/requests/api/graphql/mutations/ci/job_retry_spec.rb index 8cf559a372a..e49ee6f3163 100644 --- a/spec/requests/api/graphql/mutations/ci/job_retry_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/job_retry_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'JobRetry' do +RSpec.describe 'JobRetry', feature_category: :continuous_integration do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/ci/job_token_scope/add_project_spec.rb b/spec/requests/api/graphql/mutations/ci/job_token_scope/add_project_spec.rb index b2f84ab2869..9e2b043f889 100644 --- a/spec/requests/api/graphql/mutations/ci/job_token_scope/add_project_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/job_token_scope/add_project_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'CiJobTokenScopeAddProject' do +RSpec.describe 'CiJobTokenScopeAddProject', feature_category: :continuous_integration do include GraphqlHelpers let_it_be(:project) { create(:project, ci_outbound_job_token_scope_enabled: true).tap(&:save!) } diff --git a/spec/requests/api/graphql/mutations/ci/job_token_scope/remove_project_spec.rb b/spec/requests/api/graphql/mutations/ci/job_token_scope/remove_project_spec.rb index 2b0adf89f40..5d57b1f0872 100644 --- a/spec/requests/api/graphql/mutations/ci/job_token_scope/remove_project_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/job_token_scope/remove_project_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'CiJobTokenScopeRemoveProject' do +RSpec.describe 'CiJobTokenScopeRemoveProject', feature_category: :continuous_integration do include GraphqlHelpers let_it_be(:project) { create(:project, ci_outbound_job_token_scope_enabled: true).tap(&:save!) } diff --git a/spec/requests/api/graphql/mutations/ci/job_unschedule_spec.rb b/spec/requests/api/graphql/mutations/ci/job_unschedule_spec.rb index 4ddc019a2b5..6868b0ea279 100644 --- a/spec/requests/api/graphql/mutations/ci/job_unschedule_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/job_unschedule_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'JobUnschedule' do +RSpec.describe 'JobUnschedule', feature_category: :continuous_integration do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/ci/pipeline_cancel_spec.rb b/spec/requests/api/graphql/mutations/ci/pipeline_cancel_spec.rb index 6ec1b7ce9b6..8c1359384ed 100644 --- a/spec/requests/api/graphql/mutations/ci/pipeline_cancel_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/pipeline_cancel_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'PipelineCancel' do +RSpec.describe 'PipelineCancel', feature_category: :continuous_integration do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/ci/pipeline_destroy_spec.rb b/spec/requests/api/graphql/mutations/ci/pipeline_destroy_spec.rb index 7abd5ca8772..9ddfaf83d34 100644 --- a/spec/requests/api/graphql/mutations/ci/pipeline_destroy_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/pipeline_destroy_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'PipelineDestroy' do +RSpec.describe 'PipelineDestroy', feature_category: :continuous_integration do include GraphqlHelpers let_it_be(:project) { create(:project) } diff --git a/spec/requests/api/graphql/mutations/ci/pipeline_retry_spec.rb b/spec/requests/api/graphql/mutations/ci/pipeline_retry_spec.rb index f6acf29c321..e7edc86bea0 100644 --- a/spec/requests/api/graphql/mutations/ci/pipeline_retry_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/pipeline_retry_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'PipelineRetry' do +RSpec.describe 'PipelineRetry', feature_category: :continuous_integration do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/ci/pipeline_schedule_delete_spec.rb b/spec/requests/api/graphql/mutations/ci/pipeline_schedule_delete_spec.rb index b197d223463..b846ff0aec8 100644 --- a/spec/requests/api/graphql/mutations/ci/pipeline_schedule_delete_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/pipeline_schedule_delete_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'PipelineScheduleDelete' do +RSpec.describe 'PipelineScheduleDelete', feature_category: :continuous_integration do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/ci/pipeline_schedule_take_ownership_spec.rb b/spec/requests/api/graphql/mutations/ci/pipeline_schedule_take_ownership_spec.rb index 8dfbf20d00b..2d1f1565a73 100644 --- a/spec/requests/api/graphql/mutations/ci/pipeline_schedule_take_ownership_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/pipeline_schedule_take_ownership_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'PipelineScheduleTakeOwnership' do +RSpec.describe 'PipelineScheduleTakeOwnership', feature_category: :continuous_integration do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/ci/project_ci_cd_settings_update_spec.rb b/spec/requests/api/graphql/mutations/ci/project_ci_cd_settings_update_spec.rb index c808cf5ede9..7a6ee7c2ecc 100644 --- a/spec/requests/api/graphql/mutations/ci/project_ci_cd_settings_update_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/project_ci_cd_settings_update_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'ProjectCiCdSettingsUpdate' do +RSpec.describe 'ProjectCiCdSettingsUpdate', feature_category: :continuous_integration do include GraphqlHelpers let_it_be(:project) do diff --git a/spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb b/spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb index 54e63df96a6..17a7d0ac99c 100644 --- a/spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'RunnersRegistrationTokenReset' do +RSpec.describe 'RunnersRegistrationTokenReset', feature_category: :runner do include GraphqlHelpers let(:mutation) { graphql_mutation(:runners_registration_token_reset, input) } diff --git a/spec/requests/api/graphql/mutations/clusters/agent_tokens/agent_tokens/create_spec.rb b/spec/requests/api/graphql/mutations/clusters/agent_tokens/agent_tokens/create_spec.rb index aac8eb22771..f544cef8864 100644 --- a/spec/requests/api/graphql/mutations/clusters/agent_tokens/agent_tokens/create_spec.rb +++ b/spec/requests/api/graphql/mutations/clusters/agent_tokens/agent_tokens/create_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Create a new cluster agent token' do +RSpec.describe 'Create a new cluster agent token', feature_category: :kubernetes_management do include GraphqlHelpers let_it_be(:cluster_agent) { create(:cluster_agent) } diff --git a/spec/requests/api/graphql/mutations/clusters/agents/create_spec.rb b/spec/requests/api/graphql/mutations/clusters/agents/create_spec.rb index c2ef2362d66..66e6c5cc629 100644 --- a/spec/requests/api/graphql/mutations/clusters/agents/create_spec.rb +++ b/spec/requests/api/graphql/mutations/clusters/agents/create_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Create a new cluster agent' do +RSpec.describe 'Create a new cluster agent', feature_category: :kubernetes_management do include GraphqlHelpers let(:project) { create(:project, :public, :repository) } diff --git a/spec/requests/api/graphql/mutations/clusters/agents/delete_spec.rb b/spec/requests/api/graphql/mutations/clusters/agents/delete_spec.rb index 4891e64aab8..27a566dfb8c 100644 --- a/spec/requests/api/graphql/mutations/clusters/agents/delete_spec.rb +++ b/spec/requests/api/graphql/mutations/clusters/agents/delete_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Delete a cluster agent' do +RSpec.describe 'Delete a cluster agent', feature_category: :kubernetes_management do include GraphqlHelpers let(:cluster_agent) { create(:cluster_agent) } diff --git a/spec/requests/api/graphql/mutations/commits/create_spec.rb b/spec/requests/api/graphql/mutations/commits/create_spec.rb index 619cba99c4e..e298d8284c6 100644 --- a/spec/requests/api/graphql/mutations/commits/create_spec.rb +++ b/spec/requests/api/graphql/mutations/commits/create_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Creation of a new commit' do +RSpec.describe 'Creation of a new commit', feature_category: :source_code_management do include GraphqlHelpers let_it_be(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/container_expiration_policy/update_spec.rb b/spec/requests/api/graphql/mutations/container_expiration_policy/update_spec.rb index ca7c1b2ce5f..97e2a5d0bf7 100644 --- a/spec/requests/api/graphql/mutations/container_expiration_policy/update_spec.rb +++ b/spec/requests/api/graphql/mutations/container_expiration_policy/update_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Updating the container expiration policy' do +RSpec.describe 'Updating the container expiration policy', feature_category: :container_registry do include GraphqlHelpers using RSpec::Parameterized::TableSyntax diff --git a/spec/requests/api/graphql/mutations/container_repository/destroy_spec.rb b/spec/requests/api/graphql/mutations/container_repository/destroy_spec.rb index 5a27d39ecbc..bee90669899 100644 --- a/spec/requests/api/graphql/mutations/container_repository/destroy_spec.rb +++ b/spec/requests/api/graphql/mutations/container_repository/destroy_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Destroying a container repository' do +RSpec.describe 'Destroying a container repository', feature_category: :container_registry do using RSpec::Parameterized::TableSyntax include GraphqlHelpers diff --git a/spec/requests/api/graphql/mutations/container_repository/destroy_tags_spec.rb b/spec/requests/api/graphql/mutations/container_repository/destroy_tags_spec.rb index ef00f45ef18..9e07a831076 100644 --- a/spec/requests/api/graphql/mutations/container_repository/destroy_tags_spec.rb +++ b/spec/requests/api/graphql/mutations/container_repository/destroy_tags_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Destroying a container repository tags' do +RSpec.describe 'Destroying a container repository tags', feature_category: :container_registry do include_context 'container repository delete tags service shared context' using RSpec::Parameterized::TableSyntax diff --git a/spec/requests/api/graphql/mutations/custom_emoji/create_spec.rb b/spec/requests/api/graphql/mutations/custom_emoji/create_spec.rb index 66facdebe78..ea2ce8a13e2 100644 --- a/spec/requests/api/graphql/mutations/custom_emoji/create_spec.rb +++ b/spec/requests/api/graphql/mutations/custom_emoji/create_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Creation of a new Custom Emoji' do +RSpec.describe 'Creation of a new Custom Emoji', feature_category: :not_owned do include GraphqlHelpers let_it_be(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/custom_emoji/destroy_spec.rb b/spec/requests/api/graphql/mutations/custom_emoji/destroy_spec.rb index 7d25206e617..ad7a043909a 100644 --- a/spec/requests/api/graphql/mutations/custom_emoji/destroy_spec.rb +++ b/spec/requests/api/graphql/mutations/custom_emoji/destroy_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Deletion of custom emoji' do +RSpec.describe 'Deletion of custom emoji', feature_category: :not_owned do include GraphqlHelpers let_it_be(:group) { create(:group) } diff --git a/spec/requests/api/graphql/mutations/dependency_proxy/group_settings/update_spec.rb b/spec/requests/api/graphql/mutations/dependency_proxy/group_settings/update_spec.rb index 9eb13e534ac..5d5696d3f66 100644 --- a/spec/requests/api/graphql/mutations/dependency_proxy/group_settings/update_spec.rb +++ b/spec/requests/api/graphql/mutations/dependency_proxy/group_settings/update_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Updating the dependency proxy group settings' do +RSpec.describe 'Updating the dependency proxy group settings', feature_category: :dependency_proxy do include GraphqlHelpers using RSpec::Parameterized::TableSyntax diff --git a/spec/requests/api/graphql/mutations/dependency_proxy/image_ttl_group_policy/update_spec.rb b/spec/requests/api/graphql/mutations/dependency_proxy/image_ttl_group_policy/update_spec.rb index 31ba7ecdf0e..66ee17f356c 100644 --- a/spec/requests/api/graphql/mutations/dependency_proxy/image_ttl_group_policy/update_spec.rb +++ b/spec/requests/api/graphql/mutations/dependency_proxy/image_ttl_group_policy/update_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Updating the dependency proxy image ttl policy' do +RSpec.describe 'Updating the dependency proxy image ttl policy', feature_category: :dependency_proxy do include GraphqlHelpers using RSpec::Parameterized::TableSyntax diff --git a/spec/requests/api/graphql/mutations/design_management/delete_spec.rb b/spec/requests/api/graphql/mutations/design_management/delete_spec.rb index e2ab08b301b..7ea32ae6d19 100644 --- a/spec/requests/api/graphql/mutations/design_management/delete_spec.rb +++ b/spec/requests/api/graphql/mutations/design_management/delete_spec.rb @@ -2,7 +2,7 @@ require "spec_helper" -RSpec.describe "deleting designs" do +RSpec.describe "deleting designs", feature_category: :design_management do include GraphqlHelpers include DesignManagementTestHelpers diff --git a/spec/requests/api/graphql/mutations/design_management/move_spec.rb b/spec/requests/api/graphql/mutations/design_management/move_spec.rb index dd121ec733e..27b5259c56b 100644 --- a/spec/requests/api/graphql/mutations/design_management/move_spec.rb +++ b/spec/requests/api/graphql/mutations/design_management/move_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require "spec_helper" -RSpec.describe "moving designs" do +RSpec.describe "moving designs", feature_category: :design_management do include GraphqlHelpers include DesignManagementTestHelpers diff --git a/spec/requests/api/graphql/mutations/design_management/upload_spec.rb b/spec/requests/api/graphql/mutations/design_management/upload_spec.rb index d3e6c689a59..9b42b32c150 100644 --- a/spec/requests/api/graphql/mutations/design_management/upload_spec.rb +++ b/spec/requests/api/graphql/mutations/design_management/upload_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require "spec_helper" -RSpec.describe "uploading designs" do +RSpec.describe "uploading designs", feature_category: :design_management do include GraphqlHelpers include DesignManagementTestHelpers include WorkhorseHelpers diff --git a/spec/requests/api/graphql/mutations/discussions/toggle_resolve_spec.rb b/spec/requests/api/graphql/mutations/discussions/toggle_resolve_spec.rb index 632a934cd95..16d3bbb6518 100644 --- a/spec/requests/api/graphql/mutations/discussions/toggle_resolve_spec.rb +++ b/spec/requests/api/graphql/mutations/discussions/toggle_resolve_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Toggling the resolve status of a discussion' do +RSpec.describe 'Toggling the resolve status of a discussion', feature_category: :team_planning do include GraphqlHelpers let_it_be(:project) { create(:project, :public, :repository) } diff --git a/spec/requests/api/graphql/mutations/environments/canary_ingress/update_spec.rb b/spec/requests/api/graphql/mutations/environments/canary_ingress/update_spec.rb index 3771ae0746e..0e9317a4879 100644 --- a/spec/requests/api/graphql/mutations/environments/canary_ingress/update_spec.rb +++ b/spec/requests/api/graphql/mutations/environments/canary_ingress/update_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Update Environment Canary Ingress', :clean_gitlab_redis_cache do +RSpec.describe 'Update Environment Canary Ingress', :clean_gitlab_redis_cache, feature_category: :deployment_management do include GraphqlHelpers include KubernetesHelpers diff --git a/spec/requests/api/graphql/mutations/groups/update_spec.rb b/spec/requests/api/graphql/mutations/groups/update_spec.rb index b9dfb8e37ab..ea3d42a4463 100644 --- a/spec/requests/api/graphql/mutations/groups/update_spec.rb +++ b/spec/requests/api/graphql/mutations/groups/update_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'GroupUpdate' do +RSpec.describe 'GroupUpdate', feature_category: :subgroups do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/incident_management/timeline_event/create_spec.rb b/spec/requests/api/graphql/mutations/incident_management/timeline_event/create_spec.rb index fc3b666dd3d..49cee4f6801 100644 --- a/spec/requests/api/graphql/mutations/incident_management/timeline_event/create_spec.rb +++ b/spec/requests/api/graphql/mutations/incident_management/timeline_event/create_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Creating an incident timeline event' do +RSpec.describe 'Creating an incident timeline event', feature_category: :incident_management do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/incident_management/timeline_event/destroy_spec.rb b/spec/requests/api/graphql/mutations/incident_management/timeline_event/destroy_spec.rb index 85208869ad9..6e1a7b36736 100644 --- a/spec/requests/api/graphql/mutations/incident_management/timeline_event/destroy_spec.rb +++ b/spec/requests/api/graphql/mutations/incident_management/timeline_event/destroy_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Removing an incident timeline event' do +RSpec.describe 'Removing an incident timeline event', feature_category: :incident_management do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/incident_management/timeline_event/promote_from_note_spec.rb b/spec/requests/api/graphql/mutations/incident_management/timeline_event/promote_from_note_spec.rb index 62eeecb3fb7..ca9557b3183 100644 --- a/spec/requests/api/graphql/mutations/incident_management/timeline_event/promote_from_note_spec.rb +++ b/spec/requests/api/graphql/mutations/incident_management/timeline_event/promote_from_note_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Promote an incident timeline event from a comment' do +RSpec.describe 'Promote an incident timeline event from a comment', feature_category: :incident_management do include GraphqlHelpers include NotesHelper diff --git a/spec/requests/api/graphql/mutations/incident_management/timeline_event/update_spec.rb b/spec/requests/api/graphql/mutations/incident_management/timeline_event/update_spec.rb index 207dd55d527..163c689e399 100644 --- a/spec/requests/api/graphql/mutations/incident_management/timeline_event/update_spec.rb +++ b/spec/requests/api/graphql/mutations/incident_management/timeline_event/update_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Updating an incident timeline event' do +RSpec.describe 'Updating an incident timeline event', feature_category: :incident_management do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/incident_management/timeline_event_tag/create_spec.rb b/spec/requests/api/graphql/mutations/incident_management/timeline_event_tag/create_spec.rb index 7476499d9da..b37a5331421 100644 --- a/spec/requests/api/graphql/mutations/incident_management/timeline_event_tag/create_spec.rb +++ b/spec/requests/api/graphql/mutations/incident_management/timeline_event_tag/create_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Creating a timeline event tag' do +RSpec.describe 'Creating a timeline event tag', feature_category: :incident_management do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/issues/create_spec.rb b/spec/requests/api/graphql/mutations/issues/create_spec.rb index a489b7424e8..d2d2f0014d6 100644 --- a/spec/requests/api/graphql/mutations/issues/create_spec.rb +++ b/spec/requests/api/graphql/mutations/issues/create_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Create an issue' do +RSpec.describe 'Create an issue', feature_category: :team_planning do include GraphqlHelpers let_it_be(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/issues/move_spec.rb b/spec/requests/api/graphql/mutations/issues/move_spec.rb index 20ed16879f6..7d9579067b6 100644 --- a/spec/requests/api/graphql/mutations/issues/move_spec.rb +++ b/spec/requests/api/graphql/mutations/issues/move_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Moving an issue' do +RSpec.describe 'Moving an issue', feature_category: :team_planning do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/issues/set_confidential_spec.rb b/spec/requests/api/graphql/mutations/issues/set_confidential_spec.rb index 12ab504da14..c5e6901d8f8 100644 --- a/spec/requests/api/graphql/mutations/issues/set_confidential_spec.rb +++ b/spec/requests/api/graphql/mutations/issues/set_confidential_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Setting an issue as confidential' do +RSpec.describe 'Setting an issue as confidential', feature_category: :team_planning do include GraphqlHelpers let(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb b/spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb index 395a490bfc3..9fce5f8497f 100644 --- a/spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb +++ b/spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Setting issues crm contacts' do +RSpec.describe 'Setting issues crm contacts', feature_category: :service_desk do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/issues/set_due_date_spec.rb b/spec/requests/api/graphql/mutations/issues/set_due_date_spec.rb index 8e223b6fdaf..1a5a64e4196 100644 --- a/spec/requests/api/graphql/mutations/issues/set_due_date_spec.rb +++ b/spec/requests/api/graphql/mutations/issues/set_due_date_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Setting Due Date of an issue' do +RSpec.describe 'Setting Due Date of an issue', feature_category: :team_planning do include GraphqlHelpers let(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/issues/set_escalation_status_spec.rb b/spec/requests/api/graphql/mutations/issues/set_escalation_status_spec.rb index a81364d37b2..8fc3ad4236d 100644 --- a/spec/requests/api/graphql/mutations/issues/set_escalation_status_spec.rb +++ b/spec/requests/api/graphql/mutations/issues/set_escalation_status_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Setting the escalation status of an incident' do +RSpec.describe 'Setting the escalation status of an incident', feature_category: :incident_management do include GraphqlHelpers let_it_be(:project) { create(:project) } diff --git a/spec/requests/api/graphql/mutations/issues/set_locked_spec.rb b/spec/requests/api/graphql/mutations/issues/set_locked_spec.rb index 435ed0f9eb2..a8025894b1e 100644 --- a/spec/requests/api/graphql/mutations/issues/set_locked_spec.rb +++ b/spec/requests/api/graphql/mutations/issues/set_locked_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Setting an issue as locked' do +RSpec.describe 'Setting an issue as locked', feature_category: :team_planning do include GraphqlHelpers let_it_be(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/issues/set_severity_spec.rb b/spec/requests/api/graphql/mutations/issues/set_severity_spec.rb index cd9d695bd2c..77262c7f64f 100644 --- a/spec/requests/api/graphql/mutations/issues/set_severity_spec.rb +++ b/spec/requests/api/graphql/mutations/issues/set_severity_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Setting severity level of an incident' do +RSpec.describe 'Setting severity level of an incident', feature_category: :incident_management do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/issues/set_subscription_spec.rb b/spec/requests/api/graphql/mutations/issues/set_subscription_spec.rb index 1edc1e0553b..6c8e5b1d15d 100644 --- a/spec/requests/api/graphql/mutations/issues/set_subscription_spec.rb +++ b/spec/requests/api/graphql/mutations/issues/set_subscription_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Setting subscribed status of an issue' do +RSpec.describe 'Setting subscribed status of an issue', feature_category: :team_planning do include GraphqlHelpers it_behaves_like 'a subscribable resource api' do diff --git a/spec/requests/api/graphql/mutations/issues/update_spec.rb b/spec/requests/api/graphql/mutations/issues/update_spec.rb index f38deb426b1..e51c057c182 100644 --- a/spec/requests/api/graphql/mutations/issues/update_spec.rb +++ b/spec/requests/api/graphql/mutations/issues/update_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Update of an existing issue' do +RSpec.describe 'Update of an existing issue', feature_category: :team_planning do include GraphqlHelpers let_it_be(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/jira_import/import_users_spec.rb b/spec/requests/api/graphql/mutations/jira_import/import_users_spec.rb index b438e1ba881..ab15aa97680 100644 --- a/spec/requests/api/graphql/mutations/jira_import/import_users_spec.rb +++ b/spec/requests/api/graphql/mutations/jira_import/import_users_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Importing Jira Users' do +RSpec.describe 'Importing Jira Users', feature_category: :integrations do include JiraIntegrationHelpers include GraphqlHelpers diff --git a/spec/requests/api/graphql/mutations/jira_import/start_spec.rb b/spec/requests/api/graphql/mutations/jira_import/start_spec.rb index 1508ba31e37..a864bc88afc 100644 --- a/spec/requests/api/graphql/mutations/jira_import/start_spec.rb +++ b/spec/requests/api/graphql/mutations/jira_import/start_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Starting a Jira Import' do +RSpec.describe 'Starting a Jira Import', feature_category: :integrations do include JiraIntegrationHelpers include GraphqlHelpers diff --git a/spec/requests/api/graphql/mutations/labels/create_spec.rb b/spec/requests/api/graphql/mutations/labels/create_spec.rb index d19411f6c1d..607e20af977 100644 --- a/spec/requests/api/graphql/mutations/labels/create_spec.rb +++ b/spec/requests/api/graphql/mutations/labels/create_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Mutations::Labels::Create do +RSpec.describe Mutations::Labels::Create, feature_category: :team_planning do include GraphqlHelpers let_it_be(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/merge_requests/create_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/create_spec.rb index 3a4508489a1..c954fd50cc4 100644 --- a/spec/requests/api/graphql/mutations/merge_requests/create_spec.rb +++ b/spec/requests/api/graphql/mutations/merge_requests/create_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Creation of a new merge request' do +RSpec.describe 'Creation of a new merge request', feature_category: :code_review do include GraphqlHelpers let_it_be(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/merge_requests/reviewer_rereview_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/reviewer_rereview_spec.rb index 2e4f35cbcde..c41161eff2b 100644 --- a/spec/requests/api/graphql/mutations/merge_requests/reviewer_rereview_spec.rb +++ b/spec/requests/api/graphql/mutations/merge_requests/reviewer_rereview_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Setting assignees of a merge request' do +RSpec.describe 'Setting assignees of a merge request', feature_category: :code_review do include GraphqlHelpers let(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/merge_requests/set_assignees_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/set_assignees_spec.rb index 8cec5867aca..364d13291db 100644 --- a/spec/requests/api/graphql/mutations/merge_requests/set_assignees_spec.rb +++ b/spec/requests/api/graphql/mutations/merge_requests/set_assignees_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Setting assignees of a merge request', :assume_throttled do +RSpec.describe 'Setting assignees of a merge request', :assume_throttled, feature_category: :code_review do include GraphqlHelpers let_it_be(:project) { create(:project, :repository) } diff --git a/spec/requests/api/graphql/mutations/merge_requests/set_draft_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/set_draft_spec.rb index 9c75d984896..b48a94fbeb9 100644 --- a/spec/requests/api/graphql/mutations/merge_requests/set_draft_spec.rb +++ b/spec/requests/api/graphql/mutations/merge_requests/set_draft_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Setting Draft status of a merge request' do +RSpec.describe 'Setting Draft status of a merge request', feature_category: :code_review do include GraphqlHelpers let(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/merge_requests/set_locked_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/set_locked_spec.rb index a1a35bc1dcc..d88982c508c 100644 --- a/spec/requests/api/graphql/mutations/merge_requests/set_locked_spec.rb +++ b/spec/requests/api/graphql/mutations/merge_requests/set_locked_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Setting locked status of a merge request' do +RSpec.describe 'Setting locked status of a merge request', feature_category: :code_review do include GraphqlHelpers let(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/merge_requests/set_milestone_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/set_milestone_spec.rb index d7e2602bd0a..a0f0e45d1fc 100644 --- a/spec/requests/api/graphql/mutations/merge_requests/set_milestone_spec.rb +++ b/spec/requests/api/graphql/mutations/merge_requests/set_milestone_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Setting milestone of a merge request' do +RSpec.describe 'Setting milestone of a merge request', feature_category: :code_review do include GraphqlHelpers let(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/merge_requests/set_reviewers_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/set_reviewers_spec.rb index be786256ef2..a5be2a95c8b 100644 --- a/spec/requests/api/graphql/mutations/merge_requests/set_reviewers_spec.rb +++ b/spec/requests/api/graphql/mutations/merge_requests/set_reviewers_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Setting reviewers of a merge request', :assume_throttled do +RSpec.describe 'Setting reviewers of a merge request', :assume_throttled, feature_category: :code_review do include GraphqlHelpers let_it_be(:project) { create(:project, :repository) } diff --git a/spec/requests/api/graphql/mutations/merge_requests/set_subscription_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/set_subscription_spec.rb index d90faa605c0..daf1f529847 100644 --- a/spec/requests/api/graphql/mutations/merge_requests/set_subscription_spec.rb +++ b/spec/requests/api/graphql/mutations/merge_requests/set_subscription_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Setting subscribed status of a merge request' do +RSpec.describe 'Setting subscribed status of a merge request', feature_category: :code_review do include GraphqlHelpers it_behaves_like 'a subscribable resource api' do diff --git a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb index 9ef443af76a..bce57b47aab 100644 --- a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb +++ b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Mutations::Metrics::Dashboard::Annotations::Create do +RSpec.describe Mutations::Metrics::Dashboard::Annotations::Create, feature_category: :metrics do include GraphqlHelpers let_it_be(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb index b956734068c..f505dc25dc0 100644 --- a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb +++ b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Mutations::Metrics::Dashboard::Annotations::Delete do +RSpec.describe Mutations::Metrics::Dashboard::Annotations::Delete, feature_category: :metrics do include GraphqlHelpers let_it_be(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb b/spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb index 567d8799d93..f4f4f34fe29 100644 --- a/spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb +++ b/spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Updating the package settings' do +RSpec.describe 'Updating the package settings', feature_category: :package_registry do include GraphqlHelpers using RSpec::Parameterized::TableSyntax diff --git a/spec/requests/api/graphql/mutations/notes/create/diff_note_spec.rb b/spec/requests/api/graphql/mutations/notes/create/diff_note_spec.rb index a432fb17a70..3cf78230a4c 100644 --- a/spec/requests/api/graphql/mutations/notes/create/diff_note_spec.rb +++ b/spec/requests/api/graphql/mutations/notes/create/diff_note_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Adding a DiffNote' do +RSpec.describe 'Adding a DiffNote', feature_category: :team_planning do include GraphqlHelpers let_it_be(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/notes/create/image_diff_note_spec.rb b/spec/requests/api/graphql/mutations/notes/create/image_diff_note_spec.rb index 8f2438cb741..0ce239d9ca5 100644 --- a/spec/requests/api/graphql/mutations/notes/create/image_diff_note_spec.rb +++ b/spec/requests/api/graphql/mutations/notes/create/image_diff_note_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Adding an image DiffNote' do +RSpec.describe 'Adding an image DiffNote', feature_category: :team_planning do include GraphqlHelpers let_it_be(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/notes/create/note_spec.rb b/spec/requests/api/graphql/mutations/notes/create/note_spec.rb index 9c3842db31a..f263c11a5f0 100644 --- a/spec/requests/api/graphql/mutations/notes/create/note_spec.rb +++ b/spec/requests/api/graphql/mutations/notes/create/note_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Adding a Note' do +RSpec.describe 'Adding a Note', feature_category: :team_planning do include GraphqlHelpers let_it_be(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/notes/destroy_spec.rb b/spec/requests/api/graphql/mutations/notes/destroy_spec.rb index 49f09fadfea..3ee76b5ca03 100644 --- a/spec/requests/api/graphql/mutations/notes/destroy_spec.rb +++ b/spec/requests/api/graphql/mutations/notes/destroy_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Destroying a Note' do +RSpec.describe 'Destroying a Note', feature_category: :team_planning do include GraphqlHelpers let!(:note) { create(:note) } diff --git a/spec/requests/api/graphql/mutations/notes/reposition_image_diff_note_spec.rb b/spec/requests/api/graphql/mutations/notes/reposition_image_diff_note_spec.rb index c4674155aa0..e9cd27a1e20 100644 --- a/spec/requests/api/graphql/mutations/notes/reposition_image_diff_note_spec.rb +++ b/spec/requests/api/graphql/mutations/notes/reposition_image_diff_note_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Repositioning an ImageDiffNote' do +RSpec.describe 'Repositioning an ImageDiffNote', feature_category: :team_planning do include GraphqlHelpers let_it_be(:noteable) { create(:merge_request) } diff --git a/spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb b/spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb index cfd0b34b815..a5cd3c8b019 100644 --- a/spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb +++ b/spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Updating an image DiffNote' do +RSpec.describe 'Updating an image DiffNote', feature_category: :team_planning do include GraphqlHelpers using RSpec::Parameterized::TableSyntax diff --git a/spec/requests/api/graphql/mutations/notes/update/note_spec.rb b/spec/requests/api/graphql/mutations/notes/update/note_spec.rb index bae5c58abff..6b9dbbbfab9 100644 --- a/spec/requests/api/graphql/mutations/notes/update/note_spec.rb +++ b/spec/requests/api/graphql/mutations/notes/update/note_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Updating a Note' do +RSpec.describe 'Updating a Note', feature_category: :team_planning do include GraphqlHelpers let!(:note) { create(:note, note: original_body) } diff --git a/spec/requests/api/graphql/mutations/packages/bulk_destroy_spec.rb b/spec/requests/api/graphql/mutations/packages/bulk_destroy_spec.rb index 1fe01af4f1c..d0980a2b43d 100644 --- a/spec/requests/api/graphql/mutations/packages/bulk_destroy_spec.rb +++ b/spec/requests/api/graphql/mutations/packages/bulk_destroy_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Destroying multiple packages' do +RSpec.describe 'Destroying multiple packages', feature_category: :package_registry do using RSpec::Parameterized::TableSyntax include GraphqlHelpers diff --git a/spec/requests/api/graphql/mutations/packages/cleanup/policy/update_spec.rb b/spec/requests/api/graphql/mutations/packages/cleanup/policy/update_spec.rb index 7e00f3ca53a..2540e06be9a 100644 --- a/spec/requests/api/graphql/mutations/packages/cleanup/policy/update_spec.rb +++ b/spec/requests/api/graphql/mutations/packages/cleanup/policy/update_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Updating the packages cleanup policy' do +RSpec.describe 'Updating the packages cleanup policy', feature_category: :package_registry do include GraphqlHelpers using RSpec::Parameterized::TableSyntax diff --git a/spec/requests/api/graphql/mutations/packages/destroy_file_spec.rb b/spec/requests/api/graphql/mutations/packages/destroy_file_spec.rb index cd25aba9e00..a4b7001fdd5 100644 --- a/spec/requests/api/graphql/mutations/packages/destroy_file_spec.rb +++ b/spec/requests/api/graphql/mutations/packages/destroy_file_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Destroying a package file' do +RSpec.describe 'Destroying a package file', feature_category: :package_registry do using RSpec::Parameterized::TableSyntax include GraphqlHelpers diff --git a/spec/requests/api/graphql/mutations/packages/destroy_files_spec.rb b/spec/requests/api/graphql/mutations/packages/destroy_files_spec.rb index 002cd634ebd..cdd05d80fc2 100644 --- a/spec/requests/api/graphql/mutations/packages/destroy_files_spec.rb +++ b/spec/requests/api/graphql/mutations/packages/destroy_files_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Destroying multiple package files' do +RSpec.describe 'Destroying multiple package files', feature_category: :package_registry do using RSpec::Parameterized::TableSyntax include GraphqlHelpers diff --git a/spec/requests/api/graphql/mutations/packages/destroy_spec.rb b/spec/requests/api/graphql/mutations/packages/destroy_spec.rb index 2340a6a36d8..86167e7116f 100644 --- a/spec/requests/api/graphql/mutations/packages/destroy_spec.rb +++ b/spec/requests/api/graphql/mutations/packages/destroy_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Destroying a package' do +RSpec.describe 'Destroying a package', feature_category: :package_registry do using RSpec::Parameterized::TableSyntax include GraphqlHelpers diff --git a/spec/requests/api/graphql/mutations/release_asset_links/create_spec.rb b/spec/requests/api/graphql/mutations/release_asset_links/create_spec.rb index c7a4cb1ebce..418a0e47a36 100644 --- a/spec/requests/api/graphql/mutations/release_asset_links/create_spec.rb +++ b/spec/requests/api/graphql/mutations/release_asset_links/create_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Creation of a new release asset link' do +RSpec.describe 'Creation of a new release asset link', feature_category: :release_orchestration do include GraphqlHelpers let_it_be(:project) { create(:project, :private, :repository) } diff --git a/spec/requests/api/graphql/mutations/release_asset_links/delete_spec.rb b/spec/requests/api/graphql/mutations/release_asset_links/delete_spec.rb index 57489c82ec2..b6d2c3f691d 100644 --- a/spec/requests/api/graphql/mutations/release_asset_links/delete_spec.rb +++ b/spec/requests/api/graphql/mutations/release_asset_links/delete_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Deletes a release asset link' do +RSpec.describe 'Deletes a release asset link', feature_category: :release_orchestration do include GraphqlHelpers let_it_be(:project) { create(:project, :private, :repository) } diff --git a/spec/requests/api/graphql/mutations/release_asset_links/update_spec.rb b/spec/requests/api/graphql/mutations/release_asset_links/update_spec.rb index 92b558d4be3..61395cc4042 100644 --- a/spec/requests/api/graphql/mutations/release_asset_links/update_spec.rb +++ b/spec/requests/api/graphql/mutations/release_asset_links/update_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Updating an existing release asset link' do +RSpec.describe 'Updating an existing release asset link', feature_category: :release_orchestration do include GraphqlHelpers let_it_be(:project) { create(:project, :private, :repository) } diff --git a/spec/requests/api/graphql/mutations/releases/create_spec.rb b/spec/requests/api/graphql/mutations/releases/create_spec.rb index 2541072b766..295b8c0e97e 100644 --- a/spec/requests/api/graphql/mutations/releases/create_spec.rb +++ b/spec/requests/api/graphql/mutations/releases/create_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Creation of a new release' do +RSpec.describe 'Creation of a new release', feature_category: :release_orchestration do include GraphqlHelpers include Presentable diff --git a/spec/requests/api/graphql/mutations/releases/delete_spec.rb b/spec/requests/api/graphql/mutations/releases/delete_spec.rb index eb4f0b594ea..bb398787cc6 100644 --- a/spec/requests/api/graphql/mutations/releases/delete_spec.rb +++ b/spec/requests/api/graphql/mutations/releases/delete_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Deleting a release' do +RSpec.describe 'Deleting a release', feature_category: :release_orchestration do include GraphqlHelpers include Presentable diff --git a/spec/requests/api/graphql/mutations/releases/update_spec.rb b/spec/requests/api/graphql/mutations/releases/update_spec.rb index 240db764f40..2b88576a70e 100644 --- a/spec/requests/api/graphql/mutations/releases/update_spec.rb +++ b/spec/requests/api/graphql/mutations/releases/update_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Updating an existing release' do +RSpec.describe 'Updating an existing release', feature_category: :release_orchestration do include GraphqlHelpers include Presentable diff --git a/spec/requests/api/graphql/mutations/security/ci_configuration/configure_sast_iac_spec.rb b/spec/requests/api/graphql/mutations/security/ci_configuration/configure_sast_iac_spec.rb index 0c034f38dc8..cdd25f8f6ec 100644 --- a/spec/requests/api/graphql/mutations/security/ci_configuration/configure_sast_iac_spec.rb +++ b/spec/requests/api/graphql/mutations/security/ci_configuration/configure_sast_iac_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'ConfigureSastIac' do +RSpec.describe 'ConfigureSastIac', feature_category: :static_application_security_testing do include GraphqlHelpers let_it_be(:project) { create(:project, :test_repo) } diff --git a/spec/requests/api/graphql/mutations/security/ci_configuration/configure_secret_detection_spec.rb b/spec/requests/api/graphql/mutations/security/ci_configuration/configure_secret_detection_spec.rb index 8fa6e44b208..370abf2fe00 100644 --- a/spec/requests/api/graphql/mutations/security/ci_configuration/configure_secret_detection_spec.rb +++ b/spec/requests/api/graphql/mutations/security/ci_configuration/configure_secret_detection_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'ConfigureSecretDetection' do +RSpec.describe 'ConfigureSecretDetection', feature_category: :secret_detection do include GraphqlHelpers let_it_be(:project) { create(:project, :test_repo) } diff --git a/spec/requests/api/graphql/mutations/snippets/create_spec.rb b/spec/requests/api/graphql/mutations/snippets/create_spec.rb index 264fa5732c3..0b1af2bf628 100644 --- a/spec/requests/api/graphql/mutations/snippets/create_spec.rb +++ b/spec/requests/api/graphql/mutations/snippets/create_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Creating a Snippet' do +RSpec.describe 'Creating a Snippet', feature_category: :source_code_management do include GraphqlHelpers let_it_be(:user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/snippets/destroy_spec.rb b/spec/requests/api/graphql/mutations/snippets/destroy_spec.rb index 1be8ce142ac..09e884d9412 100644 --- a/spec/requests/api/graphql/mutations/snippets/destroy_spec.rb +++ b/spec/requests/api/graphql/mutations/snippets/destroy_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Destroying a Snippet' do +RSpec.describe 'Destroying a Snippet', feature_category: :source_code_management do include GraphqlHelpers let(:current_user) { snippet.author } diff --git a/spec/requests/api/graphql/mutations/snippets/mark_as_spam_spec.rb b/spec/requests/api/graphql/mutations/snippets/mark_as_spam_spec.rb index 77fd6cddc09..9a8c027da8a 100644 --- a/spec/requests/api/graphql/mutations/snippets/mark_as_spam_spec.rb +++ b/spec/requests/api/graphql/mutations/snippets/mark_as_spam_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Mark snippet as spam' do +RSpec.describe 'Mark snippet as spam', feature_category: :source_code_management do include GraphqlHelpers include AfterNextHelpers diff --git a/spec/requests/api/graphql/mutations/snippets/update_spec.rb b/spec/requests/api/graphql/mutations/snippets/update_spec.rb index a385c96de61..fa087e6773c 100644 --- a/spec/requests/api/graphql/mutations/snippets/update_spec.rb +++ b/spec/requests/api/graphql/mutations/snippets/update_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Updating a Snippet' do +RSpec.describe 'Updating a Snippet', feature_category: :source_code_management do include GraphqlHelpers include SessionHelpers diff --git a/spec/requests/api/graphql/mutations/timelogs/create_spec.rb b/spec/requests/api/graphql/mutations/timelogs/create_spec.rb index 9b89d053901..42249818a92 100644 --- a/spec/requests/api/graphql/mutations/timelogs/create_spec.rb +++ b/spec/requests/api/graphql/mutations/timelogs/create_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Create a timelog' do +RSpec.describe 'Create a timelog', feature_category: :team_planning do include GraphqlHelpers let_it_be(:author) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/timelogs/delete_spec.rb b/spec/requests/api/graphql/mutations/timelogs/delete_spec.rb index d304bfbdf00..d04b4d193e6 100644 --- a/spec/requests/api/graphql/mutations/timelogs/delete_spec.rb +++ b/spec/requests/api/graphql/mutations/timelogs/delete_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Delete a timelog' do +RSpec.describe 'Delete a timelog', feature_category: :team_planning do include GraphqlHelpers let_it_be(:author) { create(:user) } let_it_be(:project) { create(:project, :public) } diff --git a/spec/requests/api/graphql/mutations/todos/create_spec.rb b/spec/requests/api/graphql/mutations/todos/create_spec.rb index aca00519682..5d7ecb3c927 100644 --- a/spec/requests/api/graphql/mutations/todos/create_spec.rb +++ b/spec/requests/api/graphql/mutations/todos/create_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Create a todo' do +RSpec.describe 'Create a todo', feature_category: :team_planning do include GraphqlHelpers let_it_be(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/todos/mark_all_done_spec.rb b/spec/requests/api/graphql/mutations/todos/mark_all_done_spec.rb index dc20fde8e3c..c611c6ee2a1 100644 --- a/spec/requests/api/graphql/mutations/todos/mark_all_done_spec.rb +++ b/spec/requests/api/graphql/mutations/todos/mark_all_done_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Marking all todos done' do +RSpec.describe 'Marking all todos done', feature_category: :team_planning do include GraphqlHelpers let_it_be(:project) { create(:project) } diff --git a/spec/requests/api/graphql/mutations/todos/mark_done_spec.rb b/spec/requests/api/graphql/mutations/todos/mark_done_spec.rb index 7f5ea71c760..60700d8024c 100644 --- a/spec/requests/api/graphql/mutations/todos/mark_done_spec.rb +++ b/spec/requests/api/graphql/mutations/todos/mark_done_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Marking todos done' do +RSpec.describe 'Marking todos done', feature_category: :team_planning do include GraphqlHelpers let_it_be(:project) { create(:project) } diff --git a/spec/requests/api/graphql/mutations/todos/restore_many_spec.rb b/spec/requests/api/graphql/mutations/todos/restore_many_spec.rb index 4316bd060c1..9daa243cf8e 100644 --- a/spec/requests/api/graphql/mutations/todos/restore_many_spec.rb +++ b/spec/requests/api/graphql/mutations/todos/restore_many_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Restoring many Todos' do +RSpec.describe 'Restoring many Todos', feature_category: :team_planning do include GraphqlHelpers let_it_be(:project) { create(:project) } diff --git a/spec/requests/api/graphql/mutations/todos/restore_spec.rb b/spec/requests/api/graphql/mutations/todos/restore_spec.rb index d995191c97e..868298763ec 100644 --- a/spec/requests/api/graphql/mutations/todos/restore_spec.rb +++ b/spec/requests/api/graphql/mutations/todos/restore_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Restoring Todos' do +RSpec.describe 'Restoring Todos', feature_category: :team_planning do include GraphqlHelpers let_it_be(:project) { create(:project) } diff --git a/spec/requests/api/graphql/mutations/uploads/delete_spec.rb b/spec/requests/api/graphql/mutations/uploads/delete_spec.rb index 2d1b33cc086..08dbbe23b6b 100644 --- a/spec/requests/api/graphql/mutations/uploads/delete_spec.rb +++ b/spec/requests/api/graphql/mutations/uploads/delete_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Delete an upload' do +RSpec.describe 'Delete an upload', feature_category: :navigation do include GraphqlHelpers let_it_be(:group) { create(:group) } diff --git a/spec/requests/api/graphql/mutations/user_callouts/create_spec.rb b/spec/requests/api/graphql/mutations/user_callouts/create_spec.rb index 28a46583d2a..eb35d310760 100644 --- a/spec/requests/api/graphql/mutations/user_callouts/create_spec.rb +++ b/spec/requests/api/graphql/mutations/user_callouts/create_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Create a user callout' do +RSpec.describe 'Create a user callout', feature_category: :navigation do include GraphqlHelpers let_it_be(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/user_preferences/update_spec.rb b/spec/requests/api/graphql/mutations/user_preferences/update_spec.rb index e1c7fd9d60d..31d17401b9e 100644 --- a/spec/requests/api/graphql/mutations/user_preferences/update_spec.rb +++ b/spec/requests/api/graphql/mutations/user_preferences/update_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Mutations::UserPreferences::Update do +RSpec.describe Mutations::UserPreferences::Update, feature_category: :users do include GraphqlHelpers let_it_be(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/work_items/create_from_task_spec.rb b/spec/requests/api/graphql/mutations/work_items/create_from_task_spec.rb index c6a980b5cef..97bf060356a 100644 --- a/spec/requests/api/graphql/mutations/work_items/create_from_task_spec.rb +++ b/spec/requests/api/graphql/mutations/work_items/create_from_task_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe "Create a work item from a task in a work item's description" do +RSpec.describe "Create a work item from a task in a work item's description", feature_category: :team_planning do include GraphqlHelpers let_it_be(:project) { create(:project) } diff --git a/spec/requests/api/graphql/mutations/work_items/create_spec.rb b/spec/requests/api/graphql/mutations/work_items/create_spec.rb index 090345ca038..16f78b67b5c 100644 --- a/spec/requests/api/graphql/mutations/work_items/create_spec.rb +++ b/spec/requests/api/graphql/mutations/work_items/create_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Create a work item' do +RSpec.describe 'Create a work item', feature_category: :team_planning do include GraphqlHelpers let_it_be(:project) { create(:project) } diff --git a/spec/requests/api/graphql/mutations/work_items/delete_spec.rb b/spec/requests/api/graphql/mutations/work_items/delete_spec.rb index 0a84225a7ab..e25ff5613e4 100644 --- a/spec/requests/api/graphql/mutations/work_items/delete_spec.rb +++ b/spec/requests/api/graphql/mutations/work_items/delete_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Delete a work item' do +RSpec.describe 'Delete a work item', feature_category: :team_planning do include GraphqlHelpers let_it_be(:project) { create(:project) } diff --git a/spec/requests/api/graphql/mutations/work_items/delete_task_spec.rb b/spec/requests/api/graphql/mutations/work_items/delete_task_spec.rb index c44939c8d54..b1828de046f 100644 --- a/spec/requests/api/graphql/mutations/work_items/delete_task_spec.rb +++ b/spec/requests/api/graphql/mutations/work_items/delete_task_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe "Delete a task in a work item's description" do +RSpec.describe "Delete a task in a work item's description", feature_category: :team_planning do include GraphqlHelpers let_it_be(:project) { create(:project) } diff --git a/spec/requests/api/graphql/mutations/work_items/update_spec.rb b/spec/requests/api/graphql/mutations/work_items/update_spec.rb index b5f5ca383f3..c71c2ae6c39 100644 --- a/spec/requests/api/graphql/mutations/work_items/update_spec.rb +++ b/spec/requests/api/graphql/mutations/work_items/update_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Update a work item', feature_category: :project_management do +RSpec.describe 'Update a work item', feature_category: :team_planning do include GraphqlHelpers let_it_be(:group) { create(:group) } diff --git a/spec/requests/api/graphql/mutations/work_items/update_task_spec.rb b/spec/requests/api/graphql/mutations/work_items/update_task_spec.rb index 55285be5a5d..999c685ac6a 100644 --- a/spec/requests/api/graphql/mutations/work_items/update_task_spec.rb +++ b/spec/requests/api/graphql/mutations/work_items/update_task_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Update a work item task' do +RSpec.describe 'Update a work item task', feature_category: :team_planning do include GraphqlHelpers let_it_be(:project) { create(:project) } diff --git a/spec/requests/api/graphql/project/alert_management/alerts_spec.rb b/spec/requests/api/graphql/project/alert_management/alerts_spec.rb index fe77d9dc86d..304edfbf4e4 100644 --- a/spec/requests/api/graphql/project/alert_management/alerts_spec.rb +++ b/spec/requests/api/graphql/project/alert_management/alerts_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require 'spec_helper' -RSpec.describe 'getting Alert Management Alerts' do +RSpec.describe 'getting Alert Management Alerts', feature_category: :incident_management do include GraphqlHelpers let_it_be(:payload) { { 'custom' => { 'alert' => 'payload' }, 'runbook' => 'runbook' } } @@ -59,6 +59,7 @@ RSpec.describe 'getting Alert Management Alerts' do it 'returns the correct properties of the alerts' do expect(first_alert).to include( + 'id' => triggered_alert.to_global_id.to_s, 'iid' => triggered_alert.iid.to_s, 'title' => triggered_alert.title, 'description' => triggered_alert.description, @@ -80,6 +81,7 @@ RSpec.describe 'getting Alert Management Alerts' do ) expect(second_alert).to include( + 'id' => resolved_alert.to_global_id.to_s, 'iid' => resolved_alert.iid.to_s, 'status' => 'RESOLVED', 'endedAt' => resolved_alert.ended_at.strftime('%Y-%m-%dT%H:%M:%SZ') diff --git a/spec/requests/projects/issues_controller_spec.rb b/spec/requests/projects/issues_controller_spec.rb index 8db21e21235..bbf200eaacd 100644 --- a/spec/requests/projects/issues_controller_spec.rb +++ b/spec/requests/projects/issues_controller_spec.rb @@ -8,6 +8,30 @@ RSpec.describe Projects::IssuesController, feature_category: :team_planning do let_it_be(:project) { issue.project } let_it_be(:user) { issue.author } + describe 'GET #new' do + before do + login_as(user) + end + + it_behaves_like "observability csp policy", described_class do + let(:tested_path) do + new_project_issue_path(project) + end + end + end + + describe 'GET #show' do + before do + login_as(user) + end + + it_behaves_like "observability csp policy", described_class do + let(:tested_path) do + project_issue_path(project, issue) + end + end + end + describe 'GET #discussions' do before do login_as(user) diff --git a/spec/requests/projects/merge_requests/creations_spec.rb b/spec/requests/projects/merge_requests/creations_spec.rb index fc409d8d676..59e2047e1c7 100644 --- a/spec/requests/projects/merge_requests/creations_spec.rb +++ b/spec/requests/projects/merge_requests/creations_spec.rb @@ -24,5 +24,17 @@ RSpec.describe 'merge requests creations', feature_category: :code_review do expect { get_new }.not_to exceed_query_limit(control) end + + it_behaves_like "observability csp policy", Projects::MergeRequests::CreationsController do + let(:tested_path) do + project_new_merge_request_path(project, merge_request: { + title: 'Some feature', + source_branch: 'fix', + target_branch: 'feature', + target_project: project, + source_project: project + }) + end + end end end diff --git a/spec/requests/projects/merge_requests_controller_spec.rb b/spec/requests/projects/merge_requests_controller_spec.rb index a131d38186a..f5f8b5c2d83 100644 --- a/spec/requests/projects/merge_requests_controller_spec.rb +++ b/spec/requests/projects/merge_requests_controller_spec.rb @@ -3,10 +3,23 @@ require 'spec_helper' RSpec.describe Projects::MergeRequestsController, feature_category: :source_code_management do + let_it_be(:merge_request) { create(:merge_request) } + let_it_be(:project) { merge_request.project } + let_it_be(:user) { merge_request.author } + + describe 'GET #show' do + before do + login_as(user) + end + + it_behaves_like "observability csp policy", described_class do + let(:tested_path) do + project_merge_request_path(project, merge_request) + end + end + end + describe 'GET #discussions' do - let_it_be(:merge_request) { create(:merge_request) } - let_it_be(:project) { merge_request.project } - let_it_be(:user) { merge_request.author } let_it_be(:discussion) { create(:discussion_note_on_merge_request, noteable: merge_request, project: project) } let_it_be(:discussion_reply) { create(:discussion_note_on_merge_request, noteable: merge_request, project: project, in_reply_to: discussion) } let_it_be(:state_event) { create(:resource_state_event, merge_request: merge_request) } diff --git a/spec/serializers/deploy_keys/deploy_key_entity_spec.rb b/spec/serializers/deploy_keys/deploy_key_entity_spec.rb index 7719cafae11..4302ed3a097 100644 --- a/spec/serializers/deploy_keys/deploy_key_entity_spec.rb +++ b/spec/serializers/deploy_keys/deploy_key_entity_spec.rb @@ -39,7 +39,8 @@ RSpec.describe DeployKeys::DeployKeyEntity do id: project.id, name: project.name, full_path: project_path(project), - full_name: project.full_name + full_name: project.full_name, + refs_url: refs_project_path(project) } } ] diff --git a/spec/services/ci/enqueue_job_service_spec.rb b/spec/services/ci/enqueue_job_service_spec.rb new file mode 100644 index 00000000000..c2bb0bb2bb5 --- /dev/null +++ b/spec/services/ci/enqueue_job_service_spec.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Ci::EnqueueJobService, '#execute', feature_category: :continuous_integration do + let_it_be(:project) { create(:project) } + let(:user) { create(:user, developer_projects: [project]) } + let(:pipeline) { create(:ci_pipeline, project: project) } + let(:build) { create(:ci_build, :manual, pipeline: pipeline) } + + let(:service) do + described_class.new(build, current_user: user) + end + + subject(:execute) { service.execute } + + it 'assigns the user to the job' do + expect { execute }.to change { build.reload.user }.to(user) + end + + it 'calls enqueue!' do + expect(build).to receive(:enqueue!) + execute + end + + it 'calls Ci::ResetSkippedJobsService' do + expect_next_instance_of(Ci::ResetSkippedJobsService) do |service| + expect(service).to receive(:execute).with(build) + end + + execute + end + + it 'returns the job' do + expect(execute).to eq(build) + end + + context 'when variables are supplied' do + let(:job_variables) do + [{ key: 'first', secret_value: 'first' }, + { key: 'second', secret_value: 'second' }] + end + + let(:service) do + described_class.new(build, current_user: user, variables: job_variables) + end + + it 'assigns the variables to the job' do + execute + expect(build.reload.job_variables.map(&:key)).to contain_exactly('first', 'second') + end + end + + context 'when the job transition is invalid' do + let(:bridge) { create(:ci_bridge, :failed, pipeline: pipeline, project: project) } + + let(:service) do + described_class.new(bridge, current_user: user) + end + + it 'raises StateMachines::InvalidTransition' do + expect { execute }.to raise_error StateMachines::InvalidTransition + end + end + + context 'when a transition block is supplied' do + let(:bridge) { create(:ci_bridge, :playable, pipeline: pipeline) } + + let(:service) do + described_class.new(bridge, current_user: user) + end + + subject(:execute) { service.execute(&:pending!) } + + it 'calls the transition block instead of enqueue!' do + expect(bridge).to receive(:pending!) + expect(bridge).not_to receive(:enqueue!) + execute + end + end +end diff --git a/spec/services/ci/retry_pipeline_service_spec.rb b/spec/services/ci/retry_pipeline_service_spec.rb index 77345096537..07518c35fab 100644 --- a/spec/services/ci/retry_pipeline_service_spec.rb +++ b/spec/services/ci/retry_pipeline_service_spec.rb @@ -349,7 +349,10 @@ RSpec.describe Ci::RetryPipelineService, '#execute' do it 'marks source bridge as pending' do expect { service.execute(pipeline) }.to change { bridge.reload.status }.to('pending') - .and not_change { bridge.reload.user } + end + + it 'assigns the current user to the source bridge' do + expect { service.execute(pipeline) }.to change { bridge.reload.user }.to(user) end end end diff --git a/spec/support/helpers/content_security_policy_helpers.rb b/spec/support/helpers/content_security_policy_helpers.rb index 230075ead70..7e3de9fd219 100644 --- a/spec/support/helpers/content_security_policy_helpers.rb +++ b/spec/support/helpers/content_security_policy_helpers.rb @@ -4,11 +4,17 @@ module ContentSecurityPolicyHelpers # Expecting 2 calls to current_content_security_policy by default: # 1. call that's being tested # 2. call in ApplicationController - def setup_csp_for_controller(controller_class, csp = ActionDispatch::ContentSecurityPolicy.new, times: 2) + def setup_csp_for_controller( + controller_class, csp = ActionDispatch::ContentSecurityPolicy.new, times: 2, +any_time: false) expect_next_instance_of(controller_class) do |controller| - expect(controller) + if any_time + expect(controller).to receive(:current_content_security_policy).at_least(:once).and_return(csp) + else + expect(controller) .to receive(:current_content_security_policy).exactly(times).times .and_return(csp) + end end end end diff --git a/spec/support/shared_examples/features/creatable_merge_request_shared_examples.rb b/spec/support/shared_examples/features/creatable_merge_request_shared_examples.rb index 2cfe353d5d7..7f31ea8f9be 100644 --- a/spec/support/shared_examples/features/creatable_merge_request_shared_examples.rb +++ b/spec/support/shared_examples/features/creatable_merge_request_shared_examples.rb @@ -64,7 +64,7 @@ RSpec.shared_examples 'a creatable merge request' do visit project_new_merge_request_path(source_project) first('.js-target-project').click - find('.dropdown-target-project .dropdown-content a', text: target_project.full_path).click + find('.dropdown-target-project li', text: target_project.full_path).click wait_for_requests diff --git a/spec/support/shared_examples/observability/csp_shared_examples.rb b/spec/support/shared_examples/observability/csp_shared_examples.rb index f41aa8daa9b..868d7023d14 100644 --- a/spec/support/shared_examples/observability/csp_shared_examples.rb +++ b/spec/support/shared_examples/observability/csp_shared_examples.rb @@ -21,9 +21,18 @@ RSpec.shared_examples 'observability csp policy' do |controller_class = describe include ContentSecurityPolicyHelpers let(:observability_url) { Gitlab::Observability.observability_url } + let(:signin_url) do + Gitlab::Utils.append_path(Gitlab.config.gitlab.url, + '/users/sign_in') + end + + let(:oauth_url) do + Gitlab::Utils.append_path(Gitlab.config.gitlab.url, + '/oauth/authorize') + end before do - setup_csp_for_controller(described_class, csp) + setup_csp_for_controller(controller_class, csp, any_time: true) end subject do @@ -48,20 +57,33 @@ RSpec.shared_examples 'observability csp policy' do |controller_class = describe it 'appends the proper url to frame-src CSP directives' do expect(subject).to include( - "frame-src https://something.test #{observability_url} 'self'") + "frame-src https://something.test #{observability_url} #{signin_url} #{oauth_url}") end end - context 'when self is already present in the policy' do + context 'when signin is already present in the policy' do let(:csp) do ActionDispatch::ContentSecurityPolicy.new do |p| - p.frame_src "'self'" + p.frame_src signin_url end end - it 'does not append self again' do + it 'does not append signin again' do expect(subject).to include( - "frame-src 'self' #{observability_url};") + "frame-src #{signin_url} #{observability_url} #{oauth_url};") + end + end + + context 'when oauth is already present in the policy' do + let(:csp) do + ActionDispatch::ContentSecurityPolicy.new do |p| + p.frame_src oauth_url + end + end + + it 'does not append oauth again' do + expect(subject).to include( + "frame-src #{oauth_url} #{observability_url} #{signin_url};") end end @@ -79,7 +101,7 @@ RSpec.shared_examples 'observability csp policy' do |controller_class = describe it 'appends the proper url to frame-src CSP directives' do expect(subject).to include( - "frame-src https://something.test #{observability_url} 'self'") + "frame-src https://something.test #{observability_url} #{signin_url} #{oauth_url}") end end @@ -93,7 +115,7 @@ RSpec.shared_examples 'observability csp policy' do |controller_class = describe it 'appends to frame-src CSP directives' do expect(subject).to include( - "frame-src https://something.test #{observability_url} 'self'") + "frame-src https://something.test #{observability_url} #{signin_url} #{oauth_url}") expect(subject).to include( "default-src https://something_default.test") end