diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 9225f04ad79..1340bd975e3 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -60,7 +60,7 @@ workflow:
variables:
PG_VERSION: "12"
- DEFAULT_CI_IMAGE: "${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/debian-${DEBIAN_VERSION}-ruby-${RUBY_VERSION}.patched-golang-1.17-node-16.14-postgresql-${PG_VERSION}:git-2.36-lfs-2.9-chrome-${CHROME_VERSION}-yarn-1.22-graphicsmagick-1.3.36"
+ DEFAULT_CI_IMAGE: "${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/debian-${DEBIAN_VERSION}-ruby-${RUBY_VERSION}.patched-golang-1.17-node-16.14-postgresql-${PG_VERSION}:rubygems-3.2-git-2.36-lfs-2.9-chrome-${CHROME_VERSION}-yarn-1.22-graphicsmagick-1.3.36"
RAILS_ENV: "test"
NODE_ENV: "test"
BUNDLE_WITHOUT: "production:development"
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index 8bfda0e6684..dc246897fa2 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -11,7 +11,7 @@
- .default-retry
- .default-before_script
- .assets-compile-cache
- image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:debian-${DEBIAN_VERSION}-ruby-${RUBY_VERSION}-git-2.33-lfs-2.9-node-16.14-yarn-1.22-graphicsmagick-1.3.36
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/debian-${DEBIAN_VERSION}-ruby-${RUBY_VERSION}-node-16.14:rubygems-3.2-git-2.33-lfs-2.9-yarn-1.22-graphicsmagick-1.3.36
variables:
SETUP_DB: "false"
WEBPACK_VENDOR_DLL: "true"
diff --git a/app/assets/javascripts/editor/schema/ci.json b/app/assets/javascripts/editor/schema/ci.json
index c8015f884b7..e8b96c25965 100644
--- a/app/assets/javascripts/editor/schema/ci.json
+++ b/app/assets/javascripts/editor/schema/ci.json
@@ -436,6 +436,33 @@
"type": "string"
}
},
+ "pull_policy": {
+ "markdownDescription": "Specifies how to pull the image in Runner. It can be one of `always`, `never` or `if-not-present`. The default value is `always`. [Learn more](https://docs.gitlab.com/ee/ci/yaml/#servicepull_policy).",
+ "default": "always",
+ "oneOf": [
+ {
+ "type": "string",
+ "enum": [
+ "always",
+ "never",
+ "if-not-present"
+ ]
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "always",
+ "never",
+ "if-not-present"
+ ]
+ },
+ "minItems": 1,
+ "uniqueItems": true
+ }
+ ]
+ },
"command": {
"type": "array",
"description": "Command or script that should be used as the container's command. It will be translated to arguments passed to Docker after the image's name. The syntax is similar to Dockerfile's CMD directive, where each shell token is a separate string in the array.",
diff --git a/app/controllers/projects/settings/operations_controller.rb b/app/controllers/projects/settings/operations_controller.rb
index d4126cbd708..2723ecab336 100644
--- a/app/controllers/projects/settings/operations_controller.rb
+++ b/app/controllers/projects/settings/operations_controller.rb
@@ -14,7 +14,6 @@ module Projects
respond_to :json, only: [:reset_alerting_token, :reset_pagerduty_token]
helper_method :error_tracking_setting
- helper_method :tracing_setting
feature_category :incident_management
urgency :low
@@ -60,19 +59,9 @@ module Projects
::Gitlab::Tracking::IncidentManagement.track_from_params(
update_params[:incident_management_setting_attributes]
)
- track_tracing_external_url
end
end
- def track_tracing_external_url
- external_url_previous_change = project&.tracing_setting&.external_url_previous_change
-
- return unless external_url_previous_change
- return unless external_url_previous_change[0].blank? && external_url_previous_change[1].present?
-
- ::Gitlab::Tracking.event('project:operations:tracing', 'external_url_populated', user: current_user, project: project, namespace: project.namespace)
- end
-
def alerting_params
{ alerting_setting_attributes: { regenerate_token: true } }
end
@@ -124,10 +113,6 @@ module Projects
project.build_error_tracking_setting
end
- def tracing_setting
- @tracing_setting ||= project.tracing_setting || project.build_tracing_setting
- end
-
def update_params
params.require(:project).permit(permitted_project_params)
end
@@ -147,8 +132,7 @@ module Projects
project: [:slug, :name, :organization_slug, :organization_name]
],
- grafana_integration_attributes: [:token, :grafana_url, :enabled],
- tracing_setting_attributes: [:external_url]
+ grafana_integration_attributes: [:token, :grafana_url, :enabled]
}
end
end
diff --git a/app/services/concerns/alert_management/alert_processing.rb b/app/services/concerns/alert_management/alert_processing.rb
index de54102bdc8..f10ff4e6f19 100644
--- a/app/services/concerns/alert_management/alert_processing.rb
+++ b/app/services/concerns/alert_management/alert_processing.rb
@@ -38,7 +38,7 @@ module AlertManagement
if alert.resolve(incoming_payload.ends_at)
SystemNoteService.change_alert_status(alert, User.alert_bot)
- close_issue(alert.issue) if auto_close_incident?
+ close_issue(alert.issue_id) if auto_close_incident?
else
logger.warn(
message: 'Unable to update AlertManagement::Alert status to resolved',
@@ -52,14 +52,10 @@ module AlertManagement
alert.register_new_event!
end
- def close_issue(issue)
- return if issue.blank? || issue.closed?
+ def close_issue(issue_id)
+ return unless issue_id
- ::Issues::CloseService
- .new(project: project, current_user: User.alert_bot)
- .execute(issue, system_note: false)
-
- SystemNoteService.auto_resolve_prometheus_alert(issue, project, User.alert_bot) if issue.reset.closed?
+ ::IncidentManagement::CloseIncidentWorker.perform_async(issue_id)
end
def process_new_alert
@@ -78,7 +74,7 @@ module AlertManagement
end
def process_incident_issues
- return if alert.issue || alert.resolved?
+ return if alert.issue_id || alert.resolved?
::IncidentManagement::ProcessAlertWorkerV2.perform_async(alert.id)
end
diff --git a/app/views/admin/application_settings/reporting.html.haml b/app/views/admin/application_settings/reporting.html.haml
index 60781f86f2e..af9145bf1e7 100644
--- a/app/views/admin/application_settings/reporting.html.haml
+++ b/app/views/admin/application_settings/reporting.html.haml
@@ -27,3 +27,5 @@
= link_to _('Learn more.'), help_page_path('user/admin_area/review_abuse_reports.md'), target: '_blank', rel: 'noopener noreferrer'
.settings-content
= render 'abuse'
+
+= render_if_exists 'admin/application_settings/git_abuse_rate_limit'
diff --git a/app/views/clusters/clusters/_integrations.html.haml b/app/views/clusters/clusters/_integrations.html.haml
index 62ae551fee7..4a3062def8c 100644
--- a/app/views/clusters/clusters/_integrations.html.haml
+++ b/app/views/clusters/clusters/_integrations.html.haml
@@ -14,15 +14,3 @@
s_('ClusterIntegration|Enable Prometheus integration'),
help_text: '%{help_text} %{help_link}'.html_safe % { help_text: help_text, help_link: help_link }
= prometheus_form.submit _('Save changes'), class: 'btn gl-button btn-confirm'
-
- - if Feature.enabled?(:monitor_logging, @project)
- .sub-section.form-group
- = gitlab_ui_form_for @elastic_stack_integration, as: :integration, namespace: :elastic_stack, url: @cluster.integrations_path, method: :post, html: { class: 'js-cluster-integrations-form' } do |elastic_stack_form|
- = elastic_stack_form.hidden_field :application_type
- .form-group.gl-form-group
- - help_text = s_('ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs.')
- - help_link = link_to(_('More information.'), help_page_path("user/clusters/integrations", anchor: "elastic-stack-cluster-integration"), target: '_blank', rel: 'noopener noreferrer')
- = elastic_stack_form.gitlab_ui_checkbox_component :enabled,
- s_('ClusterIntegration|Enable Elastic Stack integration'),
- help_text: '%{help_text} %{help_link}'.html_safe % { help_text: help_text, help_link: help_link }
- = elastic_stack_form.submit _('Save changes'), class: 'btn gl-button btn-confirm'
diff --git a/app/views/clusters/clusters/_namespace.html.haml b/app/views/clusters/clusters/_namespace.html.haml
index cedece5ad93..572f2d6d9a2 100644
--- a/app/views/clusters/clusters/_namespace.html.haml
+++ b/app/views/clusters/clusters/_namespace.html.haml
@@ -1,5 +1,5 @@
- managed_namespace_help_text = s_('ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared.')
-- non_managed_namespace_help_text = s_('ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals.')
+- non_managed_namespace_help_text = s_('ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, and Web terminals.')
- managed_namespace_help_link = link_to _('More information'), help_page_path('user/project/clusters/gitlab_managed_clusters.md'), target: '_blank', rel: 'noopener noreferrer'
.js-namespace-prefixed
diff --git a/app/views/dashboard/projects/_blank_state_welcome.html.haml b/app/views/dashboard/projects/_blank_state_welcome.html.haml
index e0b8850357e..0658d548eab 100644
--- a/app/views/dashboard/projects/_blank_state_welcome.html.haml
+++ b/app/views/dashboard/projects/_blank_state_welcome.html.haml
@@ -39,7 +39,7 @@
%p
= _('Public projects are an easy way to allow everyone to have read-only access.')
- = link_to "https://docs.gitlab.com/", class: link_classes do
+ = link_to Gitlab::Saas::doc_url, class: link_classes do
.blank-state-icon
= custom_icon("lightbulb", size: 50)
.blank-state-body.gl-sm-pl-0.gl-pl-6
diff --git a/app/views/projects/settings/operations/_tracing.html.haml b/app/views/projects/settings/operations/_tracing.html.haml
deleted file mode 100644
index 3c8ebe3fb20..00000000000
--- a/app/views/projects/settings/operations/_tracing.html.haml
+++ /dev/null
@@ -1,24 +0,0 @@
-- setting = tracing_setting
-
-%section.settings.border-0.no-animate
- .settings-header{ :class => 'border-top' }
- %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
- = _('Tracing')
- = render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
- = _('Expand')
- %p
- = _('Embed an image of your existing Jaeger server in GitLab.')
- = link_to _('Learn more.'), help_page_path('operations/tracing'), target: '_blank', rel: 'noopener noreferrer'
- .settings-content
- = form_for @project, url: project_settings_operations_path(@project), method: :patch do |f|
- = form_errors(@project)
- .form-group
- = f.fields_for :tracing_setting_attributes, setting do |form|
- = form.label :external_url, _('Jaeger URL'), class: 'label-bold'
- = form.url_field :external_url, class: 'form-control gl-form-input', placeholder: 'https://jaeger.example.com'
- %p.form-text.text-muted
- - jaeger_help_url = 'https://www.jaegertracing.io/docs/getting-started/'
- - link_start_tag = ''.html_safe % { url: jaeger_help_url }
- - link_end_tag = "#{sprite_icon('external-link', css_class: 'gl-ml-2 gl-vertical-align-middle')}".html_safe
- = _('Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}.').html_safe % { link_start_tag: link_start_tag, link_end_tag: link_end_tag }
- = f.submit _('Save changes'), class: 'gl-button btn btn-confirm'
diff --git a/app/views/projects/settings/operations/show.html.haml b/app/views/projects/settings/operations/show.html.haml
index 80c22604e49..d6dd7fcc316 100644
--- a/app/views/projects/settings/operations/show.html.haml
+++ b/app/views/projects/settings/operations/show.html.haml
@@ -20,7 +20,6 @@
= html_escape(s_('Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}.')) % {opstrace_link_start: opstrace_link_start, link_end: link_end }
= render 'projects/settings/operations/metrics_dashboard'
-= render 'projects/settings/operations/tracing' if Feature.enabled?(:monitor_tracing, @project)
= render 'projects/settings/operations/error_tracking'
= render 'projects/settings/operations/alert_management'
= render 'projects/settings/operations/incidents'
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index ab75abff9ba..9bb6bd32386 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -2389,6 +2389,15 @@
:weight: 2
:idempotent: true
:tags: []
+- :name: incident_management_close_incident
+ :worker_name: IncidentManagement::CloseIncidentWorker
+ :feature_category: :incident_management
+ :has_external_dependencies: true
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: integrations_create_external_cross_reference
:worker_name: Integrations::CreateExternalCrossReferenceWorker
:feature_category: :integrations
diff --git a/app/workers/incident_management/close_incident_worker.rb b/app/workers/incident_management/close_incident_worker.rb
new file mode 100644
index 00000000000..7d45a6785ea
--- /dev/null
+++ b/app/workers/incident_management/close_incident_worker.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module IncidentManagement
+ class CloseIncidentWorker
+ include ApplicationWorker
+
+ idempotent!
+ deduplicate :until_executed
+ data_consistency :always
+ feature_category :incident_management
+ urgency :low
+
+ # Issues:CloseService execute webhooks which are treated as external dependencies
+ worker_has_external_dependencies!
+
+ def perform(issue_id)
+ incident = Issue.incident.opened.find_by_id(issue_id)
+
+ return unless incident
+
+ close_incident(incident)
+ add_system_note(incident)
+ end
+
+ private
+
+ def user
+ @user ||= User.alert_bot
+ end
+
+ def close_incident(incident)
+ ::Issues::CloseService
+ .new(project: incident.project, current_user: user)
+ .execute(incident, system_note: false)
+ end
+
+ def add_system_note(incident)
+ return unless incident.reset.closed?
+
+ SystemNoteService.auto_resolve_prometheus_alert(incident, incident.project, user)
+ end
+ end
+end
diff --git a/config/feature_flags/development/git_abuse_rate_limit_feature_flag.yml b/config/feature_flags/development/git_abuse_rate_limit_feature_flag.yml
new file mode 100644
index 00000000000..e339f7927df
--- /dev/null
+++ b/config/feature_flags/development/git_abuse_rate_limit_feature_flag.yml
@@ -0,0 +1,8 @@
+---
+name: git_abuse_rate_limit_feature_flag
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87872
+rollout_issue_url:
+milestone: '15.1'
+type: development
+group: group::anti-abuse
+default_enabled: false
diff --git a/config/initializers/wikicloth_redos_patch.rb b/config/initializers/wikicloth_redos_patch.rb
index 13180180c32..a0b7c2e2466 100644
--- a/config/initializers/wikicloth_redos_patch.rb
+++ b/config/initializers/wikicloth_redos_patch.rb
@@ -2,15 +2,22 @@
require 'wikicloth'
require 'wikicloth/wiki_buffer/var'
+require 'digest/sha2'
-# Adds patch for changes in this PR: https://github.com/nricciar/wikicloth/pull/112/files
+# Adds patch for changes in these PRs:
#
-# That fix has already been merged, but the maintainers are not releasing new versions, so we
-# need to patch it here.
+# https://github.com/nricciar/wikicloth/pull/112
+# https://github.com/nricciar/wikicloth/pull/131
+#
+# The first fix has already been merged, but the second has not,
+# and the maintainers are not releasing new versions, so we
+# need to patch them here.
#
# If they ever do release a version, then we can remove this file.
#
-# See: https://gitlab.com/gitlab-org/gitlab/-/issues/334056#note_745336618
+# See:
+# - https://gitlab.com/gitlab-org/gitlab/-/issues/334056#note_745336618
+# - https://gitlab.com/gitlab-org/gitlab/-/issues/361266
# Guard to ensure we remember to delete this patch if they ever release a new version of wikicloth
raise 'New version of WikiCloth detected, please remove this patch' unless Gem::Version.new(WikiCloth::VERSION) == Gem::Version.new('0.8.1')
@@ -30,9 +37,12 @@ raise 'New version of WikiCloth detected, please remove this patch' unless Gem::
# rubocop:disable Layout/EmptyLineAfterGuardClause
# rubocop:disable Performance/ReverseEach
# rubocop:disable Style/BlockDelimiters
-# rubocop:disable Cop/LineBreakAroundConditionalBlock
# rubocop:disable Layout/MultilineBlockLayout
# rubocop:disable Layout/BlockEndNewline
+# rubocop:disable Style/PerlBackrefs
+# rubocop:disable Style/RegexpLiteralMixedPreserve
+# rubocop:disable Style/RedundantRegexpCharacterClass
+# rubocop:disable Performance/StringInclude
module WikiCloth
class WikiCloth
def render(opt={})
@@ -110,7 +120,7 @@ module WikiCloth
key = params[0].to_s.strip
key_options = params[1..].collect { |p| p.is_a?(Hash) ? { :name => p[:name].strip, :value => p[:value].strip } : p.strip }
key_options ||= []
- key_digest = Digest::MD5.hexdigest(key_options.to_a.sort {|x,y| (x.is_a?(Hash) ? x[:name] : x) <=> (y.is_a?(Hash) ? y[:name] : y) }.inspect)
+ key_digest = Digest::SHA256.hexdigest(key_options.to_a.sort {|x,y| (x.is_a?(Hash) ? x[:name] : x) <=> (y.is_a?(Hash) ? y[:name] : y) }.inspect)
return @options[:params][key] if @options[:params].has_key?(key)
# if we have a valid cache fragment use it
@@ -138,6 +148,54 @@ module WikiCloth
end
end
end
+
+ class WikiBuffer::HTMLElement < WikiBuffer
+ def to_html
+ if NO_NEED_TO_CLOSE.include?(self.element_name)
+ return "<#{self.element_name} />" if SHORT_TAGS.include?(self.element_name)
+ return "#{self.element_name}><#{self.element_name}>" if @tag_check == self.element_name
+ end
+
+ if ESCAPED_TAGS.include?(self.element_name)
+ # remove empty first line
+ self.element_content = $1 if self.element_content =~ /^\s*\n(.*)$/m
+ # escape all html inside this element
+ self.element_content = self.element_content.gsub('<','<').gsub('>','>')
+ # hack to fix nested mess
+ self.element_content = self.element_content.gsub(/<[\/]*\s*nowiki\s*>/,'')
+ end
+
+ case self.element_name
+ when "template"
+ @options[:link_handler].cache({ :name => self.element_attributes["__name"], :content => self.element_content, :sha256 => self.element_attributes["__hash"] })
+ return self.element_content
+ when "noinclude"
+ return self.in_template? ? "" : self.element_content
+ when "includeonly"
+ return self.in_template? ? self.element_content : ""
+ when "nowiki"
+ return self.element_content
+ when "a"
+ if self.element_attributes['href'] =~ /:\/\//
+ return @options[:link_handler].external_link(self.element_attributes['href'], self.element_content)
+ elsif self.element_attributes['href'].nil? || self.element_attributes['href'] =~ /^\s*([\?\/])/
+ # if a element has no href attribute, or href starts with / or ?
+ return elem.tag!(self.element_name, self.element_attributes) { |x| x << self.element_content }
+ end
+ else
+ if Extension.element_exists?(self.element_name)
+ return Extension.html_elements[self.element_name][:klass].new(@options).instance_exec( self, &Extension.html_elements[self.element_name][:block] ).to_s
+ end
+ end
+
+ tmp = elem.tag!(self.element_name, self.element_attributes) { |x| x << self.element_content }
+ unless ALLOWED_ELEMENTS.include?(self.element_name)
+ tmp.gsub!(/[\-!\|&"\{\}\[\]]/) { |r| self.escape_char(r) }
+ return tmp.gsub('<', '<').gsub('>', '>')
+ end
+ tmp
+ end
+ end
end
# rubocop:enable Style/ClassAndModuleChildren
# rubocop:enable Layout/SpaceAroundEqualsInParameterDefault
@@ -154,6 +212,9 @@ end
# rubocop:enable Layout/EmptyLineAfterGuardClause
# rubocop:enable Performance/ReverseEach
# rubocop:enable Style/BlockDelimiters
-# rubocop:enable Cop/LineBreakAroundConditionalBlock
# rubocop:enable Layout/MultilineBlockLayout
# rubocop:enable Layout/BlockEndNewline
+# rubocop:enable Style/PerlBackrefs
+# rubocop:enable Style/RegexpLiteralMixedPreserve
+# rubocop:enable Style/RedundantRegexpCharacterClass
+# rubocop:enable Performance/StringInclude
diff --git a/config/metrics/counts_28d/20210216181002_projects_with_tracing_enabled.yml b/config/metrics/counts_28d/20210216181002_projects_with_tracing_enabled.yml
index 60b1ca2b765..b40afeabe12 100644
--- a/config/metrics/counts_28d/20210216181002_projects_with_tracing_enabled.yml
+++ b/config/metrics/counts_28d/20210216181002_projects_with_tracing_enabled.yml
@@ -7,7 +7,7 @@ product_stage: monitor
product_group: group::monitor
product_category: tracing
value_type: number
-status: active
+status: removed
time_frame: 28d
data_source: database
distribution:
@@ -19,3 +19,5 @@ tier:
- ultimate
performance_indicator_type: []
milestone: "<13.9"
+milestone_removed: "15.2"
+removed_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90607"
diff --git a/config/metrics/counts_all/20210216180929_projects_with_tracing_enabled.yml b/config/metrics/counts_all/20210216180929_projects_with_tracing_enabled.yml
index 87668ca0e4f..d2957891769 100644
--- a/config/metrics/counts_all/20210216180929_projects_with_tracing_enabled.yml
+++ b/config/metrics/counts_all/20210216180929_projects_with_tracing_enabled.yml
@@ -7,7 +7,7 @@ product_stage: monitor
product_group: group::monitor
product_category: tracing
value_type: number
-status: active
+status: removed
time_frame: all
data_source: database
distribution:
@@ -19,3 +19,5 @@ tier:
- ultimate
performance_indicator_type: []
milestone: "<13.9"
+milestone_removed: "15.2"
+removed_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90607"
diff --git a/config/metrics/counts_all/20210216180951_projects_with_tracing_enabled.yml b/config/metrics/counts_all/20210216180951_projects_with_tracing_enabled.yml
index 3532dc60ff0..cd972cc5b54 100644
--- a/config/metrics/counts_all/20210216180951_projects_with_tracing_enabled.yml
+++ b/config/metrics/counts_all/20210216180951_projects_with_tracing_enabled.yml
@@ -7,7 +7,7 @@ product_stage: monitor
product_group: group::monitor
product_category: tracing
value_type: number
-status: active
+status: removed
time_frame: all
data_source: database
distribution:
@@ -18,3 +18,5 @@ tier:
- premium
- ultimate
milestone: "<13.9"
+milestone_removed: "15.2"
+removed_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90607"
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index 2838f0a8436..9989019a70d 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -221,6 +221,8 @@
- 2
- - incident_management_apply_incident_sla_exceeded_label
- 1
+- - incident_management_close_incident
+ - 1
- - incident_management_oncall_rotations_persist_shifts_job
- 1
- - incident_management_pending_escalations_alert_check
diff --git a/db/migrate/20220608074738_add_max_repository_downloads_limit_to_application_settings.rb b/db/migrate/20220608074738_add_max_repository_downloads_limit_to_application_settings.rb
new file mode 100644
index 00000000000..9252262c26f
--- /dev/null
+++ b/db/migrate/20220608074738_add_max_repository_downloads_limit_to_application_settings.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddMaxRepositoryDownloadsLimitToApplicationSettings < Gitlab::Database::Migration[2.0]
+ def change
+ add_column :application_settings, :max_number_of_repository_downloads,
+ :smallint,
+ default: 0,
+ null: false
+
+ add_column :application_settings, :max_number_of_repository_downloads_within_time_period,
+ :integer,
+ default: 0,
+ null: false
+ end
+end
diff --git a/db/schema_migrations/20220608074738 b/db/schema_migrations/20220608074738
new file mode 100644
index 00000000000..035979d8f04
--- /dev/null
+++ b/db/schema_migrations/20220608074738
@@ -0,0 +1 @@
+0bf44279d1fd78a8df1ec2898b6170e587fb2dd5d692b9c31648aa19dffa5fe8
\ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index a4aeae58dc5..38650f7a773 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -11321,6 +11321,8 @@ CREATE TABLE application_settings (
container_registry_pre_import_tags_rate numeric(6,2) DEFAULT 0.5 NOT NULL,
license_usage_data_exported boolean DEFAULT false NOT NULL,
phone_verification_code_enabled boolean DEFAULT false NOT NULL,
+ max_number_of_repository_downloads smallint DEFAULT 0 NOT NULL,
+ max_number_of_repository_downloads_within_time_period integer DEFAULT 0 NOT NULL,
CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)),
CONSTRAINT app_settings_container_registry_pre_import_tags_rate_positive CHECK ((container_registry_pre_import_tags_rate >= (0)::numeric)),
CONSTRAINT app_settings_dep_proxy_ttl_policies_worker_capacity_positive CHECK ((dependency_proxy_ttl_group_policy_worker_capacity >= 0)),
diff --git a/doc/administration/geo/replication/configuration.md b/doc/administration/geo/replication/configuration.md
index 043b96478c9..7666a450648 100644
--- a/doc/administration/geo/replication/configuration.md
+++ b/doc/administration/geo/replication/configuration.md
@@ -12,7 +12,9 @@ type: howto
NOTE:
This is the final step in setting up a **secondary** Geo site. Stages of the
setup process must be completed in the documented order.
-Before attempting the steps in this stage, [complete all prior stages](../setup/index.md#using-omnibus-gitlab).
+If not, [complete all prior stages](../setup/index.md#using-omnibus-gitlab) before procceed.
+
+Make sure you [set up the database replication](../setup/database.md), and [configured fast lookup of authorized SSH keys](../../operations/fast_ssh_key_lookup.md) in **both primary and secondary sites**.
The basic steps of configuring a **secondary** site are to:
@@ -318,7 +320,7 @@ the **primary** site. After you sign in:
1. Verify that it's correctly identified as a **secondary** Geo site, and that
Geo is enabled.
-The initial replication, or 'backfill', is probably still in progress. You
+The initial replication may take some time. The status of the site or the ‘backfill’ may still in progress. You
can monitor the synchronization process on each Geo site from the **primary**
site's **Geo Sites** dashboard in your browser.
diff --git a/doc/administration/geo/setup/database.md b/doc/administration/geo/setup/database.md
index 89199585c94..c0ed7829fce 100644
--- a/doc/administration/geo/setup/database.md
+++ b/doc/administration/geo/setup/database.md
@@ -17,8 +17,11 @@ PostgreSQL instances, the Omnibus roles cannot perform all necessary
configuration steps. In this case, use the [Geo with external PostgreSQL instances](external_database.md)
process instead.
+NOTE:
The stages of the setup process must be completed in the documented order.
-Before you attempt the steps in this stage, [complete all prior stages](../setup/index.md#using-omnibus-gitlab).
+If not, [complete all prior stages](../setup/index.md#using-omnibus-gitlab) before proceeding.
+
+Ensure the **secondary** site is running the same version of GitLab Enterprise Edition as the **primary** site. Confirm you have added the [premium or higher licenses](https://about.gitlab.com/pricing/) to your **primary** site.
Be sure to read and review all of these steps before you execute them in your
testing or production environments.
diff --git a/doc/administration/geo/setup/index.md b/doc/administration/geo/setup/index.md
index f4c21293782..4a3f0f41a83 100644
--- a/doc/administration/geo/setup/index.md
+++ b/doc/administration/geo/setup/index.md
@@ -24,9 +24,10 @@ If you installed GitLab using the Omnibus packages (highly recommended):
1. [Set up the database replication](database.md) (`primary (read-write) <-> secondary (read-only)` topology).
1. [Configure fast lookup of authorized SSH keys in the database](../../operations/fast_ssh_key_lookup.md). This step is required and needs to be done on **both** the **primary** and **secondary** sites.
1. [Configure GitLab](../replication/configuration.md) to set the **primary** and **secondary** sites.
+1. Optional: [Configure Object storage](../../object_storage.md)
1. Optional: [Configure a secondary LDAP server](../../auth/ldap/index.md) for the **secondary** sites. See [notes on LDAP](../index.md#ldap).
+1. Optional: [Configure Geo secondary proxying](../secondary_proxy/index.md) to use a single, unified URL for all Geo sites. This step is recommended to accelerate most read requests while transparently proxying writes to the primary Geo site.
1. Follow the [Using a Geo Site](../replication/usage.md) guide.
-1. [Configure Geo secondary proxying](../secondary_proxy/index.md) to use a single, unified URL for all Geo sites. This step is recommended to accelerate most read requests while transparently proxying writes to the primary Geo site.
## Post-installation documentation
diff --git a/doc/api/settings.md b/doc/api/settings.md
index 805797792de..2fda2555e32 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -379,6 +379,8 @@ listed in the descriptions of the relevant settings.
| `max_personal_access_token_lifetime` **(ULTIMATE SELF)** | integer | no | Maximum allowable lifetime for access tokens in days. |
| `max_ssh_key_lifetime` **(ULTIMATE SELF)** | integer | no | Maximum allowable lifetime for SSH keys in days. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1007) in GitLab 14.6. |
| `metrics_method_call_threshold` | integer | no | A method call is only tracked when it takes longer than the given amount of milliseconds. |
+| `max_number_of_repository_downloads` **(ULTIMATE SELF)** | integer | no | Maximum number of unique repositories a user can download in the specified time period before they are banned. Default: 0, Maximum: 10,000 repositories. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87980) in GitLab 15.1. |
+| `max_number_of_repository_downloads_within_time_period` **(ULTIMATE SELF)** | integer | no | Reporting time period (in seconds). Default: 0, Maximum: 864000 seconds (10 days). [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87980) in GitLab 15.1. |
| `mirror_available` | boolean | no | Allow repository mirroring to configured by project Maintainers. If disabled, only Administrators can configure repository mirroring. |
| `mirror_capacity_threshold` **(PREMIUM)** | integer | no | Minimum capacity to be available before scheduling more mirrors preemptively. |
| `mirror_max_capacity` **(PREMIUM)** | integer | no | Maximum number of mirrors that can be synchronizing at the same time. |
diff --git a/doc/ci/examples/index.md b/doc/ci/examples/index.md
index 816514c4230..77591ad2ca6 100644
--- a/doc/ci/examples/index.md
+++ b/doc/ci/examples/index.md
@@ -28,7 +28,7 @@ The following table lists examples with step-by-step tutorials that are containe
| Deployment with Dpl | [Using `dpl` as deployment tool](deployment/index.md). |
| GitLab Pages | See the [GitLab Pages](../../user/project/pages/index.md) documentation for a complete example of deploying a static site. |
| End-to-end testing | [End-to-end testing with GitLab CI/CD and WebdriverIO](end_to_end_testing_webdriverio/index.md). |
-| Load performance testing | [Load Performance Testing with the k6 container](../../user/project/merge_requests/load_performance_testing.md). |
+| Load performance testing | [Load Performance Testing with the k6 container](../testing/load_performance_testing.md). |
| Multi project pipeline | [Build, test deploy using multi project pipeline](https://gitlab.com/gitlab-examples/upstream-project). |
| npm with semantic-release | [Publish npm packages to the GitLab Package Registry using semantic-release](semantic-release.md). |
| PHP with Laravel, Envoy | [Test and deploy Laravel applications with GitLab CI/CD and Envoy](laravel_with_gitlab_and_envoy/index.md). |
diff --git a/doc/ci/index.md b/doc/ci/index.md
index 6dee0943bdd..80752830b85 100644
--- a/doc/ci/index.md
+++ b/doc/ci/index.md
@@ -84,7 +84,7 @@ GitLab CI/CD features, grouped by DevOps stage, include:
| [Connect to cloud services](cloud_services/index.md) | Connect to cloud providers using OpenID Connect (OIDC) to retrieve temporary credentials to access services or secrets. |
| **Verify** | |
| [Browser Performance Testing](testing/browser_performance_testing.md) | Quickly determine the browser performance impact of pending code changes. |
-| [Load Performance Testing](../user/project/merge_requests/load_performance_testing.md) | Quickly determine the server performance impact of pending code changes. |
+| [Load Performance Testing](testing/load_performance_testing.md) | Quickly determine the server performance impact of pending code changes. |
| [CI services](services/index.md) | Link Docker containers with your base image. |
| [GitLab CI/CD for external repositories](ci_cd_for_external_repos/index.md) | Get the benefits of GitLab CI/CD combined with repositories in GitHub and Bitbucket Cloud. |
| [Interactive Web Terminals](interactive_web_terminal/index.md) | Open an interactive web terminal to debug the running jobs. |
diff --git a/doc/ci/metrics_reports.md b/doc/ci/metrics_reports.md
index 6141c8628e1..c3ab3392f36 100644
--- a/doc/ci/metrics_reports.md
+++ b/doc/ci/metrics_reports.md
@@ -1,68 +1,11 @@
---
-stage: Verify
-group: Pipeline Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: 'testing/metrics_reports.md'
+remove_date: '2022-08-31'
---
-# Metrics Reports **(PREMIUM)**
+This document was moved to [another location](testing/metrics_reports.md).
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9788) in GitLab 11.10. Requires GitLab Runner 11.10 and above.
-
-GitLab provides a lot of great reporting tools for things like [merge requests](../user/project/merge_requests/index.md) - [Unit test reports](testing/unit_test_reports.md), [code quality](testing/code_quality.md), and performance tests. While JUnit is a great open framework for tests that "pass" or "fail", it is also important to see other types of metrics from a given change.
-
-You can configure your job to use custom Metrics Reports, and GitLab displays a report on the merge request so that it's easier and faster to identify changes without having to check the entire log.
-
-![Metrics Reports](img/metrics_reports_v13_0.png)
-
-## Use cases
-
-Consider the following examples of data that can use Metrics Reports:
-
-1. Memory usage
-1. Load testing results
-1. Code complexity
-1. Code coverage stats
-
-## How it works
-
-Metrics for a branch are read from the latest metrics report artifact (default filename: `metrics.txt`) as string values.
-
-For an MR, the values of these metrics from the feature branch are compared to the values from the target branch. Then they are displayed in the MR widget in this order:
-
-- Existing metrics with changed values.
-- Metrics that have been added by the MR. Marked with a **New** badge.
-- Metrics that have been removed by the MR. Marked with a **Removed** badge.
-- Existing metrics with unchanged values.
-
-## How to set it up
-
-Add a job that creates a [metrics report](yaml/artifacts_reports.md#artifactsreportsmetrics) (default filename: `metrics.txt`). The file should conform to the [OpenMetrics](https://openmetrics.io/) format.
-
-For example:
-
-```yaml
-metrics:
- script:
- - echo 'metric_name metric_value' > metrics.txt
- artifacts:
- reports:
- metrics: metrics.txt
-```
-
-## Advanced Example
-
-An advanced example of an OpenMetrics text file (from the [Prometheus documentation](https://github.com/prometheus/docs/blob/master/content/docs/instrumenting/exposition_formats.md#text-format-example))
-renders in the merge request widget as:
-
-![Metrics Reports Advanced](img/metrics_reports_advanced_v13_0.png)
-
-## Troubleshooting
-
-### Metrics reports did not change
-
-You can see `Metrics reports did not change` when trying to view metrics reports in merge requests. Reasons for this are:
-
-- The target branch for the merge request doesn't have a baseline metrics report for comparison.
-- You don't have GitLab license at the Premium tier or above.
-
-There is [an issue open](https://gitlab.com/gitlab-org/gitlab/-/issues/343065) to improve this message.
+
+
+
+
diff --git a/doc/ci/pipelines/cicd_minutes.md b/doc/ci/pipelines/cicd_minutes.md
index 96568886e7e..1e862c87035 100644
--- a/doc/ci/pipelines/cicd_minutes.md
+++ b/doc/ci/pipelines/cicd_minutes.md
@@ -7,22 +7,33 @@ type: reference
# CI/CD minutes quota **(PREMIUM)**
-[Shared runners](../runners/runners_scope.md#shared-runners) are shared with every project and group in a GitLab instance.
-When jobs run on shared runners, CI/CD minutes are used.
+Administrators can limit the amount of time that projects can use to run jobs on
+[shared runners](../runners/runners_scope.md#shared-runners) each month. This limit
+is tracked with a quota of CI/CD minutes.
-You can set limits on the number of CI/CD minutes that are used each month.
+By default, one minute of execution time by a single job uses
+one CI/CD minute. The total amount of CI/CD minutes used by a pipeline is
+[the sum of all its jobs' durations](#how-cicd-minute-usage-is-calculated).
+Jobs can run concurrently, so the total CI/CD minute usage can be higher than the
+end-to-end duration of a pipeline.
-- On GitLab.com, the quota of CI/CD minutes is set for each [namespace](../../user/group/index.md#namespaces),
- and is determined by [your license tier](https://about.gitlab.com/pricing/).
-- On self-managed GitLab instances, the quota of CI/CD minutes for each namespace is set by administrators.
+On GitLab.com:
-In addition to the monthly quota, you can add more CI/CD minutes when needed.
+- CI/CD minutes quotas are enabled for both public and private projects, but public
+ projects [consume CI/CD minutes at a slower rate](#cost-factor).
+- The base monthly CI/CD minutes quota for a GitLab.com [namespace](../../user/group/index.md#namespaces)
+ is determined by its [license tier](https://about.gitlab.com/pricing/).
+- You can [purchase additional CI/CD minutes](#purchase-additional-cicd-minutes)
+ if you need more than the number of CI/CD minutes in your monthly quota.
-- On GitLab.com, you can [purchase additional CI/CD minutes](#purchase-additional-cicd-minutes).
-- On self-managed GitLab instances, administrators can [assign more CI/CD minutes](#set-the-quota-of-cicd-minutes-for-a-specific-namespace).
+On self-managed GitLab instances:
-[Specific runners](../runners/runners_scope.md#specific-runners)
-are not subject to a quota of CI/CD minutes.
+- CI/CD minutes quotas are disabled by default.
+- When enabled, CI/CD minutes quotas apply to private projects only.
+- Administrators can [assign more CI/CD minutes](#set-the-quota-of-cicd-minutes-for-a-specific-namespace)
+ if a namespace uses all the CI/CD minutes in its monthly quota.
+
+[Specific runners](../runners/runners_scope.md#specific-runners) are not subject to a quota of CI/CD minutes.
## Set the quota of CI/CD minutes for all namespaces
@@ -160,47 +171,44 @@ To purchase additional minutes for your personal namespace:
After your payment is processed, the additional CI/CD minutes are added to your personal
namespace.
-## How CI/CD minutes are calculated
+## How CI/CD minute usage is calculated
-CI/CD minutes for individual jobs are calculated based on:
-
-- The duration the job runs.
-- The visibility of the projects where the job runs.
-
-GitLab uses this formula to calculate CI/CD minutes consumed by a job:
+GitLab uses this formula to calculate the CI/CD minute usage of a job:
```plaintext
Job duration * Cost factor
```
-- **Job duration**: The time, in seconds, that a job took to run on a shared runner.
- It does not include time spent in `created` or `pending` status.
-- **Cost factor**: A number based on project visibility.
+- **Job duration**: The time, in seconds, that a job took to run on a shared runner,
+ not including time spent in the `created` or `pending` statuses.
+- [**Cost factor**](#cost-factor): A number based on project visibility.
-The number is transformed into minutes and added to the overall quota in the job's top-level namespace.
+The value is transformed into minutes and added to the count of used CI/CD minutes
+in the job's top-level namespace.
-For example:
+For example, if a user `alice` runs a pipeline:
-- A user, `alice`, runs a pipeline under the `gitlab-org` namespace.
-- The CI/CD minutes consumed by each job in the pipeline are added to the
- overall consumption for the `gitlab-org` namespace, not the `alice` namespace.
-- If a pipeline runs for one of the personal projects for `alice`, the CI/CD minutes
- are added to the overall consumption for the `alice` namespace.
+- Under the `gitlab-org` namespace, the CI/CD minutes used by each job in the pipeline are
+ added to the overall consumption for the `gitlab-org` namespace, not the `alice` namespace.
+- For one of the personal projects in their namespace, the CI/CD minutes are added
+ to the overall consumption for the `alice` namespace.
The CI/CD minutes used by one pipeline is the total CI/CD minutes used by all the jobs
-that ran in the pipeline. The CI/CD minute usage for a pipeline can be higher than
-the duration of the pipeline if many jobs ran at the same time.
+that ran in the pipeline. Jobs can run concurrently, so the total CI/CD minutes usage
+can be higher than the end-to-end duration of a pipeline.
### Cost factor
-The cost factor for a job running on a shared runner is:
+The cost factors for jobs running on shared runners on GitLab.com are:
-- `0.008` for public projects on GitLab SaaS.
- (For every 125 minutes of job time, you accrue 1 CI/CD minute.)
-- `0.008` for projects members of GitLab [Open Source program](../../subscriptions/index.md#gitlab-for-open-source).
- (For every 125 minutes of job time, you accrue 1 CI/CD minute.)
-- `0` for public projects on GitLab self-managed instances.
-- `1` for internal or private projects.
+- `0.008` for public projects, and projects in the [GitLab for Open Source program](../../subscriptions/index.md#gitlab-for-open-source).
+ For every 125 minutes of job execution time, you use 1 CI/CD minute.
+- `1` for internal and private projects.
+
+The cost factors on self-managed instances are:
+
+- `0` for public projects, so they do not consume CI/CD minutes.
+- `1` for internal and private projects.
### Additional costs on GitLab SaaS
diff --git a/doc/ci/pipelines/pipeline_artifacts.md b/doc/ci/pipelines/pipeline_artifacts.md
index 3a1367f4a8c..07e1c8a6d99 100644
--- a/doc/ci/pipelines/pipeline_artifacts.md
+++ b/doc/ci/pipelines/pipeline_artifacts.md
@@ -10,7 +10,7 @@ Pipeline artifacts are files created by GitLab after a pipeline finishes. Pipeli
different to [job artifacts](job_artifacts.md) because they are not explicitly managed by
`.gitlab-ci.yml` definitions.
-Pipeline artifacts are used by the [test coverage visualization feature](../../user/project/merge_requests/test_coverage_visualization.md)
+Pipeline artifacts are used by the [test coverage visualization feature](../testing/test_coverage_visualization.md)
to collect coverage information.
## Storage
diff --git a/doc/ci/pipelines/pipeline_efficiency.md b/doc/ci/pipelines/pipeline_efficiency.md
index 91cf2ebd5c1..ad43895d7ef 100644
--- a/doc/ci/pipelines/pipeline_efficiency.md
+++ b/doc/ci/pipelines/pipeline_efficiency.md
@@ -174,7 +174,7 @@ to stop them from running:
Ensure that errors are detected early in the CI/CD pipeline. A job that takes a very long
time to complete keeps a pipeline from returning a failed status until the job completes.
-Design pipelines so that jobs that can [fail fast](../../user/project/merge_requests/fail_fast_testing.md)
+Design pipelines so that jobs that can [fail fast](../testing/fail_fast_testing.md)
run earlier. For example, add an early stage and move the syntax, style linting,
Git commit message verification, and similar jobs in there.
diff --git a/doc/ci/testing/fail_fast_testing.md b/doc/ci/testing/fail_fast_testing.md
new file mode 100644
index 00000000000..7b95b1ac54a
--- /dev/null
+++ b/doc/ci/testing/fail_fast_testing.md
@@ -0,0 +1,97 @@
+---
+stage: Verify
+group: Pipeline Insights
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Fail Fast Testing **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/198550) in GitLab 13.1.
+
+For applications that use RSpec for running tests, we've introduced the `Verify/Failfast`
+[template to run subsets of your test suite](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Verify/FailFast.gitlab-ci.yml),
+based on the changes in your merge request.
+
+The template uses the [test_file_finder (`tff`) gem](https://gitlab.com/gitlab-org/ci-cd/test_file_finder/)
+that accepts a list of files as input, and returns a list of spec (test) files
+that it believes to be relevant to the input files.
+
+`tff` is designed for Ruby on Rails projects, so the `Verify/FailFast` template is
+configured to run when changes to Ruby files are detected. By default, it runs in
+the [`.pre` stage](../yaml/index.md#stage-pre) of a GitLab CI/CD pipeline,
+before all other stages.
+
+## Example use case
+
+Fail fast testing is useful when adding new functionality to a project and adding
+new automated tests.
+
+Your project could have hundreds of thousands of tests that take a long time to complete.
+You may be confident that a new test will pass, but you have to wait for all the tests
+to complete to verify it. This could take an hour or more, even when using parallelization.
+
+Fail fast testing gives you a faster feedback loop from the pipeline. It lets you
+know quickly that the new tests are passing and the new functionality did not break
+other tests.
+
+## Requirements
+
+This template requires:
+
+- A project built in Rails that uses RSpec for testing.
+- CI/CD configured to:
+ - Use a Docker image with Ruby available.
+ - Use [Merge request pipelines](../pipelines/merge_request_pipelines.md#prerequisites)
+- [Merged results pipelines](../pipelines/merged_results_pipelines.md#enable-merged-results-pipelines)
+ enabled in the project settings.
+- A Docker image with Ruby available. The template uses `image: ruby:2.6` by default, but you [can override](../yaml/includes.md#override-included-configuration-values) this.
+
+## Configuring Fast RSpec Failure
+
+We use the following plain RSpec configuration as a starting point. It installs all the
+project gems and executes `rspec`, on merge request pipelines only.
+
+```yaml
+rspec-complete:
+ stage: test
+ rules:
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+ script:
+ - bundle install
+ - bundle exec rspec
+```
+
+To run the most relevant specs first instead of the whole suite, [`include`](../yaml/index.md#include)
+the template by adding the following to your CI/CD configuration:
+
+```yaml
+include:
+ - template: Verify/FailFast.gitlab-ci.yml
+```
+
+To customize the job, specific options may be set to override the template. For example, to override the default Docker image:
+
+```yaml
+include:
+ - template: Verify/FailFast.gitlab-ci.yml
+
+rspec-rails-modified-path-specs:
+ image: custom-docker-image-with-ruby
+```
+
+### Example test loads
+
+For illustrative purposes, let's say our Rails app spec suite consists of 100 specs per model for ten models.
+
+If no Ruby files are changed:
+
+- `rspec-rails-modified-paths-specs` does not run any tests.
+- `rspec-complete` runs the full suite of 1000 tests.
+
+If one Ruby model is changed, for example `app/models/example.rb`, then `rspec-rails-modified-paths-specs`
+runs the 100 tests for `example.rb`:
+
+- If all of these 100 tests pass, then the full `rspec-complete` suite of 1000 tests is allowed to run.
+- If any of these 100 tests fail, they fail quickly, and `rspec-complete` does not run any tests.
+
+The final case saves resources and time as the full 1000 test suite does not run.
diff --git a/doc/user/project/merge_requests/img/load_performance_testing.png b/doc/ci/testing/img/load_performance_testing.png
similarity index 100%
rename from doc/user/project/merge_requests/img/load_performance_testing.png
rename to doc/ci/testing/img/load_performance_testing.png
diff --git a/doc/ci/img/metrics_reports_advanced_v13_0.png b/doc/ci/testing/img/metrics_reports_advanced_v13_0.png
similarity index 100%
rename from doc/ci/img/metrics_reports_advanced_v13_0.png
rename to doc/ci/testing/img/metrics_reports_advanced_v13_0.png
diff --git a/doc/ci/img/metrics_reports_v13_0.png b/doc/ci/testing/img/metrics_reports_v13_0.png
similarity index 100%
rename from doc/ci/img/metrics_reports_v13_0.png
rename to doc/ci/testing/img/metrics_reports_v13_0.png
diff --git a/doc/user/project/merge_requests/img/test_coverage_visualization_v12_9.png b/doc/ci/testing/img/test_coverage_visualization_v12_9.png
similarity index 100%
rename from doc/user/project/merge_requests/img/test_coverage_visualization_v12_9.png
rename to doc/ci/testing/img/test_coverage_visualization_v12_9.png
diff --git a/doc/ci/testing/index.md b/doc/ci/testing/index.md
index 807de0b51e6..a8f06ec695c 100644
--- a/doc/ci/testing/index.md
+++ b/doc/ci/testing/index.md
@@ -9,18 +9,18 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Use GitLab CI/CD to test the changes included in a feature branch. You can also
display reports or link to important information directly from [merge requests](../../user/project/merge_requests/index.md).
-| Feature | Description |
-|-------------------------------------------------------------------------------------------------|-------------|
-| [Accessibility Testing](accessibility_testing.md) | Automatically report A11y violations for changed pages in merge requests. |
-| [Browser Performance Testing](browser_performance_testing.md) | Quickly determine the browser performance impact of pending code changes. |
-| [Load Performance Testing](../../user/project/merge_requests/load_performance_testing.md) | Quickly determine the server performance impact of pending code changes. |
-| [Code Quality](code_quality.md) | Analyze your source code quality using the [Code Climate](https://codeclimate.com/) analyzer and show the Code Climate report right in the merge request widget area. |
-| [Display arbitrary job artifacts](../yaml/index.md#artifactsexpose_as) | Configure CI pipelines with the `artifacts:expose_as` parameter to directly link to selected [artifacts](../pipelines/job_artifacts.md) in merge requests. |
-| [Unit test reports](unit_test_reports.md) | Configure your CI jobs to use Unit test reports, and let GitLab display a report on the merge request so that it's easier and faster to identify the failure without having to check the entire job log. |
-| [License Compliance](../../user/compliance/license_compliance/index.md) | Manage the licenses of your dependencies. |
-| [Metrics Reports](../metrics_reports.md) | Display the Metrics Report on the merge request so that it's fast and easier to identify changes to important metrics. |
-| [Test Coverage visualization](../../user/project/merge_requests/test_coverage_visualization.md) | See test coverage results for merge requests, in the file diff. |
-| [Fail fast testing](../../user/project/merge_requests/fail_fast_testing.md#fail-fast-testing) | Run a subset of your RSpec test suite, so failed tests stop the pipeline before the full suite of tests run, saving resources. |
+| Feature | Description |
+|-------------------------------------------------------------------------|-------------|
+| [Accessibility Testing](accessibility_testing.md) | Automatically report A11y violations for changed pages in merge requests. |
+| [Browser Performance Testing](browser_performance_testing.md) | Quickly determine the browser performance impact of pending code changes. |
+| [Load Performance Testing](load_performance_testing.md) | Quickly determine the server performance impact of pending code changes. |
+| [Code Quality](code_quality.md) | Analyze your source code quality using the [Code Climate](https://codeclimate.com/) analyzer and show the Code Climate report right in the merge request widget area. |
+| [Display arbitrary job artifacts](../yaml/index.md#artifactsexpose_as) | Configure CI pipelines with the `artifacts:expose_as` parameter to directly link to selected [artifacts](../pipelines/job_artifacts.md) in merge requests. |
+| [Unit test reports](unit_test_reports.md) | Configure your CI jobs to use Unit test reports, and let GitLab display a report on the merge request so that it's easier and faster to identify the failure without having to check the entire job log. |
+| [License Compliance](../../user/compliance/license_compliance/index.md) | Manage the licenses of your dependencies. |
+| [Metrics Reports](metrics_reports.md) | Display the Metrics Report on the merge request so that it's fast and easier to identify changes to important metrics. |
+| [Test Coverage visualization](test_coverage_visualization.md) | See test coverage results for merge requests, in the file diff. |
+| [Fail fast testing](fail_fast_testing.md) | Run a subset of your RSpec test suite, so failed tests stop the pipeline before the full suite of tests run, saving resources. |
## Security Reports **(ULTIMATE)**
diff --git a/doc/ci/testing/load_performance_testing.md b/doc/ci/testing/load_performance_testing.md
new file mode 100644
index 00000000000..ae177958beb
--- /dev/null
+++ b/doc/ci/testing/load_performance_testing.md
@@ -0,0 +1,201 @@
+---
+stage: Verify
+group: Pipeline Insights
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Load Performance Testing **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10683) in GitLab 13.2.
+
+With Load Performance Testing, you can test the impact of any pending code changes
+to your application's backend in [GitLab CI/CD](../index.md).
+
+GitLab uses [k6](https://k6.io/), a free and open source
+tool, for measuring the system performance of applications under
+load.
+
+Unlike [Browser Performance Testing](browser_performance_testing.md), which is
+used to measure how web sites perform in client browsers, Load Performance Testing
+can be used to perform various types of [load tests](https://k6.io/docs/#use-cases)
+against application endpoints such as APIs, Web Controllers, and so on.
+This can be used to test how the backend or the server performs at scale.
+
+For example, you can use Load Performance Testing to perform many concurrent
+GET calls to a popular API endpoint in your application to see how it performs.
+
+## How Load Performance Testing works
+
+First, define a job in your `.gitlab-ci.yml` file that generates the
+[Load Performance report artifact](../yaml/artifacts_reports.md#artifactsreportsload_performance).
+GitLab checks this report, compares key load performance metrics
+between the source and target branches, and then shows the information in a merge request widget:
+
+![Load Performance Widget](img/load_performance_testing.png)
+
+Next, you need to configure the test environment and write the k6 test.
+
+The key performance metrics that the merge request widget shows after the test completes are:
+
+- Checks: The percentage pass rate of the [checks](https://k6.io/docs/using-k6/checks) configured in the k6 test.
+- TTFB P90: The 90th percentile of how long it took to start receiving responses, aka the [Time to First Byte](https://en.wikipedia.org/wiki/Time_to_first_byte) (TTFB).
+- TTFB P95: The 95th percentile for TTFB.
+- RPS: The average requests per second (RPS) rate the test was able to achieve.
+
+NOTE:
+If the Load Performance report has no data to compare, such as when you add the
+Load Performance job in your `.gitlab-ci.yml` for the very first time,
+the Load Performance report widget doesn't display. It must have run at least
+once on the target branch (`main`, for example), before it displays in a
+merge request targeting that branch.
+
+## Configure the Load Performance Testing job
+
+Configuring your Load Performance Testing job can be broken down into several distinct parts:
+
+- Determine the test parameters such as throughput, and so on.
+- Set up the target test environment for load performance testing.
+- Design and write the k6 test.
+
+### Determine the test parameters
+
+The first thing you need to do is determine the [type of load test](https://k6.io/docs/test-types/introduction)
+you want to run, and how it will run (for example, the number of users, throughput, and so on).
+
+Refer to the [k6 docs](https://k6.io/docs/), especially the [k6 testing guides](https://k6.io/docs/testing-guides),
+for guidance on the above and more.
+
+### Test Environment setup
+
+A large part of the effort around load performance testing is to prepare the target test environment
+for high loads. You should ensure it's able to handle the
+[throughput](https://k6.io/blog/monthly-visits-concurrent-users) it will be tested with.
+
+It's also typically required to have representative test data in the target environment
+for the load performance test to use.
+
+We strongly recommend [not running these tests against a production environment](https://k6.io/our-beliefs#load-test-in-a-pre-production-environment).
+
+### Write the load performance test
+
+After the environment is prepared, you can write the k6 test itself. k6 is a flexible
+tool and can be used to run [many kinds of performance tests](https://k6.io/docs/test-types/introduction).
+Refer to the [k6 documentation](https://k6.io/docs/) for detailed information on how to write tests.
+
+### Configure the test in GitLab CI/CD
+
+When your k6 test is ready, the next step is to configure the load performance
+testing job in GitLab CI/CD. The easiest way to do this is to use the
+[`Verify/Load-Performance-Testing.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Verify/Load-Performance-Testing.gitlab-ci.yml)
+template that is included with GitLab.
+
+NOTE:
+For large scale k6 tests you need to ensure the GitLab Runner instance performing the actual
+test is able to handle running the test. Refer to [k6's guidance](https://k6.io/docs/testing-guides/running-large-tests#hardware-considerations)
+for spec details. The [default shared GitLab.com runners](../runners/saas/linux_saas_runner.md)
+likely have insufficient specs to handle most large k6 tests.
+
+This template runs the
+[k6 Docker container](https://hub.docker.com/r/loadimpact/k6/) in the job and provides several ways to customize the
+job.
+
+An example configuration workflow:
+
+1. Set up GitLab Runner to run Docker containers, like the
+ [Docker-in-Docker workflow](../docker/using_docker_build.md#use-docker-in-docker).
+1. Configure the default Load Performance Testing CI/CD job in your `.gitlab-ci.yml` file.
+ You need to include the template and configure it with CI/CD variables:
+
+ ```yaml
+ include:
+ template: Verify/Load-Performance-Testing.gitlab-ci.yml
+
+ load_performance:
+ variables:
+ K6_TEST_FILE:
+ ```
+
+The above example creates a `load_performance` job in your CI/CD pipeline that runs
+the k6 test.
+
+NOTE:
+For Kubernetes setups a different template should be used: [`Jobs/Load-Performance-Testing.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Load-Performance-Testing.gitlab-ci.yml).
+
+k6 has [various options](https://k6.io/docs/using-k6/options) to configure how it will run tests, such as what throughput (RPS) to run with,
+how long the test should run, and so on. Almost all options can be configured in the test itself, but as
+you can also pass command line options via the `K6_OPTIONS` variable.
+
+For example, you can override the duration of the test with a CLI option:
+
+```yaml
+ include:
+ template: Verify/Load-Performance-Testing.gitlab-ci.yml
+
+ load_performance:
+ variables:
+ K6_TEST_FILE:
+ K6_OPTIONS: '--duration 30s'
+```
+
+GitLab only displays the key performance metrics in the MR widget if k6's results are saved
+via [summary export](https://k6.io/docs/results-visualization/json#summary-export)
+as a [Load Performance report artifact](../yaml/artifacts_reports.md#artifactsreportsload_performance).
+The latest Load Performance artifact available is always used, using the
+summary values from the test.
+
+If [GitLab Pages](../../user/project/pages/index.md) is enabled, you can view the report directly in your browser.
+
+### Load Performance testing in Review Apps
+
+The CI/CD YAML configuration example above works for testing against static environments,
+but it can be extended to work with [review apps](../review_apps/index.md) or
+[dynamic environments](../environments/index.md) with a few extra steps.
+
+The best approach is to capture the dynamic URL in a [`.env` file](https://docs.docker.com/compose/env-file/)
+as a job artifact to be shared, then use a custom CI/CD variable we've provided named `K6_DOCKER_OPTIONS`
+to configure the k6 Docker container to use the file. With this, k6 can then use any
+environment variables from the `.env` file in scripts using standard JavaScript,
+such as: ``http.get(`${__ENV.ENVIRONMENT_URL}`)``.
+
+For example:
+
+1. In the `review` job:
+ 1. Capture the dynamic URL and save it into a `.env` file, for example, `echo "ENVIRONMENT_URL=$CI_ENVIRONMENT_URL" >> review.env`.
+ 1. Set the `.env` file to be a [job artifact](../pipelines/job_artifacts.md).
+1. In the `load_performance` job:
+ 1. Set it to depend on the review job, so it inherits the environment file.
+ 1. Set the `K6_DOCKER_OPTIONS` variable with the [Docker CLI option for environment files](https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e---env---env-file), for example `--env-file review.env`.
+1. Configure the k6 test script to use the environment variable in it's steps.
+
+Your `.gitlab-ci.yml` file might be similar to:
+
+```yaml
+stages:
+ - deploy
+ - performance
+
+include:
+ template: Verify/Load-Performance-Testing.gitlab-ci.yml
+
+review:
+ stage: deploy
+ environment:
+ name: review/$CI_COMMIT_REF_SLUG
+ url: http://$CI_ENVIRONMENT_SLUG.example.com
+ script:
+ - run_deploy_script
+ - echo "ENVIRONMENT_URL=$CI_ENVIRONMENT_URL" >> review.env
+ artifacts:
+ paths:
+ - review.env
+ rules:
+ - if: $CI_COMMIT_BRANCH # Modify to match your pipeline rules, or use `only/except` if needed.
+
+load_performance:
+ dependencies:
+ - review
+ variables:
+ K6_DOCKER_OPTIONS: '--env-file review.env'
+ rules:
+ - if: $CI_COMMIT_BRANCH # Modify to match your pipeline rules, or use `only/except` if needed.
+```
diff --git a/doc/ci/testing/metrics_reports.md b/doc/ci/testing/metrics_reports.md
new file mode 100644
index 00000000000..e855074ddea
--- /dev/null
+++ b/doc/ci/testing/metrics_reports.md
@@ -0,0 +1,68 @@
+---
+stage: Verify
+group: Pipeline Insights
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Metrics Reports **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9788) in GitLab 11.10. Requires GitLab Runner 11.10 and above.
+
+GitLab provides a lot of great reporting tools for things like [merge requests](../../user/project/merge_requests/index.md) - [Unit test reports](unit_test_reports.md), [code quality](code_quality.md), and performance tests. While JUnit is a great open framework for tests that "pass" or "fail", it is also important to see other types of metrics from a given change.
+
+You can configure your job to use custom Metrics Reports, and GitLab displays a report on the merge request so that it's easier and faster to identify changes without having to check the entire log.
+
+![Metrics Reports](img/metrics_reports_v13_0.png)
+
+## Use cases
+
+Consider the following examples of data that can use Metrics Reports:
+
+1. Memory usage
+1. Load testing results
+1. Code complexity
+1. Code coverage stats
+
+## How it works
+
+Metrics for a branch are read from the latest metrics report artifact (default filename: `metrics.txt`) as string values.
+
+For an MR, the values of these metrics from the feature branch are compared to the values from the target branch. Then they are displayed in the MR widget in this order:
+
+- Existing metrics with changed values.
+- Metrics that have been added by the MR. Marked with a **New** badge.
+- Metrics that have been removed by the MR. Marked with a **Removed** badge.
+- Existing metrics with unchanged values.
+
+## How to set it up
+
+Add a job that creates a [metrics report](../yaml/artifacts_reports.md#artifactsreportsmetrics) (default filename: `metrics.txt`). The file should conform to the [OpenMetrics](https://openmetrics.io/) format.
+
+For example:
+
+```yaml
+metrics:
+ script:
+ - echo 'metric_name metric_value' > metrics.txt
+ artifacts:
+ reports:
+ metrics: metrics.txt
+```
+
+## Advanced Example
+
+An advanced example of an OpenMetrics text file (from the [Prometheus documentation](https://github.com/prometheus/docs/blob/master/content/docs/instrumenting/exposition_formats.md#text-format-example))
+renders in the merge request widget as:
+
+![Metrics Reports Advanced](img/metrics_reports_advanced_v13_0.png)
+
+## Troubleshooting
+
+### Metrics reports did not change
+
+You can see `Metrics reports did not change` when trying to view metrics reports in merge requests. Reasons for this are:
+
+- The target branch for the merge request doesn't have a baseline metrics report for comparison.
+- You don't have GitLab license at the Premium tier or above.
+
+There is [an issue open](https://gitlab.com/gitlab-org/gitlab/-/issues/343065) to improve this message.
diff --git a/doc/ci/testing/test_coverage_visualization.md b/doc/ci/testing/test_coverage_visualization.md
new file mode 100644
index 00000000000..93a2b721d2f
--- /dev/null
+++ b/doc/ci/testing/test_coverage_visualization.md
@@ -0,0 +1,441 @@
+---
+stage: Verify
+group: Pipeline Insights
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Test coverage visualization **(FREE)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3708) in GitLab 12.9.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/249811) in GitLab 13.5.
+
+With the help of [GitLab CI/CD](../index.md), you can collect the test
+coverage information of your favorite testing or coverage-analysis tool, and visualize
+this information inside the file diff view of your merge requests (MRs). This will allow you
+to see which lines are covered by tests, and which lines still require coverage, before the
+MR is merged.
+
+![Test Coverage Visualization Diff View](img/test_coverage_visualization_v12_9.png)
+
+## How test coverage visualization works
+
+Collecting the coverage information is done via GitLab CI/CD's
+[artifacts reports feature](../yaml/index.md#artifactsreports).
+You can specify one or more coverage reports to collect, including wildcard paths.
+GitLab then takes the coverage information in all the files and combines it
+together. Coverage files are parsed in a background job so there can be a delay
+between pipeline completion and the visualization loading on the page.
+
+For the coverage analysis to work, you have to provide a properly formatted
+[Cobertura XML](https://cobertura.github.io/cobertura/) report to
+[`artifacts:reports:coverage_report`](../yaml/artifacts_reports.md#artifactsreportscoverage_report).
+This format was originally developed for Java, but most coverage analysis frameworks
+for other languages have plugins to add support for it, like:
+
+- [simplecov-cobertura](https://rubygems.org/gems/simplecov-cobertura) (Ruby)
+- [gocover-cobertura](https://github.com/boumenot/gocover-cobertura) (Golang)
+
+Other coverage analysis frameworks support the format out of the box, for example:
+
+- [Istanbul](https://istanbul.js.org/docs/advanced/alternative-reporters/#cobertura) (JavaScript)
+- [Coverage.py](https://coverage.readthedocs.io/en/coverage-5.0.4/cmd.html#xml-reporting) (Python)
+- [PHPUnit](https://github.com/sebastianbergmann/phpunit-documentation-english/blob/master/src/textui.rst#command-line-options) (PHP)
+
+Once configured, if you create a merge request that triggers a pipeline which collects
+coverage reports, the coverage is shown in the diff view. This includes reports
+from any job in any stage in the pipeline. The coverage displays for each line:
+
+- `covered` (green): lines which have been checked at least once by tests
+- `no test coverage` (orange): lines which are loaded but never executed
+- no coverage information: lines which are non-instrumented or not loaded
+
+Hovering over the coverage bar provides further information, such as the number
+of times the line was checked by tests.
+
+Uploading a test coverage report does not enable:
+
+- [Test coverage results in merge requests](../pipelines/settings.md#merge-request-test-coverage-results).
+- [Code coverage history](../pipelines/settings.md#view-code-coverage-history).
+
+You must configure these separately.
+
+### Limits
+
+A limit of 100 `