diff --git a/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue b/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue
index bf2874b6cc7..b2be563522a 100644
--- a/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue
+++ b/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue
@@ -32,6 +32,75 @@ import {
// feature rollout plan - https://gitlab.com/gitlab-org/gitlab/-/issues/262707#note_442529171
import mockedCustomMapping from './mocks/parsedMapping.json';
+export const i18n = {
+ integrationFormSteps: {
+ step1: {
+ label: s__('AlertSettings|1. Select integration type'),
+ enterprise: s__(
+ 'AlertSettings|In free versions of GitLab, only one integration for each type can be added. %{linkStart}Upgrade your subscription%{linkEnd} to add additional integrations.',
+ ),
+ },
+ step2: {
+ label: s__('AlertSettings|2. Name integration'),
+ placeholder: s__('AlertSettings|Enter integration name'),
+ prometheus: s__('AlertSettings|Prometheus'),
+ },
+ step3: {
+ label: s__('AlertSettings|3. Set up webhook'),
+ help: s__(
+ "AlertSettings|Utilize the URL and authorization key below to authorize an external service to send alerts to GitLab. Review your external service's documentation to learn where to add these details, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint.",
+ ),
+ prometheusHelp: s__(
+ 'AlertSettings|Utilize the URL and authorization key below to authorize Prometheus to send alerts to GitLab. Review the Prometheus documentation to learn where to add these details, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint.',
+ ),
+ info: s__('AlertSettings|Authorization key'),
+ reset: s__('AlertSettings|Reset Key'),
+ },
+ step4: {
+ label: s__('AlertSettings|4. Sample alert payload (optional)'),
+ help: s__(
+ 'AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This payload can be used to create a custom mapping (optional), or to test the integration (also optional).',
+ ),
+ prometheusHelp: s__(
+ 'AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This payload can be used to test the integration (optional).',
+ ),
+ placeholder: s__('AlertSettings|{ "events": [{ "application": "Name of application" }] }'),
+ resetHeader: s__('AlertSettings|Reset the mapping'),
+ resetBody: s__(
+ "AlertSettings|If you edit the payload, the stored mapping will be reset, and you'll need to re-map the fields.",
+ ),
+ resetOk: s__('AlertSettings|Proceed with editing'),
+ editPayload: s__('AlertSettings|Edit payload'),
+ submitPayload: s__('AlertSettings|Submit payload'),
+ payloadParsedSucessMsg: s__(
+ 'AlertSettings|Sample payload has been parsed. You can now map the fields.',
+ ),
+ },
+ step5: {
+ label: s__('AlertSettings|5. Map fields (optional)'),
+ intro: s__(
+ "AlertSettings|If you've provided a sample alert payload, you can create a custom mapping for your endpoint. The default GitLab alert keys are listed below. Please define which payload key should map to the specified GitLab key.",
+ ),
+ },
+ prometheusFormUrl: {
+ label: s__('AlertSettings|Prometheus API base URL'),
+ help: s__('AlertSettings|URL cannot be blank and must start with http or https'),
+ },
+ restKeyInfo: {
+ label: s__(
+ 'AlertSettings|Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in.',
+ ),
+ },
+ // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
+ opsgenie: {
+ label: s__('AlertSettings|2. Add link to your Opsgenie alert list'),
+ info: s__(
+ 'AlertSettings|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature.',
+ ),
+ },
+ },
+};
+
export default {
placeholders: {
prometheus: targetPrometheusUrlPlaceholder,
@@ -39,73 +108,7 @@ export default {
},
JSON_VALIDATE_DELAY,
typeSet,
- i18n: {
- integrationFormSteps: {
- step1: {
- label: s__('AlertSettings|1. Select integration type'),
- enterprise: s__(
- 'AlertSettings|In free versions of GitLab, only one integration for each type can be added. %{linkStart}Upgrade your subscription%{linkEnd} to add additional integrations.',
- ),
- },
- step2: {
- label: s__('AlertSettings|2. Name integration'),
- placeholder: s__('AlertSettings|Enter integration name'),
- },
- step3: {
- label: s__('AlertSettings|3. Set up webhook'),
- help: s__(
- "AlertSettings|Utilize the URL and authorization key below to authorize an external service to send alerts to GitLab. Review your external service's documentation to learn where to add these details, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint.",
- ),
- prometheusHelp: s__(
- 'AlertSettings|Utilize the URL and authorization key below to authorize Prometheus to send alerts to GitLab. Review the Prometheus documentation to learn where to add these details, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint.',
- ),
- info: s__('AlertSettings|Authorization key'),
- reset: s__('AlertSettings|Reset Key'),
- },
- step4: {
- label: s__('AlertSettings|4. Sample alert payload (optional)'),
- help: s__(
- 'AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This payload can be used to create a custom mapping (optional), or to test the integration (also optional).',
- ),
- prometheusHelp: s__(
- 'AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This payload can be used to test the integration (optional).',
- ),
- placeholder: s__('AlertSettings|{ "events": [{ "application": "Name of application" }] }'),
- resetHeader: s__('AlertSettings|Reset the mapping'),
- resetBody: s__(
- "AlertSettings|If you edit the payload, the stored mapping will be reset, and you'll need to re-map the fields.",
- ),
- resetOk: s__('AlertSettings|Proceed with editing'),
- editPayload: s__('AlertSettings|Edit payload'),
- submitPayload: s__('AlertSettings|Submit payload'),
- payloadParsedSucessMsg: s__(
- 'AlertSettings|Sample payload has been parsed. You can now map the fields.',
- ),
- },
- step5: {
- label: s__('AlertSettings|5. Map fields (optional)'),
- intro: s__(
- "AlertSettings|If you've provided a sample alert payload, you can create a custom mapping for your endpoint. The default GitLab alert keys are listed below. Please define which payload key should map to the specified GitLab key.",
- ),
- },
- prometheusFormUrl: {
- label: s__('AlertSettings|Prometheus API base URL'),
- help: s__('AlertSettings|URL cannot be blank and must start with http or https'),
- },
- restKeyInfo: {
- label: s__(
- 'AlertSettings|Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in.',
- ),
- },
- // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
- opsgenie: {
- label: s__('AlertSettings|2. Add link to your Opsgenie alert list'),
- info: s__(
- 'AlertSettings|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature.',
- ),
- },
- },
- },
+ i18n,
components: {
ClipboardButton,
GlButton,
@@ -265,6 +268,9 @@ export default {
this.integrationTestPayload.json === ''
);
},
+ isSelectDisabled() {
+ return this.currentIntegration !== null || !this.canAddIntegration;
+ },
},
watch: {
currentIntegration(val) {
@@ -421,7 +427,8 @@ export default {
>
@@ -472,8 +479,13 @@ export default {
>
+
+
diff --git a/app/assets/javascripts/search/topbar/constants.js b/app/assets/javascripts/search/topbar/constants.js
new file mode 100644
index 00000000000..3944b2c8374
--- /dev/null
+++ b/app/assets/javascripts/search/topbar/constants.js
@@ -0,0 +1,21 @@
+import { __ } from '~/locale';
+
+export const ANY_OPTION = Object.freeze({
+ id: null,
+ name: __('Any'),
+ name_with_namespace: __('Any'),
+});
+
+export const GROUP_DATA = {
+ headerText: __('Filter results by group'),
+ queryParam: 'group_id',
+ selectedDisplayValue: 'name',
+ itemsDisplayValue: 'full_name',
+};
+
+export const PROJECT_DATA = {
+ headerText: __('Filter results by project'),
+ queryParam: 'project_id',
+ selectedDisplayValue: 'name_with_namespace',
+ itemsDisplayValue: 'name_with_namespace',
+};
diff --git a/app/assets/javascripts/search/topbar/index.js b/app/assets/javascripts/search/topbar/index.js
new file mode 100644
index 00000000000..a751fa53e03
--- /dev/null
+++ b/app/assets/javascripts/search/topbar/index.js
@@ -0,0 +1,39 @@
+import Vue from 'vue';
+import Translate from '~/vue_shared/translate';
+import GroupFilter from './components/group_filter.vue';
+
+Vue.use(Translate);
+
+const mountSearchableDropdown = (store, { id, component }) => {
+ const el = document.getElementById(id);
+
+ if (!el) {
+ return false;
+ }
+
+ let { initialData } = el.dataset;
+
+ initialData = JSON.parse(initialData);
+
+ return new Vue({
+ el,
+ store,
+ render(createElement) {
+ return createElement(component, {
+ props: {
+ initialData,
+ },
+ });
+ },
+ });
+};
+
+const searchableDropdowns = [
+ {
+ id: 'js-search-group-dropdown',
+ component: GroupFilter,
+ },
+];
+
+export const initTopbar = store =>
+ searchableDropdowns.map(dropdown => mountSearchableDropdown(store, dropdown));
diff --git a/app/controllers/projects/feature_flags_controller.rb b/app/controllers/projects/feature_flags_controller.rb
index e9d450a6ce3..8f623f90318 100644
--- a/app/controllers/projects/feature_flags_controller.rb
+++ b/app/controllers/projects/feature_flags_controller.rb
@@ -14,7 +14,6 @@ class Projects::FeatureFlagsController < Projects::ApplicationController
before_action do
push_frontend_feature_flag(:feature_flag_permissions)
- push_frontend_feature_flag(:feature_flags_new_version, project, default_enabled: true)
push_frontend_feature_flag(:feature_flags_legacy_read_only, project, default_enabled: true)
push_frontend_feature_flag(:feature_flags_legacy_read_only_override, project)
end
@@ -101,15 +100,7 @@ class Projects::FeatureFlagsController < Projects::ApplicationController
protected
def feature_flag
- @feature_flag ||= @noteable = if new_version_feature_flags_enabled?
- project.operations_feature_flags.find_by_iid!(params[:iid])
- else
- project.operations_feature_flags.legacy_flag.find_by_iid!(params[:iid])
- end
- end
-
- def new_version_feature_flags_enabled?
- ::Feature.enabled?(:feature_flags_new_version, project, default_enabled: true)
+ @feature_flag ||= @noteable = project.operations_feature_flags.find_by_iid!(params[:iid])
end
def ensure_legacy_flags_writable!
diff --git a/app/finders/feature_flags_finder.rb b/app/finders/feature_flags_finder.rb
index 9cb3bf7fa23..7b38841970d 100644
--- a/app/finders/feature_flags_finder.rb
+++ b/app/finders/feature_flags_finder.rb
@@ -24,11 +24,7 @@ class FeatureFlagsFinder
private
def feature_flags
- if Feature.enabled?(:feature_flags_new_version, project, default_enabled: true)
- project.operations_feature_flags
- else
- project.operations_feature_flags.legacy_flag
- end
+ project.operations_feature_flags
end
def by_scope(items)
diff --git a/app/helpers/system_note_helper.rb b/app/helpers/system_note_helper.rb
index 79f4810e13a..85e644967ea 100644
--- a/app/helpers/system_note_helper.rb
+++ b/app/helpers/system_note_helper.rb
@@ -38,7 +38,8 @@ module SystemNoteHelper
'status' => 'status',
'alert_issue_added' => 'issues',
'new_alert_added' => 'warning',
- 'severity' => 'information-o'
+ 'severity' => 'information-o',
+ 'cloned' => 'documents'
}.freeze
def system_note_icon_name(note)
diff --git a/app/models/environment.rb b/app/models/environment.rb
index 46cfdd74b5f..45bb8a44840 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -32,6 +32,7 @@ class Environment < ApplicationRecord
has_one :last_visible_deployment, -> { visible.distinct_on_environment }, inverse_of: :environment, class_name: 'Deployment'
has_one :last_visible_deployable, through: :last_visible_deployment, source: 'deployable', source_type: 'CommitStatus'
has_one :last_visible_pipeline, through: :last_visible_deployable, source: 'pipeline'
+ has_one :upcoming_deployment, -> { running.order('deployments.id DESC') }, class_name: 'Deployment'
has_one :latest_opened_most_severe_alert, -> { order_severity_with_open_prometheus_alert }, class_name: 'AlertManagement::Alert', inverse_of: :environment
before_validation :nullify_external_url
diff --git a/app/models/experiment.rb b/app/models/experiment.rb
index 2bced3911d0..29a40d36a79 100644
--- a/app/models/experiment.rb
+++ b/app/models/experiment.rb
@@ -5,8 +5,8 @@ class Experiment < ApplicationRecord
validates :name, presence: true, uniqueness: true, length: { maximum: 255 }
- def self.add_user(name, group_type, user)
- find_or_create_by!(name: name).record_user_and_group(user, group_type)
+ def self.add_user(name, group_type, user, context = {})
+ find_or_create_by!(name: name).record_user_and_group(user, group_type, context)
end
def self.record_conversion_event(name, user)
@@ -14,8 +14,8 @@ class Experiment < ApplicationRecord
end
# Create or update the recorded experiment_user row for the user in this experiment.
- def record_user_and_group(user, group_type)
- experiment_users.find_or_initialize_by(user: user).update!(group_type: group_type)
+ def record_user_and_group(user, group_type, context = {})
+ experiment_users.find_or_initialize_by(user: user).update!(group_type: group_type, context: context)
end
def record_conversion_event_for_user(user)
diff --git a/app/models/issue.rb b/app/models/issue.rb
index d6dba8bb9e5..b4071307e06 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -308,6 +308,7 @@ class Issue < ApplicationRecord
!moved? && persisted? &&
user.can?(:admin_issue, self.project)
end
+ alias_method :can_clone?, :can_move?
def to_branch_name
if self.confidential?
diff --git a/app/models/system_note_metadata.rb b/app/models/system_note_metadata.rb
index 8dd471b259e..20107147b4f 100644
--- a/app/models/system_note_metadata.rb
+++ b/app/models/system_note_metadata.rb
@@ -14,12 +14,13 @@ class SystemNoteMetadata < ApplicationRecord
moved merge
label milestone
relate unrelate
+ cloned
].freeze
ICON_TYPES = %w[
commit description merge confidential visible label assignee cross_reference
designs_added designs_modified designs_removed designs_discussion_added
- title time_tracking branch milestone discussion task moved
+ title time_tracking branch milestone discussion task moved cloned
opened closed merged duplicate locked unlocked outdated reviewer
tag due_date pinned_embed cherry_pick health_status approved unapproved
status alert_issue_added relate unrelate new_alert_added severity
diff --git a/app/serializers/environment_entity.rb b/app/serializers/environment_entity.rb
index 0bd9c602bf5..8c6ad010d69 100644
--- a/app/serializers/environment_entity.rb
+++ b/app/serializers/environment_entity.rb
@@ -3,6 +3,9 @@
class EnvironmentEntity < Grape::Entity
include RequestAwareEntity
+ UNNECESSARY_ENTRIES_FOR_UPCOMING_DEPLOYMENT =
+ %i[manual_actions scheduled_actions playable_build cluster].freeze
+
expose :id
expose :global_id do |environment|
@@ -17,6 +20,11 @@ class EnvironmentEntity < Grape::Entity
expose :last_deployment, using: DeploymentEntity
expose :stop_action_available?, as: :has_stop_action
+ expose :upcoming_deployment, expose_nil: false do |environment, ops|
+ DeploymentEntity.represent(environment.upcoming_deployment,
+ ops.merge(except: UNNECESSARY_ENTRIES_FOR_UPCOMING_DEPLOYMENT))
+ end
+
expose :metrics_path, if: -> (*) { environment.has_metrics? } do |environment|
metrics_project_environment_path(environment.project, environment)
end
diff --git a/app/services/feature_flags/create_service.rb b/app/services/feature_flags/create_service.rb
index b4ca90f7aae..de3a55d10fc 100644
--- a/app/services/feature_flags/create_service.rb
+++ b/app/services/feature_flags/create_service.rb
@@ -5,7 +5,6 @@ module FeatureFlags
def execute
return error('Access Denied', 403) unless can_create?
return error('Version is invalid', :bad_request) unless valid_version?
- return error('New version feature flags are not enabled for this project', :bad_request) unless flag_version_enabled?
ActiveRecord::Base.transaction do
feature_flag = project.operations_feature_flags.new(params)
@@ -40,13 +39,5 @@ module FeatureFlags
def valid_version?
!params.key?(:version) || Operations::FeatureFlag.versions.key?(params[:version])
end
-
- def flag_version_enabled?
- params[:version] != 'new_version_flag' || new_version_feature_flags_enabled?
- end
-
- def new_version_feature_flags_enabled?
- ::Feature.enabled?(:feature_flags_new_version, project, default_enabled: true)
- end
end
end
diff --git a/app/services/issues/clone_service.rb b/app/services/issues/clone_service.rb
new file mode 100644
index 00000000000..a8c0cb05ebe
--- /dev/null
+++ b/app/services/issues/clone_service.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+module Issues
+ class CloneService < Issuable::Clone::BaseService
+ CloneError = Class.new(StandardError)
+
+ def execute(issue, target_project)
+ @target_project = target_project
+
+ unless issue.can_clone?(current_user, @target_project)
+ raise CloneError, s_('CloneIssue|Cannot clone issue due to insufficient permissions!')
+ end
+
+ if target_project.pending_delete?
+ raise CloneError, s_('CloneIssue|Cannot clone issue to target project as it is pending deletion.')
+ end
+
+ super(issue, target_project)
+
+ queue_copy_designs
+
+ new_entity
+ end
+
+ private
+
+ attr_reader :target_project
+
+ def update_new_entity
+ # we don't call `super` because we want to be able to decide whether or not to copy all comments over.
+ update_new_entity_description
+ update_new_entity_attributes
+ copy_award_emoji
+ end
+
+ def update_old_entity
+ # no-op
+ # The base_service closes the old issue, we don't want that, so we override here so nothing happens.
+ end
+
+ def create_new_entity
+ new_params = {
+ id: nil,
+ iid: nil,
+ project: target_project,
+ author: original_entity.author,
+ assignee_ids: original_entity.assignee_ids
+ }
+
+ new_params = original_entity.serializable_hash.symbolize_keys.merge(new_params)
+
+ # Skip creation of system notes for existing attributes of the issue. The system notes of the old
+ # issue are copied over so we don't want to end up with duplicate notes.
+ CreateService.new(@target_project, @current_user, new_params).execute(skip_system_notes: true)
+ end
+
+ def queue_copy_designs
+ return unless original_entity.designs.present?
+
+ response = DesignManagement::CopyDesignCollection::QueueService.new(
+ current_user,
+ original_entity,
+ new_entity
+ ).execute
+
+ log_error(response.message) if response.error?
+ end
+
+ def add_note_from
+ SystemNoteService.noteable_cloned(new_entity, target_project,
+ original_entity, current_user,
+ direction: :from)
+ end
+
+ def add_note_to
+ SystemNoteService.noteable_cloned(original_entity, old_project,
+ new_entity, current_user,
+ direction: :to)
+ end
+ end
+end
diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb
index b9832400302..a2c11cb0a7c 100644
--- a/app/services/issues/update_service.rb
+++ b/app/services/issues/update_service.rb
@@ -9,7 +9,7 @@ module Issues
handle_move_between_ids(issue)
filter_spam_check_params
change_issue_duplicate(issue)
- move_issue_to_new_project(issue) || update_task_event(issue) || update(issue)
+ move_issue_to_new_project(issue) || clone_issue(issue) || update_task_event(issue) || update(issue)
end
def update(issue)
@@ -127,6 +127,17 @@ module Issues
private
+ def clone_issue(issue)
+ target_project = params.delete(:target_clone_project)
+
+ return unless target_project &&
+ issue.can_clone?(current_user, target_project)
+
+ # we've pre-empted this from running in #execute, so let's go ahead and update the Issue now.
+ update(issue)
+ Issues::CloneService.new(project, current_user).execute(issue, target_project)
+ end
+
def create_merge_request_from_quick_action
create_merge_request_params = params.delete(:create_merge_request)
return unless create_merge_request_params
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index eacc88f98a3..58f72e9badc 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -226,6 +226,10 @@ module SystemNoteService
::SystemNotes::IssuablesService.new(noteable: noteable, project: project, author: author).noteable_moved(noteable_ref, direction)
end
+ def noteable_cloned(noteable, project, noteable_ref, author, direction:)
+ ::SystemNotes::IssuablesService.new(noteable: noteable, project: project, author: author).noteable_cloned(noteable_ref, direction)
+ end
+
def mark_duplicate_issue(noteable, project, author, canonical_issue)
::SystemNotes::IssuablesService.new(noteable: noteable, project: project, author: author).mark_duplicate_issue(canonical_issue)
end
diff --git a/app/services/system_notes/issuables_service.rb b/app/services/system_notes/issuables_service.rb
index 7a73af0a81a..9f2b7d30fdc 100644
--- a/app/services/system_notes/issuables_service.rb
+++ b/app/services/system_notes/issuables_service.rb
@@ -242,6 +242,27 @@ module SystemNotes
create_note(NoteSummary.new(noteable, project, author, body, action: 'moved'))
end
+ # Called when noteable has been cloned
+ #
+ # noteable_ref - Referenced noteable
+ # direction - symbol, :to or :from
+ #
+ # Example Note text:
+ #
+ # "cloned to some_namespace/project_new#11"
+ #
+ # Returns the created Note object
+ def noteable_cloned(noteable_ref, direction)
+ unless [:to, :from].include?(direction)
+ raise ArgumentError, "Invalid direction `#{direction}`"
+ end
+
+ cross_reference = noteable_ref.to_reference(project)
+ body = "cloned #{direction} #{cross_reference}"
+
+ create_note(NoteSummary.new(noteable, project, author, body, action: 'cloned'))
+ end
+
# Called when the confidentiality changes
#
# Example Note text:
diff --git a/app/views/groups/registry/repositories/index.html.haml b/app/views/groups/registry/repositories/index.html.haml
index 21882c3e3ce..1d035bb2f7b 100644
--- a/app/views/groups/registry/repositories/index.html.haml
+++ b/app/views/groups/registry/repositories/index.html.haml
@@ -16,4 +16,5 @@
"cleanup_policies_help_page_path" => help_page_path('user/packages/container_registry/index', anchor: 'how-the-cleanup-policy-works'),
"is_admin": current_user&.admin.to_s,
is_group_page: "true",
+ "group_path": @group.full_path,
character_error: @character_error.to_s } }
diff --git a/app/views/layouts/_loading_hints.html.haml b/app/views/layouts/_loading_hints.html.haml
index a75b602ff6b..0ef50d1b122 100644
--- a/app/views/layouts/_loading_hints.html.haml
+++ b/app/views/layouts/_loading_hints.html.haml
@@ -6,6 +6,5 @@
- else
%link{ { rel: 'preload', href: stylesheet_url('application'), as: 'style' }, ActionController::Base.asset_host ? { crossorigin: 'anonymous' } : {} }
%link{ { rel: 'preload', href: stylesheet_url("highlight/themes/#{user_color_scheme}"), as: 'style' }, ActionController::Base.asset_host ? { crossorigin: 'anonymous' } : {} }
-%link{ { rel: 'preload', href: asset_url("fontawesome-webfont.woff2?v=4.7.0"), as: 'font', type: 'font/woff2' }, ActionController::Base.asset_host ? { crossorigin: 'anonymous' } : {} }
- if Gitlab::CurrentSettings.snowplow_enabled? && Gitlab::CurrentSettings.snowplow_collector_hostname
%link{ rel: 'preconnect', href: Gitlab::CurrentSettings.snowplow_collector_hostname, crossorigin: '' }
diff --git a/app/views/projects/registry/repositories/index.html.haml b/app/views/projects/registry/repositories/index.html.haml
index 9ac1fda169f..efdc54afc07 100644
--- a/app/views/projects/registry/repositories/index.html.haml
+++ b/app/views/projects/registry/repositories/index.html.haml
@@ -17,6 +17,6 @@
"garbage_collection_help_page_path" => help_page_path('administration/packages/container_registry', anchor: 'container-registry-garbage-collection'),
"run_cleanup_policies_help_page_path" => help_page_path('administration/packages/container_registry', anchor: 'run-the-cleanup-policy-now'),
"cleanup_policies_help_page_path" => help_page_path('user/packages/container_registry/index', anchor: 'how-the-cleanup-policy-works'),
-
+ "project_path": @project.full_path,
"is_admin": current_user&.admin.to_s,
character_error: @character_error.to_s } }
diff --git a/app/views/search/_filter.html.haml b/app/views/search/_filter.html.haml
index 05895d83c2b..c2f7fd23554 100644
--- a/app/views/search/_filter.html.haml
+++ b/app/views/search/_filter.html.haml
@@ -5,7 +5,7 @@
.dropdown.form-group.mb-lg-0.mx-lg-1.gl-p-0{ data: { testid: "group-filter" } }
%label.d-block{ for: "dashboard_search_group" }
= _("Group")
- %input#js-search-group-dropdown.dropdown-menu-toggle{ value: "Loading...", data: { "initial-group-data": @group.to_json } }
+ %input#js-search-group-dropdown.dropdown-menu-toggle{ value: "Loading...", data: { "initial-data": @group.to_json } }
.dropdown.form-group.mb-lg-0.mx-lg-1{ data: { testid: "project-filter" } }
%label.d-block{ for: "dashboard_search_project" }
= _("Project")
diff --git a/changelogs/unreleased/234013-add-experiment-record-context.yml b/changelogs/unreleased/234013-add-experiment-record-context.yml
new file mode 100644
index 00000000000..5613d145be5
--- /dev/null
+++ b/changelogs/unreleased/234013-add-experiment-record-context.yml
@@ -0,0 +1,5 @@
+---
+title: Add context to the experiment user records
+merge_request: 48896
+author:
+type: added
diff --git a/changelogs/unreleased/270090-add-pk-to-elasticsearch-indexed-projects.yml b/changelogs/unreleased/270090-add-pk-to-elasticsearch-indexed-projects.yml
new file mode 100644
index 00000000000..c40fcefc914
--- /dev/null
+++ b/changelogs/unreleased/270090-add-pk-to-elasticsearch-indexed-projects.yml
@@ -0,0 +1,5 @@
+---
+title: Add primary key to elasticsearch_indexed_projects
+merge_request: 48919
+author:
+type: changed
diff --git a/changelogs/unreleased/271538-remove-vsa-usage-ping.yml b/changelogs/unreleased/271538-remove-vsa-usage-ping.yml
new file mode 100644
index 00000000000..6f24b58119b
--- /dev/null
+++ b/changelogs/unreleased/271538-remove-vsa-usage-ping.yml
@@ -0,0 +1,5 @@
+---
+title: Remove avg_cycle_analytics from usage ping
+merge_request: 47812
+author:
+type: other
diff --git a/changelogs/unreleased/276432-refactor-container-registry-frontend-to-graphql.yml b/changelogs/unreleased/276432-refactor-container-registry-frontend-to-graphql.yml
new file mode 100644
index 00000000000..bd2e0a05528
--- /dev/null
+++ b/changelogs/unreleased/276432-refactor-container-registry-frontend-to-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Refactor container registry list page to grapqhl
+merge_request: 48602
+author:
+type: changed
diff --git a/changelogs/unreleased/287724-disable-name-prometheus.yml b/changelogs/unreleased/287724-disable-name-prometheus.yml
new file mode 100644
index 00000000000..b650665635d
--- /dev/null
+++ b/changelogs/unreleased/287724-disable-name-prometheus.yml
@@ -0,0 +1,5 @@
+---
+title: Prometheus integration name should not have a modifiable input field
+merge_request: 48437
+author:
+type: fixed
diff --git a/changelogs/unreleased/9421-clone-quickaction.yml b/changelogs/unreleased/9421-clone-quickaction.yml
new file mode 100644
index 00000000000..2335cafa37a
--- /dev/null
+++ b/changelogs/unreleased/9421-clone-quickaction.yml
@@ -0,0 +1,5 @@
+---
+title: Implement a /clone quick-action to quickly clone an Issue
+merge_request: 48394
+author:
+type: added
diff --git a/changelogs/unreleased/expose-upcoming-deployment.yml b/changelogs/unreleased/expose-upcoming-deployment.yml
new file mode 100644
index 00000000000..70693858bf5
--- /dev/null
+++ b/changelogs/unreleased/expose-upcoming-deployment.yml
@@ -0,0 +1,5 @@
+---
+title: Expose upcoming deployment in environment.json
+merge_request: 48449
+author:
+type: added
diff --git a/config/feature_flags/development/feature_flags_new_version.yml b/config/feature_flags/development/feature_flags_new_version.yml
deleted file mode 100644
index f42054ce3ef..00000000000
--- a/config/feature_flags/development/feature_flags_new_version.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: feature_flags_new_version
-introduced_by_url:
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/258831
-milestone: '13.7'
-type: development
-group: group::progressive delivery
-default_enabled: true
diff --git a/config/feature_flags/development/security_on_demand_scans_http_header_validation.yml b/config/feature_flags/development/security_on_demand_scans_http_header_validation.yml
deleted file mode 100644
index 475cbfa4d9a..00000000000
--- a/config/feature_flags/development/security_on_demand_scans_http_header_validation.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: security_on_demand_scans_http_header_validation
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42812
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/276403
-milestone: '13.6'
-type: development
-group: group::dynamic analysis
-default_enabled: false
diff --git a/db/migrate/20201201161655_add_primary_key_to_elastic_search_indexed_projects.rb b/db/migrate/20201201161655_add_primary_key_to_elastic_search_indexed_projects.rb
new file mode 100644
index 00000000000..cf7221693f9
--- /dev/null
+++ b/db/migrate/20201201161655_add_primary_key_to_elastic_search_indexed_projects.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+class AddPrimaryKeyToElasticSearchIndexedProjects < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ UNIQUE_INDEX_NAME = 'index_elasticsearch_indexed_projects_on_project_id'
+ PRIMARY_KEY_NAME = 'elasticsearch_indexed_projects_pkey'
+
+ def up
+ execute(<<~SQL)
+ DELETE FROM elasticsearch_indexed_projects
+ WHERE project_id IS NULL
+ SQL
+
+ execute(<<~SQL)
+ ALTER TABLE elasticsearch_indexed_projects
+ ALTER COLUMN project_id SET NOT NULL,
+ ADD CONSTRAINT #{PRIMARY_KEY_NAME} PRIMARY KEY USING INDEX #{UNIQUE_INDEX_NAME}
+ SQL
+ end
+
+ def down
+ add_index :elasticsearch_indexed_projects, :project_id, unique: true, name: UNIQUE_INDEX_NAME # rubocop:disable Migration/AddIndex
+
+ execute(<<~SQL)
+ ALTER TABLE elasticsearch_indexed_projects
+ DROP CONSTRAINT #{PRIMARY_KEY_NAME},
+ ALTER COLUMN project_id DROP NOT NULL
+ SQL
+ end
+end
diff --git a/db/migrate/20201201190002_add_other_context_to_experiment_user.rb b/db/migrate/20201201190002_add_other_context_to_experiment_user.rb
new file mode 100644
index 00000000000..c901f049e75
--- /dev/null
+++ b/db/migrate/20201201190002_add_other_context_to_experiment_user.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddOtherContextToExperimentUser < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_column :experiment_users, :context, :jsonb, default: {}, null: false
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :experiment_users, :context
+ end
+ end
+end
diff --git a/db/schema_migrations/20201201161655 b/db/schema_migrations/20201201161655
new file mode 100644
index 00000000000..892d2bfc08d
--- /dev/null
+++ b/db/schema_migrations/20201201161655
@@ -0,0 +1 @@
+d9ad12dce02d6823536f3206e9c90a0da82c08089c3ce252e8ef28a59589e747
\ No newline at end of file
diff --git a/db/schema_migrations/20201201190002 b/db/schema_migrations/20201201190002
new file mode 100644
index 00000000000..aac9ac34c64
--- /dev/null
+++ b/db/schema_migrations/20201201190002
@@ -0,0 +1 @@
+f4ec800e68cbe092775b428d3ff85a4a84be0d55d70e59d23de390847ea3c2b7
\ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 94f92b2af16..9c53bb2de03 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -11935,7 +11935,7 @@ CREATE TABLE elasticsearch_indexed_namespaces (
CREATE TABLE elasticsearch_indexed_projects (
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
- project_id integer
+ project_id integer NOT NULL
);
CREATE TABLE emails (
@@ -12124,7 +12124,8 @@ CREATE TABLE experiment_users (
group_type smallint DEFAULT 0 NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
- converted_at timestamp with time zone
+ converted_at timestamp with time zone,
+ context jsonb DEFAULT '{}'::jsonb NOT NULL
);
CREATE SEQUENCE experiment_users_id_seq
@@ -19255,6 +19256,9 @@ ALTER TABLE ONLY draft_notes
ALTER TABLE ONLY elastic_reindexing_tasks
ADD CONSTRAINT elastic_reindexing_tasks_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY elasticsearch_indexed_projects
+ ADD CONSTRAINT elasticsearch_indexed_projects_pkey PRIMARY KEY (project_id);
+
ALTER TABLE ONLY emails
ADD CONSTRAINT emails_pkey PRIMARY KEY (id);
@@ -21056,8 +21060,6 @@ CREATE INDEX index_elasticsearch_indexed_namespaces_on_created_at ON elasticsear
CREATE UNIQUE INDEX index_elasticsearch_indexed_namespaces_on_namespace_id ON elasticsearch_indexed_namespaces USING btree (namespace_id);
-CREATE UNIQUE INDEX index_elasticsearch_indexed_projects_on_project_id ON elasticsearch_indexed_projects USING btree (project_id);
-
CREATE UNIQUE INDEX index_emails_on_confirmation_token ON emails USING btree (confirmation_token);
CREATE UNIQUE INDEX index_emails_on_email ON emails USING btree (email);
diff --git a/doc/.vale/gitlab/Acronyms.yml b/doc/.vale/gitlab/Acronyms.yml
index 829f46d3a83..b3a220ccda4 100644
--- a/doc/.vale/gitlab/Acronyms.yml
+++ b/doc/.vale/gitlab/Acronyms.yml
@@ -99,6 +99,7 @@ exceptions:
- SEO
- SHA
- SLA
+ - SMS
- SMTP
- SQL
- SSD
diff --git a/doc/.vale/gitlab/spelling-exceptions.txt b/doc/.vale/gitlab/spelling-exceptions.txt
index 7ec0dcd6a77..82a4ac34689 100644
--- a/doc/.vale/gitlab/spelling-exceptions.txt
+++ b/doc/.vale/gitlab/spelling-exceptions.txt
@@ -484,6 +484,7 @@ sudo
swimlane
swimlanes
syslog
+tanuki
tcpdump
Thanos
Tiller
diff --git a/doc/administration/gitaly/praefect.md b/doc/administration/gitaly/praefect.md
index 494d1979784..618efa10cf1 100644
--- a/doc/administration/gitaly/praefect.md
+++ b/doc/administration/gitaly/praefect.md
@@ -144,7 +144,7 @@ package (highly recommended), follow the steps below:
Before beginning, you should already have a working GitLab instance. [Learn how
to install GitLab](https://about.gitlab.com/install/).
-Provision a PostgreSQL server (PostgreSQL 11 or newer).
+Provision a PostgreSQL server (PostgreSQL 11 or newer).
Prepare all your new nodes by [installing
GitLab](https://about.gitlab.com/install/).
diff --git a/doc/administration/job_logs.md b/doc/administration/job_logs.md
index c245d6f06a6..09bda0d39d2 100644
--- a/doc/administration/job_logs.md
+++ b/doc/administration/job_logs.md
@@ -185,7 +185,7 @@ Feature.enable(:ci_enable_live_trace)
```
NOTE: **Note:**
-The transition period is handled gracefully. Upcoming logs are
+The transition period is handled gracefully. Upcoming logs are
generated with the incremental architecture, and on-going logs stay with the
legacy architecture, which means that on-going logs aren't forcibly
re-generated with the incremental architecture.
diff --git a/doc/administration/packages/index.md b/doc/administration/packages/index.md
index 8013067af2a..ce09006dc5b 100644
--- a/doc/administration/packages/index.md
+++ b/doc/administration/packages/index.md
@@ -55,7 +55,7 @@ guides you through the process.
NOTE: **Note:**
After the Packages feature is enabled, the repositories are available
-for all new projects by default. To enable it for existing projects, users
+for all new projects by default. To enable it for existing projects, users
explicitly do so in the project's settings.
To enable the Packages feature:
diff --git a/doc/api/appearance.md b/doc/api/appearance.md
index 7dd7f88780a..c489f7aa316 100644
--- a/doc/api/appearance.md
+++ b/doc/api/appearance.md
@@ -94,7 +94,7 @@ Upload a logo to your GitLab instance.
To upload an avatar from your file system, use the `--form` argument. This causes
cURL to post data using the header `Content-Type: multipart/form-data`. The
-`file=` parameter must point to an image file on your file system and be
+`file=` parameter must point to an image file on your file system and be
preceded by `@`.
```plaintext
diff --git a/doc/api/feature_flags.md b/doc/api/feature_flags.md
index 4f65f649be1..45028408491 100644
--- a/doc/api/feature_flags.md
+++ b/doc/api/feature_flags.md
@@ -10,10 +10,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Starter](https://about.gitlab.com/pricing/) in 13.4.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.5.
-NOTE: **Note:**
-This API is behind a [feature flag](../operations/feature_flags.md#enable-or-disable-feature-flag-strategies).
-If this flag is not enabled in your environment, you can use the [legacy feature flags API](feature_flags_legacy.md).
-
API for accessing resources of [GitLab Feature Flags](../operations/feature_flags.md).
Users with Developer or higher [permissions](../user/permissions.md) can access Feature Flag API.
diff --git a/doc/development/documentation/styleguide/index.md b/doc/development/documentation/styleguide/index.md
index 73c83c614b5..b6ed1bf9bf4 100644
--- a/doc/development/documentation/styleguide/index.md
+++ b/doc/development/documentation/styleguide/index.md
@@ -533,7 +533,9 @@ tenses, words, and phrases:
content is accessible to more readers.
- Don't write in the first person singular.
(Tested in [`FirstPerson.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FirstPerson.yml).)
+
- Instead of _I_ or _me_, use _we_, _you_, _us_, or _one_.
+
- When possible, stay user focused by writing in the second person (_you_ or
the imperative).
- Don't overuse "that". In many cases, you can remove "that" from a sentence
@@ -795,6 +797,8 @@ Items nested in lists should always align with the first character of the list
item. In unordered lists (using `-`), this means two spaces for each level of
indentation:
+
+
````markdown
- Unordered list item 1
@@ -816,8 +820,12 @@ indentation:
![an image that will nest inside list item 4](image.png)
````
+
+
For ordered lists, use three spaces for each level of indentation:
+
+
````markdown
1. Ordered list item 1
@@ -839,6 +847,8 @@ For ordered lists, use three spaces for each level of indentation:
![an image that will nest inside list item 4](image.png)
````
+
+
You can nest full lists inside other lists using the same rules as above. If you
want to mix types, that's also possible, if you don't mix items at the same
level:
@@ -904,7 +914,7 @@ Valid for Markdown content only, not for front matter entries:
- Standard quotes: double quotes (`"`). Example: "This is wrapped in double
quotes".
- Quote inside a quote: double quotes (`"`) wrap single quotes (`'`). Example:
- "I am 'quoting' something in a quote".
+ "This sentence 'quotes' something in a quote".
For other punctuation rules, refer to the
[GitLab UX guide](https://design.gitlab.com/content/punctuation/).
@@ -1367,6 +1377,8 @@ hidden on the documentation site, but is displayed by `/help`.
- For regular fenced code blocks, always use a highlighting class corresponding to
the language for better readability. Examples:
+
+
````markdown
```ruby
Ruby code
@@ -1385,6 +1397,8 @@ hidden on the documentation site, but is displayed by `/help`.
```
````
+
+
Syntax highlighting is required for fenced code blocks added to the GitLab
documentation. Refer to the following table for the most common language classes,
or check the [complete list](https://github.com/rouge-ruby/rouge/wiki/List-of-supported-languages-and-lexers)
@@ -1771,8 +1785,7 @@ for use in GitLab X.X, and is planned for [removal](link-to-issue) in GitLab X.X
```
After the feature or product is officially deprecated and removed, remove
-its information from the GitLab documentation based on
-the GitLab version where it's actually removed.
+its information from the GitLab documentation.
### Versions in the past or future
@@ -1926,6 +1939,8 @@ Configuration settings include:
When you document a list of steps, it may entail editing the configuration file
and reconfiguring or restarting GitLab. In that case, use these styles:
+
+
````markdown
**For Omnibus installations**
@@ -1953,6 +1968,8 @@ and reconfiguring or restarting GitLab. In that case, use these styles:
GitLab for the changes to take effect.
````
+
+
In this case:
- Before each step list the installation method is declared in bold.
diff --git a/doc/development/fe_guide/performance.md b/doc/development/fe_guide/performance.md
index 8279cdbe1a4..99e56058881 100644
--- a/doc/development/fe_guide/performance.md
+++ b/doc/development/fe_guide/performance.md
@@ -119,21 +119,21 @@ browser's developer console while on any page within GitLab.
```
Note that `waitForCSSLoaded()` methods supports receiving the action in different ways:
-
+
- With a callback:
-
+
```javascript
waitForCSSLoaded(action)
```
-
+
- With `then()`:
-
+
```javascript
waitForCSSLoaded().then(action);
```
-
+
- With `await` followed by `action`:
-
+
```javascript
await waitForCSSLoaded;
action();
diff --git a/doc/development/go_guide/index.md b/doc/development/go_guide/index.md
index 5fa741f6b61..278e915c597 100644
--- a/doc/development/go_guide/index.md
+++ b/doc/development/go_guide/index.md
@@ -131,6 +131,8 @@ Once [recursive includes](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/568
become available, you can share job templates like this
[analyzer](https://gitlab.com/gitlab-org/security-products/ci-templates/raw/master/includes-dev/analyzer.yml).
+Go GitLab linter plugins are maintained in the [`gitlab-org/language-tools/go/linters`](https://gitlab.com/gitlab-org/language-tools/go/linters/) namespace.
+
## Dependencies
Dependencies should be kept to the minimum. The introduction of a new
diff --git a/doc/development/iterating_tables_in_batches.md b/doc/development/iterating_tables_in_batches.md
index c64cb5e8dfb..814397a3b52 100644
--- a/doc/development/iterating_tables_in_batches.md
+++ b/doc/development/iterating_tables_in_batches.md
@@ -243,8 +243,8 @@ end
The iteration uses the primary key index (on the `id` column) which makes it safe from statement
timeouts. The filter (`sign_in_count: 0`) is applied on the `relation` where the `id` is already constrained (range). The number of rows are limited.
-Slow iteration generally takes more time to finish. The iteration count is higher and
-one iteration could yield fewer records than the batch size. Iterations may even yield
+Slow iteration generally takes more time to finish. The iteration count is higher and
+one iteration could yield fewer records than the batch size. Iterations may even yield
0 records. This is not an optimal solution; however, in some cases (especially when
dealing with large tables) this is the only viable option.
@@ -346,7 +346,7 @@ Here, we expect that the `relation` query reads the `BATCH_SIZE` of user records
filters down the results according to the provided queries. The planner might decide that
using a bitmap index lookup with the index on the `confidential` column is a better way to
execute the query. This can cause unexpectedly high amount of rows to be read and the query
-could time out.
+could time out.
Problem: we know for sure that the relation is returning maximum `BATCH_SIZE` of records, however the planner does not know this.
diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md
index 85b14ed1c64..707251a24bd 100644
--- a/doc/development/migration_style_guide.md
+++ b/doc/development/migration_style_guide.md
@@ -462,8 +462,9 @@ class MyMigration < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
+ INDEX_NAME = 'index_name'
def up
- remove_concurrent_index :table_name, :column_name, name: :index_name
+ remove_concurrent_index :table_name, :column_name, name: INDEX_NAME
end
end
```
diff --git a/doc/development/product_analytics/usage_ping.md b/doc/development/product_analytics/usage_ping.md
index 7293397c9be..a66e92a6116 100644
--- a/doc/development/product_analytics/usage_ping.md
+++ b/doc/development/product_analytics/usage_ping.md
@@ -118,7 +118,7 @@ sequenceDiagram
1. `GitLab::UsageData.to_json` [cascades down](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L22) to ~400+ other counter method calls.
1. The response of all methods calls are [merged together](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L14) into a single JSON payload in `GitLab::UsageData.to_json`.
1. The JSON payload is then [posted to the Versions application]( https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/submit_usage_ping_service.rb#L20)
- If a firewall exception is needed, the required URL depends on several things. If
+ If a firewall exception is needed, the required URL depends on several things. If
the hostname is `version.gitlab.com`, the protocol is `TCP`, and the port number is `443`,
the required URL is .
@@ -477,11 +477,11 @@ Next, get the unique events for the current week.
We have the following recommendations for [Adding new events](#adding-new-events):
- Event aggregation: weekly.
-- Key expiry time:
+- Key expiry time:
- Daily: 29 days.
- Weekly: 42 days.
- When adding new metrics, use a [feature flag](../../operations/feature_flags.md) to control the impact.
-- For feature flags triggered by another service, set `default_enabled: false`,
+- For feature flags triggered by another service, set `default_enabled: false`,
- Events can be triggered using the `UsageData` API, which helps when there are > 10 events per change
##### Enable/Disable Redis HLL tracking
@@ -869,44 +869,6 @@ The following is example content of the Usage Ping payload.
"version": "9.6.15",
"pg_system_id": 6842684531675334351
},
- "avg_cycle_analytics": {
- "issue": {
- "average": 999,
- "sd": 999,
- "missing": 999
- },
- "plan": {
- "average": null,
- "sd": 999,
- "missing": 999
- },
- "code": {
- "average": null,
- "sd": 999,
- "missing": 999
- },
- "test": {
- "average": null,
- "sd": 999,
- "missing": 999
- },
- "review": {
- "average": null,
- "sd": 999,
- "missing": 999
- },
- "staging": {
- "average": null,
- "sd": 999,
- "missing": 999
- },
- "production": {
- "average": null,
- "sd": 999,
- "missing": 999
- },
- "total": 999
- },
"analytics_unique_visits": {
"g_analytics_contribution": 999,
...
diff --git a/doc/development/sidekiq_style_guide.md b/doc/development/sidekiq_style_guide.md
index 2d9cb40d143..909b6de1134 100644
--- a/doc/development/sidekiq_style_guide.md
+++ b/doc/development/sidekiq_style_guide.md
@@ -27,7 +27,7 @@ After adding a new queue, run `bin/rake
gitlab:sidekiq:all_queues_yml:generate` to regenerate
`app/workers/all_queues.yml` or `ee/app/workers/all_queues.yml` so that
it can be picked up by
-[`sidekiq-cluster`](../administration/operations/extra_sidekiq_processes.md).
+[`sidekiq-cluster`](../administration/operations/extra_sidekiq_processes.md).
Additionally, run
`bin/rake gitlab:sidekiq:sidekiq_queues_yml:generate` to regenerate
`config/sidekiq_queues.yml`.
diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md
index c76e6d1880e..9931e15ad44 100644
--- a/doc/development/testing_guide/frontend_testing.md
+++ b/doc/development/testing_guide/frontend_testing.md
@@ -106,7 +106,7 @@ Remember that the performance of each test depends on the environment.
### Timout error due to async components
-If your component is fetching some other components asynchroneously based on some conditions, it might happen so that your Jest suite for this component will become flaky timing out from time to time.
+If your component is fetching some other components asynchroneously based on some conditions, it might happen so that your Jest suite for this component will become flaky timing out from time to time.
```javascript
// ide.vue
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 2a0092450f1..c1eaba9913a 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -227,7 +227,7 @@ The storage requirements for Redis are minimal, about 25kB per user.
Sidekiq processes the background jobs with a multithreaded process.
This process starts with the entire Rails stack (200MB+) but it can grow over time due to memory leaks.
On a very active server (10,000 billable users) the Sidekiq process can use 1GB+ of memory.
-
+
## Prometheus and its exporters
As of Omnibus GitLab 9.0, [Prometheus](https://prometheus.io) and its related
diff --git a/doc/integration/jenkins.md b/doc/integration/jenkins.md
index 70a7f417c75..0a383f1e3b1 100644
--- a/doc/integration/jenkins.md
+++ b/doc/integration/jenkins.md
@@ -196,14 +196,14 @@ WebHook Error => execution expired
```
If those are present, the request is exceeding the
-[webhook timeout](../user/project/integrations/webhooks.md#receiving-duplicate-or-multiple-webhook-requests-triggered-by-one-event),
+[webhook timeout](../user/project/integrations/webhooks.md#webhook-fails-or-multiple-webhook-requests-are-triggered),
which is set to 10 seconds by default.
To fix this the `gitlab_rails['webhook_timeout']` value must be increased
in the `gitlab.rb` config file, followed by the [`gitlab-ctl reconfigure` command](../administration/restart_gitlab.md).
If you don't find the errors above, but do find *duplicate* entries like below (in `/var/log/gitlab/gitlab-rail`), this
-could also indicate that [webhook requests are timing out](../user/project/integrations/webhooks.md#receiving-duplicate-or-multiple-webhook-requests-triggered-by-one-event):
+could also indicate that [webhook requests are timing out](../user/project/integrations/webhooks.md#webhook-fails-or-multiple-webhook-requests-are-triggered):
```plaintext
2019-10-25_04:22:41.25630 2019-10-25T04:22:41.256Z 1584 TID-ovowh4tek WebHookWorker JID-941fb7f40b69dff3d833c99b INFO: start
diff --git a/doc/integration/sourcegraph.md b/doc/integration/sourcegraph.md
index 16492f08028..861e5563328 100644
--- a/doc/integration/sourcegraph.md
+++ b/doc/integration/sourcegraph.md
@@ -64,7 +64,7 @@ Feature.enable(:sourcegraph, Project.find_by_full_path('my_group/my_project'))
If you are new to Sourcegraph, head over to the [Sourcegraph installation documentation](https://docs.sourcegraph.com/admin) and get your instance up and running.
-If you are using an HTTPS connection to GitLab, you will need to [configure HTTPS](https://docs.sourcegraph.com/admin/http_https_configuration) for your Sourcegraph instance.
+If you are using an HTTPS connection to GitLab, you will need to [configure HTTPS](https://docs.sourcegraph.com/admin/http_https_configuration) for your Sourcegraph instance.
### Connect your Sourcegraph instance to your GitLab instance
diff --git a/doc/operations/feature_flags.md b/doc/operations/feature_flags.md
index da1dbf2bba8..37a9e0512c4 100644
--- a/doc/operations/feature_flags.md
+++ b/doc/operations/feature_flags.md
@@ -77,7 +77,6 @@ is 200. On GitLab.com, the maximum number is determined by [GitLab.com tier](htt
> - It became [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/214684) in GitLab 13.2.
> - It's recommended for production use.
> - It's enabled on GitLab.com.
-> - For GitLab self-managed instances, a GitLab administrator can choose to [disable it](#enable-or-disable-feature-flag-strategies). **(CORE ONLY)**
You can apply a feature flag strategy across multiple environments, without defining
the strategy multiple times.
@@ -222,25 +221,6 @@ To remove users from a user list:
1. Click on the **{pencil}** (edit) button next to the list you want to change.
1. Click on the **{remove}** (remove) button next to the ID you want to remove.
-### Enable or disable feature flag strategies
-
-This feature is under development, but is ready for production use. It's
-deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../administration/feature_flags.md)
-can disable it for your instance.
-
-To disable it:
-
-```ruby
-Feature.disable(:feature_flags_new_version)
-```
-
-To enable it:
-
-```ruby
-Feature.enable(:feature_flags_new_version)
-```
-
## Rollout strategy (legacy)
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8240) in GitLab 12.2.
diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md
index e931e5871a4..868c1efa3c1 100644
--- a/doc/raketasks/backup_restore.md
+++ b/doc/raketasks/backup_restore.md
@@ -266,12 +266,12 @@ You can exclude specific directories from the backup by adding the environment v
- `lfs` (LFS objects)
- `registry` (Container Registry images)
- `pages` (Pages content)
-- `repositories` (Git repositories data)
+- `repositories` (Git repositories data)
All wikis will be backed up as part of the `repositories` group. Non-existent wikis will be skipped during a backup.
-
+
NOTE: **Note:**
-When [backing up and restoring Helm Charts](https://docs.gitlab.com/charts/architecture/backup-restore.html), there is an additional option `packages`, which refers to any packages managed by the GitLab [package registry](../user/packages/package_registry/index.md).
+When [backing up and restoring Helm Charts](https://docs.gitlab.com/charts/architecture/backup-restore.html), there is an additional option `packages`, which refers to any packages managed by the GitLab [package registry](../user/packages/package_registry/index.md).
For more information see [command line arguments](https://docs.gitlab.com/charts/architecture/backup-restore.html#command-line-arguments).
All wikis are backed up as part of the `repositories` group. Non-existent
diff --git a/doc/user/application_security/secret_detection/index.md b/doc/user/application_security/secret_detection/index.md
index 0bd2bda5bfb..3d36c64e67d 100644
--- a/doc/user/application_security/secret_detection/index.md
+++ b/doc/user/application_security/secret_detection/index.md
@@ -130,13 +130,13 @@ always take the latest Secret Detection artifact available.
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4639) in GitLab 13.6.
-Upon detection of a secret, GitLab supports post processing hooks. These can be used to take actions like notifying the cloud service who issued the secret. The cloud provider can confirm the credentials and take remediation actions like revoking or reissuing a new secret and notifying the creator of the secret. Post-processing workflows vary by supported cloud providers.
+Upon detection of a secret, GitLab supports post processing hooks. These can be used to take actions like notifying the cloud service who issued the secret. The cloud provider can confirm the credentials and take remediation actions like revoking or reissuing a new secret and notifying the creator of the secret. Post-processing workflows vary by supported cloud providers.
GitLab currently supports post-processing for following service providers:
- Amazon Web Services (AWS)
-Third party cloud and SaaS providers can [express integration interest by filling out this form](https://forms.gle/wWpvrtLRK21Q2WJL9). Learn more about the [technical details of post-processing secrets](https://gitlab.com/groups/gitlab-org/-/epics/4639).
+Third party cloud and SaaS providers can [express integration interest by filling out this form](https://forms.gle/wWpvrtLRK21Q2WJL9). Learn more about the [technical details of post-processing secrets](https://gitlab.com/groups/gitlab-org/-/epics/4639).
### Customizing settings
@@ -286,14 +286,14 @@ For information on this, see the [general Application Security troubleshooting s
### Error: `Couldn't run the gitleaks command: exit status 2`
-This error is usually caused by the `GIT_DEPTH` value of 50 that is set for all [projects by default](../../../ci/pipelines/settings.md#git-shallow-clone).
+This error is usually caused by the `GIT_DEPTH` value of 50 that is set for all [projects by default](../../../ci/pipelines/settings.md#git-shallow-clone).
-For example, if a pipeline is triggered from a Merge Request containing 60 commits while the `GIT_DEPTH` is set to 50, the Secret Detection job will fail as the clone will not have been deep enough to contain all of the relevant commits.
+For example, if a pipeline is triggered from a Merge Request containing 60 commits while the `GIT_DEPTH` is set to 50, the Secret Detection job will fail as the clone will not have been deep enough to contain all of the relevant commits.
You can confirm this to be the cause of the error by implementing a [logging level](../../application_security/secret_detection/index.md#logging-level) of `debug`. Once implemented, the logs should look similar to the following example, wherein an "object not found" error can be seen:
```plaintext
-ERRO[2020-11-18T18:05:52Z] object not found
+ERRO[2020-11-18T18:05:52Z] object not found
[ERRO] [secrets] [2020-11-18T18:05:52Z] â–¶ Couldn't run the gitleaks command: exit status 2
[ERRO] [secrets] [2020-11-18T18:05:52Z] â–¶ Gitleaks analysis failed: exit status 2
```
diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md
index 31ff86adf38..df4e5ea091e 100644
--- a/doc/user/group/saml_sso/index.md
+++ b/doc/user/group/saml_sso/index.md
@@ -241,7 +241,7 @@ Users can unlink SAML for a group from their profile page. This can be helpful i
- Your SAML NameID has changed and so GitLab can no longer find your user.
CAUTION: **Warning:**
-Unlinking an account removes all roles assigned to that user within the group.
+Unlinking an account removes all roles assigned to that user within the group.
If a user relinks their account, roles need to be reassigned.
For example, to unlink the `MyOrg` account, the following **Disconnect** button is available under **Profile > Accounts**:
@@ -274,14 +274,14 @@ To link the SAML `Freelancers` group in the attribute statement example above:
1. Enter `Freelancers` in the `SAML Group Name` field.
1. Choose the desired `Access Level`.
-1. **Save** the group link.
-1. Repeat to add additional group links if desired.
+1. **Save** the group link.
+1. Repeat to add additional group links if desired.
![SAML Group Links](img/saml_group_links_v13_6.png)
-If a user is a member of multiple SAML groups mapped to the same GitLab group,
+If a user is a member of multiple SAML groups mapped to the same GitLab group,
the user gets the highest access level from the groups. For example, if one group
-is linked as `Guest` and another `Maintainer`, a user in both groups gets `Maintainer`
+is linked as `Guest` and another `Maintainer`, a user in both groups gets `Maintainer`
access.
## Glossary
diff --git a/doc/user/packages/conan_repository/index.md b/doc/user/packages/conan_repository/index.md
index 35d854b0aa3..92fdcde7331 100644
--- a/doc/user/packages/conan_repository/index.md
+++ b/doc/user/packages/conan_repository/index.md
@@ -292,7 +292,7 @@ Prerequisites:
- [Authentication](#authenticate-to-the-package-registry) with the
Package Registry must be configured.
-1. In the project where you want to install the package as a dependency, open
+1. In the project where you want to install the package as a dependency, open
`conanfile.txt`. Or, in the root of your project, create a file called
`conanfile.txt`.
diff --git a/doc/user/packages/index.md b/doc/user/packages/index.md
index d9f79505eea..9da14842845 100644
--- a/doc/user/packages/index.md
+++ b/doc/user/packages/index.md
@@ -32,7 +32,7 @@ You can also use the [API](../../api/packages.md) to administer the Package Regi
## Accepting contributions
-The below table lists formats that are not supported, but are accepting Community contributions for. Consider contributing to GitLab. This [development documentation](../../development/packages.md)
+The below table lists formats that are not supported, but are accepting Community contributions for. Consider contributing to GitLab. This [development documentation](../../development/packages.md)
guides you through the process.
| Format | Status |
diff --git a/doc/user/project/integrations/jira_server_configuration.md b/doc/user/project/integrations/jira_server_configuration.md
index 39370f8a84e..161b6754c55 100644
--- a/doc/user/project/integrations/jira_server_configuration.md
+++ b/doc/user/project/integrations/jira_server_configuration.md
@@ -23,7 +23,7 @@ access to your Jira projects. This is covered in the process below.
1. The next step is to create a new user (e.g., `gitlab`) who has write access
to projects in Jira. Enter the user's name and a _valid_ e-mail address
since Jira sends a verification e-mail to set up the password.
-
+
Jira creates the username automatically by using the e-mail
prefix. You can change it later, if needed. Our integration does not support SSO (such as SAML). You
need to create an HTTP basic authentication password. You can do this by visiting the user
diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md
index 4fc55d5afd9..089ae9e05d1 100644
--- a/doc/user/project/integrations/webhooks.md
+++ b/doc/user/project/integrations/webhooks.md
@@ -11,8 +11,8 @@ a new issue is created. You can configure webhooks to listen for specific events
like pushes, issues or merge requests. GitLab sends a POST request with data
to the webhook URL.
-In most cases, you need to set up your own [webhook receiver](#example-webhook-receiver)
-to receive information from GitLab, and send it to another app, according to your needs.
+You usually need to set up your own [webhook receiver](#example-webhook-receiver)
+to receive information from GitLab and send it to another app, according to your requirements.
We already have a [built-in receiver](slack.md)
for sending [Slack](https://api.slack.com/incoming-webhooks) notifications _per project_.
@@ -33,7 +33,7 @@ and **per project and per group** for **GitLab Enterprise Edition**.
Navigate to the webhooks page at your project's **Settings > Webhooks**.
-NOTE: **Note:**
+NOTE:
On GitLab.com, the [maximum number of webhooks and their size](../../../user/gitlab_com/index.md#webhooks) per project, and per group, is limited.
## Version history
@@ -54,7 +54,7 @@ Starting from GitLab 11.2:
`![](/uploads/...)`) have their target URL changed to an absolute URL. See
[image URL rewriting](#image-url-rewriting) for more details.
-## Use-cases
+## Possible uses for webhooks
- You can set up a webhook in GitLab to send a notification to
[Slack](https://api.slack.com/incoming-webhooks) every time a job fails.
@@ -65,12 +65,12 @@ Starting from GitLab 11.2:
## Webhook endpoint tips
If you are writing your own endpoint (web server) to receive
-GitLab webhooks, keep in mind the following things:
+GitLab webhooks, keep in mind the following:
-- Your endpoint should send its HTTP response as fast as possible. If
- you wait too long (by default, a timeout of 10 seconds), GitLab may decide
- the hook failed and retry it. You can configure this timeout with
- `gitlab_rails['webhook_timeout']`.
+- Your endpoint should send its HTTP response as fast as possible. If the response takes longer than
+ the configured timeout, GitLab decides the hook failed and retries it. For information on
+ customizing this timeout, see
+ [Webhook fails or multiple webhook requests are triggered](#webhook-fails-or-multiple-webhook-requests-are-triggered).
- Your endpoint should ALWAYS return a valid HTTP response. If you do
not do this then GitLab thinks the hook failed and retries it.
Most HTTP libraries take care of this for you automatically but if
@@ -86,7 +86,7 @@ that the request is legitimate.
## SSL verification
By default, the SSL certificate of the webhook endpoint is verified based on
-an internal list of Certificate Authorities, which means the certificate cannot
+an internal list of Certificate Authorities. This means the certificate cannot
be self-signed.
You can turn this off in the webhook settings in your GitLab projects.
@@ -109,7 +109,7 @@ Below are described the supported events.
Triggered when you push to the repository except when pushing tags.
-NOTE: **Note:**
+NOTE:
When more than 20 commits are pushed at once, the `commits` webhook
attribute only contains the first 20 for performance reasons. Loading
detailed commit data is expensive. Note that despite only 20 commits being
@@ -204,7 +204,7 @@ X-Gitlab-Event: Push Hook
Triggered when you create (or delete) tags to the repository.
-NOTE: **Note:**
+NOTE:
If a single push includes changes for more than three (by default, depending on
[`push_event_hooks_limit` setting](../../../api/settings.md#list-of-settings-that-can-be-accessed-via-api-calls))
tags, this hook is not executed.
@@ -409,12 +409,12 @@ X-Gitlab-Event: Issue Hook
}
```
-> **Note**: `assignee` and `assignee_id` keys are deprecated and now show the first assignee only.
+NOTE: `assignee` and `assignee_id` keys are deprecated and now show the first assignee only.
### Comment events
Triggered when a new comment is made on commits, merge requests, issues, and code snippets.
-The note data is stored in `object_attributes` (e.g. `note`, `noteable_type`). The
+The note data is stored in `object_attributes` (for example, `note` or `noteable_type`). The
payload also includes information about the target of the comment. For example,
a comment on an issue includes the specific issue information under the `issue` key.
Valid target types:
@@ -734,7 +734,7 @@ X-Gitlab-Event: Note Hook
}
```
-> **Note**: `assignee_id` field is deprecated and now shows the first assignee only.
+NOTE: `assignee_id` field is deprecated and now shows the first assignee only.
#### Comment on code snippet
@@ -1531,29 +1531,36 @@ You can find records for last 2 days in "Recent Deliveries" section on the edit
![Recent deliveries](img/webhook_logs.png)
-In this section you can see HTTP status code (green for 200-299 codes, red for the others, `internal error` for failed deliveries ), triggered event, a time when the event was called, elapsed time of the request.
+In this section you can see:
+
+- HTTP status code (green for `200-299` codes, red for the others, `internal error` for failed deliveries).
+- Triggered event.
+- A time when the event was called.
+- Elapsed time of the request.
If you need more information about execution, you can click `View details` link.
On this page, you can see data that GitLab sends (request headers and body) and data that it received (response headers and body).
From this page, you can repeat delivery with the same data by clicking `Resend Request` button.
-NOTE: **Note:**
+NOTE:
If URL or secret token of the webhook were updated, data is delivered to the new address.
-### Receiving duplicate or multiple webhook requests triggered by one event
+### Webhook fails or multiple webhook requests are triggered
-When GitLab sends a webhook, it expects a response in 10 seconds (set default value). If it does not receive one, it retries the webhook.
-If the endpoint doesn't send its HTTP response within those 10 seconds, GitLab may decide the hook failed and retry it.
+When GitLab sends a webhook, it expects a response in 10 seconds by default. If it does not receive
+one, it retries the webhook. If the endpoint doesn't send its HTTP response within those 10 seconds,
+GitLab may decide the hook failed and retry it.
-If you are receiving multiple requests, you can try increasing the default value to wait for the HTTP response after sending the webhook
-by uncommenting or adding the following setting to your `/etc/gitlab/gitlab.rb`:
+If your webhooks are failing or you are receiving multiple requests, you can try changing the
+default value. You can do this by uncommenting or adding the following setting to your
+`/etc/gitlab/gitlab.rb` file:
```ruby
gitlab_rails['webhook_timeout'] = 10
```
-### Troubleshooting: "Unable to get local issuer certificate"
+### Unable to get local issuer certificate
When SSL verification is enabled, this error indicates that GitLab isn't able to verify the SSL certificate of the webhook endpoint.
Typically, this is because the root certificate isn't issued by a trusted certification authority as
@@ -1584,7 +1591,7 @@ end
server.start
```
-Pick an unused port (e.g. 8000) and start the script: `ruby print_http_body.rb
+Pick an unused port (for example, `8000`) and start the script: `ruby print_http_body.rb
8000`. Then add your server as a webhook receiver in GitLab as
`http://my.host:8000/`.
@@ -1597,5 +1604,6 @@ example.com - - [14/May/2014:07:45:26 EDT] "POST / HTTP/1.1" 200 0
- -> /
```
-NOTE: **Note:**
-You may need to [allow requests to the local network](../../../security/webhooks.md) for this receiver to be added.
+NOTE:
+You may need to [allow requests to the local network](../../../security/webhooks.md) for this
+receiver to be added.
diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md
index 306eee36204..45289d615a8 100644
--- a/doc/user/project/quick_actions.md
+++ b/doc/user/project/quick_actions.md
@@ -34,6 +34,7 @@ The following quick actions are applicable to descriptions, discussions and thre
| `/award :emoji:` | ✓ | ✓ | ✓ | Toggle emoji award. |
| `/child_epic ` | | | ✓ | Add child epic to ``. The `` value should be in the format of `&epic`, `group&epic`, or a URL to an epic ([introduced in GitLab 12.0](https://gitlab.com/gitlab-org/gitlab/-/issues/7330)). **(ULTIMATE)** |
| `/clear_weight` | ✓ | | | Clear weight. **(STARTER)** |
+| `/clone ` | ✓ | | | Clone the issue to given project, or the current one if no arguments are given ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9421) in GitLab 13.7). Copies as much data as possible as long as the target project contains equivalent labels, milestones, etc. Does not copy comments or system notes. |
| `/close` | ✓ | ✓ | ✓ | Close. |
| `/confidential` | ✓ | | | Make confidential. |
| `/copy_metadata ` | ✓ | ✓ | | Copy labels and milestone from another merge request in the project. |
diff --git a/doc/user/project/releases/index.md b/doc/user/project/releases/index.md
index 56902b4a82c..3562ef1bb28 100644
--- a/doc/user/project/releases/index.md
+++ b/doc/user/project/releases/index.md
@@ -79,7 +79,7 @@ To create a new release through the GitLab UI:
[release notes](#release-notes-description), or [assets links](#links).
1. Click **Create release**.
-### Create release from GitLab CI
+### Create release from GitLab CI
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/19298) in GitLab 12.7.
diff --git a/doc/user/project/settings/project_access_tokens.md b/doc/user/project/settings/project_access_tokens.md
index fcd32989251..13c9143e512 100644
--- a/doc/user/project/settings/project_access_tokens.md
+++ b/doc/user/project/settings/project_access_tokens.md
@@ -16,6 +16,9 @@ Project access tokens are supported for self-managed instances on Core and above
> - [Became available on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/235765) in 13.5.
> - It's recommended for production use.
+CAUTION: **Warning:**
+This feature might not be available to you. Check the **version history** note above for details.
+
Project access tokens are scoped to a project and can be used to authenticate with the [GitLab API](../../../api/README.md#personalproject-access-tokens). You can also use project access tokens with Git to authenticate over HTTP.
Project access tokens expire on the date you define, at midnight UTC.
@@ -75,3 +78,33 @@ the following table.
| `write_registry` | Allows write-access (push) to [container registry](../../packages/container_registry/index.md). |
| `read_repository` | Allows read-only access (pull) to the repository. |
| `write_repository` | Allows read-write access (pull, push) to the repository. |
+
+### Enable or disable project access tokens
+
+Project access tokens are deployed behind a feature flag that is **enabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
+can disable it for your instance, globally or by project.
+
+To disable it globally:
+
+```ruby
+Feature.disable(:resource_access_token)
+```
+
+To disable it for a specific project:
+
+```ruby
+Feature.disable(:resource_access_token, project)
+```
+
+To enable it globally:
+
+```ruby
+Feature.enable(:resource_access_token)
+```
+
+To enable it for a specific project:
+
+```ruby
+Feature.enable(:resource_access_token, project)
+```
diff --git a/lib/api/entities/feature_flag.rb b/lib/api/entities/feature_flag.rb
index 82fdb20af00..f383eabd5dc 100644
--- a/lib/api/entities/feature_flag.rb
+++ b/lib/api/entities/feature_flag.rb
@@ -6,11 +6,11 @@ module API
expose :name
expose :description
expose :active
- expose :version, if: :feature_flags_new_version_enabled
+ expose :version
expose :created_at
expose :updated_at
expose :scopes, using: FeatureFlag::LegacyScope
- expose :strategies, using: FeatureFlag::Strategy, if: :feature_flags_new_version_enabled
+ expose :strategies, using: FeatureFlag::Strategy
end
end
end
diff --git a/lib/api/feature_flags.rb b/lib/api/feature_flags.rb
index 67168ba9be6..6fdc4535be3 100644
--- a/lib/api/feature_flags.rb
+++ b/lib/api/feature_flags.rb
@@ -62,8 +62,6 @@ module API
attrs = declared_params(include_missing: false)
- ensure_post_version_2_flags_enabled! if attrs[:version] == 'new_version_flag'
-
rename_key(attrs, :scopes, :scopes_attributes)
rename_key(attrs, :strategies, :strategies_attributes)
update_value(attrs, :strategies_attributes) do |strategies|
@@ -143,7 +141,7 @@ module API
end
desc 'Update a feature flag' do
- detail 'This feature will be introduced in GitLab 13.1 if feature_flags_new_version feature flag is removed'
+ detail 'This feature was introduced in GitLab 13.2'
success ::API::Entities::FeatureFlag
end
params do
@@ -163,7 +161,6 @@ module API
end
end
put do
- not_found! unless feature_flags_new_version_enabled?
authorize_update_feature_flag!
render_api_error!('PUT operations are not supported for legacy feature flags', :unprocessable_entity) if feature_flag.legacy_flag?
@@ -228,32 +225,17 @@ module API
def present_entity(result)
present result,
- with: ::API::Entities::FeatureFlag,
- feature_flags_new_version_enabled: feature_flags_new_version_enabled?
- end
-
- def ensure_post_version_2_flags_enabled!
- unless feature_flags_new_version_enabled?
- render_api_error!('Version 2 flags are not enabled for this project', :unprocessable_entity)
- end
+ with: ::API::Entities::FeatureFlag
end
def feature_flag
- @feature_flag ||= if feature_flags_new_version_enabled?
- user_project.operations_feature_flags.find_by_name!(params[:feature_flag_name])
- else
- user_project.operations_feature_flags.legacy_flag.find_by_name!(params[:feature_flag_name])
- end
+ @feature_flag ||= user_project.operations_feature_flags.find_by_name!(params[:feature_flag_name])
end
def new_version_flag_present?
user_project.operations_feature_flags.new_version_flag.find_by_name(params[:name]).present?
end
- def feature_flags_new_version_enabled?
- Feature.enabled?(:feature_flags_new_version, user_project, default_enabled: true)
- end
-
def rename_key(hash, old_key, new_key)
hash[new_key] = hash.delete(old_key) if hash.key?(old_key)
hash
diff --git a/lib/gitlab/cycle_analytics/usage_data.rb b/lib/gitlab/cycle_analytics/usage_data.rb
deleted file mode 100644
index e58def57e69..00000000000
--- a/lib/gitlab/cycle_analytics/usage_data.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- class UsageData
- include Gitlab::Utils::StrongMemoize
- PROJECTS_LIMIT = 10
-
- attr_reader :options
-
- def initialize
- @options = { from: 7.days.ago }
- end
-
- def projects
- strong_memoize(:projects) do
- projects = Project.where.not(last_activity_at: nil).order(last_activity_at: :desc).limit(10) +
- Project.where.not(last_repository_updated_at: nil).order(last_repository_updated_at: :desc).limit(10)
-
- projects = projects.uniq.sort_by do |project|
- [project.last_activity_at, project.last_repository_updated_at].min
- end
-
- if projects.size < 10
- projects.concat(Project.where(last_activity_at: nil, last_repository_updated_at: nil).limit(10))
- end
-
- projects.uniq.first(10)
- end
- end
-
- def to_json(*)
- total = 0
-
- values =
- medians_per_stage.each_with_object({}) do |(stage_name, medians), hsh|
- calculations = stage_values(medians)
-
- total += calculations.values.compact.sum
- hsh[stage_name] = calculations
- end
-
- values[:total] = total
-
- { avg_cycle_analytics: values }
- end
-
- private
-
- def medians_per_stage
- projects.each_with_object({}) do |project, hsh|
- ::CycleAnalytics::ProjectLevel.new(project, options: options).all_medians_by_stage.each do |stage_name, median|
- hsh[stage_name] ||= []
- hsh[stage_name] << median
- end
- end
- end
-
- def stage_values(medians)
- medians = medians.map(&:presence).compact
- average = calc_average(medians)
-
- {
- average: average,
- sd: standard_deviation(medians, average),
- missing: projects.length - medians.length
- }
- end
-
- def calc_average(values)
- return if values.empty?
-
- (values.sum / values.length).to_i
- end
-
- def standard_deviation(values, average)
- Math.sqrt(sample_variance(values, average)).to_i
- end
-
- def sample_variance(values, average)
- return 0 if values.length <= 1
-
- sum = values.inject(0) do |acc, val|
- acc + (val - average)**2
- end
-
- sum / (values.length - 1)
- end
- end
- end
-end
diff --git a/lib/gitlab/experimentation/controller_concern.rb b/lib/gitlab/experimentation/controller_concern.rb
index 3b9b19d5606..c85d3f4eee6 100644
--- a/lib/gitlab/experimentation/controller_concern.rb
+++ b/lib/gitlab/experimentation/controller_concern.rb
@@ -61,11 +61,11 @@ module Gitlab
end
end
- def record_experiment_user(experiment_key)
+ def record_experiment_user(experiment_key, context = {})
return if dnt_enabled?
return unless Experimentation.active?(experiment_key) && current_user
- ::Experiment.add_user(experiment_key, tracking_group(experiment_key, nil, subject: current_user), current_user)
+ ::Experiment.add_user(experiment_key, tracking_group(experiment_key, nil, subject: current_user), current_user, context)
end
def record_experiment_conversion_event(experiment_key)
diff --git a/lib/gitlab/quick_actions/issue_actions.rb b/lib/gitlab/quick_actions/issue_actions.rb
index b0aae363749..400547bb6c1 100644
--- a/lib/gitlab/quick_actions/issue_actions.rb
+++ b/lib/gitlab/quick_actions/issue_actions.rb
@@ -102,6 +102,30 @@ module Gitlab
@execution_message[:duplicate] = message
end
+ desc _('Clone this issue')
+ explanation do |project = quick_action_target.project.full_path|
+ _("Clones this issue, without comments, to %{project}.") % { project: project }
+ end
+ params 'path/to/project'
+ types Issue
+ condition do
+ quick_action_target.persisted? &&
+ current_user.can?(:"admin_#{quick_action_target.to_ability_name}", project)
+ end
+ command :clone do |target_project_path = nil|
+ target_project = target_project_path.present? ? Project.find_by_full_path(target_project_path) : quick_action_target.project
+
+ if target_project.present?
+ @updates[:target_clone_project] = target_project
+
+ message = _("Cloned this issue to %{path_to_project}.") % { path_to_project: target_project_path || quick_action_target.project.full_path }
+ else
+ message = _("Failed to clone this issue because target project doesn't exist.")
+ end
+
+ @execution_message[:clone] = message
+ end
+
desc _('Move this issue to another project.')
explanation do |path_to_project|
_("Moves this issue to %{path_to_project}.") % { path_to_project: path_to_project }
diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb
index 91f9c8c2cff..b182a160e29 100644
--- a/lib/gitlab/usage_data.rb
+++ b/lib/gitlab/usage_data.rb
@@ -47,7 +47,6 @@ module Gitlab
.merge(system_usage_data_weekly)
.merge(features_usage_data)
.merge(components_usage_data)
- .merge(cycle_analytics_usage_data)
.merge(object_store_usage_data)
.merge(topology_usage_data)
.merge(usage_activity_by_stage)
@@ -250,12 +249,6 @@ module Gitlab
}
end
- def cycle_analytics_usage_data
- Gitlab::CycleAnalytics::UsageData.new.to_json
- rescue ActiveRecord::StatementInvalid
- { avg_cycle_analytics: {} }
- end
-
# rubocop:disable CodeReuse/ActiveRecord
def grafana_embed_usage_data
count(Issue.joins('JOIN grafana_integrations USING (project_id)')
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index fcf397e3162..f94829de0b4 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -2619,6 +2619,9 @@ msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
+msgid "AlertSettings|Prometheus"
+msgstr ""
+
msgid "AlertSettings|Prometheus API base URL"
msgstr ""
@@ -5662,6 +5665,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5680,18 @@ msgstr ""
msgid "Clone with SSH"
msgstr ""
+msgid "CloneIssue|Cannot clone issue due to insufficient permissions!"
+msgstr ""
+
+msgid "CloneIssue|Cannot clone issue to target project as it is pending deletion."
+msgstr ""
+
+msgid "Cloned this issue to %{path_to_project}."
+msgstr ""
+
+msgid "Clones this issue, without comments, to %{project}."
+msgstr ""
+
msgid "Close"
msgstr ""
@@ -11421,6 +11439,9 @@ msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to clone this issue because target project doesn't exist."
+msgstr ""
+
msgid "Failed to create Merge Request. Please try again."
msgstr ""
@@ -11756,9 +11777,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
diff --git a/package.json b/package.json
index 471998f7c20..20b0cc8d958 100644
--- a/package.json
+++ b/package.json
@@ -42,7 +42,7 @@
"@babel/plugin-syntax-import-meta": "^7.10.1",
"@babel/preset-env": "^7.10.1",
"@gitlab/at.js": "1.5.5",
- "@gitlab/svgs": "1.175.0",
+ "@gitlab/svgs": "1.176.0",
"@gitlab/ui": "24.4.0",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "^6.0.3-3",
diff --git a/spec/controllers/projects/feature_flags_controller_spec.rb b/spec/controllers/projects/feature_flags_controller_spec.rb
index 96eeb6f239f..ebe964aa465 100644
--- a/spec/controllers/projects/feature_flags_controller_spec.rb
+++ b/spec/controllers/projects/feature_flags_controller_spec.rb
@@ -217,15 +217,6 @@ RSpec.describe Projects::FeatureFlagsController do
expect(json_response['feature_flags'].count).to eq(3)
end
-
- it 'returns only version 1 flags when new version flags are disabled' do
- stub_feature_flags(feature_flags_new_version: false)
-
- subject
-
- expected = [feature_flag_active.name, feature_flag_inactive.name].sort
- expect(json_response['feature_flags'].map { |f| f['name'] }.sort).to eq(expected)
- end
end
end
@@ -283,24 +274,6 @@ RSpec.describe Projects::FeatureFlagsController do
expect(json_response['name']).to eq(other_feature_flag.name)
end
- it 'routes based on iid when new version flags are disabled' do
- stub_feature_flags(feature_flags_new_version: false)
- other_project = create(:project)
- other_project.add_developer(user)
- other_feature_flag = create(:operations_feature_flag, project: other_project,
- name: 'other_flag')
- params = {
- namespace_id: other_project.namespace,
- project_id: other_project,
- iid: other_feature_flag.iid
- }
-
- get(:show, params: params, format: :json)
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['name']).to eq(other_feature_flag.name)
- end
-
context 'when feature flag is not found' do
let!(:feature_flag) { }
@@ -386,14 +359,6 @@ RSpec.describe Projects::FeatureFlagsController do
expect(json_response['version']).to eq('new_version_flag')
end
- it 'returns a 404 when new version flags are disabled' do
- stub_feature_flags(feature_flags_new_version: false)
-
- subject
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
-
it 'returns strategies ordered by id' do
first_strategy = create(:operations_strategy, feature_flag: new_version_feature_flag)
second_strategy = create(:operations_strategy, feature_flag: new_version_feature_flag)
@@ -791,54 +756,6 @@ RSpec.describe Projects::FeatureFlagsController do
expect(Operations::FeatureFlag.count).to eq(0)
end
end
-
- context 'when version 2 flags are disabled' do
- context 'and attempting to create a version 2 flag' do
- let(:params) do
- {
- namespace_id: project.namespace,
- project_id: project,
- operations_feature_flag: {
- name: 'my_feature_flag',
- active: true,
- version: 'new_version_flag'
- }
- }
- end
-
- it 'returns a 400' do
- stub_feature_flags(feature_flags_new_version: false)
-
- subject
-
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(Operations::FeatureFlag.count).to eq(0)
- end
- end
-
- context 'and attempting to create a version 1 flag' do
- let(:params) do
- {
- namespace_id: project.namespace,
- project_id: project,
- operations_feature_flag: {
- name: 'my_feature_flag',
- active: true
- }
- }
- end
-
- it 'creates the flag' do
- stub_feature_flags(feature_flags_new_version: false)
-
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(Operations::FeatureFlag.count).to eq(1)
- expect(json_response['version']).to eq('legacy_flag')
- end
- end
- end
end
describe 'DELETE destroy.json' do
@@ -913,15 +830,6 @@ RSpec.describe Projects::FeatureFlagsController do
it 'deletes the flag' do
expect { subject }.to change { Operations::FeatureFlag.count }.by(-1)
end
-
- context 'when new version flags are disabled' do
- it 'returns a 404' do
- stub_feature_flags(feature_flags_new_version: false)
-
- expect { subject }.not_to change { Operations::FeatureFlag.count }
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
end
end
@@ -1576,15 +1484,6 @@ RSpec.describe Projects::FeatureFlagsController do
expect(json_response['strategies'].first['scopes']).to eq([])
end
- it 'does not update the flag if version 2 flags are disabled' do
- stub_feature_flags(feature_flags_new_version: false)
-
- put_request(new_version_flag, { name: 'some-other-name' })
-
- expect(response).to have_gitlab_http_status(:not_found)
- expect(new_version_flag.reload.name).to eq('new-feature')
- end
-
it 'updates the flag when legacy feature flags are set to be read only' do
stub_feature_flags(feature_flags_legacy_read_only: true)
diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb
index a06ba4f229a..1889e2b81a5 100644
--- a/spec/db/schema_spec.rb
+++ b/spec/db/schema_spec.rb
@@ -184,6 +184,7 @@ RSpec.describe 'Database schema' do
"ApplicationSetting" => %w[repository_storages_weighted],
"AlertManagement::Alert" => %w[payload],
"Ci::BuildMetadata" => %w[config_options config_variables],
+ "ExperimentUser" => %w[context],
"Geo::Event" => %w[payload],
"GeoNodeStatus" => %w[status],
"Operations::FeatureFlagScope" => %w[strategies],
diff --git a/spec/features/groups/container_registry_spec.rb b/spec/features/groups/container_registry_spec.rb
index 1b23b8b4bf9..cacabdda22d 100644
--- a/spec/features/groups/container_registry_spec.rb
+++ b/spec/features/groups/container_registry_spec.rb
@@ -51,13 +51,6 @@ RSpec.describe 'Container Registry', :js do
expect(page).to have_content 'my/image'
end
- it 'image repository delete is disabled' do
- visit_container_registry
-
- delete_btn = find('[title="Remove repository"]')
- expect(delete_btn).to be_disabled
- end
-
it 'navigates to repo details' do
visit_container_registry_details('my/image')
diff --git a/spec/features/issues/user_uses_quick_actions_spec.rb b/spec/features/issues/user_uses_quick_actions_spec.rb
index c5eb3f415ff..d88b816b186 100644
--- a/spec/features/issues/user_uses_quick_actions_spec.rb
+++ b/spec/features/issues/user_uses_quick_actions_spec.rb
@@ -43,5 +43,6 @@ RSpec.describe 'Issues > User uses quick actions', :js do
it_behaves_like 'create_merge_request quick action'
it_behaves_like 'move quick action'
it_behaves_like 'zoom quick actions'
+ it_behaves_like 'clone quick action'
end
end
diff --git a/spec/features/projects/container_registry_spec.rb b/spec/features/projects/container_registry_spec.rb
index 45bf35a6aab..5231e8d5550 100644
--- a/spec/features/projects/container_registry_spec.rb
+++ b/spec/features/projects/container_registry_spec.rb
@@ -94,7 +94,8 @@ RSpec.describe 'Container Registry', :js do
end
it('pagination navigate to the second page') do
- visit_second_page
+ visit_details_second_page
+
expect(page).to have_content '20'
end
end
@@ -116,22 +117,23 @@ RSpec.describe 'Container Registry', :js do
context 'when there are more than 10 images' do
before do
- create_list(:container_repository, 12, project: project)
project.container_repositories << container_repository
+ create_list(:container_repository, 12, project: project)
+
visit_container_registry
end
it 'shows pagination' do
- expect(page).to have_css '.gl-pagination'
+ expect(page).to have_css '.gl-keyset-pagination'
end
it 'pagination goes to second page' do
- visit_second_page
+ visit_list_next_page
expect(page).to have_content 'my/image'
end
it 'pagination is preserved after navigating back from details' do
- visit_second_page
+ visit_list_next_page
click_link 'my/image'
breadcrumb = find '.breadcrumbs'
breadcrumb.click_link 'Container Registry'
@@ -148,7 +150,12 @@ RSpec.describe 'Container Registry', :js do
click_link name
end
- def visit_second_page
+ def visit_list_next_page
+ pagination = find '.gl-keyset-pagination'
+ pagination.click_button 'Next'
+ end
+
+ def visit_details_second_page
pagination = find '.gl-pagination'
pagination.click_link '2'
end
diff --git a/spec/features/projects/feature_flags/user_creates_feature_flag_spec.rb b/spec/features/projects/feature_flags/user_creates_feature_flag_spec.rb
index 830dda737b0..eaafc7e607b 100644
--- a/spec/features/projects/feature_flags/user_creates_feature_flag_spec.rb
+++ b/spec/features/projects/feature_flags/user_creates_feature_flag_spec.rb
@@ -67,118 +67,6 @@ RSpec.describe 'User creates feature flag', :js do
end
end
- context 'with new version flags disabled' do
- before do
- stub_feature_flags(feature_flags_new_version: false)
- end
-
- context 'when creates without changing scopes' do
- before do
- visit(new_project_feature_flag_path(project))
- set_feature_flag_info('ci_live_trace', 'For live trace')
- click_button 'Create feature flag'
- expect(page).to have_current_path(project_feature_flags_path(project))
- end
-
- it 'shows the created feature flag' do
- within_feature_flag_row(1) do
- expect(page.find('.feature-flag-name')).to have_content('ci_live_trace')
- expect_status_toggle_button_to_be_checked
-
- within_feature_flag_scopes do
- expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(1)')).to have_content('*')
- end
- end
- end
- end
-
- context 'when creates with disabling the default scope' do
- before do
- visit(new_project_feature_flag_path(project))
- set_feature_flag_info('ci_live_trace', 'For live trace')
-
- within_scope_row(1) do
- within_status { find('.project-feature-toggle').click }
- end
-
- click_button 'Create feature flag'
- end
-
- it 'shows the created feature flag' do
- within_feature_flag_row(1) do
- expect(page.find('.feature-flag-name')).to have_content('ci_live_trace')
- expect_status_toggle_button_to_be_checked
-
- within_feature_flag_scopes do
- expect(page.find('[data-qa-selector="feature-flag-scope-muted-badge"]:nth-child(1)')).to have_content('*')
- end
- end
- end
- end
-
- context 'when creates with an additional scope' do
- before do
- visit(new_project_feature_flag_path(project))
- set_feature_flag_info('mr_train', '')
-
- within_scope_row(2) do
- within_environment_spec do
- find('.js-env-search > input').set("review/*")
- find('.js-create-button').click
- end
- end
-
- within_scope_row(2) do
- within_status { find('.project-feature-toggle').click }
- end
-
- click_button 'Create feature flag'
- end
-
- it 'shows the created feature flag' do
- within_feature_flag_row(1) do
- expect(page.find('.feature-flag-name')).to have_content('mr_train')
- expect_status_toggle_button_to_be_checked
-
- within_feature_flag_scopes do
- expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(1)')).to have_content('*')
- expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(2)')).to have_content('review/*')
- end
- end
- end
- end
-
- context 'when searches an environment name for scope creation' do
- let!(:environment) { create(:environment, name: 'production', project: project) }
-
- before do
- visit(new_project_feature_flag_path(project))
- set_feature_flag_info('mr_train', '')
-
- within_scope_row(2) do
- within_environment_spec do
- find('.js-env-search > input').set('prod')
- click_button 'production'
- end
- end
-
- click_button 'Create feature flag'
- end
-
- it 'shows the created feature flag' do
- within_feature_flag_row(1) do
- expect(page.find('.feature-flag-name')).to have_content('mr_train')
- expect_status_toggle_button_to_be_checked
-
- within_feature_flag_scopes do
- expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(1)')).to have_content('*')
- expect(page.find('[data-qa-selector="feature-flag-scope-muted-badge"]:nth-child(2)')).to have_content('production')
- end
- end
- end
- end
- end
-
private
def set_feature_flag_info(name, description)
diff --git a/spec/finders/feature_flags_finder_spec.rb b/spec/finders/feature_flags_finder_spec.rb
index cab1094672b..8744a186212 100644
--- a/spec/finders/feature_flags_finder_spec.rb
+++ b/spec/finders/feature_flags_finder_spec.rb
@@ -80,15 +80,5 @@ RSpec.describe FeatureFlagsFinder do
is_expected.to eq([feature_flag_1, feature_flag_2, feature_flag_3])
end
end
-
- context 'when new version flags are disabled' do
- let!(:feature_flag_3) { create(:operations_feature_flag, :new_version_flag, name: 'flag-c', project: project) }
-
- it 'returns only legacy flags' do
- stub_feature_flags(feature_flags_new_version: false)
-
- is_expected.to eq([feature_flag_1, feature_flag_2])
- end
- end
end
end
diff --git a/spec/frontend/alerts_service_settings/components/alerts_service_form_spec.js b/spec/frontend/alerts_service_settings/components/alerts_service_form_spec.js
index 5574c83eb76..ed78a593944 100644
--- a/spec/frontend/alerts_service_settings/components/alerts_service_form_spec.js
+++ b/spec/frontend/alerts_service_settings/components/alerts_service_form_spec.js
@@ -42,8 +42,8 @@ describe('AlertsServiceForm', () => {
mockAxios = new MockAdapter(axios);
setFixtures(`
-
-
+
+
`);
});
diff --git a/spec/frontend/alerts_settings/alerts_settings_form_spec.js b/spec/frontend/alerts_settings/alerts_settings_form_spec.js
index dd7d32c5e75..428c6f93444 100644
--- a/spec/frontend/alerts_settings/alerts_settings_form_spec.js
+++ b/spec/frontend/alerts_settings/alerts_settings_form_spec.js
@@ -93,16 +93,28 @@ describe('AlertsSettingsFormNew', () => {
).toBe(true);
});
- it('disabled the dropdown and shows help text when multi integrations are not supported', async () => {
+ it('disables the dropdown and shows help text when multi integrations are not supported', async () => {
createComponent({ props: { canAddIntegration: false } });
expect(findSelect().attributes('disabled')).toBe('disabled');
expect(findMultiSupportText().exists()).toBe(true);
});
+
+ it('disabled the name input when the selected value is prometheus', async () => {
+ createComponent();
+ const options = findSelect().findAll('option');
+ await options.at(2).setSelected();
+
+ expect(
+ findFormFields()
+ .at(0)
+ .attributes('disabled'),
+ ).toBe('disabled');
+ });
});
describe('submitting integration form', () => {
it('allows for create-new-integration with the correct form values for HTTP', async () => {
- createComponent({});
+ createComponent();
const options = findSelect().findAll('option');
await options.at(1).setSelected();
@@ -128,7 +140,7 @@ describe('AlertsSettingsFormNew', () => {
});
it('allows for create-new-integration with the correct form values for PROMETHEUS', async () => {
- createComponent({});
+ createComponent();
const options = findSelect().findAll('option');
await options.at(2).setSelected();
diff --git a/spec/frontend/branches/ajax_loading_spinner_spec.js b/spec/frontend/branches/ajax_loading_spinner_spec.js
index a6404faa445..31cc7b99e42 100644
--- a/spec/frontend/branches/ajax_loading_spinner_spec.js
+++ b/spec/frontend/branches/ajax_loading_spinner_spec.js
@@ -9,7 +9,7 @@ describe('Ajax Loading Spinner', () => {
-
+ Remove me