summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-07-06 21:07:50 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-07-06 21:07:50 +0000
commitc47ade2adb94e4c33f87b4b825c92c7fe61ef044 (patch)
treed860f6d88abf624b23b19bc09d9792cf07507fb7
parent971f05815d2f22d7bdeab01870cb499299b8c70a (diff)
downloadgitlab-ce-c47ade2adb94e4c33f87b4b825c92c7fe61ef044.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/ci/reports.gitlab-ci.yml24
-rw-r--r--.gitlab/ci/rules.gitlab-ci.yml10
-rw-r--r--.gitlab/merge_request_templates/Security Release.md4
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock6
-rw-r--r--app/assets/javascripts/vue_shared/components/web_ide_link.vue10
-rw-r--r--app/helpers/blob_helper.rb4
-rw-r--r--app/helpers/integrations_helper.rb81
-rw-r--r--app/models/integration.rb4
-rw-r--r--app/models/integrations/jira.rb9
-rw-r--r--app/models/integrations/teamcity.rb9
-rw-r--r--app/serializers/service_event_entity.rb2
-rw-r--r--app/services/service_ping/build_payload_service.rb27
-rw-r--r--config/feature_flags/development/load_balancing_refine_load_balancer_methods.yml8
-rw-r--r--config/initializers/asciidoctor_patch.rb20
-rw-r--r--doc/administration/packages/index.md14
-rw-r--r--doc/development/i18n/proofreader.md1
-rw-r--r--doc/user/project/import/github.md3
-rw-r--r--lib/api/services.rb8
-rw-r--r--lib/gitlab/database/background_migration/batched_job.rb46
-rw-r--r--lib/gitlab/database/load_balancing/load_balancer.rb2
-rw-r--r--lib/gitlab/database/load_balancing/sticking.rb10
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/database_metric.rb34
-rw-r--r--locale/gitlab.pot6
-rw-r--r--package.json2
-rw-r--r--spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap1
-rw-r--r--spec/frontend/jira_import/components/__snapshots__/jira_import_form_spec.js.snap2
-rw-r--r--spec/frontend/vue_shared/components/web_ide_link_spec.js8
-rw-r--r--spec/helpers/blob_helper_spec.rb16
-rw-r--r--spec/helpers/integrations_helper_spec.rb16
-rw-r--r--spec/lib/gitlab/database/background_migration/batched_job_spec.rb69
-rw-r--r--spec/lib/gitlab/database/load_balancing/sticking_spec.rb14
-rw-r--r--spec/lib/gitlab/kroki_spec.rb2
-rw-r--r--spec/lib/gitlab/usage/metrics/instrumentations/database_metric_spec.rb75
-rw-r--r--spec/services/service_ping/build_payload_service_spec.rb47
-rw-r--r--spec/support/matchers/usage_metric_matchers.rb21
-rw-r--r--spec/support/shared_contexts/services/service_ping/stubbed_service_ping_metrics_definitions_shared_context.rb43
-rw-r--r--spec/support/shared_examples/services/service_ping/complete_service_ping_payload_shared_examples.rb9
-rw-r--r--spec/support/shared_examples/services/service_ping/service_ping_payload_with_all_expected_metrics_shared_examples.rb11
-rw-r--r--spec/support/shared_examples/services/service_ping/service_ping_payload_without_restricted_metrics_shared_examples.rb11
-rw-r--r--yarn.lock8
41 files changed, 580 insertions, 119 deletions
diff --git a/.gitlab/ci/reports.gitlab-ci.yml b/.gitlab/ci/reports.gitlab-ci.yml
index 7920d835a29..7671a1a8650 100644
--- a/.gitlab/ci/reports.gitlab-ci.yml
+++ b/.gitlab/ci/reports.gitlab-ci.yml
@@ -87,20 +87,22 @@ gemnasium-python-dependency_scanning:
# Analyze dependencies for malicious behavior
# See https://gitlab.com/gitlab-com/gl-security/security-research/package-hunter
-package_hunter:
+.package_hunter-base:
extends:
- .default-retry
- - .reports:rules:package_hunter
stage: test
image:
name: registry.gitlab.com/gitlab-com/gl-security/security-research/package-hunter-cli:latest
entrypoint: [""]
+ variables:
+ DEBUG: '*'
+ HTR_user: '$PACKAGE_HUNTER_USER'
+ HTR_pass: '$PACKAGE_HUNTER_PASS'
needs: []
allow_failure: true
- script:
+ before_script:
- rm -r spec locale .git app/assets/images doc/
- cd .. && tar -I "gzip --best" -cf gitlab.tgz gitlab/
- - DEBUG=* HTR_user=$PACKAGE_HUNTER_USER HTR_pass=$PACKAGE_HUNTER_PASS node /usr/src/app/cli.js analyze --format gitlab gitlab.tgz | tee $CI_PROJECT_DIR/gl-dependency-scanning-report.json
artifacts:
paths:
- gl-dependency-scanning-report.json
@@ -108,6 +110,20 @@ package_hunter:
dependency_scanning: gl-dependency-scanning-report.json
expire_in: 1 week
+package_hunter-yarn:
+ extends:
+ - .package_hunter-base
+ - .reports:rules:package_hunter-yarn
+ script:
+ - node /usr/src/app/cli.js analyze --format gitlab --manager yarn gitlab.tgz | tee $CI_PROJECT_DIR/gl-dependency-scanning-report.json
+
+package_hunter-bundler:
+ extends:
+ - .package_hunter-base
+ - .reports:rules:package_hunter-bundler
+ script:
+ - node /usr/src/app/cli.js analyze --format gitlab --manager bundler gitlab.tgz | tee $CI_PROJECT_DIR/gl-dependency-scanning-report.json
+
license_scanning:
extends: .default-retry
needs: []
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index bdeda8c5642..5910fb86356 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -1099,7 +1099,7 @@
- <<: *if-default-branch-schedule-nightly
allow_failure: true
-.reports:rules:package_hunter:
+.reports:rules:package_hunter-yarn:
rules:
- if: "$PACKAGE_HUNTER_USER == null || $PACKAGE_HUNTER_USER == ''"
when: never
@@ -1107,6 +1107,14 @@
- <<: *if-merge-request
changes: ["yarn.lock"]
+.reports:rules:package_hunter-bundler:
+ rules:
+ - if: "$PACKAGE_HUNTER_USER == null || $PACKAGE_HUNTER_USER == ''"
+ when: never
+ - <<: *if-default-branch-schedule-2-hourly
+ - <<: *if-merge-request
+ changes: ["Gemfile.lock"]
+
.reports:rules:license_scanning:
rules:
- if: '$LICENSE_SCANNING_DISABLED || $GITLAB_FEATURES !~ /\blicense_scanning\b/'
diff --git a/.gitlab/merge_request_templates/Security Release.md b/.gitlab/merge_request_templates/Security Release.md
index 77e8718c34f..33c0a5b98a8 100644
--- a/.gitlab/merge_request_templates/Security Release.md
+++ b/.gitlab/merge_request_templates/Security Release.md
@@ -30,8 +30,8 @@ See [the general developer security release guidelines](https://gitlab.com/gitla
## Maintainer checklist
-- [ ] Correct milestone is applied and the title is matching across all backports
-- [ ] Assigned to `@gitlab-release-tools-bot` with passing CI pipelines and **when all backports including the MR targeting master are ready.**
+- [ ] Correct milestone is applied and the title is matching across all backports.
+- [ ] Assigned to `@gitlab-release-tools-bot` with passing CI pipelines.
/label ~security
diff --git a/Gemfile b/Gemfile
index 85b4fde8342..da03752f287 100644
--- a/Gemfile
+++ b/Gemfile
@@ -164,7 +164,7 @@ gem 'wikicloth', '0.8.1'
gem 'asciidoctor', '~> 2.0.10'
gem 'asciidoctor-include-ext', '~> 0.3.1', require: false
gem 'asciidoctor-plantuml', '~> 0.0.12'
-gem 'asciidoctor-kroki', '~> 0.4.0', require: false
+gem 'asciidoctor-kroki', '~> 0.5.0', require: false
gem 'rouge', '~> 3.26.0'
gem 'truncato', '~> 0.7.11'
gem 'bootstrap_form', '~> 4.2.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index ca412317641..3972ab5f6bc 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -92,10 +92,10 @@ GEM
faraday_middleware (~> 1.0)
faraday_middleware-multi_json (~> 0.0)
oauth2 (~> 1.4)
- asciidoctor (2.0.12)
+ asciidoctor (2.0.15)
asciidoctor-include-ext (0.3.1)
asciidoctor (>= 1.5.6, < 3.0.0)
- asciidoctor-kroki (0.4.0)
+ asciidoctor-kroki (0.5.0)
asciidoctor (~> 2.0)
asciidoctor-plantuml (0.0.12)
asciidoctor (>= 1.5.6, < 3.0.0)
@@ -1409,7 +1409,7 @@ DEPENDENCIES
asana (~> 0.10.3)
asciidoctor (~> 2.0.10)
asciidoctor-include-ext (~> 0.3.1)
- asciidoctor-kroki (~> 0.4.0)
+ asciidoctor-kroki (~> 0.5.0)
asciidoctor-plantuml (~> 0.0.12)
atlassian-jwt (~> 0.2.0)
attr_encrypted (~> 3.1.0)
diff --git a/app/assets/javascripts/vue_shared/components/web_ide_link.vue b/app/assets/javascripts/vue_shared/components/web_ide_link.vue
index 4bd3e352fd2..5ba7c107c12 100644
--- a/app/assets/javascripts/vue_shared/components/web_ide_link.vue
+++ b/app/assets/javascripts/vue_shared/components/web_ide_link.vue
@@ -93,9 +93,8 @@ export default {
tooltip: '',
attrs: {
'data-qa-selector': 'edit_button',
- 'data-track-event': 'click_edit',
- // eslint-disable-next-line @gitlab/require-i18n-strings
- 'data-track-label': 'Edit',
+ 'data-track-action': 'click_consolidated_edit',
+ 'data-track-label': 'edit',
},
...handleOptions,
};
@@ -127,9 +126,8 @@ export default {
tooltip: '',
attrs: {
'data-qa-selector': 'web_ide_button',
- 'data-track-event': 'click_edit_ide',
- // eslint-disable-next-line @gitlab/require-i18n-strings
- 'data-track-label': 'Web IDE',
+ 'data-track-action': 'click_consolidated_edit_ide',
+ 'data-track-label': 'web_ide',
},
...handleOptions,
};
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index dfd6de3f1d5..eccd0e7a34c 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -65,7 +65,7 @@ module BlobHelper
return unless blob = readable_blob(options, path, project, ref)
common_classes = "btn gl-button btn-confirm js-edit-blob gl-ml-3 #{options[:extra_class]}"
- data = { track_event: 'click_edit', track_label: 'Edit' }
+ data = { track_action: 'click_edit', track_label: 'edit' }
if Feature.enabled?(:web_ide_primary_edit, project.group)
common_classes += " btn-inverted"
@@ -85,7 +85,7 @@ module BlobHelper
return unless blob
common_classes = 'btn gl-button btn-confirm ide-edit-button gl-ml-3'
- data = { track_event: 'click_edit_ide', track_label: 'Web IDE' }
+ data = { track_action: 'click_edit_ide', track_label: 'web_ide' }
unless Feature.enabled?(:web_ide_primary_edit, project.group)
common_classes += " btn-inverted"
diff --git a/app/helpers/integrations_helper.rb b/app/helpers/integrations_helper.rb
index f37f7518dec..b8678763f65 100644
--- a/app/helpers/integrations_helper.rb
+++ b/app/helpers/integrations_helper.rb
@@ -1,32 +1,14 @@
# frozen_string_literal: true
module IntegrationsHelper
- def integration_event_description(event)
- case event
- when "push", "push_events"
- s_("ProjectService|Trigger event for pushes to the repository.")
- when "tag_push", "tag_push_events"
- s_("ProjectService|Trigger event for new tags pushed to the repository.")
- when "note", "note_events"
- s_("ProjectService|Trigger event for new comments.")
- when "confidential_note", "confidential_note_events"
- s_("ProjectService|Trigger event for new comments on confidential issues.")
- when "issue", "issue_events"
- s_("ProjectService|Trigger event when an issue is created, updated, or closed.")
- when "confidential_issue", "confidential_issue_events"
- s_("ProjectService|Trigger event when a confidential issue is created, updated, or closed.")
- when "merge_request", "merge_request_events"
- s_("ProjectService|Trigger event when a merge request is created, updated, or merged.")
- when "pipeline", "pipeline_events"
- s_("ProjectService|Trigger event when a pipeline status changes.")
- when "wiki_page", "wiki_page_events"
- s_("ProjectService|Trigger event when a wiki page is created or updated.")
- when "commit", "commit_events"
- s_("ProjectService|Trigger event when a commit is created or updated.")
- when "deployment"
- s_("ProjectService|Trigger event when a deployment starts or finishes.")
- when "alert"
- s_("ProjectService|Trigger event when a new, unique alert is recorded.")
+ def integration_event_description(integration, event)
+ case integration
+ when Integrations::Jira
+ jira_integration_event_description(event)
+ when Integrations::Teamcity
+ teamcity_integration_event_description(event)
+ else
+ default_integration_event_description(event)
end
end
@@ -144,6 +126,53 @@ module IntegrationsHelper
private
+ def jira_integration_event_description(event)
+ case event
+ when "merge_request", "merge_request_events"
+ s_("JiraService|Jira comments are created when an issue is referenced in a merge request.")
+ when "commit", "commit_events"
+ s_("JiraService|Jira comments are created when an issue is referenced in a commit.")
+ end
+ end
+
+ def teamcity_integration_event_description(event)
+ case event
+ when 'push', 'push_events'
+ s_('TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete')
+ when 'merge_request', 'merge_request_events'
+ s_('TeamcityIntegration|Trigger TeamCity CI after a merge request has been created or updated')
+ end
+ end
+
+ def default_integration_event_description(event)
+ case event
+ when "push", "push_events"
+ s_("ProjectService|Trigger event for pushes to the repository.")
+ when "tag_push", "tag_push_events"
+ s_("ProjectService|Trigger event for new tags pushed to the repository.")
+ when "note", "note_events"
+ s_("ProjectService|Trigger event for new comments.")
+ when "confidential_note", "confidential_note_events"
+ s_("ProjectService|Trigger event for new comments on confidential issues.")
+ when "issue", "issue_events"
+ s_("ProjectService|Trigger event when an issue is created, updated, or closed.")
+ when "confidential_issue", "confidential_issue_events"
+ s_("ProjectService|Trigger event when a confidential issue is created, updated, or closed.")
+ when "merge_request", "merge_request_events"
+ s_("ProjectService|Trigger event when a merge request is created, updated, or merged.")
+ when "pipeline", "pipeline_events"
+ s_("ProjectService|Trigger event when a pipeline status changes.")
+ when "wiki_page", "wiki_page_events"
+ s_("ProjectService|Trigger event when a wiki page is created or updated.")
+ when "commit", "commit_events"
+ s_("ProjectService|Trigger event when a commit is created or updated.")
+ when "deployment"
+ s_("ProjectService|Trigger event when a deployment starts or finishes.")
+ when "alert"
+ s_("ProjectService|Trigger event when a new, unique alert is recorded.")
+ end
+ end
+
def trigger_events_for_integration(integration)
ServiceEventSerializer.new(service: integration).represent(integration.configurable_events).to_json
end
diff --git a/app/models/integration.rb b/app/models/integration.rb
index 20de51ebcd1..9d5d2a2d921 100644
--- a/app/models/integration.rb
+++ b/app/models/integration.rb
@@ -172,10 +172,6 @@ class Integration < ApplicationRecord
'push'
end
- def self.event_description(event)
- IntegrationsHelper.integration_event_description(event)
- end
-
def self.find_or_create_templates
create_nonexistent_templates
for_template
diff --git a/app/models/integrations/jira.rb b/app/models/integrations/jira.rb
index 40734a29724..7b878903bac 100644
--- a/app/models/integrations/jira.rb
+++ b/app/models/integrations/jira.rb
@@ -577,15 +577,6 @@ module Integrations
data_fields.deployment_server!
end
end
-
- def self.event_description(event)
- case event
- when "merge_request", "merge_request_events"
- s_("JiraService|Jira comments are created when an issue is referenced in a merge request.")
- when "commit", "commit_events"
- s_("JiraService|Jira comments are created when an issue is referenced in a commit.")
- end
- end
end
end
diff --git a/app/models/integrations/teamcity.rb b/app/models/integrations/teamcity.rb
index 3f14c5d82b3..403271aa6a9 100644
--- a/app/models/integrations/teamcity.rb
+++ b/app/models/integrations/teamcity.rb
@@ -29,15 +29,6 @@ module Integrations
def supported_events
%w(push merge_request)
end
-
- def event_description(event)
- case event
- when 'push', 'push_events'
- 'TeamCity CI will be triggered after every push to the repository except branch delete'
- when 'merge_request', 'merge_request_events'
- 'TeamCity CI will be triggered after a merge request has been created or updated'
- end
- end
end
def compose_service_hook
diff --git a/app/serializers/service_event_entity.rb b/app/serializers/service_event_entity.rb
index 56dfdc794eb..a1fbfa1d4c4 100644
--- a/app/serializers/service_event_entity.rb
+++ b/app/serializers/service_event_entity.rb
@@ -14,7 +14,7 @@ class ServiceEventEntity < Grape::Entity
end
expose :description do |event|
- IntegrationsHelper.integration_event_description(event)
+ IntegrationsHelper.integration_event_description(integration, event)
end
expose :field, if: -> (_, _) { event_field } do
diff --git a/app/services/service_ping/build_payload_service.rb b/app/services/service_ping/build_payload_service.rb
new file mode 100644
index 00000000000..2bef3d32103
--- /dev/null
+++ b/app/services/service_ping/build_payload_service.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module ServicePing
+ class BuildPayloadService
+ def execute
+ return {} unless allowed_to_report?
+
+ raw_payload
+ end
+
+ private
+
+ def allowed_to_report?
+ product_intelligence_enabled? && !User.single_user&.requires_usage_stats_consent?
+ end
+
+ def product_intelligence_enabled?
+ ::Gitlab::CurrentSettings.usage_ping_enabled?
+ end
+
+ def raw_payload
+ @raw_payload ||= ::Gitlab::UsageData.data(force_refresh: true)
+ end
+ end
+end
+
+ServicePing::BuildPayloadService.prepend_mod_with('ServicePing::BuildPayloadService')
diff --git a/config/feature_flags/development/load_balancing_refine_load_balancer_methods.yml b/config/feature_flags/development/load_balancing_refine_load_balancer_methods.yml
new file mode 100644
index 00000000000..bef59588f7a
--- /dev/null
+++ b/config/feature_flags/development/load_balancing_refine_load_balancer_methods.yml
@@ -0,0 +1,8 @@
+---
+name: load_balancing_refine_load_balancer_methods
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65356
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/335109
+milestone: '14.1'
+type: development
+group: group::memory
+default_enabled: false
diff --git a/config/initializers/asciidoctor_patch.rb b/config/initializers/asciidoctor_patch.rb
deleted file mode 100644
index b7da50db77c..00000000000
--- a/config/initializers/asciidoctor_patch.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-# Ensure that locked attributes can not be changed using a counter.
-# TODO: this can be removed once `asciidoctor` gem is > 2.0.12
-# and https://github.com/asciidoctor/asciidoctor/issues/3939 is merged
-module Asciidoctor
- module DocumentPatch
- def counter(name, seed = nil)
- return @parent_document.counter(name, seed) if @parent_document # rubocop: disable Gitlab/ModuleWithInstanceVariables
-
- unless attribute_locked? name
- super
- end
- end
- end
-end
-
-class Asciidoctor::Document
- prepend Asciidoctor::DocumentPatch
-end
diff --git a/doc/administration/packages/index.md b/doc/administration/packages/index.md
index 6440fb16fc6..85c7a96ef55 100644
--- a/doc/administration/packages/index.md
+++ b/doc/administration/packages/index.md
@@ -237,3 +237,17 @@ For installations from source:
```shell
RAILS_ENV=production sudo -u git -H bundle exec rake gitlab:packages:migrate
```
+
+You can optionally track progress and verify that all packages migrated successfully.
+
+From the [PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database)
+(`sudo gitlab-psql -d gitlabhq_production` for Omnibus GitLab), verify that `objectstg` below (where
+`file_store=2`) has the count of all packages:
+
+```shell
+gitlabhq_production=# SELECT count(*) AS total, sum(case when file_store = '1' then 1 else 0 end) AS filesystem, sum(case when file_store = '2' then 1 else 0 end) AS objectstg FROM packages_package_files;
+
+total | filesystem | objectstg
+------+------------+-----------
+ 34 | 0 | 34
+```
diff --git a/doc/development/i18n/proofreader.md b/doc/development/i18n/proofreader.md
index fc19ab93ecd..6e3b32e18df 100644
--- a/doc/development/i18n/proofreader.md
+++ b/doc/development/i18n/proofreader.md
@@ -93,6 +93,7 @@ are very appreciative of the work done by translators and proofreaders!
- Portuguese, Brazilian
- Paulo George Gomes Bezerra - [GitLab](https://gitlab.com/paulobezerra), [CrowdIn](https://crowdin.com/profile/paulogomes.rep)
- André Gama - [GitLab](https://gitlab.com/andregamma), [CrowdIn](https://crowdin.com/profile/ToeOficial)
+ - Eduardo Addad de Oliveira - [GitLab](https://gitlab.com/eduardoaddad), [CrowdIn](https://crowdin.com/profile/eduardoaddad)
- Romanian
- Proofreaders needed.
- Russian
diff --git a/doc/user/project/import/github.md b/doc/user/project/import/github.md
index ec56ea851d7..33bdc2bc7d8 100644
--- a/doc/user/project/import/github.md
+++ b/doc/user/project/import/github.md
@@ -134,6 +134,9 @@ If you are not using the GitHub integration, you can still perform an authorizat
1. Hit the **List Your GitHub Repositories** button and wait while GitLab reads your repositories' information.
Once done, you'll be taken to the importer page to select the repositories to import.
+To use a newer personal access token in imports after previously performing these steps, sign out of
+your GitLab account and sign in again, or revoke the older personal access token in GitHub.
+
### Select which repositories to import
After you have authorized access to your GitHub repositories, you are redirected to the GitHub importer page and
diff --git a/lib/api/services.rb b/lib/api/services.rb
index c81af1791a5..6c21a80509d 100644
--- a/lib/api/services.rb
+++ b/lib/api/services.rb
@@ -23,14 +23,14 @@ module API
INTEGRATIONS = integrations.freeze
- integration_classes.each do |service|
- event_names = service.try(:event_names) || next
+ integration_classes.each do |integration|
+ event_names = integration.try(:event_names) || next
event_names.each do |event_name|
- INTEGRATIONS[service.to_param.tr("_", "-")] << {
+ INTEGRATIONS[integration.to_param.tr("_", "-")] << {
required: false,
name: event_name.to_sym,
type: String,
- desc: service.event_description(event_name)
+ desc: IntegrationsHelper.integration_event_description(integration, event_name)
}
end
end
diff --git a/lib/gitlab/database/background_migration/batched_job.rb b/lib/gitlab/database/background_migration/batched_job.rb
index 9a1dc4ee17d..b238d0dd4b8 100644
--- a/lib/gitlab/database/background_migration/batched_job.rb
+++ b/lib/gitlab/database/background_migration/batched_job.rb
@@ -44,6 +44,52 @@ module Gitlab
# TODO: Switch to individual job interval (prereq: https://gitlab.com/gitlab-org/gitlab/-/issues/328801)
duration.to_f / batched_migration.interval
end
+
+ def split_and_retry!
+ with_lock do
+ raise 'Only failed jobs can be split' unless failed?
+
+ new_batch_size = batch_size / 2
+
+ raise 'Job cannot be split further' if new_batch_size < 1
+
+ batching_strategy = batched_migration.batch_class.new
+ next_batch_bounds = batching_strategy.next_batch(
+ batched_migration.table_name,
+ batched_migration.column_name,
+ batch_min_value: min_value,
+ batch_size: new_batch_size
+ )
+ midpoint = next_batch_bounds.last
+
+ # We don't want the midpoint to go over the existing max_value because
+ # those IDs would already be in the next batched migration job.
+ # This could happen when a lot of records in the current batch are deleted.
+ #
+ # In this case, we just lower the batch size so that future calls to this
+ # method could eventually split the job if it continues to fail.
+ if midpoint >= max_value
+ update!(batch_size: new_batch_size, status: :pending)
+ else
+ old_max_value = max_value
+
+ update!(
+ batch_size: new_batch_size,
+ max_value: midpoint,
+ attempts: 0,
+ status: :pending,
+ started_at: nil,
+ finished_at: nil,
+ metrics: {}
+ )
+
+ new_record = dup
+ new_record.min_value = midpoint.next
+ new_record.max_value = old_max_value
+ new_record.save!
+ end
+ end
+ end
end
end
end
diff --git a/lib/gitlab/database/load_balancing/load_balancer.rb b/lib/gitlab/database/load_balancing/load_balancer.rb
index d25c274edd4..b5960476759 100644
--- a/lib/gitlab/database/load_balancing/load_balancer.rb
+++ b/lib/gitlab/database/load_balancing/load_balancer.rb
@@ -165,6 +165,7 @@ module Gitlab
# while we only need a single host: https://gitlab.com/gitlab-org/gitlab/-/issues/326125#note_615271604
# Also, shuffling the list afterwards doesn't seem to be necessary.
# This may be improved by merging this method with `select_up_to_date_host`.
+ # Could be removed when `:load_balancing_refine_load_balancer_methods` FF is rolled out
def select_caught_up_hosts(location)
all_hosts = @host_list.hosts
valid_hosts = all_hosts.select { |host| host.caught_up?(location) }
@@ -201,6 +202,7 @@ module Gitlab
true
end
+ # Could be removed when `:load_balancing_refine_load_balancer_methods` FF is rolled out
def set_consistent_hosts_for_request(hosts)
RequestStore[VALID_HOSTS_CACHE_KEY] = hosts
end
diff --git a/lib/gitlab/database/load_balancing/sticking.rb b/lib/gitlab/database/load_balancing/sticking.rb
index d3b5a28074e..1223225ef5b 100644
--- a/lib/gitlab/database/load_balancing/sticking.rb
+++ b/lib/gitlab/database/load_balancing/sticking.rb
@@ -53,8 +53,14 @@ module Gitlab
# write location. If no such location exists, err on the side of caution.
return false unless location
- load_balancer.select_caught_up_hosts(location).tap do |selected|
- unstick(namespace, id) if selected
+ if ::Feature.enabled?(:load_balancing_refine_load_balancer_methods)
+ load_balancer.select_up_to_date_host(location).tap do |selected|
+ unstick(namespace, id) if selected
+ end
+ else
+ load_balancer.select_caught_up_hosts(location).tap do |selected|
+ unstick(namespace, id) if selected
+ end
end
end
diff --git a/lib/gitlab/usage/metrics/instrumentations/database_metric.rb b/lib/gitlab/usage/metrics/instrumentations/database_metric.rb
index 69a288e5b6e..7b3a545185b 100644
--- a/lib/gitlab/usage/metrics/instrumentations/database_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/database_metric.rb
@@ -16,14 +16,20 @@ module Gitlab
# end
class << self
def start(&block)
+ return @metric_start&.call unless block_given?
+
@metric_start = block
end
def finish(&block)
+ return @metric_finish&.call unless block_given?
+
@metric_finish = block
end
def relation(&block)
+ return @metric_relation&.call unless block_given?
+
@metric_relation = block
end
@@ -32,15 +38,21 @@ module Gitlab
@column = column
end
- attr_reader :metric_operation, :metric_relation, :metric_start, :metric_finish, :column
+ def cache_start_and_finish_as(cache_key)
+ @cache_key = cache_key
+ end
+
+ attr_reader :metric_operation, :metric_relation, :metric_start, :metric_finish, :column, :cache_key
end
def value
+ start, finish = get_or_cache_batch_ids
+
method(self.class.metric_operation)
.call(relation,
self.class.column,
- start: self.class.metric_start&.call,
- finish: self.class.metric_finish&.call)
+ start: start,
+ finish: finish)
end
def to_sql
@@ -73,6 +85,22 @@ module Gitlab
raise "Unknown time frame: #{time_frame} for DatabaseMetric"
end
end
+
+ def get_or_cache_batch_ids
+ return [self.class.start, self.class.finish] unless self.class.cache_key.present?
+
+ key_name = "metric_instrumentation/#{self.class.cache_key}"
+
+ start = Gitlab::Cache.fetch_once("#{key_name}_minimum_id", expires_in: 1.day) do
+ self.class.start
+ end
+
+ finish = Gitlab::Cache.fetch_once("#{key_name}_maximum_id", expires_in: 1.day) do
+ self.class.finish
+ end
+
+ [start, finish]
+ end
end
end
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 71a62f55aba..4ee339377bf 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -31905,6 +31905,12 @@ msgstr ""
msgid "Team domain"
msgstr ""
+msgid "TeamcityIntegration|Trigger TeamCity CI after a merge request has been created or updated"
+msgstr ""
+
+msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
+msgstr ""
+
msgid "Telephone number"
msgstr ""
diff --git a/package.json b/package.json
index 9a8180b92ec..3a88f17584d 100644
--- a/package.json
+++ b/package.json
@@ -59,7 +59,7 @@
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/svgs": "1.202.0",
"@gitlab/tributejs": "1.0.0",
- "@gitlab/ui": "30.2.0",
+ "@gitlab/ui": "30.2.1",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "6.1.3-2",
"@rails/ujs": "6.1.3-2",
diff --git a/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap b/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap
index e5e336eb3d5..0e1fe790771 100644
--- a/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap
+++ b/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap
@@ -156,7 +156,6 @@ exports[`Remove cluster confirmation modal renders splitbutton with modal includ
<!---->
</div>
-
</ul>
</div>
diff --git a/spec/frontend/jira_import/components/__snapshots__/jira_import_form_spec.js.snap b/spec/frontend/jira_import/components/__snapshots__/jira_import_form_spec.js.snap
index 172b6e4831c..f2142ce1fcf 100644
--- a/spec/frontend/jira_import/components/__snapshots__/jira_import_form_spec.js.snap
+++ b/spec/frontend/jira_import/components/__snapshots__/jira_import_form_spec.js.snap
@@ -176,7 +176,6 @@ exports[`JiraImportForm table body shows correct information in each cell 1`] =
<!---->
</div>
-
</ul>
</div>
</td>
@@ -304,7 +303,6 @@ exports[`JiraImportForm table body shows correct information in each cell 1`] =
<!---->
</div>
-
</ul>
</div>
</td>
diff --git a/spec/frontend/vue_shared/components/web_ide_link_spec.js b/spec/frontend/vue_shared/components/web_ide_link_spec.js
index 5a6c91bda9f..0fd4d0dab87 100644
--- a/spec/frontend/vue_shared/components/web_ide_link_spec.js
+++ b/spec/frontend/vue_shared/components/web_ide_link_spec.js
@@ -15,8 +15,8 @@ const ACTION_EDIT = {
tooltip: '',
attrs: {
'data-qa-selector': 'edit_button',
- 'data-track-event': 'click_edit',
- 'data-track-label': 'Edit',
+ 'data-track-action': 'click_consolidated_edit',
+ 'data-track-label': 'edit',
},
};
const ACTION_EDIT_CONFIRM_FORK = {
@@ -32,8 +32,8 @@ const ACTION_WEB_IDE = {
text: 'Web IDE',
attrs: {
'data-qa-selector': 'web_ide_button',
- 'data-track-event': 'click_edit_ide',
- 'data-track-label': 'Web IDE',
+ 'data-track-action': 'click_consolidated_edit_ide',
+ 'data-track-label': 'web_ide',
},
};
const ACTION_WEB_IDE_CONFIRM_FORK = {
diff --git a/spec/helpers/blob_helper_spec.rb b/spec/helpers/blob_helper_spec.rb
index 885569574a4..c48d609836d 100644
--- a/spec/helpers/blob_helper_spec.rb
+++ b/spec/helpers/blob_helper_spec.rb
@@ -67,8 +67,8 @@ RSpec.describe BlobHelper do
it 'passes on primary tracking attributes' do
parsed_link = Capybara.string(link).find_link('Edit')
- expect(parsed_link[:'data-track-event']).to eq("click_edit")
- expect(parsed_link[:'data-track-label']).to eq("Edit")
+ expect(parsed_link[:'data-track-action']).to eq("click_edit")
+ expect(parsed_link[:'data-track-label']).to eq("edit")
expect(parsed_link[:'data-track-property']).to eq(nil)
end
end
@@ -85,8 +85,8 @@ RSpec.describe BlobHelper do
it 'passes on secondary tracking attributes' do
parsed_link = Capybara.string(link).find_link('Edit')
- expect(parsed_link[:'data-track-event']).to eq("click_edit")
- expect(parsed_link[:'data-track-label']).to eq("Edit")
+ expect(parsed_link[:'data-track-action']).to eq("click_edit")
+ expect(parsed_link[:'data-track-label']).to eq("edit")
expect(parsed_link[:'data-track-property']).to eq("secondary")
end
end
@@ -332,8 +332,8 @@ RSpec.describe BlobHelper do
it 'passes on secondary tracking attributes' do
parsed_link = Capybara.string(link).find_link('Web IDE')
- expect(parsed_link[:'data-track-event']).to eq("click_edit_ide")
- expect(parsed_link[:'data-track-label']).to eq("Web IDE")
+ expect(parsed_link[:'data-track-action']).to eq("click_edit_ide")
+ expect(parsed_link[:'data-track-label']).to eq("web_ide")
expect(parsed_link[:'data-track-property']).to eq("secondary")
end
end
@@ -350,8 +350,8 @@ RSpec.describe BlobHelper do
it 'passes on primary tracking attributes' do
parsed_link = Capybara.string(link).find_link('Web IDE')
- expect(parsed_link[:'data-track-event']).to eq("click_edit_ide")
- expect(parsed_link[:'data-track-label']).to eq("Web IDE")
+ expect(parsed_link[:'data-track-action']).to eq("click_edit_ide")
+ expect(parsed_link[:'data-track-label']).to eq("web_ide")
expect(parsed_link[:'data-track-property']).to eq(nil)
end
end
diff --git a/spec/helpers/integrations_helper_spec.rb b/spec/helpers/integrations_helper_spec.rb
index 8cecf2296e8..8e652d2f150 100644
--- a/spec/helpers/integrations_helper_spec.rb
+++ b/spec/helpers/integrations_helper_spec.rb
@@ -3,6 +3,22 @@
require 'spec_helper'
RSpec.describe IntegrationsHelper do
+ describe '#integration_event_description' do
+ subject(:description) { helper.integration_event_description(integration, 'merge_request_events') }
+
+ context 'when integration is Jira' do
+ let(:integration) { Integrations::Jira.new }
+
+ it { is_expected.to include('Jira') }
+ end
+
+ context 'when integration is Team City' do
+ let(:integration) { Integrations::Teamcity.new }
+
+ it { is_expected.to include('TeamCity') }
+ end
+ end
+
describe '#integration_form_data' do
let(:fields) do
[
diff --git a/spec/lib/gitlab/database/background_migration/batched_job_spec.rb b/spec/lib/gitlab/database/background_migration/batched_job_spec.rb
index 2de784d3e16..60971a99e34 100644
--- a/spec/lib/gitlab/database/background_migration/batched_job_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/batched_job_spec.rb
@@ -124,4 +124,73 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
end
end
end
+
+ describe '#split_and_retry!' do
+ let!(:job) { create(:batched_background_migration_job, batch_size: 10, min_value: 6, max_value: 15, status: :failed) }
+
+ it 'splits the job into two and marks them as pending' do
+ allow_next_instance_of(Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchingStrategy) do |batch_class|
+ allow(batch_class).to receive(:next_batch).with(anything, anything, batch_min_value: 6, batch_size: 5).and_return([6, 10])
+ end
+
+ expect { job.split_and_retry! }.to change { described_class.count }.by(1)
+
+ expect(job).to have_attributes(
+ min_value: 6,
+ max_value: 10,
+ batch_size: 5,
+ status: 'pending',
+ attempts: 0,
+ started_at: nil,
+ finished_at: nil,
+ metrics: {}
+ )
+
+ new_job = described_class.last
+
+ expect(new_job).to have_attributes(
+ batched_background_migration_id: job.batched_background_migration_id,
+ min_value: 11,
+ max_value: 15,
+ batch_size: 5,
+ status: 'pending',
+ attempts: 0,
+ started_at: nil,
+ finished_at: nil,
+ metrics: {}
+ )
+ expect(new_job.created_at).not_to eq(job.created_at)
+ end
+
+ context 'when job is not failed' do
+ let!(:job) { create(:batched_background_migration_job, status: :succeeded) }
+
+ it 'raises an exception' do
+ expect { job.split_and_retry! }.to raise_error 'Only failed jobs can be split'
+ end
+ end
+
+ context 'when batch size is already 1' do
+ let!(:job) { create(:batched_background_migration_job, batch_size: 1, status: :failed) }
+
+ it 'raises an exception' do
+ expect { job.split_and_retry! }.to raise_error 'Job cannot be split further'
+ end
+ end
+
+ context 'when computed midpoint is larger than the max value of the batch' do
+ before do
+ allow_next_instance_of(Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchingStrategy) do |batch_class|
+ allow(batch_class).to receive(:next_batch).with(anything, anything, batch_min_value: 6, batch_size: 5).and_return([6, 16])
+ end
+ end
+
+ it 'lowers the batch size and marks the job as pending' do
+ expect { job.split_and_retry! }.not_to change { described_class.count }
+
+ expect(job.batch_size).to eq(5)
+ expect(job.status).to eq('pending')
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/database/load_balancing/sticking_spec.rb b/spec/lib/gitlab/database/load_balancing/sticking_spec.rb
index 29591f2f851..f1ab923a67e 100644
--- a/spec/lib/gitlab/database/load_balancing/sticking_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/sticking_spec.rb
@@ -325,10 +325,22 @@ RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
end
it 'returns true, selects hosts, and unsticks if any secondary has caught up' do
- expect(lb).to receive(:select_caught_up_hosts).and_return(true)
+ expect(lb).to receive(:select_up_to_date_host).and_return(true)
expect(described_class).to receive(:unstick).with(:project, 42)
expect(described_class.select_caught_up_replicas(:project, 42)).to be true
end
+
+ context 'when :load_balancing_refine_load_balancer_methods FF is disabled' do
+ before do
+ stub_feature_flags(load_balancing_refine_load_balancer_methods: false)
+ end
+
+ it 'returns true, selects hosts, and unsticks if any secondary has caught up' do
+ expect(lb).to receive(:select_caught_up_hosts).and_return(true)
+ expect(described_class).to receive(:unstick).with(:project, 42)
+ expect(described_class.select_caught_up_replicas(:project, 42)).to be true
+ end
+ end
end
end
end
diff --git a/spec/lib/gitlab/kroki_spec.rb b/spec/lib/gitlab/kroki_spec.rb
index 31d3edd158b..7d29d018ff1 100644
--- a/spec/lib/gitlab/kroki_spec.rb
+++ b/spec/lib/gitlab/kroki_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Gitlab::Kroki do
describe '.formats' do
def default_formats
- %w[bytefield c4plantuml ditaa erd graphviz nomnoml plantuml svgbob umlet vega vegalite wavedrom].freeze
+ %w[bytefield c4plantuml ditaa erd graphviz nomnoml pikchr plantuml svgbob umlet vega vegalite wavedrom].freeze
end
subject { described_class.formats(Gitlab::CurrentSettings) }
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/database_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/database_metric_spec.rb
new file mode 100644
index 00000000000..5e36820df5e
--- /dev/null
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/database_metric_spec.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DatabaseMetric do
+ subject do
+ described_class.tap do |m|
+ m.relation { Issue }
+ m.operation :count
+ m.start { m.relation.minimum(:id) }
+ m.finish { m.relation.maximum(:id) }
+ end.new(time_frame: 'all')
+ end
+
+ describe '#value' do
+ let_it_be(:issue_1) { create(:issue) }
+ let_it_be(:issue_2) { create(:issue) }
+ let_it_be(:issue_3) { create(:issue) }
+ let_it_be(:issues) { Issue.all }
+
+ before do
+ allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false)
+ end
+
+ it 'calculates a correct result' do
+ expect(subject.value).to eq(3)
+ end
+
+ it 'does not cache the result of start and finish', :request_store, :use_clean_rails_redis_caching do
+ expect(Gitlab::Cache).not_to receive(:fetch_once)
+ expect(subject).to receive(:count).with(any_args, hash_including(start: issues.min_by(&:id).id, finish: issues.max_by(&:id).id)).and_call_original
+
+ subject.value
+
+ expect(Rails.cache.read('metric_instrumentation/special_issue_count_minimum_id')).to eq(nil)
+ expect(Rails.cache.read('metric_instrumentation/special_issue_count_maximum_id')).to eq(nil)
+ end
+
+ context 'with start and finish not called' do
+ subject do
+ described_class.tap do |m|
+ m.relation { Issue }
+ m.operation :count
+ end.new(time_frame: 'all')
+ end
+
+ it 'calculates a correct result' do
+ expect(subject.value).to eq(3)
+ end
+ end
+
+ context 'with cache_start_and_finish_as called' do
+ subject do
+ described_class.tap do |m|
+ m.relation { Issue }
+ m.operation :count
+ m.start { m.relation.minimum(:id) }
+ m.finish { m.relation.maximum(:id) }
+ m.cache_start_and_finish_as :special_issue_count
+ end.new(time_frame: 'all')
+ end
+
+ it 'caches using the key name passed', :request_store, :use_clean_rails_redis_caching do
+ expect(Gitlab::Cache).to receive(:fetch_once).with('metric_instrumentation/special_issue_count_minimum_id', any_args).and_call_original
+ expect(Gitlab::Cache).to receive(:fetch_once).with('metric_instrumentation/special_issue_count_maximum_id', any_args).and_call_original
+ expect(subject).to receive(:count).with(any_args, hash_including(start: issues.min_by(&:id).id, finish: issues.max_by(&:id).id)).and_call_original
+
+ subject.value
+
+ expect(Rails.cache.read('metric_instrumentation/special_issue_count_minimum_id')).to eq(issues.min_by(&:id).id)
+ expect(Rails.cache.read('metric_instrumentation/special_issue_count_maximum_id')).to eq(issues.max_by(&:id).id)
+ end
+ end
+ end
+end
diff --git a/spec/services/service_ping/build_payload_service_spec.rb b/spec/services/service_ping/build_payload_service_spec.rb
new file mode 100644
index 00000000000..cd2685069c9
--- /dev/null
+++ b/spec/services/service_ping/build_payload_service_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ServicePing::BuildPayloadService do
+ describe '#execute', :without_license do
+ subject(:service_ping_payload) { described_class.new.execute }
+
+ include_context 'stubbed service ping metrics definitions' do
+ let(:subscription_metrics) do
+ [
+ metric_attributes('active_user_count', "Subscription")
+ ]
+ end
+ end
+
+ context 'when usage_ping_enabled setting is false' do
+ before do
+ # Gitlab::CurrentSettings.usage_ping_enabled? == false
+ stub_config_setting(usage_ping_enabled: false)
+ end
+
+ it 'returns empty service ping payload' do
+ expect(service_ping_payload).to eq({})
+ end
+ end
+
+ context 'when usage_ping_enabled setting is true' do
+ before do
+ # Gitlab::CurrentSettings.usage_ping_enabled? == true
+ stub_config_setting(usage_ping_enabled: true)
+ end
+
+ it_behaves_like 'complete service ping payload'
+
+ context 'with require stats consent enabled' do
+ before do
+ allow(User).to receive(:single_user).and_return(double(:user, requires_usage_stats_consent?: true))
+ end
+
+ it 'returns empty service ping payload' do
+ expect(service_ping_payload).to eq({})
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/matchers/usage_metric_matchers.rb b/spec/support/matchers/usage_metric_matchers.rb
new file mode 100644
index 00000000000..83433334e8b
--- /dev/null
+++ b/spec/support/matchers/usage_metric_matchers.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+RSpec::Matchers.define :have_usage_metric do |key_path|
+ match do |payload|
+ payload = payload.deep_stringify_keys
+
+ key_path.split('.').each do |part|
+ break false unless payload&.has_key?(part)
+
+ payload = payload[part]
+ end
+ end
+
+ failure_message do
+ "Payload does not contain metric with key path: '#{key_path}'"
+ end
+
+ failure_message_when_negated do
+ "Payload contains restricted metric with key path: '#{key_path}'"
+ end
+end
diff --git a/spec/support/shared_contexts/services/service_ping/stubbed_service_ping_metrics_definitions_shared_context.rb b/spec/support/shared_contexts/services/service_ping/stubbed_service_ping_metrics_definitions_shared_context.rb
new file mode 100644
index 00000000000..ea72398010c
--- /dev/null
+++ b/spec/support/shared_contexts/services/service_ping/stubbed_service_ping_metrics_definitions_shared_context.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'stubbed service ping metrics definitions' do
+ include UsageDataHelpers
+
+ let(:metrics_definitions) { standard_metrics + subscription_metrics + operational_metrics + optional_metrics }
+ let(:standard_metrics) do
+ [
+ metric_attributes('uuid', "Standard")
+ ]
+ end
+
+ let(:operational_metrics) do
+ [
+ metric_attributes('counts.merge_requests', "Operational"),
+ metric_attributes('counts.todos', "Operational")
+ ]
+ end
+
+ let(:optional_metrics) do
+ [
+ metric_attributes('counts.boards', "Optional"),
+ metric_attributes('gitaly.filesystems', '').except('data_category')
+ ]
+ end
+
+ before do
+ stub_usage_data_connections
+ stub_object_store_settings
+
+ allow(Gitlab::Usage::MetricDefinition).to(
+ receive(:definitions)
+ .and_return(metrics_definitions.to_h { |definition| [definition['key_path'], Gitlab::Usage::MetricDefinition.new('', definition.symbolize_keys)] })
+ )
+ end
+
+ def metric_attributes(key_path, category)
+ {
+ 'key_path' => key_path,
+ 'data_category' => category
+ }
+ end
+end
diff --git a/spec/support/shared_examples/services/service_ping/complete_service_ping_payload_shared_examples.rb b/spec/support/shared_examples/services/service_ping/complete_service_ping_payload_shared_examples.rb
new file mode 100644
index 00000000000..8dcff99fb6f
--- /dev/null
+++ b/spec/support/shared_examples/services/service_ping/complete_service_ping_payload_shared_examples.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'complete service ping payload' do
+ it_behaves_like 'service ping payload with all expected metrics' do
+ let(:expected_metrics) do
+ standard_metrics + subscription_metrics + operational_metrics + optional_metrics
+ end
+ end
+end
diff --git a/spec/support/shared_examples/services/service_ping/service_ping_payload_with_all_expected_metrics_shared_examples.rb b/spec/support/shared_examples/services/service_ping/service_ping_payload_with_all_expected_metrics_shared_examples.rb
new file mode 100644
index 00000000000..535e7291b7e
--- /dev/null
+++ b/spec/support/shared_examples/services/service_ping/service_ping_payload_with_all_expected_metrics_shared_examples.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'service ping payload with all expected metrics' do
+ specify do
+ aggregate_failures do
+ expected_metrics.each do |metric|
+ is_expected.to have_usage_metric metric['key_path']
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/services/service_ping/service_ping_payload_without_restricted_metrics_shared_examples.rb b/spec/support/shared_examples/services/service_ping/service_ping_payload_without_restricted_metrics_shared_examples.rb
new file mode 100644
index 00000000000..9f18174cbc7
--- /dev/null
+++ b/spec/support/shared_examples/services/service_ping/service_ping_payload_without_restricted_metrics_shared_examples.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'service ping payload without restricted metrics' do
+ specify do
+ aggregate_failures do
+ restricted_metrics.each do |metric|
+ is_expected.not_to have_usage_metric metric['key_path']
+ end
+ end
+ end
+end
diff --git a/yarn.lock b/yarn.lock
index d5af76e8829..be0d9afd4f8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -908,10 +908,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8"
integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw==
-"@gitlab/ui@30.2.0":
- version "30.2.0"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-30.2.0.tgz#eceec947f901cca9507a1ac8b3bd0031a5dcacf9"
- integrity sha512-rYG3HyUHZQyum9+6OKvp45r9b9E/wzAl8rpFyIIZMg6a14JPfsGhdjXqycWlLxf3TAsbTD6MtjQm/z/I8J6V8g==
+"@gitlab/ui@30.2.1":
+ version "30.2.1"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-30.2.1.tgz#be582413712cd2372ff01279e47579f5785591d4"
+ integrity sha512-Pv2w5ZSR7+G5zcaRjvf8KPs7wQRBqAXXNvKOw2pg/aZsRoK+JfN1neNmfeaqO6K/k1TJyiP6inDXAvhU8SqmOg==
dependencies:
"@babel/standalone" "^7.0.0"
bootstrap-vue "2.18.1"