diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-06-10 18:09:28 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-06-10 18:09:28 +0000 |
commit | 2f7719abdfde4cb50ed05346b98bac26ea06a8de (patch) | |
tree | 71bc9a5cde931b50f38f2e2fe76cc67e1181e3d6 | |
parent | 37140013714814d8ffe662a372697c56eea2fde0 (diff) | |
download | gitlab-ce-2f7719abdfde4cb50ed05346b98bac26ea06a8de.tar.gz |
Add latest changes from gitlab-org/gitlab@master
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 @@ -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 |