diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-11-30 21:07:14 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-11-30 21:07:14 +0300 |
commit | 9e7f94a7408534411dc8da69c9e3ad3a55722b51 (patch) | |
tree | baf917b2ab176390258c3a6a282b3b2432d4469c | |
parent | 826cf5293fb78029f76c5e769696e3b37e681207 (diff) |
Add latest changes from gitlab-org/gitlab@master
155 files changed, 1025 insertions, 360 deletions
diff --git a/.rubocop_todo/graphql/descriptions.yml b/.rubocop_todo/graphql/descriptions.yml new file mode 100644 index 00000000000..7a19a0cd126 --- /dev/null +++ b/.rubocop_todo/graphql/descriptions.yml @@ -0,0 +1,98 @@ +--- +# Cop supports --autocorrect. +Graphql/Descriptions: + Details: grace period + Exclude: + - 'app/graphql/mutations/boards/lists/base_update.rb' + - 'app/graphql/mutations/ci/project_ci_cd_settings_update.rb' + - 'app/graphql/mutations/clusters/agents/create.rb' + - 'app/graphql/mutations/merge_requests/accept.rb' + - 'app/graphql/mutations/notes/create/note.rb' + - 'app/graphql/mutations/releases/create.rb' + - 'app/graphql/resolvers/admin/analytics/usage_trends/measurements_resolver.rb' + - 'app/graphql/resolvers/alert_management/alert_resolver.rb' + - 'app/graphql/resolvers/concerns/issues/sort_arguments.rb' + - 'app/graphql/resolvers/concerns/resolves_pipelines.rb' + - 'app/graphql/resolvers/container_repositories_resolver.rb' + - 'app/graphql/resolvers/design_management/design_at_version_resolver.rb' + - 'app/graphql/resolvers/group_packages_resolver.rb' + - 'app/graphql/resolvers/issues/base_parent_resolver.rb' + - 'app/graphql/resolvers/issues/base_resolver.rb' + - 'app/graphql/resolvers/issues_resolver.rb' + - 'app/graphql/resolvers/merge_requests_resolver.rb' + - 'app/graphql/resolvers/milestones_resolver.rb' + - 'app/graphql/resolvers/namespace_projects_resolver.rb' + - 'app/graphql/resolvers/packages_base_resolver.rb' + - 'app/graphql/resolvers/releases_resolver.rb' + - 'app/graphql/resolvers/users_resolver.rb' + - 'app/graphql/resolvers/work_items_resolver.rb' + - 'app/graphql/types/alert_management/alert_type.rb' + - 'app/graphql/types/award_emojis/award_emoji_type.rb' + - 'app/graphql/types/board_list_type.rb' + - 'app/graphql/types/branch_protections/base_access_level_type.rb' + - 'app/graphql/types/branch_rules/branch_protection_type.rb' + - 'app/graphql/types/ci/job_token_scope_type.rb' + - 'app/graphql/types/ci/pipeline_type.rb' + - 'app/graphql/types/ci/runner_status_enum.rb' + - 'app/graphql/types/ci/runner_type.rb' + - 'app/graphql/types/ci/runner_web_url_edge.rb' + - 'app/graphql/types/ci/status_action_type.rb' + - 'app/graphql/types/clusters/agent_token_type.rb' + - 'app/graphql/types/clusters/agent_type.rb' + - 'app/graphql/types/container_expiration_policy_type.rb' + - 'app/graphql/types/container_repository_tag_type.rb' + - 'app/graphql/types/container_repository_type.rb' + - 'app/graphql/types/deployment_details_type.rb' + - 'app/graphql/types/deployment_tag_type.rb' + - 'app/graphql/types/design_management/design_at_version_type.rb' + - 'app/graphql/types/design_management/design_fields.rb' + - 'app/graphql/types/diff_stats_type.rb' + - 'app/graphql/types/event_type.rb' + - 'app/graphql/types/group_type.rb' + - 'app/graphql/types/issue_type.rb' + - 'app/graphql/types/issues/negated_issue_filter_input_type.rb' + - 'app/graphql/types/label_type.rb' + - 'app/graphql/types/merge_request_type.rb' + - 'app/graphql/types/merge_requests/interacts_with_merge_request.rb' + - 'app/graphql/types/milestone_sort_enum.rb' + - 'app/graphql/types/milestone_type.rb' + - 'app/graphql/types/namespace/package_settings_type.rb' + - 'app/graphql/types/notes/discussion_type.rb' + - 'app/graphql/types/notes/note_type.rb' + - 'app/graphql/types/notes/noteable_interface.rb' + - 'app/graphql/types/packages/cleanup/policy_type.rb' + - 'app/graphql/types/packages/package_details_type.rb' + - 'app/graphql/types/project_type.rb' + - 'app/graphql/types/projects/branch_rule_type.rb' + - 'app/graphql/types/release_links_type.rb' + - 'app/graphql/types/repository/blob_type.rb' + - 'app/graphql/types/snippet_type.rb' + - 'app/graphql/types/terraform/state_version_type.rb' + - 'app/graphql/types/todo_type.rb' + - 'app/graphql/types/todoable_interface.rb' + - 'app/graphql/types/user_interface.rb' + - 'app/graphql/types/user_merge_request_interaction_type.rb' + - 'ee/app/graphql/ee/types/branch_protections/base_access_level_type.rb' + - 'ee/app/graphql/ee/types/branch_rules/branch_protection_type.rb' + - 'ee/app/graphql/ee/types/issue_type.rb' + - 'ee/app/graphql/ee/types/merge_request_type.rb' + - 'ee/app/graphql/ee/types/projects/branch_rule_type.rb' + - 'ee/app/graphql/ee/types/user_merge_request_interaction_type.rb' + - 'ee/app/graphql/resolvers/epics_resolver.rb' + - 'ee/app/graphql/types/access_levels/user_type.rb' + - 'ee/app/graphql/types/boards/epic_list_type.rb' + - 'ee/app/graphql/types/branch_rules/approval_project_rule_type.rb' + - 'ee/app/graphql/types/burnup_chart_daily_totals_type.rb' + - 'ee/app/graphql/types/ci/namespace_ci_cd_setting_type.rb' + - 'ee/app/graphql/types/compliance_management/compliance_framework_input_type.rb' + - 'ee/app/graphql/types/compliance_management/merge_requests/compliance_violation_input_type.rb' + - 'ee/app/graphql/types/epic_descendant_weight_sum_type.rb' + - 'ee/app/graphql/types/epic_type.rb' + - 'ee/app/graphql/types/geo/geo_node_type.rb' + - 'ee/app/graphql/types/iterations/cadence_type.rb' + - 'ee/app/graphql/types/network_policy_type.rb' + - 'ee/app/graphql/types/path_lock_type.rb' + - 'ee/app/graphql/types/security_orchestration/group_security_policy_source_type.rb' + - 'ee/app/graphql/types/security_orchestration/orchestration_policy_type.rb' + - 'ee/app/graphql/types/vulnerability_type.rb' + - 'ee/app/graphql/types/vulnerable_projects_by_grade_type.rb' @@ -52,8 +52,8 @@ gem 'declarative_policy', '~> 1.1.0' gem 'devise', '~> 4.8.1' gem 'devise-pbkdf2-encryptable', '~> 0.0.0', path: 'vendor/gems/devise-pbkdf2-encryptable' gem 'bcrypt', '~> 3.1', '>= 3.1.14' -gem 'doorkeeper', '~> 5.5.0.rc2' -gem 'doorkeeper-openid_connect', '~> 1.7.5' +gem 'doorkeeper', '~> 5.5' +gem 'doorkeeper-openid_connect', '~> 1.8' gem 'rexml', '~> 3.2.5' gem 'ruby-saml', '~> 1.13.0' gem 'omniauth', '~> 2.1.0' diff --git a/Gemfile.checksum b/Gemfile.checksum index de417277434..b3bb2366ac7 100644 --- a/Gemfile.checksum +++ b/Gemfile.checksum @@ -113,8 +113,8 @@ {"name":"discordrb-webhooks","version":"3.4.2","platform":"ruby","checksum":"cfdba8a4b28236b6ab34e37389f881a59c241aeb5be0a4447249efd4e4383c6e"}, {"name":"docile","version":"1.4.0","platform":"ruby","checksum":"5f1734bde23721245c20c3d723e76c104208e1aa01277a69901ce770f0ebb8d3"}, {"name":"domain_name","version":"0.5.20190701","platform":"ruby","checksum":"000a600454cb4a344769b2f10b531765ea7bd3a304fe47ed12e5ca1eab969851"}, -{"name":"doorkeeper","version":"5.5.0.rc2","platform":"ruby","checksum":"93a322ffca3cadbfb862b0199f78674d8372780afdd7471e657064610bb7b2d5"}, -{"name":"doorkeeper-openid_connect","version":"1.7.5","platform":"ruby","checksum":"2dea201ffd9e4bec573609c90bb638254a48bfa3de3ec4af892ec64e0b5947b2"}, +{"name":"doorkeeper","version":"5.5.4","platform":"ruby","checksum":"7fe233a96f93bf0d5496e2284abf431f38ab465fd65d1972b90cbec7c45b1ea1"}, +{"name":"doorkeeper-openid_connect","version":"1.8.2","platform":"ruby","checksum":"48368db38e4a957d85ca5226775f228c08a18c03614ddd060d0287da75739cdd"}, {"name":"dotenv","version":"2.7.6","platform":"ruby","checksum":"2451ed5e8e43776d7a787e51d6f8903b98e446146c7ad143d5678cc2c409d547"}, {"name":"dry-configurable","version":"0.12.0","platform":"ruby","checksum":"87a9579a04dfbae73e401d694282800d64bbdb8631cb3e987bfb79b673df7c67"}, {"name":"dry-container","version":"0.7.2","platform":"ruby","checksum":"a071824ba3451048b23500210f96a2b9facd6e46ac687f65e49c75d18786f6da"}, diff --git a/Gemfile.lock b/Gemfile.lock index beab0c53eac..e9caca5bc6e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -363,10 +363,10 @@ GEM docile (1.4.0) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) - doorkeeper (5.5.0.rc2) + doorkeeper (5.5.4) railties (>= 5) - doorkeeper-openid_connect (1.7.5) - doorkeeper (>= 5.2, < 5.5) + doorkeeper-openid_connect (1.8.2) + doorkeeper (>= 5.5, < 5.7) json-jwt (>= 1.11.0) dotenv (2.7.6) dry-configurable (0.12.0) @@ -1632,8 +1632,8 @@ DEPENDENCIES diff_match_patch (~> 0.1.0) diffy (~> 3.4) discordrb-webhooks (~> 3.4) - doorkeeper (~> 5.5.0.rc2) - doorkeeper-openid_connect (~> 1.7.5) + doorkeeper (~> 5.5) + doorkeeper-openid_connect (~> 1.8) ed25519 (~> 1.3.0) elasticsearch-api (= 7.13.3) elasticsearch-model (~> 7.2) diff --git a/app/assets/javascripts/api/analytics_api.js b/app/assets/javascripts/api/analytics_api.js index 15457f28eff..66ed30130bb 100644 --- a/app/assets/javascripts/api/analytics_api.js +++ b/app/assets/javascripts/api/analytics_api.js @@ -7,6 +7,11 @@ const PROJECT_VSA_PATH_BASE = '/:request_path/-/analytics/value_stream_analytics const PROJECT_VSA_STAGES_PATH = `${PROJECT_VSA_PATH_BASE}/:value_stream_id/stages`; const PROJECT_VSA_STAGE_DATA_PATH = `${PROJECT_VSA_STAGES_PATH}/:stage_id`; +export const LEAD_TIME_METRIC_TYPE = 'lead_time'; +export const CYCLE_TIME_METRIC_TYPE = 'cycle_time'; +export const ISSUES_METRIC_TYPE = 'issues'; +export const DEPLOYS_METRIC_TYPE = 'deploys'; + export const METRIC_TYPE_SUMMARY = 'summary'; export const METRIC_TYPE_TIME_SUMMARY = 'time_summary'; diff --git a/app/assets/javascripts/work_items/components/work_item_detail.vue b/app/assets/javascripts/work_items/components/work_item_detail.vue index a668351a2b1..9822a999ff3 100644 --- a/app/assets/javascripts/work_items/components/work_item_detail.vue +++ b/app/assets/javascripts/work_items/components/work_item_detail.vue @@ -28,6 +28,7 @@ import { WORK_ITEM_VIEWED_STORAGE_KEY, WIDGET_TYPE_MILESTONE, WIDGET_TYPE_ITERATION, + WORK_ITEM_TYPE_VALUE_ISSUE, WORK_ITEM_TYPE_VALUE_OBJECTIVE, } from '../constants'; @@ -214,11 +215,22 @@ export default { parentWorkItem() { return this.isWidgetPresent(WIDGET_TYPE_HIERARCHY)?.parent; }, + parentWorkItemType() { + return this.parentWorkItem?.workItemType?.name; + }, + parentWorkItemIconName() { + return this.parentWorkItem?.workItemType?.iconName; + }, parentWorkItemConfidentiality() { return this.parentWorkItem?.confidential; }, parentUrl() { - return `../../issues/${this.parentWorkItem?.iid}`; + // Once more types are moved to have Work Items involved + // we need to handle this properly. + if (this.parentWorkItemType === WORK_ITEM_TYPE_VALUE_ISSUE) { + return `../../issues/${this.parentWorkItem?.iid}`; + } + return this.parentWorkItem?.webUrl; }, workItemIconName() { return this.workItem?.workItemType?.iconName; @@ -362,7 +374,7 @@ export default { <gl-button v-gl-tooltip.hover class="gl-text-truncate gl-max-w-full" - icon="issues" + :icon="parentWorkItemIconName" category="tertiary" :href="parentUrl" :title="parentWorkItem.title" diff --git a/app/assets/javascripts/work_items/constants.js b/app/assets/javascripts/work_items/constants.js index aef488739ee..e4a50de88e9 100644 --- a/app/assets/javascripts/work_items/constants.js +++ b/app/assets/javascripts/work_items/constants.js @@ -30,6 +30,7 @@ export const WORK_ITEM_TYPE_ENUM_REQUIREMENTS = 'REQUIREMENTS'; export const WORK_ITEM_TYPE_ENUM_OBJECTIVE = 'OBJECTIVE'; export const WORK_ITEM_TYPE_ENUM_KEY_RESULT = 'KEY_RESULT'; +export const WORK_ITEM_TYPE_VALUE_ISSUE = 'Issue'; export const WORK_ITEM_TYPE_VALUE_OBJECTIVE = 'Objective'; export const i18n = { diff --git a/app/assets/javascripts/work_items/graphql/work_item_widgets.fragment.graphql b/app/assets/javascripts/work_items/graphql/work_item_widgets.fragment.graphql index fe4efb64637..025a9d3673b 100644 --- a/app/assets/javascripts/work_items/graphql/work_item_widgets.fragment.graphql +++ b/app/assets/javascripts/work_items/graphql/work_item_widgets.fragment.graphql @@ -43,6 +43,12 @@ fragment WorkItemWidgets on WorkItemWidget { iid title confidential + webUrl + workItemType { + id + name + iconName + } } children { nodes { diff --git a/app/controllers/concerns/enforces_two_factor_authentication.rb b/app/controllers/concerns/enforces_two_factor_authentication.rb index b1b6e21644e..28e5bfa4529 100644 --- a/app/controllers/concerns/enforces_two_factor_authentication.rb +++ b/app/controllers/concerns/enforces_two_factor_authentication.rb @@ -10,11 +10,6 @@ module EnforcesTwoFactorAuthentication extend ActiveSupport::Concern - MFA_HELP_PAGE = Rails.application.routes.url_helpers.help_page_url( - 'user/profile/account/two_factor_authentication.html', - anchor: 'enable-two-factor-authentication' - ) - included do before_action :check_two_factor_requirement, except: [:route_not_found] @@ -33,7 +28,7 @@ module EnforcesTwoFactorAuthentication when GraphqlController render_error( _("Authentication error: enable 2FA in your profile settings to continue using GitLab: %{mfa_help_page}") % - { mfa_help_page: MFA_HELP_PAGE }, + { mfa_help_page: mfa_help_page_url }, status: :unauthorized ) else @@ -84,6 +79,13 @@ module EnforcesTwoFactorAuthentication def two_factor_verifier @two_factor_verifier ||= Gitlab::Auth::TwoFactorAuthVerifier.new(current_user) # rubocop:disable Gitlab/ModuleWithInstanceVariables end + + def mfa_help_page_url + Rails.application.routes.url_helpers.help_page_url( + 'user/profile/account/two_factor_authentication.html', + anchor: 'enable-two-factor-authentication' + ) + end end EnforcesTwoFactorAuthentication.prepend_mod_with('EnforcesTwoFactorAuthentication') diff --git a/app/controllers/projects/graphs_controller.rb b/app/controllers/projects/graphs_controller.rb index 6da70b5e157..d072381933a 100644 --- a/app/controllers/projects/graphs_controller.rb +++ b/app/controllers/projects/graphs_controller.rb @@ -21,11 +21,24 @@ class Projects::GraphsController < Projects::ApplicationController feature_category :continuous_integration, [:ci] urgency :low, [:ci] + MAX_COMMITS = 6000 + def show + @ref_type = ref_type + respond_to do |format| format.html format.json do - fetch_graph + commits = @project.repository.commits(ref, limit: MAX_COMMITS, skip_merges: true) + log = commits.map do |commit| + { + author_name: commit.author_name, + author_email: commit.author_email, + date: commit.committed_date.strftime("%Y-%m-%d") + } + end + + render json: Gitlab::Json.dump(log) end end end @@ -50,9 +63,13 @@ class Projects::GraphsController < Projects::ApplicationController private + def ref + @fully_qualified_ref || @ref + end + def get_commits @commits_limit = 2000 - @commits = @project.repository.commits(@ref, limit: @commits_limit, skip_merges: true) + @commits = @project.repository.commits(ref, limit: @commits_limit, skip_merges: true) @commits_graph = Gitlab::Graphs::Commits.new(@commits) @commits_per_week_days = @commits_graph.commits_per_week_days @commits_per_time = @commits_graph.commits_per_time @@ -76,7 +93,7 @@ class Projects::GraphsController < Projects::ApplicationController base_params: { start_date: date_today - report_window, end_date: date_today, - ref_path: @project.repository.expand_ref(@ref), + ref_path: @project.repository.expand_ref(ref), param_type: 'coverage' }, download_path: namespace_project_ci_daily_build_group_report_results_path( @@ -92,21 +109,6 @@ class Projects::GraphsController < Projects::ApplicationController } end - def fetch_graph - @commits = @project.repository.commits(@ref, limit: 6000, skip_merges: true) - @log = [] - - @commits.each do |commit| - @log << { - author_name: commit.author_name, - author_email: commit.author_email, - date: commit.committed_date.strftime("%Y-%m-%d") - } - end - - render json: Gitlab::Json.dump(@log) - end - def tracking_namespace_source project.namespace end diff --git a/app/controllers/projects/refs_controller.rb b/app/controllers/projects/refs_controller.rb index 4ba856149b5..31a0935cf96 100644 --- a/app/controllers/projects/refs_controller.rb +++ b/app/controllers/projects/refs_controller.rb @@ -26,7 +26,11 @@ class Projects::RefsController < Projects::ApplicationController when "graph" project_network_path(@project, @id, @options) when "graphs" - project_graph_path(@project, @id) + if Feature.enabled?(:use_ref_type_parameter, @project) + project_graph_path(@project, @id, ref_type: ref_type) + else + project_graph_path(@project, @id) + end when "find_file" project_find_file_path(@project, @id) when "graphs_commits" diff --git a/app/finders/autocomplete/routes_finder.rb b/app/finders/autocomplete/routes_finder.rb index 858a4b69376..ecede0c1c1c 100644 --- a/app/finders/autocomplete/routes_finder.rb +++ b/app/finders/autocomplete/routes_finder.rb @@ -13,7 +13,7 @@ module Autocomplete end def execute - return [] if @search.blank? + return Route.none if @search.blank? Route .for_routable(routables) @@ -30,7 +30,7 @@ module Autocomplete class NamespacesOnly < self def routables - return Namespace.without_project_namespaces if current_user.admin? + return Namespace.without_project_namespaces if current_user.can_admin_all_resources? current_user.namespaces end @@ -38,7 +38,7 @@ module Autocomplete class ProjectsOnly < self def routables - return Project.all if current_user.admin? + return Project.all if current_user.can_admin_all_resources? current_user.projects end diff --git a/app/models/concerns/time_trackable.rb b/app/models/concerns/time_trackable.rb index 54fe9eac2bc..2b7447dc700 100644 --- a/app/models/concerns/time_trackable.rb +++ b/app/models/concerns/time_trackable.rb @@ -15,12 +15,13 @@ module TimeTrackable alias_method :time_spent?, :time_spent - default_value_for :time_estimate, value: 0, allows_nil: false + attribute :time_estimate, default: 0 validates :time_estimate, numericality: { message: 'has an invalid format' }, allow_nil: false validate :check_negative_time_spent has_many :timelogs, dependent: :destroy, autosave: true # rubocop:disable Cop/ActiveRecordDependent + after_initialize :set_time_estimate_default_value end # rubocop:disable Gitlab/ModuleWithInstanceVariables @@ -67,6 +68,13 @@ module TimeTrackable val.is_a?(Integer) ? super([val, Gitlab::Database::MAX_INT_VALUE].min) : super(val) end + def set_time_estimate_default_value + return if new_record? + return unless has_attribute?(:time_estimate) + + self.time_estimate ||= self.class.column_defaults['time_estimate'] + end + private def reset_spent_time diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 40b2a8d16be..cff8911d84b 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -266,7 +266,7 @@ class MergeRequestDiff < ApplicationRecord end # This method will rely on repository branch sha - # in case start_commit_sha is nil. Its necesarry for old merge request diff + # in case start_commit_sha is nil. It's necessary for old merge request diff # created before version 8.4 to work def safe_start_commit_sha start_commit_sha || merge_request.target_branch_sha diff --git a/app/services/resource_access_tokens/create_service.rb b/app/services/resource_access_tokens/create_service.rb index b8a210c0a95..c6948536053 100644 --- a/app/services/resource_access_tokens/create_service.rb +++ b/app/services/resource_access_tokens/create_service.rb @@ -13,6 +13,7 @@ module ResourceAccessTokens return error("User does not have permission to create #{resource_type} access token") unless has_permission_to_create? access_level = params[:access_level] || Gitlab::Access::MAINTAINER + return error("Could not provision owner access to project access token") if do_not_allow_owner_access_level_for_project_bot?(access_level) user = create_user @@ -107,7 +108,7 @@ module ResourceAccessTokens end def create_membership(resource, user, access_level) - resource.add_member(user, access_level, current_user: current_user, expires_at: params[:expires_at]) + resource.add_member(user, access_level, expires_at: params[:expires_at]) end def log_event(token) @@ -121,6 +122,12 @@ module ResourceAccessTokens def success(access_token) ServiceResponse.success(payload: { access_token: access_token }) end + + def do_not_allow_owner_access_level_for_project_bot?(access_level) + resource.is_a?(Project) && + access_level == Gitlab::Access::OWNER && + !current_user.can?(:manage_owners, resource) + end end end diff --git a/app/services/web_hooks/log_execution_service.rb b/app/services/web_hooks/log_execution_service.rb index 5be8aee3ae8..e2f0e4174cd 100644 --- a/app/services/web_hooks/log_execution_service.rb +++ b/app/services/web_hooks/log_execution_service.rb @@ -24,9 +24,23 @@ module WebHooks private def log_execution + mask_response_headers + WebHookLog.create!(web_hook: hook, **log_data) end + def mask_response_headers + return unless hook.url_variables? + return unless log_data.key?(:response_headers) + + variables_map = hook.url_variables.invert.transform_values { "{#{_1}}" } + regex = Regexp.union(variables_map.keys) + + log_data[:response_headers].transform_values! do |value| + regex === value ? value.gsub(regex, variables_map) : value + end + end + # Perform this operation within an `Gitlab::ExclusiveLease` lock to make it # safe to be called concurrently from different workers. def update_hook_failure_state diff --git a/app/views/groups/projects.html.haml b/app/views/groups/projects.html.haml index e7ae54a8879..cae347630ee 100644 --- a/app/views/groups/projects.html.haml +++ b/app/views/groups/projects.html.haml @@ -12,19 +12,19 @@ = _("New project") - c.body do %ul.content-list - - @projects.each do |project| - %li.project-row.gl-align-items-center{ class: 'gl-display-flex!' } + - @projects.each_with_index do |project, idx| + %li.project-row.gl-align-items-center{ class: 'gl-display-flex!', data: { qa_selector: 'project_row_container', qa_index: idx } } .avatar-container.rect-avatar.s40.gl-flex-shrink-0 = project_icon(project, alt: '', class: 'avatar project-avatar s40', width: 40, height: 40) .gl-min-w-0.gl-flex-grow-1 .title = link_to project_path(project), class: 'js-prefetch-document' do - %span.project-full-name - %span.namespace-name + %span.project-full-name{ data: { qa_selector: 'project_fullname_content' } } + %span.namespace-name{ data: { qa_selector: 'project_namespace_content' } } - if project.namespace = project.namespace.human_name \/ - %span.project-name + %span.project-name{ data: { qa_selector: 'project_name_content', qa_project_name: project.name } } = project.name %span{ class: visibility_level_color(project.visibility_level) } = visibility_level_icon(project.visibility_level) @@ -38,9 +38,9 @@ = render 'project_badges', project: project .controls.gl-flex-shrink-0.gl-ml-5 - = link_to _('Members'), project_project_members_path(project), id: dom_id(project, :edit), class: "btn gl-button" - = link_to _('Edit'), edit_project_path(project), id: dom_id(project, :edit), class: "btn gl-button" - = render 'delete_project_button', project: project + = link_to _('Members'), project_project_members_path(project), id: dom_id(project, :edit), class: "btn gl-button", data: { qa_selector: 'project_members_button' } + = link_to _('Edit'), edit_project_path(project), id: dom_id(project, :edit), class: "btn gl-button", data: { qa_selector: 'project_edit_button' } + = render 'delete_project_button', project: project, data: { qa_selector: 'project_delete_button' } - if @projects.blank? .nothing-here-block= _("This group has no projects yet") diff --git a/app/views/projects/graphs/show.html.haml b/app/views/projects/graphs/show.html.haml index c7639eec75d..a27f076d5dd 100644 --- a/app/views/projects/graphs/show.html.haml +++ b/app/views/projects/graphs/show.html.haml @@ -1,8 +1,14 @@ - page_title _('Contributors') +- if Feature.enabled?(:use_ref_type_parameter, @project) + - graph_path = project_graph_path(@project, current_ref, ref_type: @ref_type, format: :json) + - commits_path = project_commits_path(@project, current_ref, ref_type: @ref_type) +- else + - graph_path = project_graph_path(@project, current_ref, format: :json) + - commits_path = project_commits_path(@project, current_ref) .sub-header-block.gl-bg-gray-10.gl-p-5 .tree-ref-holder.gl-display-inline-block.gl-vertical-align-middle.gl-mr-3> = render 'shared/ref_switcher', destination: 'graphs' - = link_to s_('Commits|History'), project_commits_path(@project, current_ref), class: 'btn gl-button btn-default' + = link_to s_('Commits|History'), commits_path, class: 'btn gl-button btn-default' -.js-contributors-graph{ class: container_class, data: { project_graph_path: project_graph_path(@project, current_ref, format: :json), project_branch: current_ref, default_branch: @project.default_branch } } +.js-contributors-graph{ class: container_class, data: { project_graph_path: graph_path, project_branch: current_ref, default_branch: @project.default_branch } } diff --git a/config/feature_flags/ops/report_jemalloc_stats.yml b/config/feature_flags/ops/report_jemalloc_stats.yml index 9cf5fd9d14b..2bbf63d2d78 100644 --- a/config/feature_flags/ops/report_jemalloc_stats.yml +++ b/config/feature_flags/ops/report_jemalloc_stats.yml @@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/367845 milestone: '15.2' type: ops group: group::memory -default_enabled: true +default_enabled: false diff --git a/db/post_migrate/20221122132812_schedule_prune_stale_project_export_jobs.rb b/db/post_migrate/20221122132812_schedule_prune_stale_project_export_jobs.rb new file mode 100644 index 00000000000..871224ea18e --- /dev/null +++ b/db/post_migrate/20221122132812_schedule_prune_stale_project_export_jobs.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +class SchedulePruneStaleProjectExportJobs < Gitlab::Database::Migration[2.0] + disable_ddl_transaction! + restrict_gitlab_migration gitlab_schema: :gitlab_main + + MIGRATION = 'PruneStaleProjectExportJobs' + DELAY_INTERVAL = 2.minutes + + def up + queue_batched_background_migration( + MIGRATION, + :project_export_jobs, + :id, + job_interval: DELAY_INTERVAL + ) + end + + def down + delete_batched_background_migration(MIGRATION, :project_export_jobs, :id, []) + end +end diff --git a/db/schema_migrations/20221122132812 b/db/schema_migrations/20221122132812 new file mode 100644 index 00000000000..d7534c717fd --- /dev/null +++ b/db/schema_migrations/20221122132812 @@ -0,0 +1 @@ +dfc5d0f35c41cde817bdb747bbbceaddc9fa77bec0219f7027ffc66191895f1b
\ No newline at end of file diff --git a/doc/development/contributing/merge_request_workflow.md b/doc/development/contributing/merge_request_workflow.md index 247383d1f39..f06e8825660 100644 --- a/doc/development/contributing/merge_request_workflow.md +++ b/doc/development/contributing/merge_request_workflow.md @@ -213,6 +213,7 @@ To reach the definition of done, the merge request must create no regressions an - Verified as working in production on GitLab.com. - Verified as working for self-managed instances. +- Verified as supporting [Geo](../../administration/geo/index.md) via the [self-service framework](../geo/framework.md). To learn more see [here](../geo/framework.md#geo-is-a-requirement-in-the-definition-of-done). If a regression occurs, we prefer you revert the change. Your contribution is *incomplete* until you have made sure it meets all of these diff --git a/doc/development/geo/framework.md b/doc/development/geo/framework.md index 3624d280f86..60529db5ce6 100644 --- a/doc/development/geo/framework.md +++ b/doc/development/geo/framework.md @@ -18,6 +18,14 @@ across Geo sites. This API is presented as a Ruby Domain-Specific Language (DSL) and aims to make it possible to replicate data with minimal effort of the engineer who created a data type. +## Geo is a requirement in the definition of done + +Geo is the GitLab solution for [disaster recovery](https://about.gitlab.com/direction/geo/disaster_recovery/). A robust disaster recovery solution must replicate **all GitLab data** such that all GitLab services can be successfully restored in their entirety with minimal data loss in the event of a disaster. + +For this reason, Geo replication and verification support for GitLab generated data is part of the [definition of done](../contributing/merge_request_workflow.md#definition-of-done). This ensures that new features ship with Geo support and our customers are not exposed to data loss. + +Adding Geo support with the Self Service Framework (SSF) is easy and outlined in detail on this page for various types of data. However, for a more general guide that can help you decide if and how you need to add Geo support for a new GitLab feature, [you may start here](../geo.md#ensuring-a-new-feature-has-geo-support). + ## Nomenclature Before digging into the API, developers need to know some Geo-specific diff --git a/doc/subscriptions/gitlab_dedicated/index.md b/doc/subscriptions/gitlab_dedicated/index.md index c503c501eeb..224ba954f1c 100644 --- a/doc/subscriptions/gitlab_dedicated/index.md +++ b/doc/subscriptions/gitlab_dedicated/index.md @@ -7,23 +7,25 @@ info: To determine the technical writer assigned to the Stage/Group associated w # GitLab Dedicated NOTE: -GitLab Dedicated is currently in limited availability. [Contact us](#contact-us) if you are interested. +GitLab Dedicated is currently in limited availability. You can learn more and join the waitlist [on our website](https://about.gitlab.com/single-tenant-saas). GitLab Dedicated is a fully isolated, single-tenant SaaS service that is: - Hosted and managed by GitLab, Inc. -- Deployed in a region of choice on AWS. +- Deployed on AWS in a cloud region of your choice (see the [regions that are not supported](#aws-regions-not-supported)). -GitLab Dedicated enables you to offload the operational overhead of managing the DevOps Platform. It offers a high level of tenant isolation and deployment customization, ideal for enterprises in highly-regulated industries. By deploying your GitLab instance onto separate Cloud Infrastructure from other tenants, GitLab Dedicated helps you better meet your security and compliance requirements. +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. - Networking: - - Public connectivity with support for IP Allowlists. During onboarding, you can optionally specify a list of IP addresses that can access your Dedicated instance. Subsequently, when an IP not on the allowlist tries to access your instance the connection will be refused. + - 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/). - You can specify an AWS IAM Principal and preferred Availability Zones during onboarding to enable this functionality. Both Ingress and Egress Private Links are supported. When connecting to an internal service running in your VPC over https via PrivateLink, Dedicated supports the ability to use a private SSL certificate, which can be provided during onboarding. + You can specify an AWS IAM Principal and preferred Availability Zones during onboarding to enable this functionality. Both Ingress and Egress PrivateLinks are supported. When connecting to an internal service running in your VPC over HTTPS via PrivateLink, GitLab Dedicated supports the ability to use a private SSL certificate, which can be provided during onboarding. - Upgrades: - Monthly upgrades tracking one release behind the latest (n-1), with the latest security release. - Out of band security patches provided for high severity releases. @@ -53,7 +55,7 @@ The following features will not be supported: - Mattermost - Server-side Git hooks -### Dedicated service features +### GitLab Dedicated service features The following operational features are not available: @@ -78,51 +80,8 @@ The following AWS regions are not available: ## Planned features -Learn more about the planned improvements to Dedicated on the public [direction page](https://about.gitlab.com/direction/saas-platforms/dedicated/). - -## Contact us - -Fill in the following form to contact us and learn more about this offering. - -<!-- markdownlint-disable --> - -<!-- NOTE: The following form only shows when the site is served under HTTPS, - so it will not appear when developing locally or in a review app. - See https://gitlab.com/gitlab-com/marketing/marketing-operations/-/issues/6238#note_923358643 ---> - -<script src="https://page.gitlab.com/js/forms2/js/forms2.min.js"></script> -<form id="mktoForm_3226"></form> -<script>MktoForms2.loadForm("https://page.gitlab.com", "194-VVC-221", 3226);</script> -<style> - #mktoForm_3226 { - font-size: .875rem !important; - } - .mktoLabel { - margin-top: 1rem !important; - padding-bottom: .5rem !important; - font-weight: 600; - } - .mktoHtmlText, - #LblPhone, - .mktoTextField, - #commentCapture, - .mktoField, - .mktoButtonRow button { - width: 20rem !important; - } - .mktoHtmlText { - font-size: .875rem; - } - .mktoButtonRow { - margin: 1em 0; - } - .mktoButtonRow span { - margin-left: 0 !important; - } - .mktoButtonRow button { - margin: 1em 0 1.5em !important; - } -</style> - -<!-- markdownlint-enable --> +Learn more about the planned improvements to GitLab Dedicated on the public [direction page](https://about.gitlab.com/direction/saas-platforms/dedicated/). + +## Learn more about GitLab Dedicated and join our waitlist + +As we scale this new offering, we are making GitLab Dedicated available by inviting customers to learn more and join our waitlist [on our website](https://about.gitlab.com/single-tenant-saas). diff --git a/doc/user/analytics/dora_metrics.md b/doc/user/analytics/dora_metrics.md index a2b2762e6da..6933c74f1b3 100644 --- a/doc/user/analytics/dora_metrics.md +++ b/doc/user/analytics/dora_metrics.md @@ -104,7 +104,7 @@ To retrieve metrics for change failure rate, use the [GraphQL](../../api/graphql ### Insights: Custom DORA reporting -Custom charts to visualize DORA data with Insights YAML-based reports. +Custom charts to visualize DORA data with [Insights YAML-based reports](../../user/project/insights/index.md#dora-query-parameters). With this new visualization, software leaders can track metrics improvements, understand patterns in their metrics trends, and compare performance between groups and projects. diff --git a/doc/user/infrastructure/iac/index.md b/doc/user/infrastructure/iac/index.md index 866b16652fa..cd139258349 100644 --- a/doc/user/infrastructure/iac/index.md +++ b/doc/user/infrastructure/iac/index.md @@ -91,6 +91,10 @@ To use a Terraform template: 1. Optional. Override in your `.gitlab-ci.yml` file the attributes present in the template you fetched to customize your configuration. +### Terraform template recipes + +For GitLab-curated template recipes, see [Terraform template recipes](tf_template_recipes.md). + ## Related topics - View [the images that contain the `gitlab-terraform` shell script](https://gitlab.com/gitlab-org/terraform-images). diff --git a/doc/user/infrastructure/iac/tf_template_recipes.md b/doc/user/infrastructure/iac/tf_template_recipes.md new file mode 100644 index 00000000000..2056a0cfda3 --- /dev/null +++ b/doc/user/infrastructure/iac/tf_template_recipes.md @@ -0,0 +1,53 @@ +--- +stage: Configure +group: Configure +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + +# Terraform template recipes **(FREE)** + +To customize your Terraform integration, you can add the recipes on this page to your pipeline using Terraform templates. + +If you'd like to share your own Terraform configuration, consider [contributing a recipe](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/infrastructure/iac/tf_template_recipes.md) to this page. + +## Enable a `terraform destroy` job + +To enable a `terraform destroy` job, add the following snippet to your `.gitlab-ci.yml`: + +```yaml +include: + - template: Terraform.latest.gitlab-ci.yml + +destroy: + extends: .terraform:destroy +``` + +The `destroy` job is part of the `cleanup` stage. Like the `deploy` job, the `destroy` job is always `manual` +and is not tied to the default branch. + +## Run a custom `terraform` command in a job + +To define a job that runs a custom `terraform` command, the `gitlab-terraform` wrapper can be used in any job, like this: + +```yaml +include: + - template: Terraform.latest.gitlab-ci.yml + +state-list: + stage: validate # you can use any stage, just make sure to define it + script: gitlab-terraform state list +``` + +The `gitlab-terraform` command sets up a `terraform` command and just forward the given arguments. + +To run this job in the Terraform state-specific [resource group](../../../ci/resource_groups/index.md), assign the job with `resource_group`: + +```yaml +include: + - template: Terraform.latest.gitlab-ci.yml + +state-list: + stage: validate # you can use any stage, just make sure to define it + resource_group: ${TF_STATE_NAME} + script: gitlab-terraform state list +``` diff --git a/doc/user/packages/generic_packages/index.md b/doc/user/packages/generic_packages/index.md index 563f35f2f4f..9b49f946984 100644 --- a/doc/user/packages/generic_packages/index.md +++ b/doc/user/packages/generic_packages/index.md @@ -118,7 +118,7 @@ API or the UI. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/293755) in GitLab 13.12. > - [Required permissions](https://gitlab.com/gitlab-org/gitlab/-/issues/350682) changed from developer to maintainer in GitLab 15.0. -To prevent users from publishing duplicate generic packages, you can use the [GraphQl API](../../../api/graphql/reference/index.md#packagesettings) +To prevent users from publishing duplicate generic packages, you can use the [GraphQL API](../../../api/graphql/reference/index.md#packagesettings) or the UI. In the UI: diff --git a/lib/api/api.rb b/lib/api/api.rb index 8611910406a..89df2b3a7ac 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -241,6 +241,7 @@ module API mount ::API::Metrics::UserStarredDashboards mount ::API::Namespaces mount ::API::NugetGroupPackages + mount ::API::NugetProjectPackages mount ::API::PackageFiles mount ::API::Pages mount ::API::PersonalAccessTokens::SelfInformation @@ -313,7 +314,6 @@ module API mount ::API::NotificationSettings mount ::API::NpmInstancePackages mount ::API::NpmProjectPackages - mount ::API::NugetProjectPackages mount ::API::PagesDomains mount ::API::ProjectDebianDistributions mount ::API::ProjectEvents diff --git a/lib/api/concerns/packages/nuget_endpoints.rb b/lib/api/concerns/packages/nuget_endpoints.rb index 9654200f4d6..31ecb529c3c 100644 --- a/lib/api/concerns/packages/nuget_endpoints.rb +++ b/lib/api/concerns/packages/nuget_endpoints.rb @@ -55,7 +55,7 @@ module API # https://docs.microsoft.com/en-us/nuget/api/service-index desc 'The NuGet Service Index' do detail 'This feature was introduced in GitLab 12.6' - success code: 200 + success code: 200, model: ::API::Entities::Nuget::ServiceIndex failure [ { code: 401, message: 'Unauthorized' }, { code: 403, message: 'Forbidden' }, @@ -83,7 +83,7 @@ module API desc 'The NuGet Metadata Service - Package name level' do detail 'This feature was introduced in GitLab 12.8' - success code: 200 + success code: 200, model: ::API::Entities::Nuget::PackagesMetadata failure [ { code: 401, message: 'Unauthorized' }, { code: 403, message: 'Forbidden' }, @@ -98,7 +98,7 @@ module API desc 'The NuGet Metadata Service - Package name and version level' do detail 'This feature was introduced in GitLab 12.8' - success code: 200 + success code: 200, model: ::API::Entities::Nuget::PackageMetadata failure [ { code: 401, message: 'Unauthorized' }, { code: 403, message: 'Forbidden' }, @@ -129,7 +129,7 @@ module API desc 'The NuGet Search Service' do detail 'This feature was introduced in GitLab 12.8' - success code: 200 + success code: 200, model: ::API::Entities::Nuget::SearchResults failure [ { code: 401, message: 'Unauthorized' }, { code: 403, message: 'Forbidden' }, diff --git a/lib/api/entities/nuget/dependency.rb b/lib/api/entities/nuget/dependency.rb index b61c37f5882..adb11376cfa 100644 --- a/lib/api/entities/nuget/dependency.rb +++ b/lib/api/entities/nuget/dependency.rb @@ -4,10 +4,10 @@ module API module Entities module Nuget class Dependency < Grape::Entity - expose :id, as: :@id - expose :type, as: :@type - expose :name, as: :id - expose :range + expose :id, as: :@id, documentation: { type: 'string', example: 'http://gitlab.com/Sandbox.App/1.0.0.json#dependency' } + expose :type, as: :@type, documentation: { type: 'string', example: 'PackageDependency' } + expose :name, as: :id, documentation: { type: 'string', example: 'Dependency' } + expose :range, documentation: { type: 'string', example: '2.0.0' } end end end diff --git a/lib/api/entities/nuget/dependency_group.rb b/lib/api/entities/nuget/dependency_group.rb index dcab9359fcf..8d943050cd8 100644 --- a/lib/api/entities/nuget/dependency_group.rb +++ b/lib/api/entities/nuget/dependency_group.rb @@ -4,10 +4,12 @@ module API module Entities module Nuget class DependencyGroup < Grape::Entity - expose :id, as: :@id - expose :type, as: :@type - expose :target_framework, as: :targetFramework, expose_nil: false - expose :dependencies, using: ::API::Entities::Nuget::Dependency + expose :id, as: :@id, documentation: { type: 'string', example: 'http://gitlab.com/Sandbox.App/1.0.0.json#dependencygroup' } + expose :type, as: :@type, documentation: { type: 'string', example: 'PackageDependencyGroup' } + expose :target_framework, as: :targetFramework, expose_nil: false, + documentation: { type: 'string', example: 'fwk test' } + expose :dependencies, using: ::API::Entities::Nuget::Dependency, + documentation: { is_array: true, type: 'API::Entities::Nuget::Dependency' } end end end diff --git a/lib/api/entities/nuget/metadatum.rb b/lib/api/entities/nuget/metadatum.rb index 87caef41a85..256b916cb64 100644 --- a/lib/api/entities/nuget/metadatum.rb +++ b/lib/api/entities/nuget/metadatum.rb @@ -4,9 +4,9 @@ module API module Entities module Nuget class Metadatum < Grape::Entity - expose :project_url, as: :projectUrl, expose_nil: false - expose :license_url, as: :licenseUrl, expose_nil: false - expose :icon_url, as: :iconUrl, expose_nil: false + expose :project_url, as: :projectUrl, expose_nil: false, documentation: { type: 'string', example: 'http://sandbox.com/project' } + expose :license_url, as: :licenseUrl, expose_nil: false, documentation: { type: 'string', example: 'http://sandbox.com/license' } + expose :icon_url, as: :iconUrl, expose_nil: false, documentation: { type: 'string', example: 'http://sandbox.com/icon' } end end end diff --git a/lib/api/entities/nuget/package_metadata.rb b/lib/api/entities/nuget/package_metadata.rb index e1c2a1ae161..1c94426bdd6 100644 --- a/lib/api/entities/nuget/package_metadata.rb +++ b/lib/api/entities/nuget/package_metadata.rb @@ -4,9 +4,10 @@ module API module Entities module Nuget class PackageMetadata < Grape::Entity - expose :json_url, as: :@id - expose :archive_url, as: :packageContent - expose :catalog_entry, as: :catalogEntry, using: ::API::Entities::Nuget::PackageMetadataCatalogEntry + expose :json_url, as: :@id, documentation: { type: 'string', example: 'https://gitlab.example.com/api/v4/projects/1/packages/nuget/metadata/MyNuGetPkg/1.3.0.17.json' } + expose :archive_url, as: :packageContent, documentation: { type: 'string', example: 'https://gitlab.example.com/api/v4/projects/1/packages/nuget/download/MyNuGetPkg/1.3.0.17/helloworld.1.3.0.17.nupkg' } + expose :catalog_entry, as: :catalogEntry, using: ::API::Entities::Nuget::PackageMetadataCatalogEntry, + documentation: { type: 'API::Entities::Nuget::PackageMetadataCatalogEntry' } end end end diff --git a/lib/api/entities/nuget/package_metadata_catalog_entry.rb b/lib/api/entities/nuget/package_metadata_catalog_entry.rb index 5533f857596..ce328c5a5ca 100644 --- a/lib/api/entities/nuget/package_metadata_catalog_entry.rb +++ b/lib/api/entities/nuget/package_metadata_catalog_entry.rb @@ -4,15 +4,17 @@ module API module Entities module Nuget class PackageMetadataCatalogEntry < Grape::Entity - expose :json_url, as: :@id - expose :authors - expose :dependency_groups, as: :dependencyGroups, using: ::API::Entities::Nuget::DependencyGroup - expose :package_name, as: :id - expose :package_version, as: :version - expose :tags - expose :archive_url, as: :packageContent - expose :summary - expose :metadatum, using: ::API::Entities::Nuget::Metadatum, merge: true + expose :json_url, as: :@id, documentation: { type: 'string', example: 'https://gitlab.example.com/api/v4/projects/1/packages/nuget/metadata/MyNuGetPkg/1.3.0.17.json' } + expose :authors, documentation: { type: 'string', example: 'Author' } + expose :dependency_groups, as: :dependencyGroups, using: ::API::Entities::Nuget::DependencyGroup, + documentation: { is_array: true, type: 'API::Entities::Nuget::DependencyGroup' } + expose :package_name, as: :id, documentation: { type: 'string', example: 'MyNuGetPkg' } + expose :package_version, as: :version, documentation: { type: 'string', example: '1.3.0.17' } + expose :tags, documentation: { type: 'string', example: 'tag#1 tag#2' } + expose :archive_url, as: :packageContent, documentation: { type: 'string', example: 'https://gitlab.example.com/api/v4/projects/1/packages/nuget/download/MyNuGetPkg/1.3.0.17/helloworld.1.3.0.17.nupkg' } + expose :summary, documentation: { type: 'string', example: 'Summary' } + expose :metadatum, using: ::API::Entities::Nuget::Metadatum, merge: true, + documentation: { type: 'API::Entities::Nuget::Metadatum' } end end end diff --git a/lib/api/entities/nuget/packages_metadata.rb b/lib/api/entities/nuget/packages_metadata.rb index 1cdf2491725..e556df0ce1f 100644 --- a/lib/api/entities/nuget/packages_metadata.rb +++ b/lib/api/entities/nuget/packages_metadata.rb @@ -4,8 +4,9 @@ module API module Entities module Nuget class PackagesMetadata < Grape::Entity - expose :count - expose :items, using: ::API::Entities::Nuget::PackagesMetadataItem + expose :count, documentation: { type: 'integer', example: 1 } + expose :items, using: ::API::Entities::Nuget::PackagesMetadataItem, + documentation: { is_array: true, type: 'API::Entities::Nuget::PackagesMetadataItem' } end end end diff --git a/lib/api/entities/nuget/packages_metadata_item.rb b/lib/api/entities/nuget/packages_metadata_item.rb index 84cc79166f3..420a4c3941c 100644 --- a/lib/api/entities/nuget/packages_metadata_item.rb +++ b/lib/api/entities/nuget/packages_metadata_item.rb @@ -4,11 +4,12 @@ module API module Entities module Nuget class PackagesMetadataItem < Grape::Entity - expose :json_url, as: :@id - expose :lower_version, as: :lower - expose :upper_version, as: :upper - expose :packages_count, as: :count - expose :packages, as: :items, using: ::API::Entities::Nuget::PackageMetadata + expose :json_url, as: :@id, documentation: { type: 'string', example: 'https://gitlab.example.com/api/v4/projects/1/packages/nuget/metadata/MyNuGetPkg/1.3.0.17.json' } + expose :lower_version, as: :lower, documentation: { type: 'string', example: '1.3.0.17' } + expose :upper_version, as: :upper, documentation: { type: 'string', example: '1.3.0.17' } + expose :packages_count, as: :count, documentation: { type: 'integer', example: 1 } + expose :packages, as: :items, using: ::API::Entities::Nuget::PackageMetadata, + documentation: { is_array: true, type: 'API::Entities::Nuget::PackageMetadata' } end end end diff --git a/lib/api/entities/nuget/packages_versions.rb b/lib/api/entities/nuget/packages_versions.rb index 498c6970d5c..e0330300ca7 100644 --- a/lib/api/entities/nuget/packages_versions.rb +++ b/lib/api/entities/nuget/packages_versions.rb @@ -4,7 +4,7 @@ module API module Entities module Nuget class PackagesVersions < Grape::Entity - expose :versions + expose :versions, documentation: { type: 'string', is_array: true, example: '1.3.0.17' } end end end diff --git a/lib/api/entities/nuget/search_result.rb b/lib/api/entities/nuget/search_result.rb index 8e028cbad95..bb3698de30b 100644 --- a/lib/api/entities/nuget/search_result.rb +++ b/lib/api/entities/nuget/search_result.rb @@ -4,17 +4,18 @@ module API module Entities module Nuget class SearchResult < Grape::Entity - expose :type, as: :@type - expose :authors - expose :name, as: :id - expose :name, as: :title - expose :summary - expose :total_downloads, as: :totalDownloads - expose :verified - expose :version + expose :type, as: :@type, documentation: { type: 'string', example: 'Package' } + expose :authors, documentation: { type: 'string', example: 'Author' } + expose :name, as: :id, documentation: { type: 'string', example: 'MyNuGetPkg' } + expose :name, as: :title, documentation: { type: 'string', example: 'MyNuGetPkg' } + expose :summary, documentation: { type: 'string', example: 'Summary' } + expose :total_downloads, as: :totalDownloads, documentation: { type: 'integer', example: 1 } + expose :verified, documentation: { type: 'boolean' } + expose :version, documentation: { type: 'string', example: '1.3.0.17' } expose :versions, using: ::API::Entities::Nuget::SearchResultVersion - expose :tags - expose :metadatum, using: ::API::Entities::Nuget::Metadatum, merge: true + expose :tags, documentation: { type: 'string', example: 'tag#1 tag#2' } + expose :metadatum, using: ::API::Entities::Nuget::Metadatum, merge: true, + documentation: { is_array: true, type: 'API::Entities::Nuget::Metadatum' } end end end diff --git a/lib/api/entities/nuget/search_result_version.rb b/lib/api/entities/nuget/search_result_version.rb index 9032c964c44..fb8d8b75f83 100644 --- a/lib/api/entities/nuget/search_result_version.rb +++ b/lib/api/entities/nuget/search_result_version.rb @@ -4,9 +4,9 @@ module API module Entities module Nuget class SearchResultVersion < Grape::Entity - expose :json_url, as: :@id - expose :version - expose :downloads + expose :json_url, as: :@id, documentation: { type: 'string', example: 'https://gitlab.example.com/api/v4/projects/1/packages/nuget/metadata/MyNuGetPkg/1.3.0.17.json' } + expose :version, documentation: { type: 'string', example: '1.3.0.17' } + expose :downloads, documentation: { type: 'integer', example: 1 } end end end diff --git a/lib/api/entities/nuget/search_results.rb b/lib/api/entities/nuget/search_results.rb index 22a77dc7b6c..117904a1aff 100644 --- a/lib/api/entities/nuget/search_results.rb +++ b/lib/api/entities/nuget/search_results.rb @@ -4,8 +4,9 @@ module API module Entities module Nuget class SearchResults < Grape::Entity - expose :total_count, as: :totalHits - expose :data, using: ::API::Entities::Nuget::SearchResult + expose :total_count, as: :totalHits, documentation: { type: 'integer', example: 1 } + expose :data, using: ::API::Entities::Nuget::SearchResult, + documentation: { is_array: true, type: 'API::Entities::Nuget::SearchResult' } end end end diff --git a/lib/api/entities/nuget/service_index.rb b/lib/api/entities/nuget/service_index.rb index e57bd04adb9..4ab6c5ddc8b 100644 --- a/lib/api/entities/nuget/service_index.rb +++ b/lib/api/entities/nuget/service_index.rb @@ -4,8 +4,8 @@ module API module Entities module Nuget class ServiceIndex < Grape::Entity - expose :version - expose :resources + expose :version, documentation: { type: 'string', example: '1.3.0.17' } + expose :resources, documentation: { type: 'object', is_array: true, example: '{ "@id": "https://gitlab.com/api/v4/projects/1/packages/nuget/query", "@type": "SearchQueryService", "comment": "Filter and search for packages by keyword."}' } end end end diff --git a/lib/api/nuget_project_packages.rb b/lib/api/nuget_project_packages.rb index b4c00eef3b4..aa517661791 100644 --- a/lib/api/nuget_project_packages.rb +++ b/lib/api/nuget_project_packages.rb @@ -102,6 +102,14 @@ module API # https://docs.microsoft.com/en-us/nuget/api/package-publish-resource desc 'The NuGet Package Publish endpoint' do detail 'This feature was introduced in GitLab 12.6' + success code: 201 + failure [ + { code: 400, message: 'Bad Request' }, + { code: 401, message: 'Unauthorized' }, + { code: 403, message: 'Forbidden' }, + { code: 404, message: 'Not Found' } + ] + tags %w[nuget_packages] end params do @@ -123,6 +131,17 @@ module API forbidden! end + + desc 'The NuGet Package Authorize endpoint' do + detail 'This feature was introduced in GitLab 14.1' + success code: 200 + failure [ + { code: 401, message: 'Unauthorized' }, + { code: 403, message: 'Forbidden' }, + { code: 404, message: 'Not Found' } + ] + tags %w[nuget_packages] + end put 'authorize', urgency: :low do authorize_nuget_upload end @@ -130,8 +149,15 @@ module API # https://docs.microsoft.com/en-us/nuget/api/symbol-package-publish-resource desc 'The NuGet Symbol Package Publish endpoint' do detail 'This feature was introduced in GitLab 14.1' + success code: 201 + failure [ + { code: 400, message: 'Bad Request' }, + { code: 401, message: 'Unauthorized' }, + { code: 403, message: 'Forbidden' }, + { code: 404, message: 'Not Found' } + ] + tags %w[nuget_packages] end - params do use :file_params end @@ -151,13 +177,24 @@ module API forbidden! end + + desc 'The NuGet Symbol Package Authorize endpoint' do + detail 'This feature was introduced in GitLab 14.1' + success code: 200 + failure [ + { code: 401, message: 'Unauthorized' }, + { code: 403, message: 'Forbidden' }, + { code: 404, message: 'Not Found' } + ] + tags %w[nuget_packages] + end put 'symbolpackage/authorize', urgency: :low do authorize_nuget_upload end # https://docs.microsoft.com/en-us/nuget/api/package-base-address-resource params do - requires :package_name, type: String, desc: 'The NuGet package name', regexp: API::NO_SLASH_URL_PART_REGEX + requires :package_name, type: String, desc: 'The NuGet package name', regexp: API::NO_SLASH_URL_PART_REGEX, documentation: { example: 'mynugetpkg.1.3.0.17.nupkg' } end namespace '/download/*package_name' do after_validation do @@ -166,6 +203,13 @@ module API desc 'The NuGet Content Service - index request' do detail 'This feature was introduced in GitLab 12.8' + success code: 200, model: ::API::Entities::Nuget::PackagesVersions + failure [ + { code: 401, message: 'Unauthorized' }, + { code: 403, message: 'Forbidden' }, + { code: 404, message: 'Not Found' } + ] + tags %w[nuget_packages] end get 'index', format: :json, urgency: :low do present ::Packages::Nuget::PackagesVersionsPresenter.new(find_packages(params[:package_name])), @@ -174,10 +218,17 @@ module API desc 'The NuGet Content Service - content request' do detail 'This feature was introduced in GitLab 12.8' + success code: 200 + failure [ + { code: 401, message: 'Unauthorized' }, + { code: 403, message: 'Forbidden' }, + { code: 404, message: 'Not Found' } + ] + tags %w[nuget_packages] end params do - requires :package_version, type: String, desc: 'The NuGet package version', regexp: API::NO_SLASH_URL_PART_REGEX - requires :package_filename, type: String, desc: 'The NuGet package filename', regexp: API::NO_SLASH_URL_PART_REGEX + requires :package_version, type: String, desc: 'The NuGet package version', regexp: API::NO_SLASH_URL_PART_REGEX, documentation: { example: '1.3.0.17' } + requires :package_filename, type: String, desc: 'The NuGet package filename', regexp: API::NO_SLASH_URL_PART_REGEX, documentation: { example: 'mynugetpkg.1.3.0.17.nupkg' } end get '*package_version/*package_filename', format: [:nupkg, :snupkg], urgency: :low do filename = "#{params[:package_filename]}.#{params[:format]}" diff --git a/lib/gitlab/background_migration/prune_stale_project_export_jobs.rb b/lib/gitlab/background_migration/prune_stale_project_export_jobs.rb new file mode 100644 index 00000000000..a91cda2c427 --- /dev/null +++ b/lib/gitlab/background_migration/prune_stale_project_export_jobs.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + # Background migration for deleting stale project import jobs + class PruneStaleProjectExportJobs < BatchedMigrationJob + EXPIRES_IN = 7.days + + scope_to ->(relation) { relation.where("updated_at < ?", EXPIRES_IN.ago) } + operation_name :delete_all + + def perform + each_sub_batch(&:delete_all) + end + end + end +end diff --git a/lib/sidebars/projects/menus/repository_menu.rb b/lib/sidebars/projects/menus/repository_menu.rb index 5006f293424..10eb9d9d22d 100644 --- a/lib/sidebars/projects/menus/repository_menu.rb +++ b/lib/sidebars/projects/menus/repository_menu.rb @@ -57,7 +57,7 @@ module Sidebars def commits_menu_item link = if Feature.enabled?(:use_ref_type_parameter, context.project) - project_commits_path(context.project, context.current_ref, ref_type: context.try(:ref_type) || 'heads') + project_commits_path(context.project, context.current_ref, ref_type: ref_type_from_context(context)) else project_commits_path(context.project, context.current_ref) end @@ -93,9 +93,15 @@ module Sidebars def contributors_menu_item return false unless context.project.analytics_enabled? + link = if Feature.enabled?(:use_ref_type_parameter, context.project) + project_graph_path(context.project, context.current_ref, ref_type: ref_type_from_context(context)) + else + project_graph_path(context.project, context.current_ref) + end + ::Sidebars::MenuItem.new( title: _('Contributors'), - link: project_graph_path(context.project, context.current_ref), + link: link, active_routes: { path: 'graphs#show' }, item_id: :contributors ) @@ -118,6 +124,12 @@ module Sidebars item_id: :compare ) end + + def ref_type_from_context(context) + ref_type = context.try(:ref_type) + ref_type ||= 'heads' if context.current_ref == context.project.repository.root_ref + ref_type + end end end end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 9a37d9d0ef0..3f65f61ed6d 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -12116,6 +12116,9 @@ msgstr "" msgid "DORA4Metrics|Change failure rate (percentage)" msgstr "" +msgid "DORA4Metrics|Cycle time" +msgstr "" + msgid "DORA4Metrics|DORA metrics for %{groupName} group" msgstr "" @@ -12134,9 +12137,15 @@ msgstr "" msgid "DORA4Metrics|Deployment frequency" msgstr "" +msgid "DORA4Metrics|Deploys" +msgstr "" + msgid "DORA4Metrics|Lead Time for Changes" msgstr "" +msgid "DORA4Metrics|Lead time" +msgstr "" + msgid "DORA4Metrics|Lead time for changes" msgstr "" @@ -12155,6 +12164,9 @@ msgstr "" msgid "DORA4Metrics|Month to date" msgstr "" +msgid "DORA4Metrics|New issues" +msgstr "" + msgid "DORA4Metrics|No incidents during this period" msgstr "" diff --git a/rubocop/cop/graphql/descriptions.rb b/rubocop/cop/graphql/descriptions.rb index 3c945507699..d49673b29b3 100644 --- a/rubocop/cop/graphql/descriptions.rb +++ b/rubocop/cop/graphql/descriptions.rb @@ -49,6 +49,8 @@ module RuboCop MSG_NO_DESCRIPTION = "Please add a `description` property. #{MSG_STYLE_GUIDE_LINK}" MSG_NO_PERIOD = "`description` strings must end with a `.`. #{MSG_STYLE_GUIDE_LINK}" MSG_BAD_START = "`description` strings should not start with \"A...\" or \"The...\". #{MSG_STYLE_GUIDE_LINK}" + MSG_CONTAINS_THIS = "`description` strings should not contain the demonstrative \"this\"."\ + " #{MSG_STYLE_GUIDE_LINK}" def_node_matcher :graphql_describable?, <<~PATTERN (send nil? {:field :argument :value} ...) @@ -82,6 +84,8 @@ module RuboCop MSG_NO_PERIOD elsif bad_start?(description) MSG_BAD_START + elsif contains_demonstrative_this?(description) + MSG_CONTAINS_THIS end return unless message @@ -114,6 +118,10 @@ module RuboCop string?(description) && description.value.strip.downcase.start_with?('a ', 'the ') end + def contains_demonstrative_this?(description) + string?(description) && /\bthis\b/.match?(description.value.strip) + end + # Returns true if `description` node is a `:str` (as opposed to a `#copy_field_description` call) def string?(description) description.type == :str diff --git a/spec/controllers/graphql_controller_spec.rb b/spec/controllers/graphql_controller_spec.rb index fe8b0291733..081e3169c3a 100644 --- a/spec/controllers/graphql_controller_spec.rb +++ b/spec/controllers/graphql_controller_spec.rb @@ -191,7 +191,7 @@ RSpec.describe GraphqlController do expected_message = "Authentication error: " \ "enable 2FA in your profile settings to continue using GitLab: %{mfa_help_page}" % - { mfa_help_page: EnforcesTwoFactorAuthentication::MFA_HELP_PAGE } + { mfa_help_page: controller.mfa_help_page_url } expect(json_response).to eq({ 'errors' => [{ 'message' => expected_message }] }) end diff --git a/spec/controllers/projects/graphs_controller_spec.rb b/spec/controllers/projects/graphs_controller_spec.rb index 3dfc22927cf..1e9d999311a 100644 --- a/spec/controllers/projects/graphs_controller_spec.rb +++ b/spec/controllers/projects/graphs_controller_spec.rb @@ -11,6 +11,50 @@ RSpec.describe Projects::GraphsController do project.add_maintainer(user) end + describe '#show' do + subject { get(:show, params: params) } + + let(:params) { { namespace_id: project.namespace.path, project_id: project.path, id: 'master' } } + + describe 'ref_type' do + it 'assigns ref_type' do + subject + + expect(assigns[:languages]).to be_nil + end + + context 'when ref_type is provided' do + before do + params[:ref_type] = 'heads' + end + + it 'assigns ref_type' do + subject + + expect(assigns[:ref_type]).to eq('heads') + end + end + end + + describe 'when format is json' do + let(:stubbed_limit) { 1 } + + before do + params[:format] = 'json' + stub_const('Projects::GraphsController::MAX_COMMITS', stubbed_limit) + end + + it 'renders json' do + subject + + expect(json_response.size).to eq(stubbed_limit) + %w[author_name author_email date].each do |key| + expect(json_response[0]).to have_key(key) + end + end + end + end + describe 'GET languages' do it "redirects_to action charts" do get(:commits, params: { namespace_id: project.namespace.path, project_id: project.path, id: 'master' }) diff --git a/spec/controllers/projects/refs_controller_spec.rb b/spec/controllers/projects/refs_controller_spec.rb index 065d2999fa2..e81193a92a3 100644 --- a/spec/controllers/projects/refs_controller_spec.rb +++ b/spec/controllers/projects/refs_controller_spec.rb @@ -65,7 +65,7 @@ RSpec.describe Projects::RefsController do 'graph' | nil | lazy { project_network_path(project, id) } 'graph' | 'heads' | lazy { project_network_path(project, id) } 'graphs' | nil | lazy { project_graph_path(project, id) } - 'graphs' | 'heads' | lazy { project_graph_path(project, id) } + 'graphs' | 'heads' | lazy { project_graph_path(project, id, ref_type: 'heads') } 'find_file' | nil | lazy { project_find_file_path(project, id) } 'find_file' | 'heads' | lazy { project_find_file_path(project, id) } 'graphs_commits' | nil | lazy { commits_project_graph_path(project, id) } diff --git a/spec/features/merge_request/batch_comments_spec.rb b/spec/features/merge_request/batch_comments_spec.rb index f01217df8c5..e16c1ae094b 100644 --- a/spec/features/merge_request/batch_comments_spec.rb +++ b/spec/features/merge_request/batch_comments_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > Batch comments', :js do +RSpec.describe 'Merge request > Batch comments', :js, feature_category: :code_review do include MergeRequestDiffHelpers include RepoHelpers diff --git a/spec/features/merge_request/close_reopen_report_toggle_spec.rb b/spec/features/merge_request/close_reopen_report_toggle_spec.rb index 5e9400935c3..6d01139223a 100644 --- a/spec/features/merge_request/close_reopen_report_toggle_spec.rb +++ b/spec/features/merge_request/close_reopen_report_toggle_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Issuables Close/Reopen/Report toggle' do +RSpec.describe 'Issuables Close/Reopen/Report toggle', feature_category: :code_review do include IssuablesHelper let(:user) { create(:user) } diff --git a/spec/features/merge_request/maintainer_edits_fork_spec.rb b/spec/features/merge_request/maintainer_edits_fork_spec.rb index 39d948bb6fb..bd040a5b894 100644 --- a/spec/features/merge_request/maintainer_edits_fork_spec.rb +++ b/spec/features/merge_request/maintainer_edits_fork_spec.rb @@ -2,7 +2,8 @@ require 'spec_helper' -RSpec.describe 'a maintainer edits files on a source-branch of an MR from a fork', :js, :sidekiq_might_not_need_inline do +RSpec.describe 'a maintainer edits files on a source-branch of an MR from a fork', :js, :sidekiq_might_not_need_inline, +feature_category: :code_review do include Spec::Support::Helpers::Features::SourceEditorSpecHelpers include ProjectForksHelper let(:user) { create(:user, username: 'the-maintainer') } diff --git a/spec/features/merge_request/merge_request_discussion_lock_spec.rb b/spec/features/merge_request/merge_request_discussion_lock_spec.rb index d69295744f7..b48d4d80647 100644 --- a/spec/features/merge_request/merge_request_discussion_lock_spec.rb +++ b/spec/features/merge_request/merge_request_discussion_lock_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' -RSpec.describe 'Merge Request Discussion Lock', :js do +RSpec.describe 'Merge Request Discussion Lock', :js, feature_category: :code_review do let(:user) { create(:user) } let(:project) { create(:project, :public, :repository) } let(:merge_request) { create(:merge_request, source_project: project, author: user) } diff --git a/spec/features/merge_request/user_accepts_merge_request_spec.rb b/spec/features/merge_request/user_accepts_merge_request_spec.rb index b50e6779e07..dda22abada0 100644 --- a/spec/features/merge_request/user_accepts_merge_request_spec.rb +++ b/spec/features/merge_request/user_accepts_merge_request_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'User accepts a merge request', :js, :sidekiq_might_not_need_inline do +RSpec.describe 'User accepts a merge request', :js, :sidekiq_might_not_need_inline, feature_category: :code_review do let(:merge_request) { create(:merge_request, :simple, source_project: project) } let(:project) { create(:project, :public, :repository) } let(:user) { create(:user) } diff --git a/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb b/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb index 75912238501..cf6836b544b 100644 --- a/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb +++ b/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb @@ -2,7 +2,8 @@ require 'spec_helper' -RSpec.describe 'create a merge request, allowing commits from members who can merge to the target branch', :js do +RSpec.describe 'create a merge request, allowing commits from members who can merge to the target branch', :js, +feature_category: :code_review do include ProjectForksHelper let(:user) { create(:user) } let(:target_project) { create(:project, :public, :repository) } diff --git a/spec/features/merge_request/user_approves_spec.rb b/spec/features/merge_request/user_approves_spec.rb index 9670012803e..bfb6a3ec8de 100644 --- a/spec/features/merge_request/user_approves_spec.rb +++ b/spec/features/merge_request/user_approves_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User approves', :js do +RSpec.describe 'Merge request > User approves', :js, feature_category: :code_review do let(:user) { create(:user) } let(:project) { create(:project, :public, :repository) } let(:merge_request) { create(:merge_request, source_project: project) } diff --git a/spec/features/merge_request/user_assigns_themselves_spec.rb b/spec/features/merge_request/user_assigns_themselves_spec.rb index 2aaddc7791b..8244668b444 100644 --- a/spec/features/merge_request/user_assigns_themselves_spec.rb +++ b/spec/features/merge_request/user_assigns_themselves_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User assigns themselves' do +RSpec.describe 'Merge request > User assigns themselves', feature_category: :code_review do let(:project) { create(:project, :public, :repository) } let(:user) { project.creator } let(:issue1) { create(:issue, project: project) } diff --git a/spec/features/merge_request/user_awards_emoji_spec.rb b/spec/features/merge_request/user_awards_emoji_spec.rb index 6fdc1a29174..dceac8d6a69 100644 --- a/spec/features/merge_request/user_awards_emoji_spec.rb +++ b/spec/features/merge_request/user_awards_emoji_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User awards emoji', :js do +RSpec.describe 'Merge request > User awards emoji', :js, feature_category: :code_review do let(:project) { create(:project, :public, :repository) } let(:user) { project.creator } let(:merge_request) { create(:merge_request, source_project: project, author: create(:user)) } diff --git a/spec/features/merge_request/user_clicks_merge_request_tabs_spec.rb b/spec/features/merge_request/user_clicks_merge_request_tabs_spec.rb index f3cbc1ea1f5..3e3ff91ad19 100644 --- a/spec/features/merge_request/user_clicks_merge_request_tabs_spec.rb +++ b/spec/features/merge_request/user_clicks_merge_request_tabs_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'User clicks on merge request tabs', :js do +RSpec.describe 'User clicks on merge request tabs', :js, feature_category: :code_review do let(:project) { create(:project, :public, :repository) } let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } diff --git a/spec/features/merge_request/user_closes_reopens_merge_request_state_spec.rb b/spec/features/merge_request/user_closes_reopens_merge_request_state_spec.rb index 70951982c22..c5ef6b912fe 100644 --- a/spec/features/merge_request/user_closes_reopens_merge_request_state_spec.rb +++ b/spec/features/merge_request/user_closes_reopens_merge_request_state_spec.rb @@ -2,7 +2,8 @@ require 'spec_helper' -RSpec.describe 'User closes/reopens a merge request', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/297500' do +RSpec.describe 'User closes/reopens a merge request', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/297500', + feature_category: :code_review do let_it_be(:project) { create(:project, :repository) } let_it_be(:user) { create(:user) } diff --git a/spec/features/merge_request/user_comments_on_commit_spec.rb b/spec/features/merge_request/user_comments_on_commit_spec.rb index 8fa1fe3812d..64fe144cd0d 100644 --- a/spec/features/merge_request/user_comments_on_commit_spec.rb +++ b/spec/features/merge_request/user_comments_on_commit_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'User comments on a commit', :js do +RSpec.describe 'User comments on a commit', :js, feature_category: :code_review do include MergeRequestDiffHelpers include RepoHelpers diff --git a/spec/features/merge_request/user_comments_on_diff_spec.rb b/spec/features/merge_request/user_comments_on_diff_spec.rb index ffaf403e873..f1a942d5708 100644 --- a/spec/features/merge_request/user_comments_on_diff_spec.rb +++ b/spec/features/merge_request/user_comments_on_diff_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'User comments on a diff', :js do +RSpec.describe 'User comments on a diff', :js, feature_category: :code_review do include MergeRequestDiffHelpers include RepoHelpers diff --git a/spec/features/merge_request/user_comments_on_merge_request_spec.rb b/spec/features/merge_request/user_comments_on_merge_request_spec.rb index dbcfc2b968f..d5ad78746f4 100644 --- a/spec/features/merge_request/user_comments_on_merge_request_spec.rb +++ b/spec/features/merge_request/user_comments_on_merge_request_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'User comments on a merge request', :js do +RSpec.describe 'User comments on a merge request', :js, feature_category: :code_review do include RepoHelpers let(:project) { create(:project, :repository) } diff --git a/spec/features/merge_request/user_creates_image_diff_notes_spec.rb b/spec/features/merge_request/user_creates_image_diff_notes_spec.rb index bd5048374d5..eb7894f4ef7 100644 --- a/spec/features/merge_request/user_creates_image_diff_notes_spec.rb +++ b/spec/features/merge_request/user_creates_image_diff_notes_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User creates image diff notes', :js do +RSpec.describe 'Merge request > User creates image diff notes', :js, feature_category: :code_review do include NoteInteractionHelpers let(:project) { create(:project, :public, :repository) } 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 0ae4ef18649..abfe78d6bce 100644 --- a/spec/features/merge_request/user_creates_merge_request_spec.rb +++ b/spec/features/merge_request/user_creates_merge_request_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'User creates a merge request', :js do +RSpec.describe 'User creates a merge request', :js, feature_category: :code_review do include ProjectForksHelper shared_examples 'creates a merge request' do diff --git a/spec/features/merge_request/user_creates_mr_spec.rb b/spec/features/merge_request/user_creates_mr_spec.rb index 9d97e57fe3a..5effde234cd 100644 --- a/spec/features/merge_request/user_creates_mr_spec.rb +++ b/spec/features/merge_request/user_creates_mr_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User creates MR' do +RSpec.describe 'Merge request > User creates MR', feature_category: :code_review do include ProjectForksHelper before do diff --git a/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb b/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb index f0c0142a6cc..4f1119d6c33 100644 --- a/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb +++ b/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request < User customizes merge commit message', :js do +RSpec.describe 'Merge request < User customizes merge commit message', :js, feature_category: :code_review do let(:project) { create(:project, :public, :repository) } let(:user) { project.creator } let(:issue_1) { create(:issue, project: project) } diff --git a/spec/features/merge_request/user_edits_assignees_sidebar_spec.rb b/spec/features/merge_request/user_edits_assignees_sidebar_spec.rb index 59b5923b2a1..c04040dd6fd 100644 --- a/spec/features/merge_request/user_edits_assignees_sidebar_spec.rb +++ b/spec/features/merge_request/user_edits_assignees_sidebar_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User edits assignees sidebar', :js do +RSpec.describe 'Merge request > User edits assignees sidebar', :js, feature_category: :code_review do let(:project) { create(:project, :public, :repository) } let(:protected_branch) { create(:protected_branch, :maintainers_can_push, name: 'master', project: project) } let(:merge_request) { create(:merge_request, :simple, source_project: project, target_branch: protected_branch.name) } diff --git a/spec/features/merge_request/user_edits_merge_request_spec.rb b/spec/features/merge_request/user_edits_merge_request_spec.rb index 4ac25ea7ae0..6701c7d91ae 100644 --- a/spec/features/merge_request/user_edits_merge_request_spec.rb +++ b/spec/features/merge_request/user_edits_merge_request_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'User edits a merge request', :js do +RSpec.describe 'User edits a merge request', :js, feature_category: :code_review do let(:project) { create(:project, :repository) } let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } let(:user) { create(:user) } diff --git a/spec/features/merge_request/user_edits_mr_spec.rb b/spec/features/merge_request/user_edits_mr_spec.rb index 2c949ed84f4..18e6827a872 100644 --- a/spec/features/merge_request/user_edits_mr_spec.rb +++ b/spec/features/merge_request/user_edits_mr_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User edits MR' do +RSpec.describe 'Merge request > User edits MR', feature_category: :code_review do include ProjectForksHelper before do diff --git a/spec/features/merge_request/user_edits_reviewers_sidebar_spec.rb b/spec/features/merge_request/user_edits_reviewers_sidebar_spec.rb index caf0c609f64..38c76314b9e 100644 --- a/spec/features/merge_request/user_edits_reviewers_sidebar_spec.rb +++ b/spec/features/merge_request/user_edits_reviewers_sidebar_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User edits reviewers sidebar', :js do +RSpec.describe 'Merge request > User edits reviewers sidebar', :js, feature_category: :code_review do context 'with invite members considerations' do let_it_be(:merge_request) { create(:merge_request) } let_it_be(:project) { merge_request.project } diff --git a/spec/features/merge_request/user_expands_diff_spec.rb b/spec/features/merge_request/user_expands_diff_spec.rb index 25c9584350d..8adbdcd310c 100644 --- a/spec/features/merge_request/user_expands_diff_spec.rb +++ b/spec/features/merge_request/user_expands_diff_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'User expands diff', :js do +RSpec.describe 'User expands diff', :js, feature_category: :code_review do let(:project) { create(:project, :public, :repository) } let(:merge_request) { create(:merge_request, source_branch: 'expand-collapse-files', source_project: project, target_project: project) } diff --git a/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb b/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb index 07d99a786ba..1b9b3941714 100644 --- a/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb +++ b/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Batch diffs', :js do +RSpec.describe 'Batch diffs', :js, feature_category: :code_review do include MergeRequestDiffHelpers include RepoHelpers diff --git a/spec/features/merge_request/user_locks_discussion_spec.rb b/spec/features/merge_request/user_locks_discussion_spec.rb index c8a6fdd4007..1bfd52d49e8 100644 --- a/spec/features/merge_request/user_locks_discussion_spec.rb +++ b/spec/features/merge_request/user_locks_discussion_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User locks discussion', :js do +RSpec.describe 'Merge request > User locks discussion', :js, feature_category: :code_review do let(:user) { create(:user) } let(:project) { create(:project, :public, :repository) } let(:merge_request) { create(:merge_request, source_project: project) } diff --git a/spec/features/merge_request/user_manages_subscription_spec.rb b/spec/features/merge_request/user_manages_subscription_spec.rb index a8d59a6ffb5..16d869fc5a1 100644 --- a/spec/features/merge_request/user_manages_subscription_spec.rb +++ b/spec/features/merge_request/user_manages_subscription_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'User manages subscription', :js do +RSpec.describe 'User manages subscription', :js, feature_category: :code_review do let(:project) { create(:project, :public, :repository) } let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } let(:user) { create(:user) } diff --git a/spec/features/merge_request/user_marks_merge_request_as_draft_spec.rb b/spec/features/merge_request/user_marks_merge_request_as_draft_spec.rb index d85f275b724..201cdc94b56 100644 --- a/spec/features/merge_request/user_marks_merge_request_as_draft_spec.rb +++ b/spec/features/merge_request/user_marks_merge_request_as_draft_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User marks merge request as draft', :js do +RSpec.describe 'Merge request > User marks merge request as draft', :js, feature_category: :code_review do let(:user) { create(:user) } let(:project) { create(:project, :public, :repository) } let(:merge_request) { create(:merge_request, source_project: project) } diff --git a/spec/features/merge_request/user_merges_immediately_spec.rb b/spec/features/merge_request/user_merges_immediately_spec.rb index 91327059e0f..b0aeea997f0 100644 --- a/spec/features/merge_request/user_merges_immediately_spec.rb +++ b/spec/features/merge_request/user_merges_immediately_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge requests > User merges immediately', :js do +RSpec.describe 'Merge requests > User merges immediately', :js, feature_category: :code_review do let(:project) { create(:project, :public, :repository) } let(:user) { project.creator } let!(:merge_request) do diff --git a/spec/features/merge_request/user_merges_merge_request_spec.rb b/spec/features/merge_request/user_merges_merge_request_spec.rb index c91dc7b1c00..4196fdd5dac 100644 --- a/spec/features/merge_request/user_merges_merge_request_spec.rb +++ b/spec/features/merge_request/user_merges_merge_request_spec.rb @@ -2,7 +2,7 @@ require "spec_helper" -RSpec.describe "User merges a merge request", :js do +RSpec.describe "User merges a merge request", :js, feature_category: :code_review do let(:user) { project.first_owner } before do diff --git a/spec/features/merge_request/user_merges_only_if_pipeline_succeeds_spec.rb b/spec/features/merge_request/user_merges_only_if_pipeline_succeeds_spec.rb index d6b132b18da..447418b5a4b 100644 --- a/spec/features/merge_request/user_merges_only_if_pipeline_succeeds_spec.rb +++ b/spec/features/merge_request/user_merges_only_if_pipeline_succeeds_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User merges only if pipeline succeeds', :js do +RSpec.describe 'Merge request > User merges only if pipeline succeeds', :js, feature_category: :code_review do let(:merge_request) { create(:merge_request_with_diffs) } let(:project) { merge_request.target_project } diff --git a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb index abf916c72b3..78a21527794 100644 --- a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb +++ b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User merges when pipeline succeeds', :js do +RSpec.describe 'Merge request > User merges when pipeline succeeds', :js, feature_category: :code_review do let(:project) { create(:project, :public, :repository) } let(:user) { project.creator } let(:merge_request) do diff --git a/spec/features/merge_request/user_opens_checkout_branch_modal_spec.rb b/spec/features/merge_request/user_opens_checkout_branch_modal_spec.rb index 4d2c59665bb..116de50f2a2 100644 --- a/spec/features/merge_request/user_opens_checkout_branch_modal_spec.rb +++ b/spec/features/merge_request/user_opens_checkout_branch_modal_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User opens checkout branch modal', :js do +RSpec.describe 'Merge request > User opens checkout branch modal', :js, feature_category: :code_review do include ProjectForksHelper let(:project) { create(:project, :public, :repository) } diff --git a/spec/features/merge_request/user_opens_context_commits_modal_spec.rb b/spec/features/merge_request/user_opens_context_commits_modal_spec.rb index 2d574e57fe9..f32a51cfcd4 100644 --- a/spec/features/merge_request/user_opens_context_commits_modal_spec.rb +++ b/spec/features/merge_request/user_opens_context_commits_modal_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > Context commits', :js do +RSpec.describe 'Merge request > Context commits', :js, feature_category: :code_review do let(:user) { create(:user) } let(:project) { create(:project, :public, :repository) } let(:merge_request) { create(:merge_request, source_project: project) } diff --git a/spec/features/merge_request/user_posts_diff_notes_spec.rb b/spec/features/merge_request/user_posts_diff_notes_spec.rb index 8af0e957c14..f2ec0e2df6d 100644 --- a/spec/features/merge_request/user_posts_diff_notes_spec.rb +++ b/spec/features/merge_request/user_posts_diff_notes_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User posts diff notes', :js do +RSpec.describe 'Merge request > User posts diff notes', :js, feature_category: :code_review do include MergeRequestDiffHelpers include Spec::Support::Helpers::ModalHelpers diff --git a/spec/features/merge_request/user_posts_notes_spec.rb b/spec/features/merge_request/user_posts_notes_spec.rb index 844ef6133c8..194e04a9544 100644 --- a/spec/features/merge_request/user_posts_notes_spec.rb +++ b/spec/features/merge_request/user_posts_notes_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User posts notes', :js do +RSpec.describe 'Merge request > User posts notes', :js, feature_category: :code_review do include NoteInteractionHelpers let_it_be(:project) { create(:project, :repository) } diff --git a/spec/features/merge_request/user_rebases_merge_request_spec.rb b/spec/features/merge_request/user_rebases_merge_request_spec.rb index d42864200ec..c3ee5ddc3b1 100644 --- a/spec/features/merge_request/user_rebases_merge_request_spec.rb +++ b/spec/features/merge_request/user_rebases_merge_request_spec.rb @@ -2,7 +2,7 @@ require "spec_helper" -RSpec.describe "User rebases a merge request", :js do +RSpec.describe "User rebases a merge request", :js, feature_category: :code_review do let(:merge_request) { create(:merge_request, :simple, source_project: project) } let(:user) { project.first_owner } diff --git a/spec/features/merge_request/user_resolves_conflicts_spec.rb b/spec/features/merge_request/user_resolves_conflicts_spec.rb index a04ca4e789c..d4c80c1e9e2 100644 --- a/spec/features/merge_request/user_resolves_conflicts_spec.rb +++ b/spec/features/merge_request/user_resolves_conflicts_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User resolves conflicts', :js do +RSpec.describe 'Merge request > User resolves conflicts', :js, feature_category: :code_review do include Spec::Support::Helpers::Features::SourceEditorSpecHelpers let(:project) { create(:project, :repository) } diff --git a/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb b/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb index 99f1b1ab1ad..f0507e94424 100644 --- a/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb +++ b/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User resolves diff notes and threads', :js do +RSpec.describe 'Merge request > User resolves diff notes and threads', :js, feature_category: :code_review do let(:project) { create(:project, :public, :repository) } let(:user) { project.creator } let(:guest) { create(:user) } diff --git a/spec/features/merge_request/user_resolves_outdated_diff_discussions_spec.rb b/spec/features/merge_request/user_resolves_outdated_diff_discussions_spec.rb index f8f3467f6fb..a7508ede1a1 100644 --- a/spec/features/merge_request/user_resolves_outdated_diff_discussions_spec.rb +++ b/spec/features/merge_request/user_resolves_outdated_diff_discussions_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User resolves outdated diff discussions', :js do +RSpec.describe 'Merge request > User resolves outdated diff discussions', :js, feature_category: :code_review do let(:project) { create(:project, :repository, :public) } let(:merge_request) do diff --git a/spec/features/merge_request/user_resolves_wip_mr_spec.rb b/spec/features/merge_request/user_resolves_wip_mr_spec.rb index 92927b713f1..b7f20a16a3f 100644 --- a/spec/features/merge_request/user_resolves_wip_mr_spec.rb +++ b/spec/features/merge_request/user_resolves_wip_mr_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User resolves Draft', :js do +RSpec.describe 'Merge request > User resolves Draft', :js, feature_category: :code_review do let(:project) { create(:project, :public, :repository) } let(:user) { project.creator } let(:merge_request) do diff --git a/spec/features/merge_request/user_reverts_merge_request_spec.rb b/spec/features/merge_request/user_reverts_merge_request_spec.rb index 9cbba6c470f..edfa9267871 100644 --- a/spec/features/merge_request/user_reverts_merge_request_spec.rb +++ b/spec/features/merge_request/user_reverts_merge_request_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'User reverts a merge request', :js do +RSpec.describe 'User reverts a merge request', :js, feature_category: :code_review do let(:merge_request) { create(:merge_request, :simple, source_project: project) } let(:project) { create(:project, :public, :repository) } let(:user) { create(:user) } diff --git a/spec/features/merge_request/user_reviews_image_spec.rb b/spec/features/merge_request/user_reviews_image_spec.rb index bd490294829..5814dc6b58c 100644 --- a/spec/features/merge_request/user_reviews_image_spec.rb +++ b/spec/features/merge_request/user_reviews_image_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > image review', :js do +RSpec.describe 'Merge request > image review', :js, feature_category: :code_review do include MergeRequestDiffHelpers include RepoHelpers diff --git a/spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb b/spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb index cf4875a7a25..fdd2aeec274 100644 --- a/spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb +++ b/spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User scrolls to note on load', :js do +RSpec.describe 'Merge request > User scrolls to note on load', :js, feature_category: :code_review do let(:project) { create(:project, :public, :repository) } let(:user) { project.creator } let(:merge_request) { create(:merge_request, source_project: project, author: user) } diff --git a/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb b/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb index a6c024be698..8c2fc62d16f 100644 --- a/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb +++ b/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' include Spec::Support::Helpers::ModalHelpers # rubocop:disable Style/MixinUsage -RSpec.describe 'Merge request > User sees avatars on diff notes', :js do +RSpec.describe 'Merge request > User sees avatars on diff notes', :js, feature_category: :code_review do include NoteInteractionHelpers include Spec::Support::Helpers::ModalHelpers include MergeRequestDiffHelpers diff --git a/spec/features/merge_request/user_sees_breadcrumb_links_spec.rb b/spec/features/merge_request/user_sees_breadcrumb_links_spec.rb index d8b258bac47..0b6aefcdab6 100644 --- a/spec/features/merge_request/user_sees_breadcrumb_links_spec.rb +++ b/spec/features/merge_request/user_sees_breadcrumb_links_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'New merge request breadcrumb' do +RSpec.describe 'New merge request breadcrumb', feature_category: :code_review do let(:project) { create(:project, :repository) } let(:user) { project.creator } diff --git a/spec/features/merge_request/user_sees_check_out_branch_modal_spec.rb b/spec/features/merge_request/user_sees_check_out_branch_modal_spec.rb index 5827266d4b7..bbfa2be47cc 100644 --- a/spec/features/merge_request/user_sees_check_out_branch_modal_spec.rb +++ b/spec/features/merge_request/user_sees_check_out_branch_modal_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User sees check out branch modal', :js do +RSpec.describe 'Merge request > User sees check out branch modal', :js, feature_category: :code_review do let(:project) { create(:project, :public, :repository) } let(:user) { project.creator } let(:merge_request) { create(:merge_request, source_project: project) } diff --git a/spec/features/merge_request/user_sees_cherry_pick_modal_spec.rb b/spec/features/merge_request/user_sees_cherry_pick_modal_spec.rb index 35be21a646e..07b7cb1e8d8 100644 --- a/spec/features/merge_request/user_sees_cherry_pick_modal_spec.rb +++ b/spec/features/merge_request/user_sees_cherry_pick_modal_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User cherry-picks', :js do +RSpec.describe 'Merge request > User cherry-picks', :js, feature_category: :code_review do let(:group) { create(:group) } let(:project) { create(:project, :repository, namespace: group) } let(:user) { project.creator } diff --git a/spec/features/merge_request/user_sees_closing_issues_message_spec.rb b/spec/features/merge_request/user_sees_closing_issues_message_spec.rb index f56db3d3dbe..9a1d47a13b5 100644 --- a/spec/features/merge_request/user_sees_closing_issues_message_spec.rb +++ b/spec/features/merge_request/user_sees_closing_issues_message_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User sees closing issues message', :js do +RSpec.describe 'Merge request > User sees closing issues message', :js, feature_category: :code_review do let(:project) { create(:project, :public, :repository) } let(:user) { project.creator } let(:issue_1) { create(:issue, project: project) } diff --git a/spec/features/merge_request/user_sees_deleted_target_branch_spec.rb b/spec/features/merge_request/user_sees_deleted_target_branch_spec.rb index dc50c3bc8db..16ae8b4304b 100644 --- a/spec/features/merge_request/user_sees_deleted_target_branch_spec.rb +++ b/spec/features/merge_request/user_sees_deleted_target_branch_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User sees deleted target branch', :js do +RSpec.describe 'Merge request > User sees deleted target branch', :js, feature_category: :code_review do let(:merge_request) { create(:merge_request) } let(:project) { merge_request.project } let(:user) { project.creator } diff --git a/spec/features/merge_request/user_sees_deployment_widget_spec.rb b/spec/features/merge_request/user_sees_deployment_widget_spec.rb index 6f8ecf5f5c2..40ab06937ff 100644 --- a/spec/features/merge_request/user_sees_deployment_widget_spec.rb +++ b/spec/features/merge_request/user_sees_deployment_widget_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User sees deployment widget', :js do +RSpec.describe 'Merge request > User sees deployment widget', :js, feature_category: :continuous_delivery do include Spec::Support::Helpers::ModalHelpers describe 'when merge request has associated environments' do diff --git a/spec/features/merge_request/user_sees_diff_spec.rb b/spec/features/merge_request/user_sees_diff_spec.rb index 0bae019793c..101ff8fc152 100644 --- a/spec/features/merge_request/user_sees_diff_spec.rb +++ b/spec/features/merge_request/user_sees_diff_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User sees diff', :js do +RSpec.describe 'Merge request > User sees diff', :js, feature_category: :code_review do include ProjectForksHelper include RepoHelpers include MergeRequestDiffHelpers diff --git a/spec/features/merge_request/user_sees_discussions_navigation_spec.rb b/spec/features/merge_request/user_sees_discussions_navigation_spec.rb index 9fbe7662fc0..a22fb2cff00 100644 --- a/spec/features/merge_request/user_sees_discussions_navigation_spec.rb +++ b/spec/features/merge_request/user_sees_discussions_navigation_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User sees discussions navigation', :js do +RSpec.describe 'Merge request > User sees discussions navigation', :js, feature_category: :code_review do let_it_be(:project) { create(:project, :public, :repository) } let_it_be(:user) { project.creator } let_it_be(:merge_request) { create(:merge_request, source_project: project) } diff --git a/spec/features/merge_request/user_sees_discussions_spec.rb b/spec/features/merge_request/user_sees_discussions_spec.rb index cc477e363a4..0eae6e39eec 100644 --- a/spec/features/merge_request/user_sees_discussions_spec.rb +++ b/spec/features/merge_request/user_sees_discussions_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User sees threads', :js do +RSpec.describe 'Merge request > User sees threads', :js, feature_category: :code_review do let(:project) { create(:project, :public, :repository) } let(:user) { project.creator } let(:merge_request) { create(:merge_request, source_project: project) } diff --git a/spec/features/merge_request/user_sees_merge_button_depending_on_unresolved_discussions_spec.rb b/spec/features/merge_request/user_sees_merge_button_depending_on_unresolved_discussions_spec.rb index e250837f398..6db5480abb4 100644 --- a/spec/features/merge_request/user_sees_merge_button_depending_on_unresolved_discussions_spec.rb +++ b/spec/features/merge_request/user_sees_merge_button_depending_on_unresolved_discussions_spec.rb @@ -2,7 +2,8 @@ require 'spec_helper' -RSpec.describe 'Merge request > User sees merge button depending on unresolved threads', :js do +RSpec.describe 'Merge request > User sees merge button depending on unresolved threads', :js, +feature_category: :code_review do let(:project) { create(:project, :repository) } let(:user) { project.creator } let!(:merge_request) { create(:merge_request_with_diff_notes, source_project: project, author: user) } diff --git a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb index 2a1b9ea6009..f7594c717d1 100644 --- a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb +++ b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User sees pipelines triggered by merge request', :js do +RSpec.describe 'Merge request > User sees pipelines triggered by merge request', :js, feature_category: :code_review do include ProjectForksHelper include TestReportsHelper diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb index c4a29c1fb07..e5aa0f6e64d 100644 --- a/spec/features/merge_request/user_sees_merge_widget_spec.rb +++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User sees merge widget', :js do +RSpec.describe 'Merge request > User sees merge widget', :js, feature_category: :code_review do include ProjectForksHelper include TestReportsHelper include ReactiveCachingHelpers diff --git a/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb b/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb index 03f9f6ef565..5756218d20f 100644 --- a/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb +++ b/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request < User sees mini pipeline graph', :js do +RSpec.describe 'Merge request < User sees mini pipeline graph', :js, feature_category: :continuous_integration do let(:project) { create(:project, :public, :repository) } let(:user) { project.creator } let(:merge_request) { create(:merge_request, source_project: project, head_pipeline: pipeline) } diff --git a/spec/features/merge_request/user_sees_mr_from_deleted_forked_project_spec.rb b/spec/features/merge_request/user_sees_mr_from_deleted_forked_project_spec.rb index a764dd97878..4bfdce29c6a 100644 --- a/spec/features/merge_request/user_sees_mr_from_deleted_forked_project_spec.rb +++ b/spec/features/merge_request/user_sees_mr_from_deleted_forked_project_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User sees MR from deleted forked project', :js do +RSpec.describe 'Merge request > User sees MR from deleted forked project', :js, feature_category: :code_review do include ProjectForksHelper let(:project) { create(:project, :public, :repository) } diff --git a/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb b/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb index 39bba3f2f73..8e6f6d04676 100644 --- a/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb +++ b/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' # This test serves as a regression test for a bug that caused an error # message to be shown by JavaScript when the source branch was deleted. # Please do not remove ":js". -RSpec.describe 'Merge request > User sees MR with deleted source branch', :js do +RSpec.describe 'Merge request > User sees MR with deleted source branch', :js, feature_category: :code_review do let(:project) { create(:project, :public, :repository) } let(:merge_request) { create(:merge_request, source_project: project) } let(:user) { project.creator } diff --git a/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb b/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb index b8b7fc2009f..8f011f5616b 100644 --- a/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb +++ b/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User sees notes from forked project', :js do +RSpec.describe 'Merge request > User sees notes from forked project', :js, feature_category: :code_review do include ProjectForksHelper let(:project) { create(:project, :public, :repository) } diff --git a/spec/features/merge_request/user_sees_page_metadata_spec.rb b/spec/features/merge_request/user_sees_page_metadata_spec.rb index 7b3e07152a0..f97732f91a7 100644 --- a/spec/features/merge_request/user_sees_page_metadata_spec.rb +++ b/spec/features/merge_request/user_sees_page_metadata_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User sees page metadata' do +RSpec.describe 'Merge request > User sees page metadata', feature_category: :code_review do let(:merge_request) { create(:merge_request, description: '**Lorem** _ipsum_ dolor sit [amet](https://example.com)') } let(:project) { merge_request.target_project } let(:user) { project.creator } diff --git a/spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb b/spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb index a9fefc89d6c..0816b14f9a5 100644 --- a/spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb +++ b/spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb @@ -2,7 +2,8 @@ require 'spec_helper' -RSpec.describe 'Merge request > User sees pipelines from forked project', :js do +RSpec.describe 'Merge request > User sees pipelines from forked project', :js, +feature_category: :continuous_integration do include ProjectForksHelper let(:target_project) { create(:project, :public, :repository) } diff --git a/spec/features/merge_request/user_sees_pipelines_spec.rb b/spec/features/merge_request/user_sees_pipelines_spec.rb index 11e542916f9..0e03522040b 100644 --- a/spec/features/merge_request/user_sees_pipelines_spec.rb +++ b/spec/features/merge_request/user_sees_pipelines_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User sees pipelines', :js do +RSpec.describe 'Merge request > User sees pipelines', :js, feature_category: :code_review do describe 'pipeline tab' do let(:merge_request) { create(:merge_request) } let(:project) { merge_request.target_project } diff --git a/spec/features/merge_request/user_sees_suggest_pipeline_spec.rb b/spec/features/merge_request/user_sees_suggest_pipeline_spec.rb index 448ef750508..3a2e382fe99 100644 --- a/spec/features/merge_request/user_sees_suggest_pipeline_spec.rb +++ b/spec/features/merge_request/user_sees_suggest_pipeline_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User sees suggest pipeline', :js do +RSpec.describe 'Merge request > User sees suggest pipeline', :js, feature_category: :continuous_integration do let(:merge_request) { create(:merge_request) } let(:project) { merge_request.source_project } let(:user) { project.creator } diff --git a/spec/features/merge_request/user_sees_system_notes_spec.rb b/spec/features/merge_request/user_sees_system_notes_spec.rb index 9f8d4c6d63f..40402c95d6f 100644 --- a/spec/features/merge_request/user_sees_system_notes_spec.rb +++ b/spec/features/merge_request/user_sees_system_notes_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User sees system notes', :js do +RSpec.describe 'Merge request > User sees system notes', :js, feature_category: :code_review do let(:public_project) { create(:project, :public, :repository) } let(:private_project) { create(:project, :private, :repository) } let(:user) { private_project.creator } diff --git a/spec/features/merge_request/user_sees_versions_spec.rb b/spec/features/merge_request/user_sees_versions_spec.rb index 0e86e970f46..f0ff6e1769a 100644 --- a/spec/features/merge_request/user_sees_versions_spec.rb +++ b/spec/features/merge_request/user_sees_versions_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User sees versions', :js do +RSpec.describe 'Merge request > User sees versions', :js, feature_category: :code_review do include MergeRequestDiffHelpers let(:merge_request) do diff --git a/spec/features/merge_request/user_sees_wip_help_message_spec.rb b/spec/features/merge_request/user_sees_wip_help_message_spec.rb index d33e54f2e3d..1a751af6ded 100644 --- a/spec/features/merge_request/user_sees_wip_help_message_spec.rb +++ b/spec/features/merge_request/user_sees_wip_help_message_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User sees draft help message' do +RSpec.describe 'Merge request > User sees draft help message', feature_category: :code_review do let(:project) { create(:project, :public, :repository) } let(:user) { project.creator } diff --git a/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb b/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb index bcc6abd4f65..8b6c9dc18f6 100644 --- a/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb +++ b/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User selects branches for new MR', :js do +RSpec.describe 'Merge request > User selects branches for new MR', :js, feature_category: :code_review do let(:project) { create(:project, :public, :repository) } let(:user) { project.creator } diff --git a/spec/features/merge_request/user_squashes_merge_request_spec.rb b/spec/features/merge_request/user_squashes_merge_request_spec.rb index da0d4ca23d1..43590aed3cc 100644 --- a/spec/features/merge_request/user_squashes_merge_request_spec.rb +++ b/spec/features/merge_request/user_squashes_merge_request_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'User squashes a merge request', :js do +RSpec.describe 'User squashes a merge request', :js, feature_category: :code_review do let(:user) { create(:user) } let(:project) { create(:project, :repository) } let(:source_branch) { 'csv' } diff --git a/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb b/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb index f77a42ee506..5a5494a2fe9 100644 --- a/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb +++ b/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'User comments on a diff', :js do +RSpec.describe 'User comments on a diff', :js, feature_category: :code_review do include MergeRequestDiffHelpers include RepoHelpers diff --git a/spec/features/merge_request/user_toggles_whitespace_changes_spec.rb b/spec/features/merge_request/user_toggles_whitespace_changes_spec.rb index 19774accaaf..993eb59cb74 100644 --- a/spec/features/merge_request/user_toggles_whitespace_changes_spec.rb +++ b/spec/features/merge_request/user_toggles_whitespace_changes_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Merge request > User toggles whitespace changes', :js do +RSpec.describe 'Merge request > User toggles whitespace changes', :js, feature_category: :code_review do let(:merge_request) { create(:merge_request) } let(:project) { merge_request.project } let(:user) { project.creator } diff --git a/spec/features/merge_request/user_tries_to_access_private_project_info_through_new_mr_spec.rb b/spec/features/merge_request/user_tries_to_access_private_project_info_through_new_mr_spec.rb index 96a1cd81c93..5095457509a 100644 --- a/spec/features/merge_request/user_tries_to_access_private_project_info_through_new_mr_spec.rb +++ b/spec/features/merge_request/user_tries_to_access_private_project_info_through_new_mr_spec.rb @@ -2,7 +2,8 @@ require 'spec_helper' -RSpec.describe 'Merge Request > User tries to access private project information through the new mr page' do +RSpec.describe 'Merge Request > User tries to access private project information through the new mr page', +feature_category: :code_review do let(:current_user) { create(:user) } let(:private_project) do create(:project, :public, :repository, diff --git a/spec/features/merge_request/user_uses_quick_actions_spec.rb b/spec/features/merge_request/user_uses_quick_actions_spec.rb index ca102913369..99befbace74 100644 --- a/spec/features/merge_request/user_uses_quick_actions_spec.rb +++ b/spec/features/merge_request/user_uses_quick_actions_spec.rb @@ -7,7 +7,8 @@ require 'spec_helper' # for example, adding quick actions when creating the issue and checking DateTime formats on UI. # Because this kind of spec takes more time to run there is no need to add new ones # for each existing quick action unless they test something not tested by existing tests. -RSpec.describe 'Merge request > User uses quick actions', :js, :use_clean_rails_redis_caching do +RSpec.describe 'Merge request > User uses quick actions', :js, :use_clean_rails_redis_caching, +feature_category: :code_review do include Spec::Support::Helpers::Features::NotesHelpers let(:project) { create(:project, :public, :repository) } diff --git a/spec/features/merge_request/user_views_auto_expanding_diff_spec.rb b/spec/features/merge_request/user_views_auto_expanding_diff_spec.rb index 1748f66c934..19a77a9192c 100644 --- a/spec/features/merge_request/user_views_auto_expanding_diff_spec.rb +++ b/spec/features/merge_request/user_views_auto_expanding_diff_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'User views diffs file-by-file', :js do +RSpec.describe 'User views diffs file-by-file', :js, feature_category: :code_review do let(:merge_request) do create(:merge_request, source_branch: 'squash-large-files', source_project: project, target_project: project) end diff --git a/spec/features/merge_request/user_views_diffs_commit_spec.rb b/spec/features/merge_request/user_views_diffs_commit_spec.rb index cf92603972e..84cbfb35539 100644 --- a/spec/features/merge_request/user_views_diffs_commit_spec.rb +++ b/spec/features/merge_request/user_views_diffs_commit_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'User views diff by commit', :js do +RSpec.describe 'User views diff by commit', :js, feature_category: :code_review do let(:merge_request) do create(:merge_request_with_diffs, source_project: project, target_project: project, source_branch: 'merge-test') end diff --git a/spec/features/merge_request/user_views_diffs_file_by_file_spec.rb b/spec/features/merge_request/user_views_diffs_file_by_file_spec.rb index ad9c342df3e..9db6f86e14d 100644 --- a/spec/features/merge_request/user_views_diffs_file_by_file_spec.rb +++ b/spec/features/merge_request/user_views_diffs_file_by_file_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'User views diffs file-by-file', :js do +RSpec.describe 'User views diffs file-by-file', :js, feature_category: :code_review do let(:merge_request) do create(:merge_request_with_diffs, source_project: project, target_project: project, source_branch: 'merge-test') end diff --git a/spec/features/merge_request/user_views_diffs_spec.rb b/spec/features/merge_request/user_views_diffs_spec.rb index 894292c99eb..7363f6dfb32 100644 --- a/spec/features/merge_request/user_views_diffs_spec.rb +++ b/spec/features/merge_request/user_views_diffs_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'User views diffs', :js do +RSpec.describe 'User views diffs', :js, feature_category: :code_review do let(:merge_request) do create(:merge_request_with_diffs, source_project: project, target_project: project, source_branch: 'merge-test') end diff --git a/spec/features/merge_request/user_views_merge_request_from_deleted_fork_spec.rb b/spec/features/merge_request/user_views_merge_request_from_deleted_fork_spec.rb index e3272a6e280..2a9275adfcf 100644 --- a/spec/features/merge_request/user_views_merge_request_from_deleted_fork_spec.rb +++ b/spec/features/merge_request/user_views_merge_request_from_deleted_fork_spec.rb @@ -6,7 +6,7 @@ require 'spec_helper' # updated. # This can occur when the fork a merge request is created from is in the process # of being destroyed. -RSpec.describe 'User views merged merge request from deleted fork' do +RSpec.describe 'User views merged merge request from deleted fork', feature_category: :code_review do include ProjectForksHelper let(:project) { create(:project, :repository) } diff --git a/spec/features/merge_request/user_views_open_merge_request_spec.rb b/spec/features/merge_request/user_views_open_merge_request_spec.rb index 1f4682b4a46..8b9e973217d 100644 --- a/spec/features/merge_request/user_views_open_merge_request_spec.rb +++ b/spec/features/merge_request/user_views_open_merge_request_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'User views an open merge request' do +RSpec.describe 'User views an open merge request', feature_category: :code_review do let(:merge_request) do create(:merge_request, source_project: project, target_project: project, description: '# Description header') end diff --git a/spec/finders/autocomplete/routes_finder_spec.rb b/spec/finders/autocomplete/routes_finder_spec.rb index c5b040a5640..f37e8e8de7b 100644 --- a/spec/finders/autocomplete/routes_finder_spec.rb +++ b/spec/finders/autocomplete/routes_finder_spec.rb @@ -32,8 +32,24 @@ RSpec.describe Autocomplete::RoutesFinder do context 'when user is admin' do let(:current_user) { admin } - it 'finds all namespaces matching the search excluding project namespaces' do - is_expected.to match_array([group.route, group2.route, user_route]) + context 'when admin mode setting is disabled', :do_not_mock_admin_mode_setting do + it 'finds all namespaces matching the search excluding project namespaces' do + is_expected.to match_array([group.route, group2.route, user_route]) + end + end + + context 'when admin mode setting is enabled' do + context 'when in admin mode', :enable_admin_mode do + it 'finds all namespaces matching the search excluding project namespaces' do + is_expected.to match_array([group.route, group2.route, user_route]) + end + end + + context 'when not in admin mode' do + it 'does not find all namespaces' do + is_expected.to match_array([]) + end + end end end end @@ -48,8 +64,24 @@ RSpec.describe Autocomplete::RoutesFinder do context 'when user is admin' do let(:current_user) { admin } - it 'finds all projects matching the search' do - is_expected.to match_array([project.route, project2.route]) + context 'when admin mode setting is disabled', :do_not_mock_admin_mode_setting do + it 'finds all projects matching the search' do + is_expected.to match_array([project.route, project2.route]) + end + end + + context 'when admin mode setting is enabled' do + context 'when in admin mode', :enable_admin_mode do + it 'finds all projects matching the search' do + is_expected.to match_array([project.route, project2.route]) + end + end + + context 'when not in admin mode' do + it 'does not find all projects' do + is_expected.to match_array([]) + end + end end end end diff --git a/spec/frontend/work_items/components/work_item_detail_spec.js b/spec/frontend/work_items/components/work_item_detail_spec.js index d6e4b0ece36..a016960a85a 100644 --- a/spec/frontend/work_items/components/work_item_detail_spec.js +++ b/spec/frontend/work_items/components/work_item_detail_spec.js @@ -400,9 +400,31 @@ describe('WorkItemDetail component', () => { expect(findWorkItemType().exists()).toBe(false); }); - it('sets the parent breadcrumb URL', () => { + it('shows parent breadcrumb icon', () => { + expect(findParentButton().props('icon')).toBe(mockParent.parent.workItemType.iconName); + }); + + it('sets the parent breadcrumb URL pointing to issue page when parent type is `Issue`', () => { expect(findParentButton().attributes().href).toBe('../../issues/5'); }); + + it('sets the parent breadcrumb URL based on parent webUrl when parent type is not `Issue`', async () => { + const mockParentObjective = { + parent: { + ...mockParent.parent, + workItemType: { + id: mockParent.parent.workItemType.id, + name: 'Objective', + iconName: 'issue-type-objective', + }, + }, + }; + const parentResponse = workItemResponseFactory(mockParentObjective); + createComponent({ handler: jest.fn().mockResolvedValue(parentResponse) }); + await waitForPromises(); + + expect(findParentButton().attributes().href).toBe(mockParentObjective.parent.webUrl); + }); }); }); diff --git a/spec/frontend/work_items/mock_data.js b/spec/frontend/work_items/mock_data.js index 6385f12ccea..a4c16e014ef 100644 --- a/spec/frontend/work_items/mock_data.js +++ b/spec/frontend/work_items/mock_data.js @@ -90,6 +90,12 @@ export const workItemQueryResponse = { iid: '5', title: 'Parent title', confidential: false, + webUrl: 'http://gdk.test/gitlab-org/gitlab/-/issues/1', + workItemType: { + id: 'gid://gitlab/WorkItems::Type/1', + name: 'Issue', + iconName: 'issue-type-issue', + }, }, children: { nodes: [ @@ -191,6 +197,12 @@ export const mockParent = { iid: '5', title: 'Parent title', confidential: false, + webUrl: 'http://gdk.test/gitlab-org/gitlab/-/issues/1', + workItemType: { + id: 'gid://gitlab/WorkItems::Type/1', + name: 'Issue', + iconName: 'issue-type-issue', + }, }, }; diff --git a/spec/lib/gitlab/background_migration/prune_stale_project_export_jobs_spec.rb b/spec/lib/gitlab/background_migration/prune_stale_project_export_jobs_spec.rb new file mode 100644 index 00000000000..5150d0ea4b0 --- /dev/null +++ b/spec/lib/gitlab/background_migration/prune_stale_project_export_jobs_spec.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::PruneStaleProjectExportJobs, feature_category: :importers do + let(:namespaces) { table(:namespaces) } + let(:projects) { table(:projects) } + let(:project_export_jobs) { table(:project_export_jobs) } + let(:project_relation_exports) { table(:project_relation_exports) } + let(:uploads) { table(:project_relation_export_uploads) } + + subject(:perform_migration) do + described_class.new(start_id: 1, + end_id: 300, + batch_table: :project_export_jobs, + batch_column: :id, + sub_batch_size: 2, + pause_ms: 0, + connection: ActiveRecord::Base.connection) + .perform + end + + it 'removes export jobs and associated relations older than 7 days' do + namespaces.create!(id: 1000, name: "Sally", path: 'sally') + projects.create!(id: 1, namespace_id: 1000, project_namespace_id: 1000) + + project = Project.find 1 + + project_export_jobs.create!(id: 10, project_id: project.id, jid: SecureRandom.hex(10), updated_at: 37.months.ago) + project_export_jobs.create!(id: 20, project_id: project.id, jid: SecureRandom.hex(10), updated_at: 12.months.ago) + project_export_jobs.create!(id: 30, project_id: project.id, jid: SecureRandom.hex(10), updated_at: 8.days.ago) + project_export_jobs.create!(id: 40, project_id: project.id, jid: SecureRandom.hex(10), updated_at: 1.day.ago) + project_export_jobs.create!(id: 50, project_id: project.id, jid: SecureRandom.hex(10), updated_at: 2.days.ago) + project_export_jobs.create!(id: 60, project_id: project.id, jid: SecureRandom.hex(10), updated_at: 6.days.ago) + + project_relation_exports.create!(id: 100, project_export_job_id: 10, relation: 'Project') + project_relation_exports.create!(id: 200, project_export_job_id: 20, relation: 'Project') + project_relation_exports.create!(id: 300, project_export_job_id: 30, relation: 'Project') + project_relation_exports.create!(id: 400, project_export_job_id: 40, relation: 'Project') + project_relation_exports.create!(id: 500, project_export_job_id: 50, relation: 'Project') + project_relation_exports.create!(id: 600, project_export_job_id: 60, relation: 'Project') + + uploads.create!(project_relation_export_id: 100, export_file: "#{SecureRandom.alphanumeric(5)}_export.tar.gz") + uploads.create!(project_relation_export_id: 200, export_file: "#{SecureRandom.alphanumeric(5)}_export.tar.gz") + uploads.create!(project_relation_export_id: 300, export_file: "#{SecureRandom.alphanumeric(5)}_export.tar.gz") + uploads.create!(project_relation_export_id: 400, export_file: "#{SecureRandom.alphanumeric(5)}_export.tar.gz") + uploads.create!(project_relation_export_id: 500, export_file: "#{SecureRandom.alphanumeric(5)}_export.tar.gz") + uploads.create!(project_relation_export_id: 600, export_file: "#{SecureRandom.alphanumeric(5)}_export.tar.gz") + + expect(project_export_jobs.all.size).to eq(6) + expect(project_relation_exports.all.size).to eq(6) + expect(uploads.all.size).to eq(6) + + expect { perform_migration } + .to change { project_export_jobs.count }.by(-3) + .and change { project_relation_exports.count }.by(-3) + .and change { uploads.count }.by(-3) + + expect(project_export_jobs.all.size).to eq(3) + expect(project_relation_exports.all.size).to eq(3) + expect(uploads.all.size).to eq(3) + end +end diff --git a/spec/lib/gitlab/import/merge_request_helpers_spec.rb b/spec/lib/gitlab/import/merge_request_helpers_spec.rb index f858ab934bb..9626b7b893f 100644 --- a/spec/lib/gitlab/import/merge_request_helpers_spec.rb +++ b/spec/lib/gitlab/import/merge_request_helpers_spec.rb @@ -37,11 +37,8 @@ RSpec.describe Gitlab::Import::MergeRequestHelpers, type: :helper do attributes.merge(iid: iid, source_branch: iid.to_s)) end - # does ensure that we only load object twice - # 1. by #insert_and_return_id - # 2. by project.merge_requests.find - expect_any_instance_of(MergeRequest).to receive(:attributes) - .twice.times.and_call_original + # ensures that we only load object once by project.merge_requests.find + expect(MergeRequest).to receive(:allocate).once.and_call_original expect(subject.first).not_to be_nil expect(subject.second).to eq(false) diff --git a/spec/lib/sidebars/projects/menus/repository_menu_spec.rb b/spec/lib/sidebars/projects/menus/repository_menu_spec.rb index 3d87e57824b..9d712cfc9f1 100644 --- a/spec/lib/sidebars/projects/menus/repository_menu_spec.rb +++ b/spec/lib/sidebars/projects/menus/repository_menu_spec.rb @@ -36,11 +36,12 @@ RSpec.describe Sidebars::Projects::Menus::RepositoryMenu do end context 'for menu items' do - describe 'Commits' do - let_it_be(:item_id) { :contributors } - let(:ref) { 'master' } + let(:ref) { 'master' } - subject { described_class.new(context).renderable_items.find { |e| e.item_id == :commits }.link } + subject { described_class.new(context).renderable_items.find { |e| e.item_id == item_id } } + + describe 'Commits' do + let_it_be(:item_id) { :commits } context 'when there is a ref_type' do let(:context) do @@ -51,7 +52,7 @@ RSpec.describe Sidebars::Projects::Menus::RepositoryMenu do let(:ref_type) { 'tags' } it 'has a links to commits with ref_type' do - expect(subject).to eq("/#{project.full_path}/-/commits/#{ref}?ref_type=#{ref_type}") + expect(subject.link).to eq("/#{project.full_path}/-/commits/#{ref}?ref_type=#{ref_type}") end end @@ -64,21 +65,19 @@ RSpec.describe Sidebars::Projects::Menus::RepositoryMenu do end it 'has a links to commits' do - expect(subject).to eq("/#{project.full_path}/-/commits/#{ref}") + expect(subject.link).to eq("/#{project.full_path}/-/commits/#{ref}") end end context 'and the use_ref_type_parameter flag is enabled' do it 'has a links to commits ref_type' do - expect(subject).to eq("/#{project.full_path}/-/commits/#{ref}?ref_type=heads") + expect(subject.link).to eq("/#{project.full_path}/-/commits/#{ref}?ref_type=heads") end end end end describe 'Contributors' do - subject { described_class.new(context).renderable_items.index { |e| e.item_id == item_id } } - let_it_be(:item_id) { :contributors } context 'when analytics is disabled' do @@ -94,7 +93,53 @@ RSpec.describe Sidebars::Projects::Menus::RepositoryMenu do project.project_feature.update!(analytics_access_level: ProjectFeature::ENABLED) end + using RSpec::Parameterized::TableSyntax it { is_expected.not_to be_nil } + + shared_examples_for 'contributors menu link' do + with_them do + before do + stub_feature_flags(use_ref_type_parameter: feature_flag_enabled) + end + + it 'has a link to graphs with the fully qualifed ref route' do + expect(subject.link).to eq(link) + end + end + end + + describe 'link' do + let(:context) do + Sidebars::Projects::Context.new(current_user: user, container: project, current_ref: ref, + ref_type: ref_type) + end + + it_behaves_like 'contributors menu link' do + where(:feature_flag_enabled, :ref_type, :link) do + true | nil | lazy { "/#{project.full_path}/-/graphs/#{ref}?ref_type=heads" } + true | 'heads' | lazy { "/#{project.full_path}/-/graphs/#{ref}?ref_type=heads" } + true | 'tags' | lazy { "/#{project.full_path}/-/graphs/#{ref}?ref_type=tags" } + false | nil | lazy { "/#{project.full_path}/-/graphs/#{ref}" } + false | 'heads' | lazy { "/#{project.full_path}/-/graphs/#{ref}" } + false | 'tags' | lazy { "/#{project.full_path}/-/graphs/#{ref}" } + end + end + + context 'when ref is not the default' do + let(:ref) { 'nonmain' } + + it_behaves_like 'contributors menu link' do + where(:feature_flag_enabled, :ref_type, :link) do + true | nil | lazy { "/#{project.full_path}/-/graphs/#{context.current_ref}" } + true | 'heads' | lazy { "/#{project.full_path}/-/graphs/#{context.current_ref}?ref_type=heads" } + true | 'tags' | lazy { "/#{project.full_path}/-/graphs/#{context.current_ref}?ref_type=tags" } + false | nil | lazy { "/#{project.full_path}/-/graphs/#{context.current_ref}" } + false | 'heads' | lazy { "/#{project.full_path}/-/graphs/#{context.current_ref}" } + false | 'tags' | lazy { "/#{project.full_path}/-/graphs/#{context.current_ref}" } + end + end + end + end end end end diff --git a/spec/migrations/20221122132812_schedule_prune_stale_project_export_jobs_spec.rb b/spec/migrations/20221122132812_schedule_prune_stale_project_export_jobs_spec.rb new file mode 100644 index 00000000000..72ae080f859 --- /dev/null +++ b/spec/migrations/20221122132812_schedule_prune_stale_project_export_jobs_spec.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe SchedulePruneStaleProjectExportJobs, category: :importers do + let_it_be(:batched_migration) { described_class::MIGRATION } + + it 'schedules a new batched migration' do + reversible_migration do |migration| + migration.before -> { + expect(batched_migration).not_to have_scheduled_batched_migration + } + + migration.after -> { + expect(batched_migration).to have_scheduled_batched_migration( + table_name: :project_export_jobs, + column_name: :id, + interval: described_class::DELAY_INTERVAL + ) + } + end + end +end diff --git a/spec/requests/api/oauth_tokens_spec.rb b/spec/requests/api/oauth_tokens_spec.rb index f07dcfcccd6..cb7024b7166 100644 --- a/spec/requests/api/oauth_tokens_spec.rb +++ b/spec/requests/api/oauth_tokens_spec.rb @@ -85,8 +85,6 @@ RSpec.describe 'OAuth tokens' do context 'with invalid credentials' do it 'does not create an access token' do - pending 'Enable this example after https://github.com/doorkeeper-gem/doorkeeper/pull/1488 is merged and released' - user = create(:user) request_oauth_token(user, basic_auth_header(client.uid, 'invalid secret')) diff --git a/spec/rubocop/cop/graphql/descriptions_spec.rb b/spec/rubocop/cop/graphql/descriptions_spec.rb index 8826e700fdf..5e3f9539ff4 100644 --- a/spec/rubocop/cop/graphql/descriptions_spec.rb +++ b/spec/rubocop/cop/graphql/descriptions_spec.rb @@ -60,6 +60,33 @@ RSpec.describe RuboCop::Cop::Graphql::Descriptions do TYPE end + it 'adds an offense when description contains the demonstrative "this"' do + expect_offense(<<~TYPE) + module Types + class FakeType < BaseObject + field :a_thing, + ^^^^^^^^^^^^^^^ #{described_class::MSG_CONTAINS_THIS} + GraphQL::Types::String, + null: false, + description: 'Description of this thing.' + end + end + TYPE + end + + it 'does not add an offense when a word contains the substring "this"' do + expect_no_offenses(<<~TYPE) + module Types + class FakeType < BaseObject + field :a_thing, + GraphQL::Types::String, + null: false, + description: 'Description of thistle.' + end + end + TYPE + end + it 'does not add an offense when description is correct' do expect_no_offenses(<<~TYPE.strip) module Types @@ -140,6 +167,33 @@ RSpec.describe RuboCop::Cop::Graphql::Descriptions do TYPE end + it 'adds an offense when description contains the demonstrative "this"' do + expect_offense(<<~TYPE) + module Types + class FakeType < BaseObject + argument :a_thing, + ^^^^^^^^^^^^^^^^^^ #{described_class::MSG_CONTAINS_THIS} + GraphQL::Types::String, + null: false, + description: 'Description of this thing.' + end + end + TYPE + end + + it 'does not add an offense when a word contains the substring "this"' do + expect_no_offenses(<<~TYPE) + module Types + class FakeType < BaseObject + argument :a_thing, + GraphQL::Types::String, + null: false, + description: 'Description of thistle.' + end + end + TYPE + end + it 'does not add an offense when description is correct' do expect_no_offenses(<<~TYPE.strip) module Types @@ -199,6 +253,27 @@ RSpec.describe RuboCop::Cop::Graphql::Descriptions do TYPE end + it 'adds an offense when description contains the demonstrative "this"' do + expect_offense(<<~TYPE.strip) + module Types + class FakeEnum < BaseEnum + value 'FOO', value: 'foo', description: 'Description of this issue.' + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{described_class::MSG_CONTAINS_THIS} + end + end + TYPE + end + + it 'does not add an offense when a word contains the substring "this"' do + expect_no_offenses(<<~TYPE.strip) + module Types + class FakeEnum < BaseEnum + value 'FOO', value: 'foo', description: 'Description of thistle.' + end + end + TYPE + end + it 'does not add an offense when description is correct (defined using `description:`)' do expect_no_offenses(<<~TYPE.strip) module Types diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb index 5ddf91e167e..7b51f9db8cd 100644 --- a/spec/services/issues/create_service_spec.rb +++ b/spec/services/issues/create_service_spec.rb @@ -405,7 +405,8 @@ RSpec.describe Issues::CreateService do iid: { current: kind_of(Integer), previous: nil }, project_id: { current: project.id, previous: nil }, title: { current: opts[:title], previous: nil }, - updated_at: { current: kind_of(Time), previous: nil } + updated_at: { current: kind_of(Time), previous: nil }, + time_estimate: { current: 0, previous: nil } }, object_attributes: include( opts.merge( diff --git a/spec/services/web_hooks/log_execution_service_spec.rb b/spec/services/web_hooks/log_execution_service_spec.rb index ef251e30bb2..9f1968b4f41 100644 --- a/spec/services/web_hooks/log_execution_service_spec.rb +++ b/spec/services/web_hooks/log_execution_service_spec.rb @@ -142,5 +142,23 @@ RSpec.describe WebHooks::LogExecutionService do service.execute end end + + context 'with url_variables' do + before do + project_hook.update!( + url: 'http://example1.test/{foo}-{bar}', + url_variables: { 'foo' => 'supers3cret', 'bar' => 'token' } + ) + end + + let(:data) { super().merge(response_headers: { 'X-Token-Id' => 'supers3cret-token', 'X-Request' => 'PUBLIC-token' }) } + let(:expected_headers) { { 'X-Token-Id' => '{foo}-{bar}', 'X-Request' => 'PUBLIC-{bar}' } } + + it 'logs the data and masks response headers' do + expect { service.execute }.to change(::WebHookLog, :count).by(1) + + expect(WebHookLog.recent.first.response_headers).to eq(expected_headers) + end + end end end diff --git a/spec/support/helpers/features/invite_members_modal_helper.rb b/spec/support/helpers/features/invite_members_modal_helper.rb index 13b07ad034a..c815e52dc80 100644 --- a/spec/support/helpers/features/invite_members_modal_helper.rb +++ b/spec/support/helpers/features/invite_members_modal_helper.rb @@ -19,6 +19,20 @@ module Spec page.refresh if refresh end + def invite_member_by_email(role) + click_on _('Invite members') + + page.within invite_modal_selector do + choose_options(role, nil) + find(member_dropdown_selector).set('new_email@gitlab.com') + wait_for_requests + + find('.dropdown-item', text: 'Invite "new_email@gitlab.com" by email').click + + submit_invites + end + end + def input_invites(names) click_on 'Invite members' diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb index 6292cf83297..eceb29e0667 100644 --- a/spec/support/helpers/test_env.rb +++ b/spec/support/helpers/test_env.rb @@ -420,6 +420,8 @@ module TestEnv end def component_timed_setup(component, install_dir:, version:, task:, fresh_install: true, task_args: []) + puts "==> Starting #{component} set up...\n" + start = Time.now ensure_component_dir_name_is_correct!(component, install_dir) diff --git a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb index d2f4c180574..080a53cc1a2 100644 --- a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb +++ b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb @@ -134,10 +134,24 @@ RSpec.describe 'layouts/nav/sidebar/_project' do end describe 'Contributors' do - it 'has a link to the project contributors path' do - render + context 'and the use_ref_type_parameter flag is disabled' do + before do + stub_feature_flags(use_ref_type_parameter: false) + end + + it 'has a link to the project contributors path' do + render - expect(rendered).to have_link('Contributors', href: project_graph_path(project, current_ref)) + expect(rendered).to have_link('Contributors', href: project_graph_path(project, current_ref)) + end + end + + context 'and the use_ref_type_parameter flag is enabled' do + it 'has a link to the project contributors path' do + render + + expect(rendered).to have_link('Contributors', href: project_graph_path(project, current_ref, ref_type: 'heads')) + end end end diff --git a/workhorse/internal/artifacts/entry.go b/workhorse/internal/artifacts/entry.go index d5b3dfb672c..3ec3a559100 100644 --- a/workhorse/internal/artifacts/entry.go +++ b/workhorse/internal/artifacts/entry.go @@ -17,6 +17,7 @@ import ( "gitlab.com/gitlab-org/labkit/mask" "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper" + "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/command" "gitlab.com/gitlab-org/gitlab/workhorse/internal/senddata" "gitlab.com/gitlab-org/gitlab/workhorse/internal/zipartifacts" ) @@ -83,7 +84,7 @@ func unpackFileFromZip(ctx context.Context, archivePath, encodedFilename string, if err := catFile.Start(); err != nil { return fmt.Errorf("start %v: %v", catFile.Args, err) } - defer helper.CleanUpProcessGroup(catFile) + defer command.KillProcessGroup(catFile) basename := filepath.Base(fileName) reader := bufio.NewReader(stdout) @@ -114,7 +115,7 @@ func waitCatFile(cmd *exec.Cmd) error { return nil } - st, ok := helper.ExitStatus(err) + st, ok := command.ExitStatus(err) if ok && (st == zipartifacts.CodeArchiveNotFound || st == zipartifacts.CodeEntryNotFound) { return os.ErrNotExist diff --git a/workhorse/internal/helper/command/command.go b/workhorse/internal/helper/command/command.go new file mode 100644 index 00000000000..59c8c9a3db2 --- /dev/null +++ b/workhorse/internal/helper/command/command.go @@ -0,0 +1,30 @@ +package command + +import ( + "os/exec" + "syscall" +) + +func ExitStatus(err error) (int, bool) { + if v, ok := err.(interface{ ExitCode() int }); ok { + return v.ExitCode(), true + } else if err != nil { + return -1, false + } else { + return 0, false + } +} + +func KillProcessGroup(cmd *exec.Cmd) { + if cmd == nil { + return + } + + if p := cmd.Process; p != nil && p.Pid > 0 { + // Send SIGTERM to the process group of cmd + syscall.Kill(-p.Pid, syscall.SIGTERM) + } + + // reap our child process + cmd.Wait() +} diff --git a/workhorse/internal/helper/helpers.go b/workhorse/internal/helper/helpers.go index 33318407f88..ea35d45fa33 100644 --- a/workhorse/internal/helper/helpers.go +++ b/workhorse/internal/helper/helpers.go @@ -9,17 +9,13 @@ import ( "net/http" "net/url" "os" - "os/exec" "strings" - "syscall" "github.com/sebest/xff" "gitlab.com/gitlab-org/labkit/log" "gitlab.com/gitlab-org/labkit/mask" ) -const NginxResponseBufferHeader = "X-Accel-Buffering" - func logErrorWithFields(r *http.Request, err error, fields log.Fields) { if err != nil { CaptureRavenError(r, err, fields) @@ -121,43 +117,6 @@ func HeaderClone(h http.Header) http.Header { return h2 } -func CleanUpProcessGroup(cmd *exec.Cmd) { - if cmd == nil { - return - } - - process := cmd.Process - if process != nil && process.Pid > 0 { - // Send SIGTERM to the process group of cmd - syscall.Kill(-process.Pid, syscall.SIGTERM) - } - - // reap our child process - cmd.Wait() -} - -func ExitStatus(err error) (int, bool) { - exitError, ok := err.(*exec.ExitError) - if !ok { - return 0, false - } - - waitStatus, ok := exitError.Sys().(syscall.WaitStatus) - if !ok { - return 0, false - } - - return waitStatus.ExitStatus(), true -} - -func DisableResponseBuffering(w http.ResponseWriter) { - w.Header().Set(NginxResponseBufferHeader, "no") -} - -func AllowResponseBuffering(w http.ResponseWriter) { - w.Header().Del(NginxResponseBufferHeader) -} - func FixRemoteAddr(r *http.Request) { // Unix domain sockets have a remote addr of @. This will make the // xff package lookup the X-Forwarded-For address if available. diff --git a/workhorse/internal/helper/nginx/nginx.go b/workhorse/internal/helper/nginx/nginx.go new file mode 100644 index 00000000000..ca7c8543f75 --- /dev/null +++ b/workhorse/internal/helper/nginx/nginx.go @@ -0,0 +1,13 @@ +package nginx + +import "net/http" + +const ResponseBufferHeader = "X-Accel-Buffering" + +func DisableResponseBuffering(w http.ResponseWriter) { + w.Header().Set(ResponseBufferHeader, "no") +} + +func AllowResponseBuffering(w http.ResponseWriter) { + w.Header().Del(ResponseBufferHeader) +} diff --git a/workhorse/internal/helper/tempfile.go b/workhorse/internal/helper/tempfile.go deleted file mode 100644 index f5864f549d0..00000000000 --- a/workhorse/internal/helper/tempfile.go +++ /dev/null @@ -1,34 +0,0 @@ -package helper - -import ( - "io" - "os" -) - -func ReadAllTempfile(r io.Reader) (tempfile *os.File, err error) { - tempfile, err = os.CreateTemp("", "gitlab-workhorse-read-all-tempfile") - if err != nil { - return nil, err - } - - defer func() { - // Avoid leaking an open file if the function returns with an error - if err != nil { - tempfile.Close() - } - }() - - if err := os.Remove(tempfile.Name()); err != nil { - return nil, err - } - - if _, err := io.Copy(tempfile, r); err != nil { - return nil, err - } - - if _, err := tempfile.Seek(0, 0); err != nil { - return nil, err - } - - return tempfile, nil -} diff --git a/workhorse/internal/imageresizer/image_resizer.go b/workhorse/internal/imageresizer/image_resizer.go index 092369cd2af..4a7e52d92d9 100644 --- a/workhorse/internal/imageresizer/image_resizer.go +++ b/workhorse/internal/imageresizer/image_resizer.go @@ -21,6 +21,7 @@ import ( "gitlab.com/gitlab-org/gitlab/workhorse/internal/config" "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper" + "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/command" "gitlab.com/gitlab-org/gitlab/workhorse/internal/log" "gitlab.com/gitlab-org/gitlab/workhorse/internal/senddata" "gitlab.com/gitlab-org/gitlab/workhorse/internal/transport" @@ -191,7 +192,7 @@ func (r *Resizer) Inject(w http.ResponseWriter, req *http.Request, paramsData st // We need to log this separately since the subsequent steps might add other failures. log.WithRequest(req).WithFields(logFields(start, params, &outcome)).WithError(err).Error() } - defer helper.CleanUpProcessGroup(resizeCmd) + defer command.KillProcessGroup(resizeCmd) w.Header().Del("Content-Length") outcome.bytesWritten, err = serveImage(imageReader, w, resizeCmd) diff --git a/workhorse/internal/proxy/proxy.go b/workhorse/internal/proxy/proxy.go index 06e2c65a6a8..5725d56592f 100644 --- a/workhorse/internal/proxy/proxy.go +++ b/workhorse/internal/proxy/proxy.go @@ -8,6 +8,7 @@ import ( "time" "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper" + "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/nginx" ) var ( @@ -86,7 +87,7 @@ func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { } if p.AllowResponseBuffering { - helper.AllowResponseBuffering(w) + nginx.AllowResponseBuffering(w) } // If the ultimate client disconnects when the response isn't fully written diff --git a/workhorse/internal/senddata/senddata.go b/workhorse/internal/senddata/senddata.go index 190a37c1a15..4cb96890ee2 100644 --- a/workhorse/internal/senddata/senddata.go +++ b/workhorse/internal/senddata/senddata.go @@ -5,6 +5,7 @@ import ( "gitlab.com/gitlab-org/gitlab/workhorse/internal/headers" "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper" + "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/nginx" "gitlab.com/gitlab-org/gitlab/workhorse/internal/senddata/contentprocessor" "github.com/prometheus/client_golang/prometheus" @@ -88,7 +89,7 @@ func (s *sendDataResponseWriter) tryInject() bool { for _, injecter := range s.injecters { if injecter.Match(header) { s.hijacked = true - helper.DisableResponseBuffering(s.rw) + nginx.DisableResponseBuffering(s.rw) crw := helper.NewCountingResponseWriter(s.rw) injecter.Inject(crw, s.req, header) sendDataResponses.WithLabelValues(injecter.Name()).Inc() diff --git a/workhorse/internal/sendfile/sendfile.go b/workhorse/internal/sendfile/sendfile.go index 07b1789445a..e9d6d763b88 100644 --- a/workhorse/internal/sendfile/sendfile.go +++ b/workhorse/internal/sendfile/sendfile.go @@ -20,6 +20,7 @@ import ( "gitlab.com/gitlab-org/gitlab/workhorse/internal/headers" "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper" + "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/nginx" ) var ( @@ -93,7 +94,7 @@ func (s *sendFileResponseWriter) WriteHeader(status int) { s.hijacked = true // Serve the file - helper.DisableResponseBuffering(s.rw) + nginx.DisableResponseBuffering(s.rw) sendFileFromDisk(s.rw, s.req, file) return } diff --git a/workhorse/internal/upload/artifacts_uploader.go b/workhorse/internal/upload/artifacts_uploader.go index a8c944a1d33..c83874e7293 100644 --- a/workhorse/internal/upload/artifacts_uploader.go +++ b/workhorse/internal/upload/artifacts_uploader.go @@ -16,7 +16,7 @@ import ( "gitlab.com/gitlab-org/labkit/log" "gitlab.com/gitlab-org/gitlab/workhorse/internal/api" - "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper" + "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/command" "gitlab.com/gitlab-org/gitlab/workhorse/internal/lsif_transformer/parser" "gitlab.com/gitlab-org/gitlab/workhorse/internal/upload/destination" "gitlab.com/gitlab-org/gitlab/workhorse/internal/zipartifacts" @@ -83,7 +83,7 @@ func (a *artifactsUploadProcessor) generateMetadataFromZip(ctx context.Context, if err := zipMd.Start(); err != nil { return nil, err } - defer helper.CleanUpProcessGroup(zipMd) + defer command.KillProcessGroup(zipMd) fh, err := destination.Upload(ctx, zipMdOut, -1, "metadata.gz", metaOpts) if err != nil { @@ -91,7 +91,7 @@ func (a *artifactsUploadProcessor) generateMetadataFromZip(ctx context.Context, } if err := zipMd.Wait(); err != nil { - st, ok := helper.ExitStatus(err) + st, ok := command.ExitStatus(err) if !ok { return nil, err diff --git a/workhorse/internal/upstream/upstream.go b/workhorse/internal/upstream/upstream.go index 248f190e316..cde1967460c 100644 --- a/workhorse/internal/upstream/upstream.go +++ b/workhorse/internal/upstream/upstream.go @@ -24,6 +24,7 @@ import ( "gitlab.com/gitlab-org/gitlab/workhorse/internal/builds" "gitlab.com/gitlab-org/gitlab/workhorse/internal/config" "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper" + "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/nginx" proxypkg "gitlab.com/gitlab-org/gitlab/workhorse/internal/proxy" "gitlab.com/gitlab-org/gitlab/workhorse/internal/rejectmethods" "gitlab.com/gitlab-org/gitlab/workhorse/internal/upload" @@ -126,7 +127,7 @@ func (u *upstream) configureURLPrefix() { func (u *upstream) ServeHTTP(w http.ResponseWriter, r *http.Request) { helper.FixRemoteAddr(r) - helper.DisableResponseBuffering(w) + nginx.DisableResponseBuffering(w) // Drop RequestURI == "*" (FIXME: why?) if r.RequestURI == "*" { diff --git a/workhorse/main_test.go b/workhorse/main_test.go index 5ebc26c7ac7..fc4981492a4 100644 --- a/workhorse/main_test.go +++ b/workhorse/main_test.go @@ -29,6 +29,7 @@ import ( "gitlab.com/gitlab-org/gitlab/workhorse/internal/config" "gitlab.com/gitlab-org/gitlab/workhorse/internal/gitaly" "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper" + "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/nginx" "gitlab.com/gitlab-org/gitlab/workhorse/internal/secret" "gitlab.com/gitlab-org/gitlab/workhorse/internal/testhelper" "gitlab.com/gitlab-org/gitlab/workhorse/internal/upstream" @@ -853,7 +854,7 @@ func httpPost(t *testing.T, url string, headers map[string]string, reqBody io.Re } func requireNginxResponseBuffering(t *testing.T, expected string, resp *http.Response, msgAndArgs ...interface{}) { - actual := resp.Header.Get(helper.NginxResponseBufferHeader) + actual := resp.Header.Get(nginx.ResponseBufferHeader) require.Equal(t, expected, actual, msgAndArgs...) } |