diff --git a/app/assets/javascripts/projects/pipelines/charts/components/app.vue b/app/assets/javascripts/projects/pipelines/charts/components/app.vue
index 18c0a6173a2..e8304fe9e2d 100644
--- a/app/assets/javascripts/projects/pipelines/charts/components/app.vue
+++ b/app/assets/javascripts/projects/pipelines/charts/components/app.vue
@@ -1,6 +1,5 @@
@@ -93,7 +85,7 @@ export default {
@@ -101,28 +93,28 @@ export default {
diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb
index 7b105606793..04dcf9ffae0 100644
--- a/app/controllers/groups/group_members_controller.rb
+++ b/app/controllers/groups/group_members_controller.rb
@@ -17,7 +17,7 @@ class Groups::GroupMembersController < Groups::ApplicationController
before_action :authorize_read_group_member!, only: :index
before_action only: [:index] do
- push_frontend_feature_flag(:bulk_import_user_mapping, @group)
+ push_frontend_feature_flag(:bulk_import_user_mapping, current_user)
push_frontend_feature_flag(:service_accounts_crud, @group)
push_frontend_feature_flag(:webui_members_inherited_users, current_user)
end
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index 59b4ee1e397..96e57a5eed7 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -38,8 +38,8 @@ class Projects::PipelinesController < Projects::ApplicationController
track_internal_event :charts, name: 'p_analytics_ci_cd_pipelines', conditions: -> { should_track_ci_cd_pipelines? }
track_internal_event :charts, name: 'p_analytics_ci_cd_deployment_frequency', conditions: -> { should_track_ci_cd_deployment_frequency? }
track_internal_event :charts, name: 'p_analytics_ci_cd_lead_time', conditions: -> { should_track_ci_cd_lead_time? }
- track_event :charts, name: 'p_analytics_ci_cd_time_to_restore_service', conditions: -> { should_track_ci_cd_time_to_restore_service? }
- track_event :charts, name: 'p_analytics_ci_cd_change_failure_rate', conditions: -> { should_track_ci_cd_change_failure_rate? }
+ track_internal_event :charts, name: 'visit_ci_cd_time_to_restore_service_tab', conditions: -> { should_track_visit_ci_cd_time_to_restore_service_tab? }
+ track_internal_event :charts, name: 'visit_ci_cd_failure_rate_tab', conditions: -> { should_track_visit_ci_cd_change_failure_tab? }
wrap_parameters Ci::Pipeline
@@ -357,11 +357,11 @@ class Projects::PipelinesController < Projects::ApplicationController
params[:chart] == 'lead-time'
end
- def should_track_ci_cd_time_to_restore_service?
+ def should_track_visit_ci_cd_time_to_restore_service_tab?
params[:chart] == 'time-to-restore-service'
end
- def should_track_ci_cd_change_failure_rate?
+ def should_track_visit_ci_cd_change_failure_tab?
params[:chart] == 'change-failure-rate'
end
diff --git a/app/graphql/mutations/concerns/mutations/work_items/shared_arguments.rb b/app/graphql/mutations/concerns/mutations/work_items/shared_arguments.rb
new file mode 100644
index 00000000000..f7246d0aa82
--- /dev/null
+++ b/app/graphql/mutations/concerns/mutations/work_items/shared_arguments.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Mutations
+ module WorkItems
+ module SharedArguments
+ extend ActiveSupport::Concern
+
+ included do
+ argument :assignees_widget,
+ ::Types::WorkItems::Widgets::AssigneesInputType,
+ required: false,
+ description: 'Input for assignees widget.'
+ argument :confidential,
+ GraphQL::Types::Boolean,
+ required: false,
+ description: 'Sets the work item confidentiality.'
+ argument :description_widget,
+ ::Types::WorkItems::Widgets::DescriptionInputType,
+ required: false,
+ description: 'Input for description widget.'
+ argument :milestone_widget,
+ ::Types::WorkItems::Widgets::MilestoneInputType,
+ required: false,
+ description: 'Input for milestone widget.'
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb b/app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb
deleted file mode 100644
index 73eff799103..00000000000
--- a/app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-# frozen_string_literal: true
-
-module Mutations
- module WorkItems
- module UpdateArguments
- extend ActiveSupport::Concern
-
- included do
- argument :id, ::Types::GlobalIDType[::WorkItem],
- required: true,
- description: 'Global ID of the work item.'
- argument :state_event, Types::WorkItems::StateEventEnum,
- description: 'Close or reopen a work item.',
- required: false
- argument :title, GraphQL::Types::String,
- required: false,
- description: copy_field_description(Types::WorkItemType, :title)
- argument :confidential, GraphQL::Types::Boolean,
- required: false,
- description: 'Sets the work item confidentiality.'
- argument :description_widget, ::Types::WorkItems::Widgets::DescriptionInputType,
- required: false,
- description: 'Input for description widget.'
- argument :assignees_widget, ::Types::WorkItems::Widgets::AssigneesInputType,
- required: false,
- description: 'Input for assignees widget.'
- argument :hierarchy_widget, ::Types::WorkItems::Widgets::HierarchyUpdateInputType,
- required: false,
- description: 'Input for hierarchy widget.'
- argument :start_and_due_date_widget, ::Types::WorkItems::Widgets::StartAndDueDateUpdateInputType,
- required: false,
- description: 'Input for start and due date widget.'
- argument :labels_widget, ::Types::WorkItems::Widgets::LabelsUpdateInputType,
- required: false,
- description: 'Input for labels widget.'
- argument :milestone_widget, ::Types::WorkItems::Widgets::MilestoneInputType,
- required: false,
- description: 'Input for milestone widget.'
- argument :notifications_widget,
- ::Types::WorkItems::Widgets::NotificationsUpdateInputType,
- required: false,
- description: 'Input for notifications widget.'
- argument :current_user_todos_widget,
- ::Types::WorkItems::Widgets::CurrentUserTodosInputType,
- required: false,
- description: 'Input for to-dos widget.'
- argument :award_emoji_widget,
- ::Types::WorkItems::Widgets::AwardEmojiUpdateInputType,
- required: false,
- description: 'Input for emoji reactions widget.'
- argument :notes_widget,
- ::Types::WorkItems::Widgets::NotesInputType,
- required: false,
- description: 'Input for notes widget.'
- argument :time_tracking_widget,
- ::Types::WorkItems::Widgets::TimeTracking::TimeTrackingInputType,
- required: false,
- description: 'Input for time tracking widget.'
- end
- end
- end
-end
diff --git a/app/graphql/mutations/work_items/create.rb b/app/graphql/mutations/work_items/create.rb
index 0556950e2e3..590e1feb939 100644
--- a/app/graphql/mutations/work_items/create.rb
+++ b/app/graphql/mutations/work_items/create.rb
@@ -7,6 +7,7 @@ module Mutations
include Mutations::SpamProtection
include FindsNamespace
+ include Mutations::WorkItems::SharedArguments
include Mutations::WorkItems::Widgetable
description "Creates a work item."
@@ -16,44 +17,39 @@ module Mutations
MUTUALLY_EXCLUSIVE_ARGUMENTS_ERROR = 'Please provide either projectPath or namespacePath argument, but not both.'
DISABLED_FF_ERROR = 'create_group_level_work_items feature flag is disabled. Only project paths allowed.'
- argument :assignees_widget, ::Types::WorkItems::Widgets::AssigneesInputType,
- required: false,
- description: 'Input for assignees widget.'
- argument :confidential, GraphQL::Types::Boolean,
- required: false,
- description: 'Sets the work item confidentiality.'
- argument :description, GraphQL::Types::String,
- required: false,
- description: copy_field_description(Types::WorkItemType, :description),
- deprecated: { milestone: '16.9', reason: 'use description widget instead' }
- argument :description_widget, ::Types::WorkItems::Widgets::DescriptionInputType,
- required: false,
- description: 'Input for description widget.'
- argument :hierarchy_widget, ::Types::WorkItems::Widgets::HierarchyCreateInputType,
- required: false,
- description: 'Input for hierarchy widget.'
- argument :labels_widget, ::Types::WorkItems::Widgets::LabelsCreateInputType,
- required: false,
- description: 'Input for labels widget.'
- argument :milestone_widget, ::Types::WorkItems::Widgets::MilestoneInputType,
- required: false,
- description: 'Input for milestone widget.'
- argument :namespace_path, GraphQL::Types::ID,
- required: false,
- description: 'Full path of the namespace(project or group) the work item is created in.'
- argument :project_path, GraphQL::Types::ID,
- required: false,
- description: 'Full path of the project the work item is associated with.',
- deprecated: {
- reason: 'Please use namespace_path instead. That will cover for both projects and groups',
- milestone: '15.10'
- }
- argument :title, GraphQL::Types::String,
- required: true,
- description: copy_field_description(Types::WorkItemType, :title)
- argument :work_item_type_id, ::Types::GlobalIDType[::WorkItems::Type],
- required: true,
- description: 'Global ID of a work item type.'
+ argument :description,
+ GraphQL::Types::String,
+ required: false,
+ description: copy_field_description(Types::WorkItemType, :description),
+ deprecated: { milestone: '16.9', reason: 'use description widget instead' }
+ argument :hierarchy_widget,
+ ::Types::WorkItems::Widgets::HierarchyCreateInputType,
+ required: false,
+ description: 'Input for hierarchy widget.'
+ argument :labels_widget,
+ ::Types::WorkItems::Widgets::LabelsCreateInputType,
+ required: false,
+ description: 'Input for labels widget.'
+ argument :namespace_path,
+ GraphQL::Types::ID,
+ required: false,
+ description: 'Full path of the namespace(project or group) the work item is created in.'
+ argument :project_path,
+ GraphQL::Types::ID,
+ required: false,
+ description: 'Full path of the project the work item is associated with.',
+ deprecated: {
+ reason: 'Please use namespace_path instead. That will cover for both projects and groups',
+ milestone: '15.10'
+ }
+ argument :title,
+ GraphQL::Types::String,
+ required: true,
+ description: copy_field_description(Types::WorkItemType, :title)
+ argument :work_item_type_id,
+ ::Types::GlobalIDType[::WorkItems::Type],
+ required: true,
+ description: 'Global ID of a work item type.'
field :work_item, Types::WorkItemType,
null: true,
diff --git a/app/graphql/mutations/work_items/update.rb b/app/graphql/mutations/work_items/update.rb
index 1a140f0c0ca..b9e4b7cc4f2 100644
--- a/app/graphql/mutations/work_items/update.rb
+++ b/app/graphql/mutations/work_items/update.rb
@@ -7,11 +7,56 @@ module Mutations
description "Updates a work item by Global ID."
include Mutations::SpamProtection
- include Mutations::WorkItems::UpdateArguments
+ include Mutations::WorkItems::SharedArguments
include Mutations::WorkItems::Widgetable
authorize :read_work_item
+ argument :award_emoji_widget,
+ ::Types::WorkItems::Widgets::AwardEmojiUpdateInputType,
+ required: false,
+ description: 'Input for emoji reactions widget.'
+ argument :current_user_todos_widget,
+ ::Types::WorkItems::Widgets::CurrentUserTodosInputType,
+ required: false,
+ description: 'Input for to-dos widget.'
+ argument :hierarchy_widget,
+ ::Types::WorkItems::Widgets::HierarchyUpdateInputType,
+ required: false,
+ description: 'Input for hierarchy widget.'
+ argument :id,
+ ::Types::GlobalIDType[::WorkItem],
+ required: true,
+ description: 'Global ID of the work item.'
+ argument :labels_widget,
+ ::Types::WorkItems::Widgets::LabelsUpdateInputType,
+ required: false,
+ description: 'Input for labels widget.'
+ argument :notes_widget,
+ ::Types::WorkItems::Widgets::NotesInputType,
+ required: false,
+ description: 'Input for notes widget.'
+ argument :notifications_widget,
+ ::Types::WorkItems::Widgets::NotificationsUpdateInputType,
+ required: false,
+ description: 'Input for notifications widget.'
+ argument :start_and_due_date_widget,
+ ::Types::WorkItems::Widgets::StartAndDueDateUpdateInputType,
+ required: false,
+ description: 'Input for start and due date widget.'
+ argument :state_event,
+ Types::WorkItems::StateEventEnum,
+ description: 'Close or reopen a work item.',
+ required: false
+ argument :time_tracking_widget,
+ ::Types::WorkItems::Widgets::TimeTracking::TimeTrackingInputType,
+ required: false,
+ description: 'Input for time tracking widget.'
+ argument :title,
+ GraphQL::Types::String,
+ required: false,
+ description: copy_field_description(Types::WorkItemType, :title)
+
field :work_item, Types::WorkItemType,
null: true,
description: 'Updated work item.'
diff --git a/app/models/virtual_registries/packages/maven.rb b/app/models/virtual_registries/packages/maven.rb
new file mode 100644
index 00000000000..87042b2043c
--- /dev/null
+++ b/app/models/virtual_registries/packages/maven.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module VirtualRegistries
+ module Packages
+ module Maven
+ def self.table_name_prefix
+ 'virtual_registries_packages_maven_'
+ end
+ end
+ end
+end
diff --git a/app/models/virtual_registries/packages/maven/registry.rb b/app/models/virtual_registries/packages/maven/registry.rb
new file mode 100644
index 00000000000..f1006196899
--- /dev/null
+++ b/app/models/virtual_registries/packages/maven/registry.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module VirtualRegistries
+ module Packages
+ module Maven
+ class Registry < ApplicationRecord
+ belongs_to :group
+ has_one :registry_upstream,
+ class_name: 'VirtualRegistries::Packages::Maven::RegistryUpstream',
+ inverse_of: :registry
+ has_one :upstream, class_name: 'VirtualRegistries::Packages::Maven::Upstream', through: :registry_upstream
+
+ validates :group, top_level_group: true, presence: true, uniqueness: true
+ validates :cache_validity_hours, numericality: { greater_than_or_equal_to: 0, only_integer: true }
+ end
+ end
+ end
+end
diff --git a/app/models/virtual_registries/packages/maven/registry_upstream.rb b/app/models/virtual_registries/packages/maven/registry_upstream.rb
new file mode 100644
index 00000000000..b06de684424
--- /dev/null
+++ b/app/models/virtual_registries/packages/maven/registry_upstream.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module VirtualRegistries
+ module Packages
+ module Maven
+ class RegistryUpstream < ApplicationRecord
+ belongs_to :group
+ belongs_to :registry, class_name: 'VirtualRegistries::Packages::Maven::Registry', inverse_of: :registry_upstream
+ belongs_to :upstream, class_name: 'VirtualRegistries::Packages::Maven::Upstream', inverse_of: :registry_upstream
+
+ validates :registry_id, :upstream_id, uniqueness: true
+ validates :group, top_level_group: true, presence: true
+ end
+ end
+ end
+end
diff --git a/app/models/virtual_registries/packages/maven/upstream.rb b/app/models/virtual_registries/packages/maven/upstream.rb
new file mode 100644
index 00000000000..0a19e8f3193
--- /dev/null
+++ b/app/models/virtual_registries/packages/maven/upstream.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module VirtualRegistries
+ module Packages
+ module Maven
+ class Upstream < ApplicationRecord
+ belongs_to :group
+ has_one :registry_upstream,
+ class_name: 'VirtualRegistries::Packages::Maven::RegistryUpstream',
+ inverse_of: :upstream
+ has_one :registry, class_name: 'VirtualRegistries::Packages::Maven::Registry', through: :registry_upstream
+
+ attr_encrypted :credentials,
+ mode: :per_attribute_iv,
+ key: Settings.attr_encrypted_db_key_base_32,
+ algorithm: 'aes-256-gcm',
+ marshal: true,
+ marshaler: ::Gitlab::Json,
+ encode: false,
+ encode_iv: false
+ attribute :username, :string, default: nil
+ attribute :password, :string, default: nil
+
+ validates :group, top_level_group: true, presence: true
+ validates :url, addressable_url: { allow_localhost: false, allow_local_network: false }, presence: true
+ validates :username, presence: true, if: :password?
+ validates :password, presence: true, if: :username?
+ validates :url, :username, :password, length: { maximum: 255 }
+
+ after_initialize :read_credentials
+ before_save :write_credentials
+
+ private
+
+ def read_credentials
+ self.username, self.password = (credentials || {}).values_at('username', 'password')
+ end
+
+ def write_credentials
+ self.credentials = (credentials || {}).merge('username' => username, 'password' => password)
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/projects/update_pages_service.rb b/app/services/projects/update_pages_service.rb
index 96cb9425c25..ee2d9ddfef6 100644
--- a/app/services/projects/update_pages_service.rb
+++ b/app/services/projects/update_pages_service.rb
@@ -2,6 +2,7 @@
module Projects
class UpdatePagesService < BaseService
+ include Gitlab::InternalEventsTracking
include Gitlab::Utils::StrongMemoize
# old deployment can be cached by pages daemon
@@ -33,6 +34,22 @@ module Projects
break error('The uploaded artifact size does not match the expected value') unless deployment
break error(deployment_validations.errors.first.full_message) unless deployment_validations.valid?
+ track_internal_event(
+ 'create_pages_deployment',
+ project: project,
+ namespace: project.namespace,
+ user: build.user
+ )
+
+ if deployment.path_prefix.present?
+ track_internal_event(
+ 'create_pages_extra_deployment',
+ project: project,
+ namespace: project.namespace,
+ user: build.user
+ )
+ end
+
deactive_old_deployments(deployment)
success
end
diff --git a/app/workers/bulk_imports/relation_export_worker.rb b/app/workers/bulk_imports/relation_export_worker.rb
index 8d49e557b2a..c0934b786e5 100644
--- a/app/workers/bulk_imports/relation_export_worker.rb
+++ b/app/workers/bulk_imports/relation_export_worker.rb
@@ -38,7 +38,7 @@ module BulkImports
log_extra_metadata_on_done(:batched, true)
BatchedRelationExportService.new(user, portable, relation, jid).execute
elsif config.user_contributions_relation?(relation)
- return if Feature.disabled?(:bulk_import_user_mapping, portable)
+ return if Feature.disabled?(:bulk_import_user_mapping, user)
log_extra_metadata_on_done(:batched, false)
UserContributionsExportWorker.perform_async(portable_id, portable_class, user_id)
diff --git a/config/bounded_contexts.yml b/config/bounded_contexts.yml
index efa3013683d..fd1823e4ad2 100644
--- a/config/bounded_contexts.yml
+++ b/config/bounded_contexts.yml
@@ -118,7 +118,7 @@ domains:
- dependency_management
DependencyProxy:
- description:
+ description: Dependency Proxy for container images.
feature_categories:
- virtual_registry
- package_registry
@@ -227,7 +227,7 @@ domains:
- cell
Packages:
- description:
+ description: Package registry implementation for each supported format (such as Maven, NPM, NuGet, ...).
feature_categories:
- package_registry
- mlops
@@ -310,6 +310,11 @@ domains:
feature_categories:
- consumables_cost_management
+ VirtualRegistries:
+ description: Virtual registries implementation that manage artifacts (packages or container images) from external upstreams.
+ feature_categories:
+ - virtual_registry
+
Vulnerabilities:
description: Vulnerability management
feature_categories:
diff --git a/config/events/create_pages_deployment.yml b/config/events/create_pages_deployment.yml
new file mode 100644
index 00000000000..d375c35a4ae
--- /dev/null
+++ b/config/events/create_pages_deployment.yml
@@ -0,0 +1,18 @@
+---
+description: GitLab Pages deployment created
+internal_events: true
+action: create_pages_deployment
+identifiers:
+- project
+- namespace
+- user
+product_group: knowledge
+milestone: '17.2'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/157474
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/visit_ci_cd_failure_rate_tab.yml b/config/events/visit_ci_cd_failure_rate_tab.yml
new file mode 100644
index 00000000000..d10f5cc1456
--- /dev/null
+++ b/config/events/visit_ci_cd_failure_rate_tab.yml
@@ -0,0 +1,18 @@
+---
+description: "Visits to the project level CI/CD Analytics Change failure rate tab"
+internal_events: true
+action: visit_ci_cd_failure_rate_tab
+identifiers:
+ - project
+ - namespace
+ - user
+product_group: optimize
+milestone: '17.2'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/156593
+distributions:
+ - ce
+ - ee
+tiers:
+ - free
+ - premium
+ - ultimate
diff --git a/config/events/visit_ci_cd_time_to_restore_service_tab.yml b/config/events/visit_ci_cd_time_to_restore_service_tab.yml
new file mode 100644
index 00000000000..216c5184d1f
--- /dev/null
+++ b/config/events/visit_ci_cd_time_to_restore_service_tab.yml
@@ -0,0 +1,18 @@
+---
+description: Tracks visits to the project level CI/CD Analytics Time to Restore Service tab
+internal_events: true
+action: visit_ci_cd_time_to_restore_service_tab
+identifiers:
+- project
+- namespace
+- user
+product_group: optimize
+milestone: '17.2'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/156593
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216174910_analytics_unique_visits_for_any_target_monthly.yml b/config/metrics/counts_28d/20210216174910_analytics_unique_visits_for_any_target_monthly.yml
index 0b74b7f861e..9f292450cbf 100644
--- a/config/metrics/counts_28d/20210216174910_analytics_unique_visits_for_any_target_monthly.yml
+++ b/config/metrics/counts_28d/20210216174910_analytics_unique_visits_for_any_target_monthly.yml
@@ -49,8 +49,12 @@ events:
unique: user.id
- name: p_analytics_ci_cd_lead_time
unique: user.id
+- name: visit_ci_cd_time_to_restore_service_tab
+ unique: user.id
- name: p_analytics_ci_cd_time_to_restore_service
unique: user.id
+- name: visit_ci_cd_failure_rate_tab
+ unique: user.id
- name: p_analytics_ci_cd_change_failure_rate
unique: user.id
- name: g_analytics_ci_cd_release_statistics
diff --git a/config/metrics/counts_28d/20220622084700_p_analytics_ci_cd_time_to_restore_service_monthly.yml b/config/metrics/counts_28d/20220622084700_p_analytics_ci_cd_time_to_restore_service_monthly.yml
index f554572066b..c75dc10752a 100644
--- a/config/metrics/counts_28d/20220622084700_p_analytics_ci_cd_time_to_restore_service_monthly.yml
+++ b/config/metrics/counts_28d/20220622084700_p_analytics_ci_cd_time_to_restore_service_monthly.yml
@@ -7,9 +7,8 @@ status: active
milestone: "15.2"
introduced_by_url:
time_frame: 28d
-data_source: redis_hll
+data_source: internal_events
data_category: operational
-instrumentation_class: RedisHLLMetric
performance_indicator_type: []
distribution:
- ce
@@ -17,6 +16,6 @@ distribution:
tier:
- premium
- ultimate
-options:
- events:
- - p_analytics_ci_cd_time_to_restore_service
+events:
+ - name: visit_ci_cd_time_to_restore_service_tab
+ unique: user.id
diff --git a/config/metrics/counts_28d/20220707054530_p_analytics_ci_cd_change_failure_rate_monthly.yml b/config/metrics/counts_28d/20220707054530_p_analytics_ci_cd_change_failure_rate_monthly.yml
index e3edbc05828..bd8b6bb1fae 100644
--- a/config/metrics/counts_28d/20220707054530_p_analytics_ci_cd_change_failure_rate_monthly.yml
+++ b/config/metrics/counts_28d/20220707054530_p_analytics_ci_cd_change_failure_rate_monthly.yml
@@ -7,9 +7,8 @@ status: active
milestone: "15.2"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91726
time_frame: 28d
-data_source: redis_hll
+data_source: internal_events
data_category: operational
-instrumentation_class: RedisHLLMetric
performance_indicator_type: []
distribution:
- ce
@@ -17,6 +16,6 @@ distribution:
tier:
- premium
- ultimate
-options:
- events:
- - p_analytics_ci_cd_change_failure_rate
+events:
+ - name: visit_ci_cd_failure_rate_tab
+ unique: user.id
diff --git a/config/metrics/counts_28d/count_distinct_project_id_from_create_pages_deployment_monthly.yml b/config/metrics/counts_28d/count_distinct_project_id_from_create_pages_deployment_monthly.yml
new file mode 100644
index 00000000000..6063f68dd9b
--- /dev/null
+++ b/config/metrics/counts_28d/count_distinct_project_id_from_create_pages_deployment_monthly.yml
@@ -0,0 +1,22 @@
+---
+key_path: redis_hll_counters.count_distinct_project_id_from_create_pages_deployment_monthly
+description: Monthly count of unique projects where a Pages deployment was created
+product_group: knowledge
+performance_indicator_type: []
+value_type: number
+status: active
+milestone: '17.2'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/157474
+time_frame: 28d
+data_source: internal_events
+data_category: optional
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+events:
+- name: create_pages_deployment
+ unique: project.id
diff --git a/config/metrics/counts_28d/count_distinct_user_id_from_create_pages_deployment_monthly.yml b/config/metrics/counts_28d/count_distinct_user_id_from_create_pages_deployment_monthly.yml
new file mode 100644
index 00000000000..90d5fac1535
--- /dev/null
+++ b/config/metrics/counts_28d/count_distinct_user_id_from_create_pages_deployment_monthly.yml
@@ -0,0 +1,22 @@
+---
+key_path: redis_hll_counters.count_distinct_user_id_from_create_pages_deployment_monthly
+description: Monthly count of unique users who created a Pages deployment
+product_group: knowledge
+performance_indicator_type: []
+value_type: number
+status: active
+milestone: '17.2'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/157474
+time_frame: 28d
+data_source: internal_events
+data_category: optional
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+events:
+- name: create_pages_deployment
+ unique: user.id
diff --git a/config/metrics/counts_7d/20220622084654_p_analytics_ci_cd_time_to_restore_service_weekly.yml b/config/metrics/counts_7d/20220622084654_p_analytics_ci_cd_time_to_restore_service_weekly.yml
index 32120f03018..864816c64bb 100644
--- a/config/metrics/counts_7d/20220622084654_p_analytics_ci_cd_time_to_restore_service_weekly.yml
+++ b/config/metrics/counts_7d/20220622084654_p_analytics_ci_cd_time_to_restore_service_weekly.yml
@@ -7,9 +7,8 @@ status: active
milestone: "15.2"
introduced_by_url:
time_frame: 7d
-data_source: redis_hll
+data_source: internal_events
data_category: operational
-instrumentation_class: RedisHLLMetric
performance_indicator_type: []
distribution:
- ce
@@ -17,6 +16,6 @@ distribution:
tier:
- premium
- ultimate
-options:
- events:
- - p_analytics_ci_cd_time_to_restore_service
+events:
+ - name: visit_ci_cd_time_to_restore_service_tab
+ unique: user.id
diff --git a/config/metrics/counts_7d/20220707054526_p_analytics_ci_cd_change_failure_rate_weekly.yml b/config/metrics/counts_7d/20220707054526_p_analytics_ci_cd_change_failure_rate_weekly.yml
index 36f17024f06..a34ed8ce596 100644
--- a/config/metrics/counts_7d/20220707054526_p_analytics_ci_cd_change_failure_rate_weekly.yml
+++ b/config/metrics/counts_7d/20220707054526_p_analytics_ci_cd_change_failure_rate_weekly.yml
@@ -7,9 +7,8 @@ status: active
milestone: "15.2"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91726
time_frame: 7d
-data_source: redis_hll
+data_source: internal_events
data_category: operational
-instrumentation_class: RedisHLLMetric
performance_indicator_type: []
distribution:
- ce
@@ -17,6 +16,6 @@ distribution:
tier:
- premium
- ultimate
-options:
- events:
- - p_analytics_ci_cd_change_failure_rate
+events:
+ - name: visit_ci_cd_failure_rate_tab
+ unique: user.id
diff --git a/config/metrics/counts_7d/count_distinct_project_id_from_create_pages_deployment_weekly.yml b/config/metrics/counts_7d/count_distinct_project_id_from_create_pages_deployment_weekly.yml
new file mode 100644
index 00000000000..93e5f5f92f0
--- /dev/null
+++ b/config/metrics/counts_7d/count_distinct_project_id_from_create_pages_deployment_weekly.yml
@@ -0,0 +1,22 @@
+---
+key_path: redis_hll_counters.count_distinct_project_id_from_create_pages_deployment_weekly
+description: Weekly count of unique projects where a Pages deployment was created
+product_group: knowledge
+performance_indicator_type: []
+value_type: number
+status: active
+milestone: '17.2'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/157474
+time_frame: 7d
+data_source: internal_events
+data_category: optional
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+events:
+- name: create_pages_deployment
+ unique: project.id
diff --git a/config/metrics/counts_7d/count_distinct_user_id_from_create_pages_deployment_weekly.yml b/config/metrics/counts_7d/count_distinct_user_id_from_create_pages_deployment_weekly.yml
new file mode 100644
index 00000000000..c994603fec8
--- /dev/null
+++ b/config/metrics/counts_7d/count_distinct_user_id_from_create_pages_deployment_weekly.yml
@@ -0,0 +1,22 @@
+---
+key_path: redis_hll_counters.count_distinct_user_id_from_create_pages_deployment_weekly
+description: Weekly count of unique users who created a Pages deployment
+product_group: knowledge
+performance_indicator_type: []
+value_type: number
+status: active
+milestone: '17.2'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/157474
+time_frame: 7d
+data_source: internal_events
+data_category: optional
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+events:
+- name: create_pages_deployment
+ unique: user.id
diff --git a/config/metrics/counts_all/count_total_create_pages_deployment.yml b/config/metrics/counts_all/count_total_create_pages_deployment.yml
new file mode 100644
index 00000000000..6206231924b
--- /dev/null
+++ b/config/metrics/counts_all/count_total_create_pages_deployment.yml
@@ -0,0 +1,21 @@
+---
+key_path: counts.count_total_create_pages_deployment
+description: Total count of Pages deployments created
+product_group: knowledge
+performance_indicator_type: []
+value_type: number
+status: active
+milestone: '17.2'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/157474
+time_frame: all
+data_source: internal_events
+data_category: optional
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+events:
+- name: create_pages_deployment
diff --git a/db/docs/virtual_registries_packages_maven_registries.yml b/db/docs/virtual_registries_packages_maven_registries.yml
new file mode 100644
index 00000000000..04a25d23ed7
--- /dev/null
+++ b/db/docs/virtual_registries_packages_maven_registries.yml
@@ -0,0 +1,12 @@
+---
+table_name: virtual_registries_packages_maven_registries
+classes:
+- VirtualRegistries::Packages::Maven::Registry
+feature_categories:
+- virtual_registry
+description: A virtual registry object for a packages of kind Maven.
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/156930
+milestone: '17.2'
+gitlab_schema: gitlab_main_cell
+sharding_key:
+ group_id: namespaces
diff --git a/db/docs/virtual_registries_packages_maven_registry_upstreams.yml b/db/docs/virtual_registries_packages_maven_registry_upstreams.yml
new file mode 100644
index 00000000000..977c3394930
--- /dev/null
+++ b/db/docs/virtual_registries_packages_maven_registry_upstreams.yml
@@ -0,0 +1,12 @@
+---
+table_name: virtual_registries_packages_maven_registry_upstreams
+classes:
+- VirtualRegistries::Packages::Maven::RegistryUpstream
+feature_categories:
+- virtual_registry
+description: Link a Maven Registry with a Maven Upstream.
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/156930
+milestone: '17.2'
+gitlab_schema: gitlab_main_cell
+sharding_key:
+ group_id: namespaces
diff --git a/db/docs/virtual_registries_packages_maven_upstreams.yml b/db/docs/virtual_registries_packages_maven_upstreams.yml
new file mode 100644
index 00000000000..03e6d81f74a
--- /dev/null
+++ b/db/docs/virtual_registries_packages_maven_upstreams.yml
@@ -0,0 +1,12 @@
+---
+table_name: virtual_registries_packages_maven_upstreams
+classes:
+- VirtualRegistries::Packages::Maven::Upstream
+feature_categories:
+- virtual_registry
+description: Upstream object for Maven Virtual Registries.
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/156930
+milestone: '17.2'
+gitlab_schema: gitlab_main_cell
+sharding_key:
+ group_id: namespaces
diff --git a/db/migrate/20240619141712_create_virtual_registries_packages_maven_registries.rb b/db/migrate/20240619141712_create_virtual_registries_packages_maven_registries.rb
new file mode 100644
index 00000000000..da220b6f87c
--- /dev/null
+++ b/db/migrate/20240619141712_create_virtual_registries_packages_maven_registries.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class CreateVirtualRegistriesPackagesMavenRegistries < Gitlab::Database::Migration[2.2]
+ milestone '17.2'
+ disable_ddl_transaction!
+
+ TABLE_NAME = :virtual_registries_packages_maven_registries
+ INDEX_NAME = 'virtual_registries_pkgs_maven_registries_on_unique_group_ids'
+
+ def up
+ with_lock_retries do
+ create_table TABLE_NAME, if_not_exists: true do |t|
+ t.references :group,
+ null: false,
+ index: { unique: true, name: INDEX_NAME },
+ foreign_key: { to_table: :namespaces, on_delete: :cascade }
+ t.timestamps_with_timezone null: false
+ t.integer :cache_validity_hours, limit: 2, null: false, default: 1
+ end
+ end
+
+ constraint = check_constraint_name(TABLE_NAME.to_s, 'cache_validity_hours', 'zero_or_positive')
+ add_check_constraint(TABLE_NAME, 'cache_validity_hours >= 0', constraint)
+ end
+
+ def down
+ drop_table TABLE_NAME
+ end
+end
diff --git a/db/migrate/20240619154655_create_virtual_registries_packages_maven_upstreams.rb b/db/migrate/20240619154655_create_virtual_registries_packages_maven_upstreams.rb
new file mode 100644
index 00000000000..46d47f635a1
--- /dev/null
+++ b/db/migrate/20240619154655_create_virtual_registries_packages_maven_upstreams.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+class CreateVirtualRegistriesPackagesMavenUpstreams < Gitlab::Database::Migration[2.2]
+ milestone '17.2'
+ disable_ddl_transaction!
+
+ TABLE_NAME = :virtual_registries_packages_maven_upstreams
+
+ def up
+ with_lock_retries do
+ create_table TABLE_NAME, if_not_exists: true do |t|
+ t.references :group,
+ null: false,
+ index: { name: 'index_virtual_reg_pkgs_maven_upstreams_on_group_id' },
+ foreign_key: { to_table: :namespaces, on_delete: :cascade }
+ t.timestamps_with_timezone null: false
+ t.text :url, null: false, limit: 255
+ t.binary :encrypted_credentials, null: true
+ t.binary :encrypted_credentials_iv, null: true
+ end
+ end
+
+ constraint = check_constraint_name(TABLE_NAME.to_s, 'encrypted_credentials', 'max_length')
+ add_check_constraint(TABLE_NAME, 'octet_length(encrypted_credentials) <= 1020', constraint)
+
+ constraint = check_constraint_name(TABLE_NAME.to_s, 'encrypted_credentials_iv', 'max_length')
+ add_check_constraint(TABLE_NAME, 'octet_length(encrypted_credentials_iv) <= 1020', constraint)
+ end
+
+ def down
+ drop_table TABLE_NAME
+ end
+end
diff --git a/db/migrate/20240619192156_create_virtual_registries_packages_maven_registry_upstreams.rb b/db/migrate/20240619192156_create_virtual_registries_packages_maven_registry_upstreams.rb
new file mode 100644
index 00000000000..32acf54273d
--- /dev/null
+++ b/db/migrate/20240619192156_create_virtual_registries_packages_maven_registry_upstreams.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+class CreateVirtualRegistriesPackagesMavenRegistryUpstreams < Gitlab::Database::Migration[2.2]
+ milestone '17.2'
+ disable_ddl_transaction!
+
+ TABLE_NAME = :virtual_registries_packages_maven_registry_upstreams
+
+ def up
+ with_lock_retries do
+ create_table TABLE_NAME, if_not_exists: true do |t|
+ t.references :group,
+ null: false,
+ index: { name: 'index_virtual_reg_pkgs_maven_reg_upstreams_on_group_id' },
+ foreign_key: { to_table: :namespaces, on_delete: :cascade }
+ t.references :registry,
+ null: false,
+ index: { unique: true, name: 'virtual_reg_packages_maven_reg_upstreams_on_unique_reg_ids' },
+ foreign_key: { to_table: :virtual_registries_packages_maven_registries, on_delete: :cascade }
+ t.references :upstream,
+ null: false,
+ index: { unique: true, name: 'virtual_reg_packages_maven_reg_upstreams_on_unique_upstream_ids' },
+ foreign_key: { to_table: :virtual_registries_packages_maven_upstreams, on_delete: :cascade }
+
+ t.timestamps_with_timezone null: false
+ end
+ end
+ end
+
+ def down
+ drop_table TABLE_NAME
+ end
+end
diff --git a/db/schema_migrations/20240619141712 b/db/schema_migrations/20240619141712
new file mode 100644
index 00000000000..7e6aabdacf3
--- /dev/null
+++ b/db/schema_migrations/20240619141712
@@ -0,0 +1 @@
+16b265699f55b815bd1ac4e9b71242ac9b3ccfa06b91426168912fac45d6c019
\ No newline at end of file
diff --git a/db/schema_migrations/20240619154655 b/db/schema_migrations/20240619154655
new file mode 100644
index 00000000000..37d7751ea92
--- /dev/null
+++ b/db/schema_migrations/20240619154655
@@ -0,0 +1 @@
+aca6b5cc21a8b5f1dff79352b2a6f851fd07069af22d84925cc618a73dd49d98
\ No newline at end of file
diff --git a/db/schema_migrations/20240619192156 b/db/schema_migrations/20240619192156
new file mode 100644
index 00000000000..c9717eec9b8
--- /dev/null
+++ b/db/schema_migrations/20240619192156
@@ -0,0 +1 @@
+39a0c550cd99b1c52e980c31f04723ba353f241474fb8d9efcb9453c695d4ed9
\ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 0016e042634..742197e1959 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -18900,6 +18900,64 @@ CREATE SEQUENCE value_stream_dashboard_counts_id_seq
ALTER SEQUENCE value_stream_dashboard_counts_id_seq OWNED BY value_stream_dashboard_counts.id;
+CREATE TABLE virtual_registries_packages_maven_registries (
+ id bigint NOT NULL,
+ group_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ cache_validity_hours smallint DEFAULT 1 NOT NULL,
+ CONSTRAINT check_b3fbe8eb62 CHECK ((cache_validity_hours >= 0))
+);
+
+CREATE SEQUENCE virtual_registries_packages_maven_registries_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE virtual_registries_packages_maven_registries_id_seq OWNED BY virtual_registries_packages_maven_registries.id;
+
+CREATE TABLE virtual_registries_packages_maven_registry_upstreams (
+ id bigint NOT NULL,
+ group_id bigint NOT NULL,
+ registry_id bigint NOT NULL,
+ upstream_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL
+);
+
+CREATE SEQUENCE virtual_registries_packages_maven_registry_upstreams_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE virtual_registries_packages_maven_registry_upstreams_id_seq OWNED BY virtual_registries_packages_maven_registry_upstreams.id;
+
+CREATE TABLE virtual_registries_packages_maven_upstreams (
+ id bigint NOT NULL,
+ group_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ url text NOT NULL,
+ encrypted_credentials bytea,
+ encrypted_credentials_iv bytea,
+ CONSTRAINT check_26c0572777 CHECK ((char_length(url) <= 255)),
+ CONSTRAINT check_4af2999ab8 CHECK ((octet_length(encrypted_credentials_iv) <= 1020)),
+ CONSTRAINT check_b9e3bfa31a CHECK ((octet_length(encrypted_credentials) <= 1020))
+);
+
+CREATE SEQUENCE virtual_registries_packages_maven_upstreams_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE virtual_registries_packages_maven_upstreams_id_seq OWNED BY virtual_registries_packages_maven_upstreams.id;
+
CREATE TABLE vs_code_settings (
id bigint NOT NULL,
user_id bigint NOT NULL,
@@ -21564,6 +21622,12 @@ ALTER TABLE ONLY users_statistics ALTER COLUMN id SET DEFAULT nextval('users_sta
ALTER TABLE ONLY value_stream_dashboard_counts ALTER COLUMN id SET DEFAULT nextval('value_stream_dashboard_counts_id_seq'::regclass);
+ALTER TABLE ONLY virtual_registries_packages_maven_registries ALTER COLUMN id SET DEFAULT nextval('virtual_registries_packages_maven_registries_id_seq'::regclass);
+
+ALTER TABLE ONLY virtual_registries_packages_maven_registry_upstreams ALTER COLUMN id SET DEFAULT nextval('virtual_registries_packages_maven_registry_upstreams_id_seq'::regclass);
+
+ALTER TABLE ONLY virtual_registries_packages_maven_upstreams ALTER COLUMN id SET DEFAULT nextval('virtual_registries_packages_maven_upstreams_id_seq'::regclass);
+
ALTER TABLE ONLY vs_code_settings ALTER COLUMN id SET DEFAULT nextval('vs_code_settings_id_seq'::regclass);
ALTER TABLE ONLY vulnerabilities ALTER COLUMN id SET DEFAULT nextval('vulnerabilities_id_seq'::regclass);
@@ -24266,6 +24330,15 @@ ALTER TABLE ONLY value_stream_dashboard_counts
ALTER TABLE ONLY verification_codes
ADD CONSTRAINT verification_codes_pkey PRIMARY KEY (created_at, visitor_id_code, code, phone);
+ALTER TABLE ONLY virtual_registries_packages_maven_registries
+ ADD CONSTRAINT virtual_registries_packages_maven_registries_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY virtual_registries_packages_maven_registry_upstreams
+ ADD CONSTRAINT virtual_registries_packages_maven_registry_upstreams_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY virtual_registries_packages_maven_upstreams
+ ADD CONSTRAINT virtual_registries_packages_maven_upstreams_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY vs_code_settings
ADD CONSTRAINT vs_code_settings_pkey PRIMARY KEY (id);
@@ -29535,6 +29608,10 @@ CREATE UNIQUE INDEX index_verification_codes_on_phone_and_visitor_id_code ON ONL
COMMENT ON INDEX index_verification_codes_on_phone_and_visitor_id_code IS 'JiHu-specific index';
+CREATE INDEX index_virtual_reg_pkgs_maven_reg_upstreams_on_group_id ON virtual_registries_packages_maven_registry_upstreams USING btree (group_id);
+
+CREATE INDEX index_virtual_reg_pkgs_maven_upstreams_on_group_id ON virtual_registries_packages_maven_upstreams USING btree (group_id);
+
CREATE UNIQUE INDEX index_vuln_findings_on_uuid_including_vuln_id_1 ON vulnerability_occurrences USING btree (uuid) INCLUDE (vulnerability_id);
CREATE UNIQUE INDEX index_vuln_historical_statistics_on_project_id_and_date ON vulnerability_historical_statistics USING btree (project_id, date);
@@ -30091,6 +30168,12 @@ CREATE UNIQUE INDEX unique_zoekt_shards_uuid ON zoekt_shards USING btree (uuid);
CREATE INDEX user_follow_users_followee_id_idx ON user_follow_users USING btree (followee_id);
+CREATE UNIQUE INDEX virtual_reg_packages_maven_reg_upstreams_on_unique_reg_ids ON virtual_registries_packages_maven_registry_upstreams USING btree (registry_id);
+
+CREATE UNIQUE INDEX virtual_reg_packages_maven_reg_upstreams_on_unique_upstream_ids ON virtual_registries_packages_maven_registry_upstreams USING btree (upstream_id);
+
+CREATE UNIQUE INDEX virtual_registries_pkgs_maven_registries_on_unique_group_ids ON virtual_registries_packages_maven_registries USING btree (group_id);
+
CREATE UNIQUE INDEX vulnerability_occurrence_pipelines_on_unique_keys ON vulnerability_occurrence_pipelines USING btree (occurrence_id, pipeline_id);
CREATE INDEX wi_colors_namespace_id_index ON work_item_colors USING btree (namespace_id);
@@ -33775,6 +33858,9 @@ ALTER TABLE ONLY wiki_page_slugs
ALTER TABLE ONLY board_labels
ADD CONSTRAINT fk_rails_362b0600a3 FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE;
+ALTER TABLE ONLY virtual_registries_packages_maven_upstreams
+ ADD CONSTRAINT fk_rails_3649ef6e9a FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY merge_request_blocks
ADD CONSTRAINT fk_rails_364d4bea8b FOREIGN KEY (blocked_merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
@@ -33817,6 +33903,9 @@ ALTER TABLE ONLY cluster_groups
ALTER TABLE ONLY note_diff_files
ADD CONSTRAINT fk_rails_3d66047aeb FOREIGN KEY (diff_note_id) REFERENCES notes(id) ON DELETE CASCADE;
+ALTER TABLE ONLY virtual_registries_packages_maven_registry_upstreams
+ ADD CONSTRAINT fk_rails_3dc6bd8333 FOREIGN KEY (upstream_id) REFERENCES virtual_registries_packages_maven_upstreams(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY snippet_user_mentions
ADD CONSTRAINT fk_rails_3e00189191 FOREIGN KEY (snippet_id) REFERENCES snippets(id) ON DELETE CASCADE;
@@ -33991,6 +34080,9 @@ ALTER TABLE ONLY geo_node_namespace_links
ALTER TABLE ONLY abuse_events
ADD CONSTRAINT fk_rails_55101e588c FOREIGN KEY (abuse_report_id) REFERENCES abuse_reports(id);
+ALTER TABLE ONLY virtual_registries_packages_maven_registries
+ ADD CONSTRAINT fk_rails_555e85e52c FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY issuable_metric_images
ADD CONSTRAINT fk_rails_56417a5a7f FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
@@ -34324,6 +34416,9 @@ ALTER TABLE ONLY group_wiki_repository_states
ALTER TABLE ONLY cluster_enabled_grants
ADD CONSTRAINT fk_rails_8336ce35af FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY virtual_registries_packages_maven_registry_upstreams
+ ADD CONSTRAINT fk_rails_838d054752 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY dast_site_profiles
ADD CONSTRAINT fk_rails_83e309d69e FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -34738,6 +34833,9 @@ ALTER TABLE ONLY packages_composer_cache_files
ALTER TABLE ONLY abuse_trust_scores
ADD CONSTRAINT fk_rails_b903079eb4 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY virtual_registries_packages_maven_registry_upstreams
+ ADD CONSTRAINT fk_rails_b991fff0be FOREIGN KEY (registry_id) REFERENCES virtual_registries_packages_maven_registries(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY dora_configurations
ADD CONSTRAINT fk_rails_b9b8d90ddb FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
diff --git a/doc/administration/gitaly/configure_gitaly.md b/doc/administration/gitaly/configure_gitaly.md
index 16ecdb3f994..2d81cfc0b72 100644
--- a/doc/administration/gitaly/configure_gitaly.md
+++ b/doc/administration/gitaly/configure_gitaly.md
@@ -395,7 +395,7 @@ You can't define Gitaly servers with some as a local Gitaly server
server (with `gitaly_address`) unless you use
[mixed configuration](#mixed-configuration).
-Configure Gitaly clients in one of two ways:
+Configure Gitaly clients in one of two ways. These instructions are for unencrypted connections but you can also enable [TLS support](tls_support.md):
::Tabs
diff --git a/doc/topics/git/troubleshooting_git.md b/doc/topics/git/troubleshooting_git.md
index c9eb72a9d8c..1f424aba00a 100644
--- a/doc/topics/git/troubleshooting_git.md
+++ b/doc/topics/git/troubleshooting_git.md
@@ -92,7 +92,7 @@ If neither approach fixes the error, you may need a different internet service p
**If pushing over SSH**, first check your SSH configuration as 'Broken pipe'
errors can sometimes be caused by underlying issues with SSH (such as
authentication). Make sure that SSH is correctly configured by following the
-instructions in the [SSH troubleshooting](../../user/ssh.md#password-prompt-with-git-clone) documentation.
+instructions in the [SSH troubleshooting](../../user/ssh_troubleshooting.md#password-prompt-with-git-clone) documentation.
If you're a GitLab administrator with server access, you can also prevent
session timeouts by configuring SSH `keep-alive` on the client or the server.
diff --git a/doc/user/analytics/dora_metrics.md b/doc/user/analytics/dora_metrics.md
index bce361c8041..7f947100fb6 100644
--- a/doc/user/analytics/dora_metrics.md
+++ b/doc/user/analytics/dora_metrics.md
@@ -49,6 +49,8 @@ GitLab calculates the deployment frequency from the number of finished deploymen
The calculation takes into account the production `environment tier` or the environments named `production/prod`. The environment must be part of the production deployment tier for its deployment information to appear on the graphs.
+You can configure DORA metrics for different environments by specifying `other` under the `environment_tiers` parameter in the [`.gitlab/insights.yml` file](../project/insights/index.md#insights-configuration-file).
+
### How to improve deployment frequency
The first step is to benchmark the cadence of code releases between groups and projects. Next, you should consider:
diff --git a/doc/user/project/merge_requests/reviews/img/bypass_17_2.png b/doc/user/project/merge_requests/reviews/img/bypass_17_2.png
new file mode 100644
index 00000000000..ac19cff3d56
Binary files /dev/null and b/doc/user/project/merge_requests/reviews/img/bypass_17_2.png differ
diff --git a/doc/user/project/merge_requests/reviews/index.md b/doc/user/project/merge_requests/reviews/index.md
index 62b79ce1730..3b87e78cfad 100644
--- a/doc/user/project/merge_requests/reviews/index.md
+++ b/doc/user/project/merge_requests/reviews/index.md
@@ -50,7 +50,7 @@ DETAILS:
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
To assign multiple reviewers to a merge request, in a text area in
-the merge request, use the `/assign_reviewer @user`
+the merge request, use the `/assign_reviewer @user1 @user2`
[quick action](../../quick_actions.md#issues-merge-requests-and-epics), or:
1. On the left sidebar, select **Search or go to** and find your project.
@@ -123,7 +123,7 @@ To submit your completed review, you can:
- Use the `/submit_review` [quick action](../../quick_actions.md) in the text of a non-review comment.
- Select **Finish review**, then select **Submit review** at the bottom of the dialog.
- In the dialog, you can supply a **Summary comment**, approve the merge request, and
+ In the dialog, you can supply a **Summary comment**, approve (or reject) the merge request, and
include quick actions:

@@ -137,8 +137,8 @@ When you submit your review, GitLab:
- Optional. Shows whether you have also approved or requested changes:
- **Comment**: Leave general feedback without explicit approval.
- **Approve**: Leave feedback and approve the changes.
- - **Request changes**: Leave feedback the author should address before merging.
- You can use this status to block the merge request from merging.
+ - **Request changes**: Block the merge request from merging until the author
+ addresses your feedback.
### Prevent merge when you request changes
@@ -147,17 +147,24 @@ DETAILS:
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/430728) in GitLab 16.11 [with a flag](../../../../administration/feature_flags.md) named `mr_reviewer_requests_changes`. Disabled by default.
-> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/451211) in GitLab 17.2.
-> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/158226) in GitLab 17.2 by default.
+> - Enabled by default [on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/451211) and [self-managed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/158226) in GitLab 17.2.
-Any reviewer [requesting changes](#submit-a-review) blocks the merge request.
-In the merge request reports area, it shows the message **The change requests must be completed or resolved.**
-The request for changes is resolved when the reviewer who requested changes is asked
-to [re-review](#re-request-a-review) and then approves the merge request.
+A reviewer [requesting changes](#submit-a-review) blocks a merge request from merging.
+When this happens, the merge request reports area shows the message
+**The change requests must be completed or resolved.** To unblock the merge request,
+the reviewer who requested changes should [re-review and approve](#re-request-a-review) the merge request.
-If the user who has previously requested changes is unable to re-review or provide an approval,
-users with permission to merge the merge request can override this check in the
-merge request reports area by selecting **Bypass**.
+If the user who requested changes is unable to re-review or provide an approval,
+another user with permission to merge the merge request can override this check in the
+merge request reports area by selecting **Bypass**:
+
+1. On the left sidebar, select **Search or go to** and find your project.
+1. Select **Code > Merge requests** and find your merge request.
+1. Select the title of the merge request to view it.
+1. On the merge request **Overview**, scroll to the merge request reports area.
+1. Next to **The change requests must be completed or resolved**, select **Bypass**:
+
+ 
### See how reviewers map to approval rules
diff --git a/doc/user/ssh.md b/doc/user/ssh.md
index f8ad75d3c13..fbd618da493 100644
--- a/doc/user/ssh.md
+++ b/doc/user/ssh.md
@@ -80,7 +80,7 @@ Available documentation suggests ED25519 is more secure than RSA.
If you use an RSA key, the US National Institute of Standards and Technology in
[Publication 800-57 Part 3 (PDF)](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57Pt3r1.pdf)
recommends a key size of at least 2048 bits. Due to limitations in Go,
-RSA keys [cannot exceed 8192 bits](#tls-server-sent-certificate-containing-rsa-key-larger-than-8192-bits).
+RSA keys [cannot exceed 8192 bits](ssh_troubleshooting.md#tls-server-sent-certificate-containing-rsa-key-larger-than-8192-bits).
The default key size depends on your version of `ssh-keygen`.
Review the `man` page for your installed `ssh-keygen` command for details.
@@ -559,68 +559,3 @@ chmod 700 /var/opt/gitlab/.ssh/
chmod 600 /var/opt/gitlab/.ssh/authorized_keys
chmod 644 /var/opt/gitlab/.ssh/authorized_keys.lock
```
-
-## Troubleshooting
-
-### TLS: server sent certificate containing RSA key larger than 8192 bits
-
-In GitLab 16.3 and later, Go limits RSA keys to a maximum of 8192 bits.
-To check the length of a key:
-
-```shell
-openssl rsa -in -text -noout | grep "Key:"
-```
-
-Replace any key longer than 8192 bits with a shorter key.
-
-### Password prompt with `git clone`
-
-When you run `git clone`, you may be prompted for a password, like `git@gitlab.example.com's password:`.
-This indicates that something is wrong with your SSH setup.
-
-- Ensure that you generated your SSH key pair correctly and added the public SSH
- key to your GitLab profile.
-- Try to manually register your private SSH key by using `ssh-agent`.
-- Try to debug the connection by running `ssh -Tv git@example.com`.
- Replace `example.com` with your GitLab URL.
-- Ensure you followed all the instructions in [Use SSH on Microsoft Windows](#use-ssh-on-microsoft-windows).
-- Ensure that you have [Verify GitLab SSH ownership and permissions](#verify-gitlab-ssh-ownership-and-permissions). If you have several hosts ensure that permissions are correct in all hosts.
-
-### `Could not resolve hostname` error
-
-You may receive the following error when [verifying that you can connect](#verify-that-you-can-connect):
-
-```shell
-ssh: Could not resolve hostname gitlab.example.com: nodename nor servname provided, or not known
-```
-
-If you receive this error, restart your terminal and try the command again.
-
-### `Key enrollment failed: invalid format` error
-
-You may receive the following error when [generating an SSH key pair for a FIDO2 hardware security key](#generate-an-ssh-key-pair-for-a-fido2-hardware-security-key):
-
-```shell
-Key enrollment failed: invalid format
-```
-
-You can troubleshoot this by trying the following:
-
-- Run the `ssh-keygen` command using `sudo`.
-- Verify your FIDO2 hardware security key supports
- the key type provided.
-- Verify the version of OpenSSH is 8.2 or greater by
- running `ssh -V`.
-
-### Error: `SSH host keys are not available on this system.`
-
-If GitLab does not have access to the host SSH keys, when you visit `gitlab.example/help/instance_configuration`, you see the following error message under the **SSH host key fingerprints** header instead of the instance SSH fingerprint:
-
-```plaintext
-SSH host keys are not available on this system. Please use ssh-keyscan command or contact your GitLab administrator for more information.
-```
-
-To resolve this error:
-
-- On Helm chart (Kubernetes) deployments, update the `values.yaml` to set [`sshHostKeys.mount`](https://docs.gitlab.com/charts/charts/gitlab/webservice/) to `true` under the `webservice` section.
-- On GitLab self-managed installations, check the `/etc/ssh` directory for the host keys.
diff --git a/doc/user/ssh_troubleshooting.md b/doc/user/ssh_troubleshooting.md
new file mode 100644
index 00000000000..0e0e5d89e60
--- /dev/null
+++ b/doc/user/ssh_troubleshooting.md
@@ -0,0 +1,72 @@
+---
+stage: Govern
+group: Authentication
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
+---
+
+# Troubleshooting SSH
+
+When working with SSH keys, you might encounter the following issues.
+
+## TLS: server sent certificate containing RSA key larger than 8192 bits
+
+In GitLab 16.3 and later, Go limits RSA keys to a maximum of 8192 bits.
+To check the length of a key:
+
+```shell
+openssl rsa -in -text -noout | grep "Key:"
+```
+
+Replace any key longer than 8192 bits with a shorter key.
+
+## Password prompt with `git clone`
+
+When you run `git clone`, you may be prompted for a password, like `git@gitlab.example.com's password:`.
+This indicates that something is wrong with your SSH setup.
+
+- Ensure that you generated your SSH key pair correctly and added the public SSH
+ key to your GitLab profile.
+- Try to manually register your private SSH key by using `ssh-agent`.
+- Try to debug the connection by running `ssh -Tv git@example.com`.
+ Replace `example.com` with your GitLab URL.
+- Ensure you followed all the instructions in [Use SSH on Microsoft Windows](ssh.md#use-ssh-on-microsoft-windows).
+- Ensure that you have [Verify GitLab SSH ownership and permissions](ssh.md#verify-gitlab-ssh-ownership-and-permissions). If you have several hosts ensure that permissions are correct in all hosts.
+
+## `Could not resolve hostname` error
+
+You may receive the following error when [verifying that you can connect](ssh.md#verify-that-you-can-connect):
+
+```shell
+ssh: Could not resolve hostname gitlab.example.com: nodename nor servname provided, or not known
+```
+
+If you receive this error, restart your terminal and try the command again.
+
+### `Key enrollment failed: invalid format` error
+
+You may receive the following error when [generating an SSH key pair for a FIDO2 hardware security key](ssh.md#generate-an-ssh-key-pair-for-a-fido2-hardware-security-key):
+
+```shell
+Key enrollment failed: invalid format
+```
+
+You can troubleshoot this by trying the following:
+
+- Run the `ssh-keygen` command using `sudo`.
+- Verify your FIDO2 hardware security key supports
+ the key type provided.
+- Verify the version of OpenSSH is 8.2 or greater by
+ running `ssh -V`.
+
+## Error: `SSH host keys are not available on this system.`
+
+If GitLab does not have access to the host SSH keys, when you visit `gitlab.example/help/instance_configuration`, you see the following error message under the **SSH host key fingerprints** header instead of the instance SSH fingerprint:
+
+```plaintext
+SSH host keys are not available on this system. Please use ssh-keyscan command or contact your GitLab administrator for more information.
+```
+
+To resolve this error:
+
+- On Helm chart (Kubernetes) deployments, update the `values.yaml` to set [`sshHostKeys.mount`](https://docs.gitlab.com/charts/charts/gitlab/webservice/) to `true` under the `webservice` section.
+- On GitLab self-managed installations, check the `/etc/ssh` directory for the host keys.
diff --git a/lib/gitlab/import_export/json/streaming_serializer.rb b/lib/gitlab/import_export/json/streaming_serializer.rb
index 1ea68fcfa8b..f7b8c4954cd 100644
--- a/lib/gitlab/import_export/json/streaming_serializer.rb
+++ b/lib/gitlab/import_export/json/streaming_serializer.rb
@@ -257,7 +257,7 @@ module Gitlab
end
def after_read_callback(record)
- if Feature.enabled?(:bulk_import_user_mapping, exportable)
+ if Feature.enabled?(:bulk_import_user_mapping, current_user)
user_contributions_export_mapper.cache_user_contributions_on_record(record)
end
diff --git a/lib/gitlab/usage_data_counters/hll_redis_key_overrides.yml b/lib/gitlab/usage_data_counters/hll_redis_key_overrides.yml
index ef2990c34d8..ddfcba56a12 100644
--- a/lib/gitlab/usage_data_counters/hll_redis_key_overrides.yml
+++ b/lib/gitlab/usage_data_counters/hll_redis_key_overrides.yml
@@ -177,3 +177,13 @@ value_streams_dashboard_metric_link_clicked-user: value_streams_dashboard_metric
value_streams_dashboard_time_to_restore_service_link_clicked-user: value_streams_dashboard_time_to_restore_service_link_clicked
value_streams_dashboard_vulnerability_critical_link_clicked-user: value_streams_dashboard_vulnerability_critical_link_clicked
value_streams_dashboard_vulnerability_high_link_clicked-user: value_streams_dashboard_vulnerability_high_link_clicked
+'view_merge_request_widget-filter:[label:accessibility]-user': i_code_review_merge_request_widget_accessibility_view
+'view_merge_request_widget-filter:[label:code_quality]-user': i_code_review_merge_request_widget_code_quality_view
+'view_merge_request_widget-filter:[label:license_compliance]-user': i_code_review_merge_request_widget_license_compliance_view
+'view_merge_request_widget-filter:[label:status_checks]-user': i_code_review_merge_request_widget_status_checks_view
+'view_merge_request_widget-filter:[label:terraform]-user': i_code_review_merge_request_widget_terraform_view
+'view_merge_request_widget-filter:[label:test_summary]-user': i_code_review_merge_request_widget_test_summary_view
+'view_merge_request_widget-filter:[label:metrics]-user': i_code_review_merge_request_widget_metrics_view
+'view_merge_request_widget-filter:[label:security_reports]-user': i_code_review_merge_request_widget_security_reports_view
+visit_ci_cd_failure_rate_tab-user: p_analytics_ci_cd_change_failure_rate
+visit_ci_cd_time_to_restore_service_tab-user: p_analytics_ci_cd_time_to_restore_service
diff --git a/lib/gitlab/usage_data_counters/hll_redis_legacy_events.yml b/lib/gitlab/usage_data_counters/hll_redis_legacy_events.yml
index b719162e118..4480670311c 100644
--- a/lib/gitlab/usage_data_counters/hll_redis_legacy_events.yml
+++ b/lib/gitlab/usage_data_counters/hll_redis_legacy_events.yml
@@ -355,8 +355,6 @@
- merge_request_action
- o_pipeline_authoring_unique_users_committing_ciconfigfile
- o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile
-- p_analytics_ci_cd_change_failure_rate
-- p_analytics_ci_cd_time_to_restore_service
- p_analytics_code_reviews
- p_analytics_insights
- p_analytics_issues
diff --git a/lib/tasks/dev.rake b/lib/tasks/dev.rake
index e1799617ea0..ffc9f7ecbb0 100644
--- a/lib/tasks/dev.rake
+++ b/lib/tasks/dev.rake
@@ -74,7 +74,7 @@ namespace :dev do
databases = ActiveRecord::Tasks::DatabaseTasks.setup_initial_database_yaml
namespace :copy_db do
- ALLOWED_DATABASES = %w[ci].freeze
+ ALLOWED_DATABASES = %w[ci sec].freeze
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
next unless ALLOWED_DATABASES.include?(name)
diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb
index e39a9cc34bd..f549b1b763e 100644
--- a/spec/controllers/projects/pipelines_controller_spec.rb
+++ b/spec/controllers/projects/pipelines_controller_spec.rb
@@ -768,27 +768,17 @@ RSpec.describe Projects::PipelinesController, feature_category: :continuous_inte
[
{
chart_param: 'time-to-restore-service',
- event: 'p_analytics_ci_cd_time_to_restore_service'
+ event: 'visit_ci_cd_time_to_restore_service_tab'
},
{
chart_param: 'change-failure-rate',
- event: 'p_analytics_ci_cd_change_failure_rate'
+ event: 'visit_ci_cd_failure_rate_tab'
}
].each do |tab|
- it_behaves_like 'tracking unique visits', :charts do
- let(:request_params) { { namespace_id: project.namespace, project_id: project, id: pipeline.id, chart: tab[:chart_param] } }
- let(:target_id) { ['p_analytics_pipelines', tab[:event]] }
- end
+ it 'tracks internal events' do
+ request_params = { namespace_id: project.namespace, project_id: project, id: pipeline.id, chart: tab[:chart_param] }
- it_behaves_like 'Snowplow event tracking with RedisHLL context' do
- subject { get :charts, params: request_params, format: :html }
-
- let(:request_params) { { namespace_id: project.namespace, project_id: project, id: pipeline.id, chart: tab[:chart_param] } }
- let(:category) { described_class.name }
- let(:action) { 'perform_analytics_usage_action' }
- let(:namespace) { project.namespace }
- let(:label) { 'redis_hll_counters.analytics.analytics_total_unique_counts_monthly' }
- let(:property) { 'p_analytics_pipelines' }
+ expect { get :charts, params: request_params, format: :html }.to trigger_internal_events(tab[:event])
end
end
diff --git a/spec/factories/virtual_registries/packages/maven/registries.rb b/spec/factories/virtual_registries/packages/maven/registries.rb
new file mode 100644
index 00000000000..cdfa5d1b012
--- /dev/null
+++ b/spec/factories/virtual_registries/packages/maven/registries.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :virtual_registries_packages_maven_registry, class: 'VirtualRegistries::Packages::Maven::Registry' do
+ group
+ cache_validity_hours { 1 }
+ end
+end
diff --git a/spec/factories/virtual_registries/packages/maven/registry_upstreams.rb b/spec/factories/virtual_registries/packages/maven/registry_upstreams.rb
new file mode 100644
index 00000000000..cc6ca46d348
--- /dev/null
+++ b/spec/factories/virtual_registries/packages/maven/registry_upstreams.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :virtual_registries_packages_maven_registry_upstream,
+ class: 'VirtualRegistries::Packages::Maven::RegistryUpstream' do
+ group { registry.group }
+ registry { association(:virtual_registries_packages_maven_registry) }
+ upstream do
+ association(
+ :virtual_registries_packages_maven_upstream,
+ group: registry.group,
+ registry: registry,
+ registry_upstream: nil
+ )
+ end
+ end
+end
diff --git a/spec/factories/virtual_registries/packages/maven/upstreams.rb b/spec/factories/virtual_registries/packages/maven/upstreams.rb
new file mode 100644
index 00000000000..bb43effa890
--- /dev/null
+++ b/spec/factories/virtual_registries/packages/maven/upstreams.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :virtual_registries_packages_maven_upstream, class: 'VirtualRegistries::Packages::Maven::Upstream' do
+ url { 'http://local.test/maven' }
+ username { 'user' }
+ password { 'password' }
+ registry { association(:virtual_registries_packages_maven_registry) }
+ group { registry.group }
+
+ after(:build) do |entry, _|
+ entry.registry_upstream.group = entry.group if entry.registry_upstream
+ end
+ end
+end
diff --git a/spec/frontend/projects/pipelines/charts/components/app_spec.js b/spec/frontend/projects/pipelines/charts/components/app_spec.js
index 631757ca90e..927872c60f8 100644
--- a/spec/frontend/projects/pipelines/charts/components/app_spec.js
+++ b/spec/frontend/projects/pipelines/charts/components/app_spec.js
@@ -123,28 +123,14 @@ describe('ProjectsPipelinesChartsApp', () => {
});
describe('event tracking', () => {
- describe('RedisHLL events', () => {
- it.each`
- testId | event
- ${'time-to-restore-service-tab'} | ${'p_analytics_ci_cd_time_to_restore_service'}
- ${'change-failure-rate-tab'} | ${'p_analytics_ci_cd_change_failure_rate'}
- `('tracks the $event event when clicked', ({ testId, event }) => {
- const trackApiSpy = jest.spyOn(API, 'trackRedisHllUserEvent');
-
- expect(trackApiSpy).not.toHaveBeenCalled();
-
- wrapper.findByTestId(testId).vm.$emit('click');
-
- expect(trackApiSpy).toHaveBeenCalledWith(event);
- });
- });
-
describe('Internal Events RedisHLL events', () => {
it.each`
- testId | event
- ${'pipelines-tab'} | ${'p_analytics_ci_cd_pipelines'}
- ${'deployment-frequency-tab'} | ${'p_analytics_ci_cd_deployment_frequency'}
- ${'lead-time-tab'} | ${'p_analytics_ci_cd_lead_time'}
+ testId | event
+ ${'pipelines-tab'} | ${'p_analytics_ci_cd_pipelines'}
+ ${'deployment-frequency-tab'} | ${'p_analytics_ci_cd_deployment_frequency'}
+ ${'lead-time-tab'} | ${'p_analytics_ci_cd_lead_time'}
+ ${'time-to-restore-service-tab'} | ${'visit_ci_cd_time_to_restore_service_tab'}
+ ${'change-failure-rate-tab'} | ${'visit_ci_cd_failure_rate_tab'}
`('tracks the $event event when clicked', ({ testId, event }) => {
const trackApiSpy = jest.spyOn(API, 'trackInternalEvent');
@@ -177,18 +163,6 @@ describe('ProjectsPipelinesChartsApp', () => {
},
});
});
-
- it.each`
- tab
- ${'time-to-restore-service-tab'}
- ${'change-failure-rate-tab'}
- `('does not track when tab $tab is clicked', ({ tab }) => {
- const trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
-
- wrapper.findByTestId(tab).vm.$emit('click');
-
- expect(trackingSpy).not.toHaveBeenCalled();
- });
});
});
});
diff --git a/spec/models/virtual_registries/packages/maven/registry_spec.rb b/spec/models/virtual_registries/packages/maven/registry_spec.rb
new file mode 100644
index 00000000000..d188772fd84
--- /dev/null
+++ b/spec/models/virtual_registries/packages/maven/registry_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe VirtualRegistries::Packages::Maven::Registry, type: :model, feature_category: :virtual_registry do
+ subject(:registry) { build(:virtual_registries_packages_maven_registry) }
+
+ describe 'associations' do
+ it { is_expected.to belong_to(:group) }
+
+ it do
+ is_expected.to have_one(:registry_upstream)
+ .class_name('VirtualRegistries::Packages::Maven::RegistryUpstream')
+ .inverse_of(:registry)
+ end
+
+ it do
+ is_expected.to have_one(:upstream)
+ .through(:registry_upstream)
+ .class_name('VirtualRegistries::Packages::Maven::Upstream')
+ end
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_uniqueness_of(:group) }
+ it { is_expected.to validate_presence_of(:group) }
+ it { is_expected.to validate_numericality_of(:cache_validity_hours).only_integer.is_greater_than_or_equal_to(0) }
+ end
+end
diff --git a/spec/models/virtual_registries/packages/maven/registry_upstream_spec.rb b/spec/models/virtual_registries/packages/maven/registry_upstream_spec.rb
new file mode 100644
index 00000000000..2b0e8ba83e2
--- /dev/null
+++ b/spec/models/virtual_registries/packages/maven/registry_upstream_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe VirtualRegistries::Packages::Maven::RegistryUpstream, type: :model, feature_category: :virtual_registry do
+ subject(:registry_upstream) { build(:virtual_registries_packages_maven_registry_upstream) }
+
+ describe 'associations' do
+ it { is_expected.to belong_to(:group) }
+
+ it do
+ is_expected.to belong_to(:registry)
+ .class_name('VirtualRegistries::Packages::Maven::Registry')
+ .inverse_of(:registry_upstream)
+ end
+
+ it do
+ is_expected.to belong_to(:upstream)
+ .class_name('VirtualRegistries::Packages::Maven::Upstream')
+ .inverse_of(:registry_upstream)
+ end
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:group) }
+ it { is_expected.to validate_uniqueness_of(:registry_id) }
+ it { is_expected.to validate_uniqueness_of(:upstream_id) }
+ end
+end
diff --git a/spec/models/virtual_registries/packages/maven/upstream_spec.rb b/spec/models/virtual_registries/packages/maven/upstream_spec.rb
new file mode 100644
index 00000000000..bcacc8f9f00
--- /dev/null
+++ b/spec/models/virtual_registries/packages/maven/upstream_spec.rb
@@ -0,0 +1,106 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe VirtualRegistries::Packages::Maven::Upstream, type: :model, feature_category: :virtual_registry do
+ using RSpec::Parameterized::TableSyntax
+
+ subject(:upstream) { build(:virtual_registries_packages_maven_upstream) }
+
+ describe 'associations' do
+ it do
+ is_expected.to have_one(:registry_upstream)
+ .class_name('VirtualRegistries::Packages::Maven::RegistryUpstream')
+ .inverse_of(:upstream)
+ end
+
+ it do
+ is_expected.to have_one(:registry)
+ .through(:registry_upstream)
+ .class_name('VirtualRegistries::Packages::Maven::Registry')
+ end
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:group) }
+ it { is_expected.to validate_presence_of(:url) }
+ it { is_expected.to validate_presence_of(:username) }
+ it { is_expected.to validate_presence_of(:password) }
+ it { is_expected.to validate_length_of(:url).is_at_most(255) }
+ it { is_expected.to validate_length_of(:username).is_at_most(255) }
+ it { is_expected.to validate_length_of(:password).is_at_most(255) }
+
+ context 'for url' do
+ where(:url, :valid, :error_messages) do
+ 'http://test.maven' | true | nil
+ 'https://test.maven' | true | nil
+ 'git://test.maven' | false | ['Url is blocked: Only allowed schemes are http, https']
+ nil | false | ["Url can't be blank", 'Url must be a valid URL']
+ '' | false | ["Url can't be blank", 'Url must be a valid URL']
+ "http://#{'a' * 255}" | false | 'Url is too long (maximum is 255 characters)'
+ 'http://127.0.0.1' | false | 'Url is blocked: Requests to localhost are not allowed'
+ 'maven.local' | false | 'Url is blocked: Only allowed schemes are http, https'
+ 'http://192.168.1.2' | false | 'Url is blocked: Requests to the local network are not allowed'
+ end
+
+ with_them do
+ before do
+ upstream.url = url
+ end
+
+ if params[:valid]
+ it { expect(upstream).to be_valid }
+ else
+ it do
+ expect(upstream).not_to be_valid
+ expect(upstream.errors).to contain_exactly(*error_messages)
+ end
+ end
+ end
+ end
+
+ context 'for credentials' do
+ where(:username, :password, :valid, :error_message) do
+ 'user' | 'password' | true | nil
+ '' | '' | true | nil
+ '' | nil | true | nil
+ nil | '' | true | nil
+ nil | 'password' | false | "Username can't be blank"
+ 'user' | nil | false | "Password can't be blank"
+ '' | 'password' | false | "Username can't be blank"
+ 'user' | '' | false | "Password can't be blank"
+ ('a' * 256) | 'password' | false | 'Username is too long (maximum is 255 characters)'
+ 'user' | ('a' * 256) | false | 'Password is too long (maximum is 255 characters)'
+ end
+
+ with_them do
+ before do
+ upstream.username = username
+ upstream.password = password
+ end
+
+ if params[:valid]
+ it { expect(upstream).to be_valid }
+ else
+ it do
+ expect(upstream).not_to be_valid
+ expect(upstream.errors).to contain_exactly(error_message)
+ end
+ end
+ end
+ end
+ end
+
+ context 'for credentials persistance' do
+ it 'persists and reads back credentials properly' do
+ upstream.username = 'test'
+ upstream.password = 'test'
+
+ upstream.save!
+
+ upstream_read = upstream.reload
+ expect(upstream_read.username).to eq('test')
+ expect(upstream_read.password).to eq('test')
+ end
+ end
+end
diff --git a/spec/services/projects/update_pages_service_spec.rb b/spec/services/projects/update_pages_service_spec.rb
index b5d1276988f..6712c12fab6 100644
--- a/spec/services/projects/update_pages_service_spec.rb
+++ b/spec/services/projects/update_pages_service_spec.rb
@@ -160,6 +160,14 @@ RSpec.describe Projects::UpdatePagesService, feature_category: :pages do
.by(1)
end
+ it_behaves_like 'internal event tracking' do
+ let(:event) { 'create_pages_deployment' }
+ let(:category) { 'Projects::UpdatePagesService' }
+ let(:namespace) { project.namespace }
+
+ subject(:track_event) { service.execute }
+ end
+
context 'when archive does not have pages directory' do
let(:file) { empty_file }
let(:metadata_filename) { empty_metadata_filename }