summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-06-10 18:09:28 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-06-10 18:09:28 +0000
commit2f7719abdfde4cb50ed05346b98bac26ea06a8de (patch)
tree71bc9a5cde931b50f38f2e2fe76cc67e1181e3d6
parent37140013714814d8ffe662a372697c56eea2fde0 (diff)
downloadgitlab-ce-2f7719abdfde4cb50ed05346b98bac26ea06a8de.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.rubocop_todo/layout/line_length.yml3
-rw-r--r--.rubocop_todo/style/open_struct_use.yml21
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock8
-rw-r--r--app/assets/javascripts/environments/components/deploy_board_wrapper.vue2
-rw-r--r--app/assets/javascripts/issuable/components/related_issuable_item.vue3
-rw-r--r--app/assets/stylesheets/components/avatar.scss4
-rw-r--r--app/assets/stylesheets/components/feature_highlight.scss26
-rw-r--r--app/assets/stylesheets/components/related_items_list.scss6
-rw-r--r--app/components/pajamas/button_component.rb6
-rw-r--r--app/models/error_tracking/client_key.rb1
-rw-r--r--app/services/event_create_service.rb18
-rw-r--r--app/views/profiles/keys/_form.html.haml5
-rw-r--r--config/events/1654698269_merge_request_action_create.yml26
-rw-r--r--config/events/1654698359_merge_request_action_close.yml26
-rw-r--r--config/events/1654698407_merge_request_action_merge.yml26
-rw-r--r--config/events/1654843786_merge_request_action_comment.yml27
-rw-r--r--config/feature_flags/development/fix_sliding_list_partitioning.yml8
-rw-r--r--db/post_migrate/20220518102414_add_index_to_error_tracking_client_keys.rb20
-rw-r--r--db/schema_migrations/202205181024141
-rw-r--r--db/structure.sql2
-rw-r--r--doc/administration/gitaly/index.md5
-rw-r--r--doc/administration/gitaly/praefect.md3
-rw-r--r--doc/development/database_debugging.md6
-rw-r--r--doc/development/internal_api/index.md31
-rw-r--r--doc/integration/gitpod.md2
-rw-r--r--doc/update/upgrading_from_source.md3
-rw-r--r--doc/update/zero_downtime.md91
-rw-r--r--doc/user/infrastructure/clusters/connect/new_eks_cluster.md2
-rw-r--r--doc/user/infrastructure/clusters/connect/new_gke_cluster.md5
-rw-r--r--lib/api/internal/base.rb12
-rw-r--r--lib/gitlab/database/partitioning/monthly_strategy.rb4
-rw-r--r--lib/gitlab/database/partitioning/partition_manager.rb13
-rw-r--r--lib/gitlab/database/partitioning/sliding_list_strategy.rb53
-rw-r--r--lib/gitlab/event_store/subscription.rb3
-rw-r--r--spec/components/pajamas/button_component_spec.rb44
-rw-r--r--spec/frontend/environments/deploy_board_wrapper_spec.js4
-rw-r--r--spec/lib/gitlab/database/partitioning/partition_manager_spec.rb34
-rw-r--r--spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb68
-rw-r--r--spec/lib/gitlab/event_store/store_spec.rb18
-rw-r--r--spec/requests/api/internal/base_spec.rb58
-rw-r--r--spec/services/event_create_service_spec.rb80
43 files changed, 626 insertions, 156 deletions
diff --git a/.rubocop_todo/layout/line_length.yml b/.rubocop_todo/layout/line_length.yml
index eeb5c7c20da..5a593ca31df 100644
--- a/.rubocop_todo/layout/line_length.yml
+++ b/.rubocop_todo/layout/line_length.yml
@@ -3462,11 +3462,9 @@ Layout/LineLength:
- 'lib/gitlab/database/migrations/runner.rb'
- 'lib/gitlab/database/migrations/test_background_runner.rb'
- 'lib/gitlab/database/partitioning/detached_partition_dropper.rb'
- - 'lib/gitlab/database/partitioning/partition_manager.rb'
- 'lib/gitlab/database/partitioning/partition_monitoring.rb'
- 'lib/gitlab/database/partitioning/replace_table.rb'
- 'lib/gitlab/database/partitioning/single_numeric_list_partition.rb'
- - 'lib/gitlab/database/partitioning/sliding_list_strategy.rb'
- 'lib/gitlab/database/partitioning/time_partition.rb'
- 'lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb'
- 'lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb'
@@ -4990,7 +4988,6 @@ Layout/LineLength:
- 'spec/lib/gitlab/database/partitioning/monthly_strategy_spec.rb'
- 'spec/lib/gitlab/database/partitioning/partition_manager_spec.rb'
- 'spec/lib/gitlab/database/partitioning/partition_monitoring_spec.rb'
- - 'spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb'
- 'spec/lib/gitlab/database/partitioning_migration_helpers/index_helpers_spec.rb'
- 'spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb'
- 'spec/lib/gitlab/database/postgres_foreign_key_spec.rb'
diff --git a/.rubocop_todo/style/open_struct_use.yml b/.rubocop_todo/style/open_struct_use.yml
index eb8d467ef9f..15e4539072d 100644
--- a/.rubocop_todo/style/open_struct_use.yml
+++ b/.rubocop_todo/style/open_struct_use.yml
@@ -1,15 +1,12 @@
---
Style/OpenStructUse:
Exclude:
- - ee/spec/features/projects/new_project_spec.rb
- - ee/spec/finders/template_finder_spec.rb
- - ee/spec/helpers/ee/blob_helper_spec.rb
- - ee/spec/lib/gitlab/auth/group_saml/failure_handler_spec.rb
- - lib/gitlab/testing/request_inspector_middleware.rb
- - spec/factories/wiki_pages.rb
- - spec/helpers/application_settings_helper_spec.rb
- - spec/helpers/profiles_helper_spec.rb
- - spec/lib/gitlab/gitaly_client/blobs_stitcher_spec.rb
- - spec/lib/gitlab/gitaly_client/diff_stitcher_spec.rb
- - spec/services/system_note_service_spec.rb
- - spec/support/helpers/repo_helpers.rb
+ - 'ee/spec/features/projects/new_project_spec.rb'
+ - 'ee/spec/finders/template_finder_spec.rb'
+ - 'ee/spec/helpers/ee/blob_helper_spec.rb'
+ - 'ee/spec/lib/gitlab/auth/group_saml/failure_handler_spec.rb'
+ - 'spec/factories/wiki_pages.rb'
+ - 'spec/helpers/profiles_helper_spec.rb'
+ - 'spec/lib/gitlab/gitaly_client/blobs_stitcher_spec.rb'
+ - 'spec/lib/gitlab/gitaly_client/diff_stitcher_spec.rb'
+ - 'spec/support/helpers/repo_helpers.rb'
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index e754d61ec81..bddcdfaaa62 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-30b922784b9d0492ba525a35ec09782dd2bcace3
+1fb1d2f7119c5d7bfdbc53e8ae9cc22058921219
diff --git a/Gemfile b/Gemfile
index 5915e0384d1..ffcc8e289b3 100644
--- a/Gemfile
+++ b/Gemfile
@@ -4,7 +4,7 @@ source 'https://rubygems.org'
gem 'rails', '~> 6.1.4.7'
-gem 'bootsnap', '~> 1.9.4', require: false
+gem 'bootsnap', '~> 1.12.0', require: false
# Responders respond_to and respond_with
gem 'responders', '~> 3.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index f5323c0744e..b98a18d8f8f 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -150,8 +150,8 @@ GEM
rack (>= 0.9.0)
bindata (2.4.10)
binding_ninja (0.2.3)
- bootsnap (1.9.4)
- msgpack (~> 1.0)
+ bootsnap (1.12.0)
+ msgpack (~> 1.2)
bootstrap_form (4.2.0)
actionpack (>= 5.0)
activemodel (>= 5.0)
@@ -785,7 +785,7 @@ GEM
faraday (>= 0.9, < 2.0.0)
faraday-cookie_jar (~> 0.0.6)
ms_rest (~> 0.7.6)
- msgpack (1.5.1)
+ msgpack (1.5.2)
multi_json (1.14.1)
multi_xml (0.6.0)
multipart-post (2.1.1)
@@ -1472,7 +1472,7 @@ DEPENDENCIES
benchmark-ips (~> 2.3.0)
benchmark-memory (~> 0.1)
better_errors (~> 2.9.0)
- bootsnap (~> 1.9.4)
+ bootsnap (~> 1.12.0)
bootstrap_form (~> 4.2.0)
browser (~> 4.2)
bullet (~> 6.1.3)
diff --git a/app/assets/javascripts/environments/components/deploy_board_wrapper.vue b/app/assets/javascripts/environments/components/deploy_board_wrapper.vue
index d9d77088ad3..d1132bc6e24 100644
--- a/app/assets/javascripts/environments/components/deploy_board_wrapper.vue
+++ b/app/assets/javascripts/environments/components/deploy_board_wrapper.vue
@@ -25,7 +25,7 @@ export default {
},
computed: {
icon() {
- return this.visible ? 'angle-down' : 'angle-right';
+ return this.visible ? 'chevron-lg-down' : 'chevron-lg-right';
},
label() {
return this.visible ? this.$options.i18n.collapse : this.$options.i18n.expand;
diff --git a/app/assets/javascripts/issuable/components/related_issuable_item.vue b/app/assets/javascripts/issuable/components/related_issuable_item.vue
index dfe18567608..e7d951fffaa 100644
--- a/app/assets/javascripts/issuable/components/related_issuable_item.vue
+++ b/app/assets/javascripts/issuable/components/related_issuable_item.vue
@@ -71,8 +71,9 @@ export default {
:class="{
'issuable-info-container': !canReorder,
'card-body': canReorder,
+ 'gl-pr-2': canRemove,
}"
- class="item-body d-flex align-items-center py-2 px-3"
+ class="item-body d-flex align-items-center gl-py-3 gl-px-5"
>
<div
class="item-contents gl-display-flex gl-align-items-center gl-flex-wrap gl-flex-grow-1 flex-xl-nowrap gl-min-h-7"
diff --git a/app/assets/stylesheets/components/avatar.scss b/app/assets/stylesheets/components/avatar.scss
index 3885134e276..ceac5da7f80 100644
--- a/app/assets/stylesheets/components/avatar.scss
+++ b/app/assets/stylesheets/components/avatar.scss
@@ -113,10 +113,6 @@ $avatar-sizes: (
border-radius: 0;
border: 0;
}
-
- &.avatar-placeholder {
- border: 0;
- }
}
.identicon {
diff --git a/app/assets/stylesheets/components/feature_highlight.scss b/app/assets/stylesheets/components/feature_highlight.scss
index 54123e74675..4d301cc5617 100644
--- a/app/assets/stylesheets/components/feature_highlight.scss
+++ b/app/assets/stylesheets/components/feature_highlight.scss
@@ -1,29 +1,3 @@
-.gl-badge.feature-highlight-badge {
- background-color: $purple-light;
- color: $purple;
-
- &,
- &.sm {
- padding: 0.25rem;
- }
-}
-
-.gl-order-1 {
- order: 1;
-}
-
-.gl-sm-order-init {
- @media (min-width: $breakpoint-sm) {
- order: initial;
- }
-}
-
-.gl-xs-ml-3 {
- @media (max-width: $breakpoint-sm) {
- @include gl-ml-3;
- }
-}
-
.gl-sm-mr-3 {
@media (min-width: $breakpoint-sm) {
@include gl-mr-3;
diff --git a/app/assets/stylesheets/components/related_items_list.scss b/app/assets/stylesheets/components/related_items_list.scss
index 7c668666d70..3bb889b6ba0 100644
--- a/app/assets/stylesheets/components/related_items_list.scss
+++ b/app/assets/stylesheets/components/related_items_list.scss
@@ -80,11 +80,6 @@ $item-remove-button-space: 42px;
.health-label-short {
max-width: 0;
}
-
- .bullet-separator {
- font-size: 9px;
- color: $gray-200;
- }
}
.card-header {
@@ -198,7 +193,6 @@ $item-remove-button-space: 42px;
}
}
-.mr-status-wrapper,
.mr-ci-status {
line-height: 0;
}
diff --git a/app/components/pajamas/button_component.rb b/app/components/pajamas/button_component.rb
index da00301516a..c6193d1ae05 100644
--- a/app/components/pajamas/button_component.rb
+++ b/app/components/pajamas/button_component.rb
@@ -5,6 +5,7 @@ module Pajamas
# @param [Symbol] category
# @param [Symbol] variant
# @param [Symbol] size
+ # @param [Symbol] type
# @param [Boolean] disabled
# @param [Boolean] loading
# @param [Boolean] block
@@ -19,6 +20,7 @@ module Pajamas
category: :primary,
variant: :default,
size: :medium,
+ type: :button,
disabled: false,
loading: false,
block: false,
@@ -33,6 +35,7 @@ module Pajamas
@category = filter_attribute(category.to_sym, CATEGORY_OPTIONS)
@variant = filter_attribute(variant.to_sym, VARIANT_OPTIONS)
@size = filter_attribute(size.to_sym, SIZE_OPTIONS)
+ @type = filter_attribute(type.to_sym, TYPE_OPTIONS, default: :button)
@disabled = disabled
@loading = loading
@block = block
@@ -70,6 +73,7 @@ module Pajamas
CATEGORY_OPTIONS = [:primary, :secondary, :tertiary].freeze
VARIANT_OPTIONS = [:default, :confirm, :danger, :dashed, :link, :reset].freeze
SIZE_OPTIONS = [:small, :medium].freeze
+ TYPE_OPTIONS = [:button, :reset, :submit].freeze
TARGET_OPTIONS = %w[_self _blank _parent _top].freeze
CATEGORY_CLASSES = {
@@ -106,7 +110,7 @@ module Pajamas
attributes['disabled'] = '' if @disabled || @loading
attributes['aria-disabled'] = true if @disabled || @loading
- attributes['type'] = 'button' unless @href
+ attributes['type'] = @type unless @href
attributes
end
diff --git a/app/models/error_tracking/client_key.rb b/app/models/error_tracking/client_key.rb
index 8e59f6f9ecb..bbc57573aa9 100644
--- a/app/models/error_tracking/client_key.rb
+++ b/app/models/error_tracking/client_key.rb
@@ -7,6 +7,7 @@ class ErrorTracking::ClientKey < ApplicationRecord
validates :public_key, presence: true, length: { maximum: 255 }
scope :active, -> { where(active: true) }
+ scope :enabled_key_for, -> (project_id, public_key) { active.where(project_id: project_id, public_key: public_key) }
after_initialize :generate_key
diff --git a/app/services/event_create_service.rb b/app/services/event_create_service.rb
index 5a2c29f8e7a..2ab4bb47462 100644
--- a/app/services/event_create_service.rb
+++ b/app/services/event_create_service.rb
@@ -25,12 +25,14 @@ class EventCreateService
def open_mr(merge_request, current_user)
create_record_event(merge_request, current_user, :created).tap do
track_event(event_action: :created, event_target: MergeRequest, author_id: current_user.id)
+ track_mr_snowplow_event(merge_request, current_user, :create)
end
end
def close_mr(merge_request, current_user)
create_record_event(merge_request, current_user, :closed).tap do
track_event(event_action: :closed, event_target: MergeRequest, author_id: current_user.id)
+ track_mr_snowplow_event(merge_request, current_user, :close)
end
end
@@ -41,6 +43,7 @@ class EventCreateService
def merge_mr(merge_request, current_user)
create_record_event(merge_request, current_user, :merged).tap do
track_event(event_action: :merged, event_target: MergeRequest, author_id: current_user.id)
+ track_mr_snowplow_event(merge_request, current_user, :merge)
end
end
@@ -64,6 +67,7 @@ class EventCreateService
create_record_event(note, current_user, :commented).tap do
if note.is_a?(DiffNote) && note.for_merge_request?
track_event(event_action: :commented, event_target: MergeRequest, author_id: current_user.id)
+ track_mr_snowplow_event(note, current_user, :comment)
end
end
end
@@ -225,6 +229,20 @@ class EventCreateService
def track_event(**params)
Gitlab::UsageDataCounters::TrackUniqueEvents.track_event(**params)
end
+
+ def track_mr_snowplow_event(record, current_user, action)
+ return unless Feature.enabled?(:route_hll_to_snowplow_phase2)
+
+ project = record.project
+ Gitlab::Tracking.event(
+ Gitlab::UsageDataCounters::TrackUniqueEvents::MERGE_REQUEST_ACTION.to_s,
+ action.to_s,
+ label: 'merge_requests_users',
+ project: project,
+ namespace: project.namespace,
+ user: current_user
+ )
+ end
end
EventCreateService.prepend_mod_with('EventCreateService')
diff --git a/app/views/profiles/keys/_form.html.haml b/app/views/profiles/keys/_form.html.haml
index 941b8545745..db13a7f7ba4 100644
--- a/app/views/profiles/keys/_form.html.haml
+++ b/app/views/profiles/keys/_form.html.haml
@@ -23,7 +23,8 @@
%strong= _('Oops, are you sure?')
%p= s_("Profiles|Publicly visible private SSH keys can compromise your system.")
- %button.btn.gl-button.btn-confirm.js-add-ssh-key-validation-confirm-submit= _("Yes, add it")
-
+ = render Pajamas::ButtonComponent.new(variant: :confirm,
+ button_options: { class: 'js-add-ssh-key-validation-confirm-submit' }) do
+ = _("Yes, add it")
.gl-mt-3
= f.submit s_('Profiles|Add key'), class: "gl-button btn btn-confirm js-add-ssh-key-validation-original-submit qa-add-key-button"
diff --git a/config/events/1654698269_merge_request_action_create.yml b/config/events/1654698269_merge_request_action_create.yml
new file mode 100644
index 00000000000..999d9744c92
--- /dev/null
+++ b/config/events/1654698269_merge_request_action_create.yml
@@ -0,0 +1,26 @@
+---
+description: Triggered from backend layer when merge request is created
+category: merge_request_action
+action: create
+label_description: Constant string that match with ServicePing metric name of merge_requests_users
+property_description:
+value_description:
+extra_properties:
+identifiers:
+- project
+- user
+- namespace
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+milestone: "15.1"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89544
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
+
diff --git a/config/events/1654698359_merge_request_action_close.yml b/config/events/1654698359_merge_request_action_close.yml
new file mode 100644
index 00000000000..79807fa378d
--- /dev/null
+++ b/config/events/1654698359_merge_request_action_close.yml
@@ -0,0 +1,26 @@
+---
+description: Triggered from backend layer when merge request is closed
+category: merge_request_action
+action: close
+label_description: Constant string that match with ServicePing metric name of merge_requests_users
+property_description:
+value_description:
+extra_properties:
+identifiers:
+- project
+- user
+- namespace
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+milestone: "15.1"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89544
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
+
diff --git a/config/events/1654698407_merge_request_action_merge.yml b/config/events/1654698407_merge_request_action_merge.yml
new file mode 100644
index 00000000000..3a0a1282e93
--- /dev/null
+++ b/config/events/1654698407_merge_request_action_merge.yml
@@ -0,0 +1,26 @@
+---
+description: Triggered from backend layer when merge request is merged
+category: merge_request_action
+action: merge
+label_description: Constant string that match with ServicePing metric name of merge_requests_users
+property_description:
+value_description:
+extra_properties:
+identifiers:
+- project
+- user
+- namespace
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+milestone: "15.1"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89544
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
+
diff --git a/config/events/1654843786_merge_request_action_comment.yml b/config/events/1654843786_merge_request_action_comment.yml
new file mode 100644
index 00000000000..5cd384cd78e
--- /dev/null
+++ b/config/events/1654843786_merge_request_action_comment.yml
@@ -0,0 +1,27 @@
+---
+description: Triggered from backend layer when merge request is commented
+category: merge_request_action
+action: comment
+label_description: Constant string that match with ServicePing metric name of merge_requests_users
+property_description:
+value_description:
+extra_properties:
+identifiers:
+ - project
+ - user
+ - namespace
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+milestone: "15.1"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89544
+distributions:
+ - ce
+ - ee
+tiers:
+ - free
+ - premium
+ - ultimate
+
+
diff --git a/config/feature_flags/development/fix_sliding_list_partitioning.yml b/config/feature_flags/development/fix_sliding_list_partitioning.yml
new file mode 100644
index 00000000000..90b4bf87740
--- /dev/null
+++ b/config/feature_flags/development/fix_sliding_list_partitioning.yml
@@ -0,0 +1,8 @@
+---
+name: fix_sliding_list_partitioning
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85222
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/362246
+milestone: '15.1'
+type: development
+group: group::sharding
+default_enabled: false
diff --git a/db/post_migrate/20220518102414_add_index_to_error_tracking_client_keys.rb b/db/post_migrate/20220518102414_add_index_to_error_tracking_client_keys.rb
new file mode 100644
index 00000000000..25923bf00f6
--- /dev/null
+++ b/db/post_migrate/20220518102414_add_index_to_error_tracking_client_keys.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class AddIndexToErrorTrackingClientKeys < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_error_tracking_client_for_enabled_check'
+
+ def up
+ add_concurrent_index(
+ :error_tracking_client_keys,
+ [:project_id, :public_key],
+ where: 'active = true',
+ name: INDEX_NAME
+ )
+ end
+
+ def down
+ remove_concurrent_index_by_name(:error_tracking_client_keys, INDEX_NAME)
+ end
+end
diff --git a/db/schema_migrations/20220518102414 b/db/schema_migrations/20220518102414
new file mode 100644
index 00000000000..4c614b132b0
--- /dev/null
+++ b/db/schema_migrations/20220518102414
@@ -0,0 +1 @@
+753b40cdcd5d7b23098c1f7a7f68e25132a75bf1343f59dee583d5a55168f8be \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 71c4caad2b4..a9c9750835a 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -27860,6 +27860,8 @@ CREATE INDEX index_epics_on_start_date_sourcing_epic_id ON epics USING btree (st
CREATE INDEX index_epics_on_start_date_sourcing_milestone_id ON epics USING btree (start_date_sourcing_milestone_id);
+CREATE INDEX index_error_tracking_client_for_enabled_check ON error_tracking_client_keys USING btree (project_id, public_key) WHERE (active = true);
+
CREATE INDEX index_error_tracking_client_keys_on_project_id ON error_tracking_client_keys USING btree (project_id);
CREATE INDEX index_error_tracking_error_events_on_error_id ON error_tracking_error_events USING btree (error_id);
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index 1d8d8d87734..3acd58392e8 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -518,6 +518,11 @@ For configuration information, see [Configure replication factor](praefect.md#co
For more information on configuring Gitaly Cluster, see [Configure Gitaly Cluster](praefect.md).
+### Upgrade Gitaly Cluster
+
+To upgrade a Gitaly Cluster, follow the documentation for
+[zero downtime upgrades](../../update/zero_downtime.md#gitaly-or-gitaly-cluster).
+
## Migrating to Gitaly Cluster
See the [Before deploying Gitaly Cluster](#before-deploying-gitaly-cluster) section before continuing. The basic process
diff --git a/doc/administration/gitaly/praefect.md b/doc/administration/gitaly/praefect.md
index b086016c8ff..43734b66232 100644
--- a/doc/administration/gitaly/praefect.md
+++ b/doc/administration/gitaly/praefect.md
@@ -19,9 +19,6 @@ Configure Gitaly Cluster using either:
Smaller GitLab installations may need only [Gitaly itself](index.md).
-To upgrade a Gitaly Cluster, follow the documentation for
-[zero downtime upgrades](../../update/zero_downtime.md#gitaly-cluster).
-
## Requirements
The minimum recommended configuration for a Gitaly Cluster requires:
diff --git a/doc/development/database_debugging.md b/doc/development/database_debugging.md
index c734799cdc4..5d46ade98bb 100644
--- a/doc/development/database_debugging.md
+++ b/doc/development/database_debugging.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
This section is to help give some copy-pasta you can use as a reference when you
run into some head-banging database problems.
-An easy first step is to search for your error in Slack, or search for `GitLab <my error>` with Google.
+A first step is to search for your error in Slack, or search for `GitLab <my error>` with Google.
Available `RAILS_ENV`:
@@ -106,7 +106,7 @@ Use these instructions for exploring the GitLab database while developing with t
1. Install or open [Visual Studio Code](https://code.visualstudio.com/download).
1. Install the [PostgreSQL VSCode Extension](https://marketplace.visualstudio.com/items?itemName=ckolkman.vscode-postgres).
-1. In Visual Studio Code select the PostgreSQL Explorer button in the left toolbar.
+1. In Visual Studio Code select **PostgreSQL Explorer** in the left toolbar.
1. In the top bar of the new window, select `+` to **Add Database Connection**, and follow the prompts to fill in the details:
1. **Hostname**: the path to the PostgreSQL folder in your GDK directory (for example `/dev/gitlab-development-kit/postgresql`).
1. **PostgreSQL user to authenticate as**: usually your local username, unless otherwise specified during PostgreSQL installation.
@@ -169,7 +169,7 @@ possible to migrate GitLab from every previous version.
In some cases you may want to bypass this check. For example, if you were on a version
of GitLab schema later than the `MIN_SCHEMA_VERSION`, and then rolled back the
-to an older migration, from before. In this case, in order to migrate forward again,
+to an older migration, from before. In this case, to migrate forward again,
you should set the `SKIP_SCHEMA_VERSION_CHECK` environment variable.
```shell
diff --git a/doc/development/internal_api/index.md b/doc/development/internal_api/index.md
index 06252ed1f79..fad651709e3 100644
--- a/doc/development/internal_api/index.md
+++ b/doc/development/internal_api/index.md
@@ -331,6 +331,37 @@ Example response:
- GitLab Shell
+## Authenticate Error Tracking requests
+
+This endpoint will be called by the error tracking GO REST API application to authenticate a project.
+
+| Attribute | Type | Required | Description |
+|:-------------|:--------|:---------|:-------------------------------------------------------------------|
+| `project_id` | integer | yes | The ID of the project which has the associated key. |
+| `public_key` | string | yes | The public key generated by the integrated error tracking feature. |
+
+```plaintext
+POST /internal/error_tracking_allowed
+```
+
+Example request:
+
+```shell
+curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded secret>" \
+ --data "project_id=111&public_key=generated-error-tracking-key" \
+ "http://localhost:3001/api/v4/internal/error_tracking_allowed"
+```
+
+Example response:
+
+```json
+{ "enabled": true }
+```
+
+### Known consumers
+
+- OpsTrace
+
## Incrementing counter on pre-receive
This is called from the Gitaly hooks increasing the reference counter
diff --git a/doc/integration/gitpod.md b/doc/integration/gitpod.md
index 84294a99ef9..271505d3d6f 100644
--- a/doc/integration/gitpod.md
+++ b/doc/integration/gitpod.md
@@ -62,7 +62,7 @@ You can launch Gitpod directly from GitLab in one of these ways:
- *From your project's page:*
1. Go to your project, then go to the page you want to edit.
- 1. Select the caret **(angle-down)** next to **Web IDE**, and select **Gitpod**
+ 1. Select the caret (**{chevron-lg-down}**) next to **Web IDE**, and select **Gitpod**
from the list:
![Gitpod Button on Project Page](img/gitpod_button_project_page_v13_4.png)
diff --git a/doc/update/upgrading_from_source.md b/doc/update/upgrading_from_source.md
index 1a36c76919a..29bb956cb54 100644
--- a/doc/update/upgrading_from_source.md
+++ b/doc/update/upgrading_from_source.md
@@ -346,6 +346,9 @@ upgrade instructions.
### 13. Update Gitaly
+If Gitaly is located on its own server, or you use Gitaly Cluster, see [Gitaly or Gitaly Cluster](zero_downtime.md#gitaly-or-gitaly-cluster)
+on the Zero downtime upgrades page.
+
#### Compile Gitaly
```shell
diff --git a/doc/update/zero_downtime.md b/doc/update/zero_downtime.md
index 2da5df09d31..834331d7fe7 100644
--- a/doc/update/zero_downtime.md
+++ b/doc/update/zero_downtime.md
@@ -21,7 +21,7 @@ If you meet all the requirements above, follow these instructions in order. Ther
| Deployment type | Description |
| --------------------------------------------------------------- | ------------------------------------------------ |
-| [Gitaly Cluster](#gitaly-cluster) | GitLab CE/EE using HA architecture for Gitaly Cluster |
+| [Gitaly or Gitaly Cluster](#gitaly-or-gitaly-cluster) | GitLab CE/EE using HA architecture for Gitaly or Gitaly Cluster |
| [Multi-node / PostgreSQL HA](#use-postgresql-ha) | GitLab CE/EE using HA architecture for PostgreSQL |
| [Multi-node / Redis HA](#use-redis-ha-using-sentinel) | GitLab CE/EE using HA architecture for Redis |
| [Geo](#geo-deployment) | GitLab EE with Geo enabled |
@@ -176,21 +176,19 @@ load balancer to latest GitLab version.
sudo gitlab-rake db:migrate
```
-### Gitaly Cluster
+### Gitaly or Gitaly Cluster
-[Gitaly Cluster](../administration/gitaly/praefect.md) is built using
-Gitaly and the Praefect component. It has its own PostgreSQL database, independent of the rest of
-the application.
+Gitaly nodes can be located on their own server, either as part of a sharded setup, or as part of
+[Gitaly Cluster](../administration/gitaly/praefect.md).
-Before you update the main GitLab application you need to update the Gitaly nodes
-and then Praefect.
+Before you update the main GitLab application you must (in order):
-**Gitaly nodes**
+1. Upgrade the Gitaly nodes that reside on separate servers.
+1. Upgrade Praefect if using Gitaly Cluster.
-Upgrade the Gitaly nodes in your Gitaly cluster one at a time
-to ensure access to Git repositories is maintained.
+#### Upgrade Gitaly nodes
-Update the GitLab package:
+Upgrade the Gitaly nodes one at a time to ensure access to Git repositories is maintained:
```shell
# Debian/Ubuntu
@@ -202,61 +200,60 @@ sudo yum install gitlab-ee
If you are a Community Edition user, replace `gitlab-ee` with `gitlab-ce` in the above command.
-**Praefect**
+#### Upgrade Praefect
-Out of your Praefect nodes, pick one to be your Praefect deploy node.
-This is where you install the new Omnibus package first and run
-database migrations.
+From the Praefect nodes, select one to be your Praefect deploy node. You install the new Omnibus package on the deploy
+node first and run database migrations.
-**Praefect deploy node**
+1. On the **Praefect deploy node**:
-- Create an empty file at `/etc/gitlab/skip-auto-reconfigure`. This prevents upgrades from running `gitlab-ctl reconfigure`, which by default automatically stops GitLab, runs all database migrations, and restarts GitLab:
+ 1. Create an empty file at `/etc/gitlab/skip-auto-reconfigure`. This prevents upgrades from running `gitlab-ctl reconfigure`,
+ which by default automatically stops GitLab, runs all database migrations, and restarts GitLab:
- ```shell
- sudo touch /etc/gitlab/skip-auto-reconfigure
- ```
-
-- Ensure that `praefect['auto_migrate'] = true` is set in `/etc/gitlab/gitlab.rb`
+ ```shell
+ sudo touch /etc/gitlab/skip-auto-reconfigure
+ ```
-**All Praefect nodes _excluding_ the Praefect deploy node**
+ 1. Ensure that `praefect['auto_migrate'] = true` is set in `/etc/gitlab/gitlab.rb`.
-- To prevent `reconfigure` from automatically running database migrations, ensure that `praefect['auto_migrate'] = false` is set in `/etc/gitlab/gitlab.rb`.
+1. On all **remaining Praefect nodes**, ensure that `praefect['auto_migrate'] = false` is
+ set in `/etc/gitlab/gitlab.rb` to prevent `reconfigure` from automatically running database migrations.
-**Praefect deploy node**
+1. On the **Praefect deploy node**:
-- Update the GitLab package:
+ 1. Upgrade the GitLab package:
- ```shell
- # Debian/Ubuntu
- sudo apt-get update && sudo apt-get install gitlab-ee
+ ```shell
+ # Debian/Ubuntu
+ sudo apt-get update && sudo apt-get install gitlab-ee
- # Centos/RHEL
- sudo yum install gitlab-ee
- ```
+ # Centos/RHEL
+ sudo yum install gitlab-ee
+ ```
- If you are a Community Edition user, replace `gitlab-ee` with `gitlab-ce` in the above command.
+ If you are a Community Edition user, replace `gitlab-ee` with `gitlab-ce` in the command above.
-- To apply the Praefect database migrations and restart Praefect, run:
+ 1. To apply the Praefect database migrations and restart Praefect, run:
- ```shell
- sudo gitlab-ctl reconfigure
- ```
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
-**All Praefect nodes _excluding_ the Praefect deploy node**
+1. On all **remaining Praefect nodes**:
-- Update the GitLab package:
+ 1. Upgrade the GitLab package:
- ```shell
- sudo apt-get update && sudo apt-get install gitlab-ee
- ```
+ ```shell
+ sudo apt-get update && sudo apt-get install gitlab-ee
+ ```
- If you are a Community Edition user, replace `gitlab-ee` with `gitlab-ce` in the above command.
+ If you are a Community Edition user, replace `gitlab-ee` with `gitlab-ce` in the command above.
-- Ensure nodes are running the latest code:
+ 1. Ensure nodes are running the latest code:
- ```shell
- sudo gitlab-ctl reconfigure
- ```
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
### Use PostgreSQL HA
diff --git a/doc/user/infrastructure/clusters/connect/new_eks_cluster.md b/doc/user/infrastructure/clusters/connect/new_eks_cluster.md
index 5ca97b5e147..798e02ab9b4 100644
--- a/doc/user/infrastructure/clusters/connect/new_eks_cluster.md
+++ b/doc/user/infrastructure/clusters/connect/new_eks_cluster.md
@@ -92,7 +92,7 @@ View the [AWS Terraform provider](https://registry.terraform.io/providers/hashic
After configuring your project, manually trigger the provisioning of your cluster. In GitLab:
1. On the left sidebar, go to **CI/CD > Pipelines**.
-1. Next to **Play** (**{play}**), select the dropdown icon (**{angle-down}**).
+1. Next to **Play** (**{play}**), select the dropdown icon (**{chevron-lg-down}**).
1. Select **Deploy** to manually trigger the deployment job.
When the pipeline finishes successfully, you can view the new cluster:
diff --git a/doc/user/infrastructure/clusters/connect/new_gke_cluster.md b/doc/user/infrastructure/clusters/connect/new_gke_cluster.md
index 75ce842e70d..1899f90c069 100644
--- a/doc/user/infrastructure/clusters/connect/new_gke_cluster.md
+++ b/doc/user/infrastructure/clusters/connect/new_gke_cluster.md
@@ -70,9 +70,6 @@ To create a GitLab agent for Kubernetes:
To set up your project to communicate to GCP and the GitLab API:
-1. Create a [GitLab personal access token](../../../profile/personal_access_tokens.md) with
- `api` scope. The Terraform script uses it to connect the cluster to your GitLab group. Take note of the generated token. You will
- need it when you [configure your project](#configure-your-project).
1. To authenticate GCP with GitLab, create a [GCP service account](https://cloud.google.com/docs/authentication/getting-started)
with following roles: `Compute Network Viewer`, `Kubernetes Engine Admin`, `Service Account User`, and `Service Account Admin`. Both User and Admin
service accounts are necessary. The User role impersonates the [default service account](https://cloud.google.com/compute/docs/access/service-accounts#default_service_account)
@@ -120,7 +117,7 @@ Refer to the [Google Terraform provider](https://registry.terraform.io/providers
After configuring your project, manually trigger the provisioning of your cluster. In GitLab:
1. On the left sidebar, go to **CI/CD > Pipelines**.
-1. Next to **Play** (**{play}**), select the dropdown icon (**{angle-down}**).
+1. Next to **Play** (**{play}**), select the dropdown icon (**{chevron-lg-down}**).
1. Select **Deploy** to manually trigger the deployment job.
When the pipeline finishes successfully, you can see your new cluster:
diff --git a/lib/api/internal/base.rb b/lib/api/internal/base.rb
index b53f855c3a2..3edd38a0108 100644
--- a/lib/api/internal/base.rb
+++ b/lib/api/internal/base.rb
@@ -164,6 +164,18 @@ module API
check_allowed(params)
end
+ post '/error_tracking_allowed', feature_category: :error_tracking do
+ public_key = params[:public_key]
+ project_id = params[:project_id]
+
+ unprocessable_entity! if public_key.blank? || project_id.blank?
+
+ enabled = ::ErrorTracking::ClientKey.enabled_key_for(project_id, public_key).exists?
+
+ status 200
+ { enabled: enabled }
+ end
+
post "/lfs_authenticate", feature_category: :source_code_management, urgency: :high do
not_found! unless container&.lfs_enabled?
diff --git a/lib/gitlab/database/partitioning/monthly_strategy.rb b/lib/gitlab/database/partitioning/monthly_strategy.rb
index 9c8cccb3dc6..0f08a47d754 100644
--- a/lib/gitlab/database/partitioning/monthly_strategy.rb
+++ b/lib/gitlab/database/partitioning/monthly_strategy.rb
@@ -40,6 +40,10 @@ module Gitlab
# No-op, required by the partition manager
end
+ def validate_and_fix
+ # No-op, required by the partition manager
+ end
+
private
def desired_partitions
diff --git a/lib/gitlab/database/partitioning/partition_manager.rb b/lib/gitlab/database/partitioning/partition_manager.rb
index 3ee9a193b45..aac91eaadb1 100644
--- a/lib/gitlab/database/partitioning/partition_manager.rb
+++ b/lib/gitlab/database/partitioning/partition_manager.rb
@@ -22,15 +22,13 @@ module Gitlab
connection_name: @connection_name
)
- # Double-checking before getting the lease:
- # The prevailing situation is no missing partitions and no extra partitions
- return if missing_partitions.empty? && extra_partitions.empty?
-
only_with_exclusive_lease(model, lease_key: MANAGEMENT_LEASE_KEY) do
- partitions_to_create = missing_partitions
- create(partitions_to_create) unless partitions_to_create.empty?
+ model.partitioning_strategy.validate_and_fix
+ partitions_to_create = missing_partitions
partitions_to_detach = extra_partitions
+
+ create(partitions_to_create) unless partitions_to_create.empty?
detach(partitions_to_detach) unless partitions_to_detach.empty?
end
rescue StandardError => e
@@ -119,7 +117,8 @@ module Gitlab
parent_table_identifier = "#{connection.current_schema}.#{partition.table}"
if (example_fk = PostgresForeignKey.by_referenced_table_identifier(parent_table_identifier).first)
- raise UnsafeToDetachPartitionError, "Cannot detach #{partition.partition_name}, it would block while checking foreign key #{example_fk.name} on #{example_fk.constrained_table_identifier}"
+ raise UnsafeToDetachPartitionError, "Cannot detach #{partition.partition_name}, it would block while " \
+ "checking foreign key #{example_fk.name} on #{example_fk.constrained_table_identifier}"
end
end
diff --git a/lib/gitlab/database/partitioning/sliding_list_strategy.rb b/lib/gitlab/database/partitioning/sliding_list_strategy.rb
index e9865fb91d6..5cf32d3272c 100644
--- a/lib/gitlab/database/partitioning/sliding_list_strategy.rb
+++ b/lib/gitlab/database/partitioning/sliding_list_strategy.rb
@@ -48,9 +48,12 @@ module Gitlab
default_value = current_default_value
if extra.any? { |p| p.value == default_value }
- Gitlab::AppLogger.error(message: "Inconsistent partition detected: partition with value #{current_default_value} should not be deleted because it's used as the default value.",
- partition_number: current_default_value,
- table_name: model.table_name)
+ Gitlab::AppLogger.error(
+ message: "Inconsistent partition detected: partition with value #{current_default_value} should " \
+ "not be deleted because it's used as the default value.",
+ partition_number: current_default_value,
+ table_name: model.table_name
+ )
extra = extra.reject { |p| p.value == default_value }
end
@@ -73,6 +76,42 @@ module Gitlab
current_partitions.empty?
end
+ def validate_and_fix
+ return unless Feature.enabled?(:fix_sliding_list_partitioning)
+ return if no_partitions_exist?
+
+ old_default_value = current_default_value
+ expected_default_value = active_partition.value
+
+ if old_default_value != expected_default_value
+ with_lock_retries do
+ model.connection.execute("LOCK TABLE #{model.table_name} IN ACCESS EXCLUSIVE MODE")
+
+ old_default_value = current_default_value
+ expected_default_value = active_partition.value
+
+ if old_default_value == expected_default_value
+ Gitlab::AppLogger.warn(
+ message: "Table partitions or partition key default value have been changed by another process",
+ table_name: table_name,
+ default_value: expected_default_value
+ )
+ raise ActiveRecord::Rollback
+ end
+
+ model.connection.change_column_default(model.table_name, partitioning_key, expected_default_value)
+ Gitlab::AppLogger.warn(
+ message: "Fixed default value of sliding_list_strategy partitioning_key",
+ column: partitioning_key,
+ table_name: table_name,
+ connection_name: model.connection.pool.db_config.name,
+ old_value: old_default_value,
+ new_value: expected_default_value
+ )
+ end
+ end
+ end
+
private
def current_default_value
@@ -95,6 +134,14 @@ module Gitlab
raise "Add #{partitioning_key} to #{model.name}.ignored_columns to use it with SlidingListStrategy"
end
end
+
+ def with_lock_retries(&block)
+ Gitlab::Database::WithLockRetries.new(
+ klass: self.class,
+ logger: Gitlab::AppLogger,
+ connection: model.connection
+ ).run(&block)
+ end
end
end
end
diff --git a/lib/gitlab/event_store/subscription.rb b/lib/gitlab/event_store/subscription.rb
index e5c92ab969f..01986355d2d 100644
--- a/lib/gitlab/event_store/subscription.rb
+++ b/lib/gitlab/event_store/subscription.rb
@@ -13,8 +13,7 @@ module Gitlab
def consume_event(event)
return unless condition_met?(event)
- worker.perform_async(event.class.name, event.data)
- # TODO: Log dispatching of events to subscriber
+ worker.perform_async(event.class.name, event.data.deep_stringify_keys)
# We rescue and track any exceptions here because we don't want to
# impact other subscribers if one is faulty.
diff --git a/spec/components/pajamas/button_component_spec.rb b/spec/components/pajamas/button_component_spec.rb
index 0009228e58c..60c2a2e5a06 100644
--- a/spec/components/pajamas/button_component_spec.rb
+++ b/spec/components/pajamas/button_component_spec.rb
@@ -38,6 +38,14 @@ RSpec.describe Pajamas::ButtonComponent, type: :component do
expect(rendered_component).to have_css '.gl-button.btn-danger.btn-danger-tertiary.custom-class'
end
end
+
+ context 'overriding base attributes' do
+ let(:options) { { button_options: { type: 'submit' } } }
+
+ it 'overrides type' do
+ expect(rendered_component).to have_css '[type="submit"]'
+ end
+ end
end
describe 'button_text_classes' do
@@ -211,6 +219,42 @@ RSpec.describe Pajamas::ButtonComponent, type: :component do
end
end
+ describe 'type' do
+ context 'by default (without href)' do
+ it 'has type "button"' do
+ expect(rendered_component).to have_css "button[type='button']"
+ end
+ end
+
+ context 'when set to known type' do
+ where(:type) { [:button, :reset, :submit] }
+
+ let(:options) { { type: type } }
+
+ with_them do
+ it 'has the correct type' do
+ expect(rendered_component).to have_css "button[type='#{type}']"
+ end
+ end
+ end
+
+ context 'when set to unkown type' do
+ let(:options) { { type: :madeup } }
+
+ it 'has type "button"' do
+ expect(rendered_component).to have_css "button[type='button']"
+ end
+ end
+
+ context 'for links (with href)' do
+ let(:options) { { href: 'https://example.com', type: :reset } }
+
+ it 'ignores type' do
+ expect(rendered_component).not_to have_css "[type]"
+ end
+ end
+ end
+
describe 'link button' do
it 'renders a button tag with type="button" when "href" is not set' do
expect(rendered_component).to have_css "button[type='button']"
diff --git a/spec/frontend/environments/deploy_board_wrapper_spec.js b/spec/frontend/environments/deploy_board_wrapper_spec.js
index c8e6df4d324..49eed68fa11 100644
--- a/spec/frontend/environments/deploy_board_wrapper_spec.js
+++ b/spec/frontend/environments/deploy_board_wrapper_spec.js
@@ -57,7 +57,7 @@ describe('~/environments/components/deploy_board_wrapper.vue', () => {
it('is collapsed by default', () => {
expect(collapse.attributes('visible')).toBeUndefined();
- expect(icon.props('name')).toBe('angle-right');
+ expect(icon.props('name')).toBe('chevron-lg-right');
});
it('opens on click', async () => {
@@ -65,7 +65,7 @@ describe('~/environments/components/deploy_board_wrapper.vue', () => {
expect(button.attributes('aria-label')).toBe(__('Collapse'));
expect(collapse.attributes('visible')).toBe('visible');
- expect(icon.props('name')).toBe('angle-down');
+ expect(icon.props('name')).toBe('chevron-lg-down');
const deployBoard = findDeployBoard();
expect(deployBoard.exists()).toBe(true);
diff --git a/spec/lib/gitlab/database/partitioning/partition_manager_spec.rb b/spec/lib/gitlab/database/partitioning/partition_manager_spec.rb
index 64dcdb9628a..dca4548a0a3 100644
--- a/spec/lib/gitlab/database/partitioning/partition_manager_spec.rb
+++ b/spec/lib/gitlab/database/partitioning/partition_manager_spec.rb
@@ -8,7 +8,11 @@ RSpec.describe Gitlab::Database::Partitioning::PartitionManager do
def has_partition(model, month)
Gitlab::Database::PostgresPartition.for_parent_table(model.table_name).any? do |partition|
- Gitlab::Database::Partitioning::TimePartition.from_sql(model.table_name, partition.name, partition.condition).from == month
+ Gitlab::Database::Partitioning::TimePartition.from_sql(
+ model.table_name,
+ partition.name,
+ partition.condition
+ ).from == month
end
end
@@ -16,14 +20,17 @@ RSpec.describe Gitlab::Database::Partitioning::PartitionManager do
subject(:sync_partitions) { described_class.new(model).sync_partitions }
let(:model) { double(partitioning_strategy: partitioning_strategy, table_name: table, connection: connection) }
- let(:partitioning_strategy) { double(missing_partitions: partitions, extra_partitions: [], after_adding_partitions: nil) }
let(:connection) { ActiveRecord::Base.connection }
let(:table) { "issues" }
+ let(:partitioning_strategy) do
+ double(missing_partitions: partitions, extra_partitions: [], after_adding_partitions: nil)
+ end
before do
allow(connection).to receive(:table_exists?).and_call_original
allow(connection).to receive(:table_exists?).with(table).and_return(true)
allow(connection).to receive(:execute).and_call_original
+ expect(partitioning_strategy).to receive(:validate_and_fix)
stub_exclusive_lease(described_class::MANAGEMENT_LEASE_KEY % table, timeout: described_class::LEASE_TIMEOUT)
end
@@ -84,13 +91,16 @@ RSpec.describe Gitlab::Database::Partitioning::PartitionManager do
let(:manager) { described_class.new(model) }
let(:model) { double(partitioning_strategy: partitioning_strategy, table_name: table, connection: connection) }
- let(:partitioning_strategy) { double(extra_partitions: extra_partitions, missing_partitions: [], after_adding_partitions: nil) }
let(:connection) { ActiveRecord::Base.connection }
let(:table) { "foo" }
+ let(:partitioning_strategy) do
+ double(extra_partitions: extra_partitions, missing_partitions: [], after_adding_partitions: nil)
+ end
before do
allow(connection).to receive(:table_exists?).and_call_original
allow(connection).to receive(:table_exists?).with(table).and_return(true)
+ expect(partitioning_strategy).to receive(:validate_and_fix)
stub_exclusive_lease(described_class::MANAGEMENT_LEASE_KEY % table, timeout: described_class::LEASE_TIMEOUT)
end
@@ -107,6 +117,24 @@ RSpec.describe Gitlab::Database::Partitioning::PartitionManager do
sync_partitions
end
+
+ it 'logs an error if the partitions are not detachable' do
+ allow(Gitlab::Database::PostgresForeignKey).to receive(:by_referenced_table_identifier).with("public.foo")
+ .and_return([double(name: "fk_1", constrained_table_identifier: "public.constrainted_table_1")])
+
+ expect(Gitlab::AppLogger).to receive(:error).with(
+ {
+ message: "Failed to create / detach partition(s)",
+ connection_name: "main",
+ exception_class: Gitlab::Database::Partitioning::PartitionManager::UnsafeToDetachPartitionError,
+ exception_message:
+ "Cannot detach foo1, it would block while checking foreign key fk_1 on public.constrainted_table_1",
+ table_name: "foo"
+ }
+ )
+
+ sync_partitions
+ end
end
describe '#detach_partitions' do
diff --git a/spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb b/spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb
index 1cec0463055..d8b06ee1a5d 100644
--- a/spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb
+++ b/spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb
@@ -37,12 +37,75 @@ RSpec.describe Gitlab::Database::Partitioning::SlidingListStrategy do
describe '#current_partitions' do
it 'detects both partitions' do
expect(strategy.current_partitions).to eq([
- Gitlab::Database::Partitioning::SingleNumericListPartition.new(table_name, 1, partition_name: '_test_partitioned_test_1'),
- Gitlab::Database::Partitioning::SingleNumericListPartition.new(table_name, 2, partition_name: '_test_partitioned_test_2')
+ Gitlab::Database::Partitioning::SingleNumericListPartition.new(
+ table_name, 1, partition_name: '_test_partitioned_test_1'
+ ),
+ Gitlab::Database::Partitioning::SingleNumericListPartition.new(
+ table_name, 2, partition_name: '_test_partitioned_test_2'
+ )
])
end
end
+ describe '#validate_and_fix' do
+ context 'feature flag is disabled' do
+ before do
+ stub_feature_flags(fix_sliding_list_partitioning: false)
+ end
+
+ it 'does not try to fix the default partition value' do
+ connection.change_column_default(model.table_name, strategy.partitioning_key, 3)
+ expect(strategy.model.connection).not_to receive(:change_column_default)
+ strategy.validate_and_fix
+ end
+ end
+
+ context 'feature flag is enabled' do
+ before do
+ stub_feature_flags(fix_sliding_list_partitioning: true)
+ end
+
+ it 'does not call change_column_default if the partitioning in a valid state' do
+ expect(strategy.model.connection).not_to receive(:change_column_default)
+
+ strategy.validate_and_fix
+ end
+
+ it 'calls change_column_default on partition_key with the most default partition number' do
+ connection.change_column_default(model.table_name, strategy.partitioning_key, 1)
+
+ expect(Gitlab::AppLogger).to receive(:warn).with(
+ message: 'Fixed default value of sliding_list_strategy partitioning_key',
+ connection_name: 'main',
+ old_value: 1,
+ new_value: 2,
+ table_name: table_name,
+ column: strategy.partitioning_key
+ )
+
+ expect(strategy.model.connection).to receive(:change_column_default).with(
+ model.table_name, strategy.partitioning_key, 2
+ ).and_call_original
+
+ strategy.validate_and_fix
+ end
+
+ it 'does not change the default column if it has been changed in the meanwhile by another process' do
+ expect(strategy).to receive(:current_default_value).and_return(1, 2)
+
+ expect(strategy.model.connection).not_to receive(:change_column_default)
+
+ expect(Gitlab::AppLogger).to receive(:warn).with(
+ message: 'Table partitions or partition key default value have been changed by another process',
+ table_name: table_name,
+ default_value: 2
+ )
+
+ strategy.validate_and_fix
+ end
+ end
+ end
+
describe '#active_partition' do
it 'is the partition with the largest value' do
expect(strategy.active_partition.value).to eq(2)
@@ -157,6 +220,7 @@ RSpec.describe Gitlab::Database::Partitioning::SlidingListStrategy do
end.not_to raise_error
end
end
+
context 'redirecting inserts as the active partition changes' do
let(:model) do
Class.new(ApplicationRecord) do
diff --git a/spec/lib/gitlab/event_store/store_spec.rb b/spec/lib/gitlab/event_store/store_spec.rb
index 94e8f0ff2ff..bbdfecc897a 100644
--- a/spec/lib/gitlab/event_store/store_spec.rb
+++ b/spec/lib/gitlab/event_store/store_spec.rb
@@ -134,6 +134,7 @@ RSpec.describe Gitlab::EventStore::Store do
describe '#publish' do
let(:data) { { name: 'Bob', id: 123 } }
+ let(:serialized_data) { data.deep_stringify_keys }
context 'when event has a subscribed worker' do
let(:store) do
@@ -144,12 +145,21 @@ RSpec.describe Gitlab::EventStore::Store do
end
it 'dispatches the event to the subscribed worker' do
- expect(worker).to receive(:perform_async).with('TestEvent', data)
+ expect(worker).to receive(:perform_async).with('TestEvent', serialized_data)
expect(another_worker).not_to receive(:perform_async)
store.publish(event)
end
+ it 'does not raise any Sidekiq warning' do
+ logger = double(:logger, info: nil)
+ allow(Sidekiq).to receive(:logger).and_return(logger)
+ expect(logger).not_to receive(:warn).with(/do not serialize to JSON safely/)
+ expect(worker).to receive(:perform_async).with('TestEvent', serialized_data).and_call_original
+
+ store.publish(event)
+ end
+
context 'when other workers subscribe to the same event' do
let(:store) do
described_class.new do |store|
@@ -160,8 +170,8 @@ RSpec.describe Gitlab::EventStore::Store do
end
it 'dispatches the event to each subscribed worker' do
- expect(worker).to receive(:perform_async).with('TestEvent', data)
- expect(another_worker).to receive(:perform_async).with('TestEvent', data)
+ expect(worker).to receive(:perform_async).with('TestEvent', serialized_data)
+ expect(another_worker).to receive(:perform_async).with('TestEvent', serialized_data)
expect(unrelated_worker).not_to receive(:perform_async)
store.publish(event)
@@ -215,7 +225,7 @@ RSpec.describe Gitlab::EventStore::Store do
let(:event) { event_klass.new(data: data) }
it 'dispatches the event to the workers satisfying the condition' do
- expect(worker).to receive(:perform_async).with('TestEvent', data)
+ expect(worker).to receive(:perform_async).with('TestEvent', serialized_data)
expect(another_worker).not_to receive(:perform_async)
store.publish(event)
diff --git a/spec/requests/api/internal/base_spec.rb b/spec/requests/api/internal/base_spec.rb
index acfe476a864..93e4e72f78f 100644
--- a/spec/requests/api/internal/base_spec.rb
+++ b/spec/requests/api/internal/base_spec.rb
@@ -51,6 +51,64 @@ RSpec.describe API::Internal::Base do
end
end
+ describe 'GET /internal/error_tracking_allowed' do
+ let_it_be(:project) { create(:project) }
+
+ let(:params) { { project_id: project.id, public_key: 'key' } }
+
+ context 'when the secret header is missing' do
+ it 'responds with unauthorized entity' do
+ post api("/internal/error_tracking_allowed"), params: params
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'when some params are missing' do
+ it 'responds with unprocessable entity' do
+ post api("/internal/error_tracking_allowed"), params: params.except(:public_key),
+ headers: { API::Helpers::GITLAB_SHARED_SECRET_HEADER => Base64.encode64(secret_token) }
+
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ end
+ end
+
+ context 'when the error tracking is disabled' do
+ it 'returns enabled: false' do
+ create(:error_tracking_client_key, project: project, active: false)
+
+ post api("/internal/error_tracking_allowed"), params: params,
+ headers: { API::Helpers::GITLAB_SHARED_SECRET_HEADER => Base64.encode64(secret_token) }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq({ 'enabled' => false })
+ end
+
+ context 'when the error tracking record does not exist' do
+ it 'returns enabled: false' do
+ post api("/internal/error_tracking_allowed"), params: params,
+ headers: { API::Helpers::GITLAB_SHARED_SECRET_HEADER => Base64.encode64(secret_token) }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq({ 'enabled' => false })
+ end
+ end
+ end
+
+ context 'when the error tracking is enabled' do
+ it 'returns enabled: true' do
+ client_key = create(:error_tracking_client_key, project: project, active: true)
+ params[:public_key] = client_key.public_key
+
+ post api("/internal/error_tracking_allowed"), params: params,
+ headers: { API::Helpers::GITLAB_SHARED_SECRET_HEADER => Base64.encode64(secret_token) }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq({ 'enabled' => true })
+ end
+ end
+ end
+
describe 'GET /internal/two_factor_recovery_codes' do
let(:key_id) { key.id }
diff --git a/spec/services/event_create_service_spec.rb b/spec/services/event_create_service_spec.rb
index c22099fe410..56da85cc4a0 100644
--- a/spec/services/event_create_service_spec.rb
+++ b/spec/services/event_create_service_spec.rb
@@ -21,8 +21,10 @@ RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redi
end
shared_examples 'Snowplow event' do
+ let(:label) { nil }
+
it 'is not emitted if FF is disabled' do
- stub_feature_flags(route_hll_to_snowplow: false)
+ stub_feature_flags(feature_flag_name => false)
subject
@@ -30,15 +32,18 @@ RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redi
end
it 'is emitted' do
+ params = {
+ category: category,
+ action: action,
+ namespace: namespace,
+ user: user,
+ project: project,
+ label: label
+ }.compact
+
subject
- expect_snowplow_event(
- category: described_class.to_s,
- action: 'action_active_users_project_repo',
- namespace: project.namespace,
- user: user,
- project: project
- )
+ expect_snowplow_event(**params)
end
end
@@ -74,7 +79,7 @@ RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redi
end
end
- describe 'Merge Requests' do
+ describe 'Merge Requests', :snowplow do
describe '#open_mr' do
subject(:open_mr) { service.open_mr(merge_request, merge_request.author) }
@@ -89,6 +94,16 @@ RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redi
it_behaves_like "it records the event in the event counter" do
let(:event_action) { Gitlab::UsageDataCounters::TrackUniqueEvents::MERGE_REQUEST_ACTION }
end
+
+ it_behaves_like 'Snowplow event' do
+ let(:category) { Gitlab::UsageDataCounters::TrackUniqueEvents::MERGE_REQUEST_ACTION.to_s }
+ let(:label) { 'merge_requests_users' }
+ let(:action) { 'create' }
+ let(:namespace) { project.namespace }
+ let(:project) { merge_request.project }
+ let(:user) { merge_request.author }
+ let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
+ end
end
describe '#close_mr' do
@@ -105,6 +120,16 @@ RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redi
it_behaves_like "it records the event in the event counter" do
let(:event_action) { Gitlab::UsageDataCounters::TrackUniqueEvents::MERGE_REQUEST_ACTION }
end
+
+ it_behaves_like 'Snowplow event' do
+ let(:category) { Gitlab::UsageDataCounters::TrackUniqueEvents::MERGE_REQUEST_ACTION.to_s }
+ let(:label) { 'merge_requests_users' }
+ let(:action) { 'close' }
+ let(:namespace) { project.namespace }
+ let(:project) { merge_request.project }
+ let(:user) { merge_request.author }
+ let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
+ end
end
describe '#merge_mr' do
@@ -121,6 +146,16 @@ RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redi
it_behaves_like "it records the event in the event counter" do
let(:event_action) { Gitlab::UsageDataCounters::TrackUniqueEvents::MERGE_REQUEST_ACTION }
end
+
+ it_behaves_like 'Snowplow event' do
+ let(:category) { Gitlab::UsageDataCounters::TrackUniqueEvents::MERGE_REQUEST_ACTION.to_s }
+ let(:label) { 'merge_requests_users' }
+ let(:action) { 'merge' }
+ let(:namespace) { project.namespace }
+ let(:project) { merge_request.project }
+ let(:user) { merge_request.author }
+ let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
+ end
end
describe '#reopen_mr' do
@@ -295,7 +330,12 @@ RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redi
let(:event_action) { Gitlab::UsageDataCounters::TrackUniqueEvents::PUSH_ACTION }
end
- it_behaves_like 'Snowplow event'
+ it_behaves_like 'Snowplow event' do
+ let(:category) { described_class.to_s }
+ let(:action) { 'action_active_users_project_repo' }
+ let(:namespace) { project.namespace }
+ let(:feature_flag_name) { :route_hll_to_snowplow }
+ end
end
describe '#bulk_push', :snowplow do
@@ -315,7 +355,12 @@ RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redi
let(:event_action) { Gitlab::UsageDataCounters::TrackUniqueEvents::PUSH_ACTION }
end
- it_behaves_like 'Snowplow event'
+ it_behaves_like 'Snowplow event' do
+ let(:category) { described_class.to_s }
+ let(:action) { 'action_active_users_project_repo' }
+ let(:namespace) { project.namespace }
+ let(:feature_flag_name) { :route_hll_to_snowplow }
+ end
end
describe 'Project' do
@@ -392,7 +437,7 @@ RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redi
end
end
- describe '#leave_note' do
+ describe '#leave_note', :snowplow do
subject(:leave_note) { service.leave_note(note, author) }
let(:note) { create(:note) }
@@ -409,6 +454,17 @@ RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redi
it_behaves_like "it records the event in the event counter" do
let(:note) { create(:diff_note_on_merge_request) }
end
+
+ it_behaves_like 'Snowplow event' do
+ let(:note) { create(:diff_note_on_merge_request) }
+ let(:category) { Gitlab::UsageDataCounters::TrackUniqueEvents::MERGE_REQUEST_ACTION.to_s }
+ let(:label) { 'merge_requests_users' }
+ let(:action) { 'comment' }
+ let(:project) { note.project }
+ let(:namespace) { project.namespace }
+ let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
+ let(:user) { author }
+ end
end
context 'when it is not a diff note' do