diff options
33 files changed, 518 insertions, 310 deletions
diff --git a/app/assets/javascripts/ci/runner/admin_new_runner/admin_new_runner_app.vue b/app/assets/javascripts/ci/runner/admin_new_runner/admin_new_runner_app.vue index f0a41a5949e..97163c1f55c 100644 --- a/app/assets/javascripts/ci/runner/admin_new_runner/admin_new_runner_app.vue +++ b/app/assets/javascripts/ci/runner/admin_new_runner/admin_new_runner_app.vue @@ -4,7 +4,6 @@ import { visitUrl, setUrlParams } from '~/lib/utils/url_utility'; import { s__ } from '~/locale'; import RegistrationCompatibilityAlert from '~/ci/runner/components/registration/registration_compatibility_alert.vue'; -import RegistrationFeedbackBanner from '~/ci/runner/components/registration/registration_feedback_banner.vue'; import RunnerPlatformsRadioGroup from '~/ci/runner/components/runner_platforms_radio_group.vue'; import RunnerCreateForm from '~/ci/runner/components/runner_create_form.vue'; import { DEFAULT_PLATFORM, PARAM_KEY_PLATFORM, INSTANCE_TYPE } from '../constants'; @@ -14,7 +13,6 @@ export default { name: 'AdminNewRunnerApp', components: { RegistrationCompatibilityAlert, - RegistrationFeedbackBanner, RunnerPlatformsRadioGroup, RunnerCreateForm, }, @@ -44,8 +42,6 @@ export default { <template> <div> - <registration-feedback-banner /> - <h1 class="gl-font-size-h2">{{ s__('Runners|New instance runner') }}</h1> <registration-compatibility-alert :alert-key="$options.INSTANCE_TYPE" /> diff --git a/app/assets/javascripts/ci/runner/components/registration/registration_feedback_banner.vue b/app/assets/javascripts/ci/runner/components/registration/registration_feedback_banner.vue deleted file mode 100644 index 6fd4edf5847..00000000000 --- a/app/assets/javascripts/ci/runner/components/registration/registration_feedback_banner.vue +++ /dev/null @@ -1,41 +0,0 @@ -<script> -import ILLUSTRATION_URL from '@gitlab/svgs/dist/illustrations/rocket-launch-md.svg?url'; -import { GlBanner } from '@gitlab/ui'; -import { s__ } from '~/locale'; -import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue'; - -const FEEDBACK_ISSUE_URL = 'https://gitlab.com/gitlab-org/gitlab/-/issues/387993'; - -export default { - components: { - GlBanner, - UserCalloutDismisser, - }, - i18n: { - title: s__("Runners|We've made some changes and want your feedback"), - body: s__( - "Runners|We've been making improvements to how you register runners so that it's more secure and efficient. Tell us how we're doing.", - ), - button: s__('Runners|Add your feedback to this issue'), - }, - ILLUSTRATION_URL, - FEEDBACK_ISSUE_URL, -}; -</script> -<template> - <user-callout-dismisser feature-name="create_runner_workflow_banner"> - <template #default="{ dismiss, shouldShowCallout }"> - <gl-banner - v-if="shouldShowCallout" - class="gl-my-6" - :title="$options.i18n.title" - :svg-path="$options.ILLUSTRATION_URL" - :button-text="$options.i18n.button" - :button-link="$options.FEEDBACK_ISSUE_URL" - @close="dismiss" - > - <p>{{ $options.i18n.body }}</p> - </gl-banner> - </template> - </user-callout-dismisser> -</template> diff --git a/app/assets/javascripts/ci/runner/group_new_runner/group_new_runner_app.vue b/app/assets/javascripts/ci/runner/group_new_runner/group_new_runner_app.vue index 2e1706ddae9..c907f9c8982 100644 --- a/app/assets/javascripts/ci/runner/group_new_runner/group_new_runner_app.vue +++ b/app/assets/javascripts/ci/runner/group_new_runner/group_new_runner_app.vue @@ -4,7 +4,6 @@ import { visitUrl, setUrlParams } from '~/lib/utils/url_utility'; import { s__ } from '~/locale'; import RegistrationCompatibilityAlert from '~/ci/runner/components/registration/registration_compatibility_alert.vue'; -import RegistrationFeedbackBanner from '~/ci/runner/components/registration/registration_feedback_banner.vue'; import RunnerPlatformsRadioGroup from '~/ci/runner/components/runner_platforms_radio_group.vue'; import RunnerCreateForm from '~/ci/runner/components/runner_create_form.vue'; import { DEFAULT_PLATFORM, GROUP_TYPE, PARAM_KEY_PLATFORM } from '../constants'; @@ -14,7 +13,6 @@ export default { name: 'GroupNewRunnerApp', components: { RegistrationCompatibilityAlert, - RegistrationFeedbackBanner, RunnerPlatformsRadioGroup, RunnerCreateForm, }, @@ -50,8 +48,6 @@ export default { <template> <div> - <registration-feedback-banner /> - <h1 class="gl-font-size-h2">{{ s__('Runners|New group runner') }}</h1> <registration-compatibility-alert :alert-key="groupId" /> diff --git a/app/assets/javascripts/ci/runner/project_new_runner/project_new_runner_app.vue b/app/assets/javascripts/ci/runner/project_new_runner/project_new_runner_app.vue index 51f5a9ce8d9..241479a8c98 100644 --- a/app/assets/javascripts/ci/runner/project_new_runner/project_new_runner_app.vue +++ b/app/assets/javascripts/ci/runner/project_new_runner/project_new_runner_app.vue @@ -4,7 +4,6 @@ import { visitUrl, setUrlParams } from '~/lib/utils/url_utility'; import { s__ } from '~/locale'; import RegistrationCompatibilityAlert from '~/ci/runner/components/registration/registration_compatibility_alert.vue'; -import RegistrationFeedbackBanner from '~/ci/runner/components/registration/registration_feedback_banner.vue'; import RunnerPlatformsRadioGroup from '~/ci/runner/components/runner_platforms_radio_group.vue'; import RunnerCreateForm from '~/ci/runner/components/runner_create_form.vue'; import { DEFAULT_PLATFORM, PARAM_KEY_PLATFORM, PROJECT_TYPE } from '../constants'; @@ -14,7 +13,6 @@ export default { name: 'ProjectNewRunnerApp', components: { RegistrationCompatibilityAlert, - RegistrationFeedbackBanner, RunnerPlatformsRadioGroup, RunnerCreateForm, }, @@ -50,8 +48,6 @@ export default { <template> <div> - <registration-feedback-banner /> - <h1 class="gl-font-size-h2">{{ s__('Runners|New project runner') }}</h1> <registration-compatibility-alert :alert-key="projectId" /> diff --git a/app/assets/javascripts/search/sidebar/components/merge_requests_filters.vue b/app/assets/javascripts/search/sidebar/components/merge_requests_filters.vue index 6e476ef7935..f86906ebd26 100644 --- a/app/assets/javascripts/search/sidebar/components/merge_requests_filters.vue +++ b/app/assets/javascripts/search/sidebar/components/merge_requests_filters.vue @@ -1,7 +1,6 @@ <script> // eslint-disable-next-line no-restricted-imports import { mapGetters, mapState } from 'vuex'; -import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { HR_DEFAULT_CLASSES } from '../constants'; import { statusFilterData } from './status_filter/data'; import StatusFilter from './status_filter/index.vue'; @@ -16,15 +15,11 @@ export default { FiltersTemplate, ArchivedFilter, }, - mixins: [glFeatureFlagsMixin()], computed: { ...mapGetters(['currentScope']), ...mapState(['useSidebarNavigation', 'searchType']), showArchivedFilter() { - return ( - archivedFilterData.scopes.includes(this.currentScope) && - this.glFeatures.searchMergeRequestsHideArchivedProjects - ); + return archivedFilterData.scopes.includes(this.currentScope); }, showStatusFilter() { return Object.values(statusFilterData.scopes).includes(this.currentScope); diff --git a/app/assets/stylesheets/page_bundles/branches.scss b/app/assets/stylesheets/page_bundles/branches.scss index daf828fb559..973ba1afb17 100644 --- a/app/assets/stylesheets/page_bundles/branches.scss +++ b/app/assets/stylesheets/page_bundles/branches.scss @@ -42,6 +42,10 @@ .branches-list .branch-item:not(:last-of-type) { border-bottom: 1px solid $border-color; + + .gl-dark & { + border-bottom-color: $gray-800; + } } .branch-item { diff --git a/app/models/users/callout.rb b/app/models/users/callout.rb index b2f0fd01019..aad763555bf 100644 --- a/app/models/users/callout.rb +++ b/app/models/users/callout.rb @@ -65,7 +65,7 @@ module Users # 62, removed in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131314 # 63 and 64 were removed with https://gitlab.com/gitlab-org/gitlab/-/merge_requests/120233 branch_rules_info_callout: 65, - create_runner_workflow_banner: 66, + # 66 removed in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/135470/ # 67 removed in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121920 project_repository_limit_alert_warning_threshold: 68, # EE-only project_repository_limit_alert_alert_threshold: 69, # EE-only diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml index 765727e700d..9f0c910c1c0 100644 --- a/app/views/projects/commits/_commit.html.haml +++ b/app/views/projects/commits/_commit.html.haml @@ -36,7 +36,7 @@ = commit.short_id - if commit.description? && collapsible = render Pajamas::ButtonComponent.new(icon: 'ellipsis_h', - button_options: { class: 'button-ellipsis-horizontal text-expander js-toggle-button', data: { toggle: 'tooltip', container: 'body' }, :title => _("Toggle commit description"), aria: { label: _("Toggle commit description") }}) + button_options: { class: 'button-ellipsis-horizontal text-expander js-toggle-button', data: { toggle: 'tooltip', container: 'body', collapse_title: _("Toggle commit description"), expand_title: _("Toggle commit description") }, :title => _("Toggle commit description"), aria: { label: _("Toggle commit description") }}) .committer - commit_author_link = commit_author_link(commit, avatar: false, size: 24) diff --git a/config/feature_flags/development/verify_push_rules_for_first_commit.yml b/config/feature_flags/development/verify_push_rules_for_first_commit.yml deleted file mode 100644 index f18f9eecfdb..00000000000 --- a/config/feature_flags/development/verify_push_rules_for_first_commit.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: verify_push_rules_for_first_commit -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/123950 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/419128 -milestone: '16.3' -type: development -group: group::source code -default_enabled: true diff --git a/config/metrics/schema.json b/config/metrics/schema/base.json index fe53b92f7de..5f571566651 100644 --- a/config/metrics/schema.json +++ b/config/metrics/schema/base.json @@ -87,28 +87,6 @@ "options": { "type": "object" }, - "events": { - "type": "array", - "items": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "name": { - "type": "string" - }, - "unique": { - "type": "string", - "enum": [ - "user.id", - "project.id", - "namespace.id" - ] - } - } - } - }, "time_frame": { "type": "string", "enum": [ @@ -188,50 +166,5 @@ "value_json_schema": { "type": "string" } - }, - "allOf": [ - { - "if": { - "properties": { - "status": { - "const": "broken" - } - } - }, - "then": { - "required": [ - "repair_issue_url" - ] - } - }, - { - "if": { - "properties": { - "data_source": { - "const": "internal_events" - } - } - }, - "then": { - "required": [ - "events" - ] - } - }, - { - "if": { - "properties": { - "status": { - "const": "removed" - } - } - }, - "then": { - "required": [ - "removed_by_url", - "milestone_removed" - ] - } - } - ] + } } diff --git a/config/metrics/schema/internal_events.json b/config/metrics/schema/internal_events.json new file mode 100644 index 00000000000..d925b8af1eb --- /dev/null +++ b/config/metrics/schema/internal_events.json @@ -0,0 +1,74 @@ +{ + "if": { + "properties": { + "data_source": { + "const": "internal_events" + } + } + }, + "then": { + "oneOf": [ + { + "properties": { + "instrumentation_class": { + "const": "RedisHLLMetric" + }, + "options": { + "type": "object", + "properties": { + "events": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "events" + ], + "additionalProperties": false + }, + "events": { + "type": "array", + "items": { + "type": "object", + "required": [ + "name", + "unique" + ], + "properties": { + "name": { + "type": "string" + }, + "unique": { + "type": "string", + "enum": [ + "user.id", + "project.id", + "namespace.id" + ] + } + }, + "additionalProperties": false + } + } + }, + "required": [ + "events", + "options", + "instrumentation_class" + ] + }, + { + "properties": { + "instrumentation_class": { + "const": "TotalCountMetric" + } + }, + "required": [ + "instrumentation_class" + ] + } + ] + } +} diff --git a/config/metrics/schema/redis.json b/config/metrics/schema/redis.json new file mode 100644 index 00000000000..3fe3ba3e7ec --- /dev/null +++ b/config/metrics/schema/redis.json @@ -0,0 +1,95 @@ +{ + "if": { + "properties": { + "data_source": { + "const": "redis" + } + } + }, + "then": { + "oneOf": [ + { + "properties": { + "instrumentation_class": { + "const": "MergeRequestWidgetExtensionMetric" + }, + "options": { + "type": "object", + "properties": { + "event": { + "type": "string" + }, + "widget": { + "type": "string" + } + }, + "required": [ + "event", + "widget" + ], + "additionalProperties": false + } + }, + "required": [ + "instrumentation_class", + "options" + ] + }, + { + "properties": { + "instrumentation_class": { + "const": "RedisMetric" + }, + "options": { + "type": "object", + "properties": { + "event": { + "type": "string" + }, + "prefix": { + "type": [ + "string", + "null" + ] + }, + "include_usage_prefix": { + "type": "boolean" + } + }, + "required": [ + "event", + "prefix" + ], + "additionalProperties": false + } + }, + "required": [ + "instrumentation_class", + "options" + ] + }, + { + "properties": { + "key_path": { + "description": "Legacy metrics that do not match with the schema", + "enum": [ + "counts.dependency_list_usages_total", + "counts.network_policy_forwards", + "counts.network_policy_drops", + "counts.static_site_editor_views", + "counts.static_site_editor_commits", + "counts.static_site_editor_merge_requests", + "counts.package_events_i_package_container_delete_package", + "counts.package_events_i_package_container_pull_package", + "counts.package_events_i_package_container_push_package", + "counts.package_events_i_package_debian_push_package", + "counts.package_events_i_package_tag_delete_package", + "counts.package_events_i_package_tag_pull_package", + "counts.package_events_i_package_tag_push_package" + ] + } + } + } + ] + } +} diff --git a/config/metrics/schema/redis_hll.json b/config/metrics/schema/redis_hll.json new file mode 100644 index 00000000000..31de5d27e40 --- /dev/null +++ b/config/metrics/schema/redis_hll.json @@ -0,0 +1,67 @@ +{ + "if": { + "properties": { + "data_source": { + "const": "redis_hll" + } + } + }, + "then": { + "oneOf": [ + { + "properties": { + "instrumentation_class": { + "const": "RedisHLLMetric" + }, + "options": { + "type": "object", + "properties": { + "events": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "events" + ], + "additionalProperties": false + } + }, + "required": [ + "instrumentation_class", + "options" + ] + }, + { + "properties": { + "instrumentation_class": { + "const": "AggregatedMetric" + } + }, + "required": [ + "instrumentation_class" + ] + }, + { + "properties": { + "key_path": { + "description": "Legacy metrics that do not match with the schema", + "enum": [ + "usage_activity_by_stage_monthly.create.merge_requests_users", + "usage_activity_by_stage_monthly.create.action_monthly_active_users_web_ide_edit", + "usage_activity_by_stage_monthly.create.action_monthly_active_users_sfe_edit", + "usage_activity_by_stage_monthly.create.action_monthly_active_users_snippet_editor_edit", + "usage_activity_by_stage_monthly.create.action_monthly_active_users_sse_edit", + "counts_monthly.aggregated_metrics.product_analytics_test_metrics_union", + "counts_weekly.aggregated_metrics.product_analytics_test_metrics_union", + "counts_monthly.aggregated_metrics.product_analytics_test_metrics_intersection", + "counts_weekly.aggregated_metrics.product_analytics_test_metrics_intersection" + ] + } + } + } + ] + } +} diff --git a/config/metrics/schema/status.json b/config/metrics/schema/status.json new file mode 100644 index 00000000000..7b71a22b4c6 --- /dev/null +++ b/config/metrics/schema/status.json @@ -0,0 +1,33 @@ +{ + "allOf": [ + { + "if": { + "properties": { + "status": { + "const": "broken" + } + } + }, + "then": { + "required": [ + "repair_issue_url" + ] + } + }, + { + "if": { + "properties": { + "status": { + "const": "removed" + } + } + }, + "then": { + "required": [ + "removed_by_url", + "milestone_removed" + ] + } + } + ] +} diff --git a/db/post_migrate/20231030094755_add_index_to_catalog_resources_on_state.rb b/db/post_migrate/20231030094755_add_index_to_catalog_resources_on_state.rb new file mode 100644 index 00000000000..b7c6c8affdb --- /dev/null +++ b/db/post_migrate/20231030094755_add_index_to_catalog_resources_on_state.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class AddIndexToCatalogResourcesOnState < Gitlab::Database::Migration[2.2] + milestone '16.6' + + disable_ddl_transaction! + + INDEX_NAME = 'index_catalog_resources_on_state' + + def up + add_concurrent_index :catalog_resources, :state, name: INDEX_NAME + end + + def down + remove_concurrent_index_by_name :catalog_resources, INDEX_NAME + end +end diff --git a/db/schema_migrations/20231030094755 b/db/schema_migrations/20231030094755 new file mode 100644 index 00000000000..5a18105655b --- /dev/null +++ b/db/schema_migrations/20231030094755 @@ -0,0 +1 @@ +981110baa181be00e7195b9f6e9773d14683b00a0de851b23b261561e7aaae27
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index c9d55842ba2..e0682562a36 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -31670,6 +31670,8 @@ CREATE INDEX index_catalog_resources_on_name_trigram ON catalog_resources USING CREATE UNIQUE INDEX index_catalog_resources_on_project_id ON catalog_resources USING btree (project_id); +CREATE INDEX index_catalog_resources_on_state ON catalog_resources USING btree (state); + CREATE INDEX index_chat_names_on_team_id_and_chat_id ON chat_names USING btree (team_id, chat_id); CREATE INDEX index_chat_names_on_user_id ON chat_names USING btree (user_id); diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 3edefe0c320..f73865cc502 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -29940,7 +29940,6 @@ Name of the feature that the callout is for. | <a id="usercalloutfeaturenameenumci_deprecation_warning_for_types_keyword"></a>`CI_DEPRECATION_WARNING_FOR_TYPES_KEYWORD` | Callout feature name for ci_deprecation_warning_for_types_keyword. | | <a id="usercalloutfeaturenameenumcloud_licensing_subscription_activation_banner"></a>`CLOUD_LICENSING_SUBSCRIPTION_ACTIVATION_BANNER` | Callout feature name for cloud_licensing_subscription_activation_banner. | | <a id="usercalloutfeaturenameenumcluster_security_warning"></a>`CLUSTER_SECURITY_WARNING` | Callout feature name for cluster_security_warning. | -| <a id="usercalloutfeaturenameenumcreate_runner_workflow_banner"></a>`CREATE_RUNNER_WORKFLOW_BANNER` | Callout feature name for create_runner_workflow_banner. | | <a id="usercalloutfeaturenameenumeoa_bronze_plan_banner"></a>`EOA_BRONZE_PLAN_BANNER` | Callout feature name for eoa_bronze_plan_banner. | | <a id="usercalloutfeaturenameenumfeature_flags_new_version"></a>`FEATURE_FLAGS_NEW_VERSION` | Callout feature name for feature_flags_new_version. | | <a id="usercalloutfeaturenameenumgcp_signup_offer"></a>`GCP_SIGNUP_OFFER` | Callout feature name for gcp_signup_offer. | diff --git a/lib/bulk_imports/clients/graphql.rb b/lib/bulk_imports/clients/graphql.rb index 94bbdfaa681..3055c8d24ce 100644 --- a/lib/bulk_imports/clients/graphql.rb +++ b/lib/bulk_imports/clients/graphql.rb @@ -4,11 +4,14 @@ module BulkImports module Clients class Graphql class HTTP < Graphlient::Adapters::HTTP::Adapter + REQUEST_TIMEOUT = 60 + def execute(document:, operation_name: nil, variables: {}, context: {}) response = ::Gitlab::HTTP.post( url, headers: headers, follow_redirects: false, + timeout: REQUEST_TIMEOUT, body: { query: document.to_query_string, operationName: operation_name, diff --git a/lib/gitlab/checks/diff_check.rb b/lib/gitlab/checks/diff_check.rb index 15b38188f13..a359236e150 100644 --- a/lib/gitlab/checks/diff_check.rb +++ b/lib/gitlab/checks/diff_check.rb @@ -31,8 +31,7 @@ module Gitlab def treeish_objects objects = commits - return objects unless project.repository.empty? && - Feature.enabled?(:verify_push_rules_for_first_commit, project) + return objects unless project.repository.empty? # It's a special case for the push to the empty repository # diff --git a/lib/gitlab/usage/metric_definition.rb b/lib/gitlab/usage/metric_definition.rb index 7252283d1b9..941c2f793c4 100644 --- a/lib/gitlab/usage/metric_definition.rb +++ b/lib/gitlab/usage/metric_definition.rb @@ -3,7 +3,7 @@ module Gitlab module Usage class MetricDefinition - METRIC_SCHEMA_PATH = Rails.root.join('config', 'metrics', 'schema.json') + METRIC_SCHEMA_PATH = Rails.root.join('config', 'metrics', 'schema', '**', '*.json') AVAILABLE_STATUSES = %w[active broken].to_set.freeze VALID_SERVICE_PING_STATUSES = %w[active broken].to_set.freeze @@ -52,7 +52,7 @@ module Gitlab end def validate! - self.class.schemer.validate(attributes.deep_stringify_keys).each do |error| + errors.each do |error| error_message = <<~ERROR_MSG Error type: #{error['type']} Data: #{error['data']} @@ -104,8 +104,10 @@ module Gitlab definitions[key_path]&.to_context end - def schemer - @schemer ||= ::JSONSchemer.schema(Pathname.new(METRIC_SCHEMA_PATH)) + def schemers + @schemers ||= Dir[METRIC_SCHEMA_PATH].map do |path| + ::JSONSchemer.schema(Pathname.new(path)) + end end def dump_metrics_yaml @@ -145,6 +147,19 @@ module Gitlab private + def errors + result = [] + + self.class.schemers.each do |schemer| + # schemer.validate returns an Enumerator object + schemer.validate(attributes.deep_stringify_keys).each do |error| + result << error + end + end + + result + end + def method_missing(method, *args) attributes[method] || super end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index c658795361c..645f04963a7 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -40764,9 +40764,6 @@ msgstr "" msgid "Runners|Add tags to specify jobs that the runner can run. %{helpLinkStart}Learn more.%{helpLinkEnd}" msgstr "" -msgid "Runners|Add your feedback to this issue" -msgstr "" - msgid "Runners|Admin area › Runners" msgstr "" @@ -41548,12 +41545,6 @@ msgstr "" msgid "Runners|Wait time to pick a job" msgstr "" -msgid "Runners|We've been making improvements to how you register runners so that it's more secure and efficient. Tell us how we're doing." -msgstr "" - -msgid "Runners|We've made some changes and want your feedback" -msgstr "" - msgid "Runners|Windows 2019 Shell with manual scaling and optional scheduling. %{percentage} spot." msgstr "" diff --git a/package.json b/package.json index 80b869465e2..7bff6132996 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "@gitlab/favicon-overlay": "2.0.0", "@gitlab/fonts": "^1.3.0", "@gitlab/svgs": "3.69.0", - "@gitlab/ui": "66.37.0", + "@gitlab/ui": "67.3.0", "@gitlab/visual-review-tools": "1.7.3", "@gitlab/web-ide": "0.0.1-dev-20231004090414", "@mattiasbuelens/web-streams-adapter": "^0.1.0", diff --git a/spec/features/projects/active_tabs_spec.rb b/spec/features/projects/active_tabs_spec.rb index 8879636e4dc..199ea638f61 100644 --- a/spec/features/projects/active_tabs_spec.rb +++ b/spec/features/projects/active_tabs_spec.rb @@ -2,8 +2,8 @@ require 'spec_helper' -RSpec.describe 'Project active tab', feature_category: :groups_and_projects do - let_it_be(:user) { create(:user, :no_super_sidebar) } +RSpec.describe 'Project active tab', :js, feature_category: :groups_and_projects do + let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project, :repository, :with_namespace_settings, namespace: user.namespace) } before do @@ -11,7 +11,7 @@ RSpec.describe 'Project active tab', feature_category: :groups_and_projects do end def click_tab(title) - page.within '.sidebar-top-level-items > .active' do + within_testid('super-sidebar') do click_link(title) end end @@ -20,66 +20,68 @@ RSpec.describe 'Project active tab', feature_category: :groups_and_projects do it 'activates Project scope menu' do visit project_path(project) - expect(page).to have_selector('.sidebar-top-level-items > li.active', count: 1) - expect(find('.sidebar-top-level-items > li.active')).to have_content(project.name) + expect(page).to have_selector('a[aria-current="page"]', count: 1) + expect(find('a[aria-current="page"]')).to have_content(project.name) end end - context 'on Project information' do - context 'default link' do - before do - visit project_path(project) - - click_link('Project information', match: :first) - end - - it_behaves_like 'page has active tab', 'Project' - it_behaves_like 'page has active sub tab', 'Activity' - end + context 'on Project Manage' do + %w[Activity Members Labels].each do |sub_menu| + context "on project Manage/#{sub_menu}" do + before do + visit project_path(project) + within_testid('super-sidebar') do + click_button("Manage") + end + click_tab(sub_menu) + end - context 'on Project information/Activity' do - before do - visit activity_project_path(project) + it_behaves_like 'page has active tab', 'Manage' + it_behaves_like 'page has active sub tab', sub_menu end - - it_behaves_like 'page has active tab', 'Project' - it_behaves_like 'page has active sub tab', 'Activity' end end - context 'on project Repository' do + context 'on project Code' do before do root_ref = project.repository.root_ref visit project_tree_path(project, root_ref) + + # Enabling Js in here causes more SQL queries to be caught by the query limiter. + # We are increasing the limit here so that the tests pass. + allow(Gitlab::QueryLimiting::Transaction).to receive(:threshold).and_return(110) end - it_behaves_like 'page has active tab', 'Repository' + it_behaves_like 'page has active tab', 'Code' - %w[Files Commits Graph Compare Branches Tags].each do |sub_menu| - context "on project Repository/#{sub_menu}" do + ["Repository", "Branches", "Commits", "Tags", "Repository graph", "Compare revisions"].each do |sub_menu| + context "on project Code/#{sub_menu}" do before do click_tab(sub_menu) end - it_behaves_like 'page has active tab', 'Repository' + it_behaves_like 'page has active tab', 'Code' it_behaves_like 'page has active sub tab', sub_menu end end end - context 'on project Issues' do + context 'on project Plan' do before do visit project_issues_path(project) end - it_behaves_like 'page has active tab', 'Issues' + it_behaves_like 'page has active tab', 'Pinned' - context "on project Issues/Milestones" do + context "on project Code/Milestones" do before do + within_testid('super-sidebar') do + click_button("Plan") + end click_tab('Milestones') end - it_behaves_like 'page has active tab', 'Issues' + it_behaves_like 'page has active tab', 'Plan' it_behaves_like 'page has active sub tab', 'Milestones' end end @@ -89,7 +91,7 @@ RSpec.describe 'Project active tab', feature_category: :groups_and_projects do visit project_merge_requests_path(project) end - it_behaves_like 'page has active tab', 'Merge requests' + it_behaves_like 'page has active tab', 'Pinned' end context 'on project Wiki' do @@ -97,7 +99,8 @@ RSpec.describe 'Project active tab', feature_category: :groups_and_projects do visit wiki_path(project.wiki) end - it_behaves_like 'page has active tab', 'Wiki' + it_behaves_like 'page has active tab', 'Plan' + it_behaves_like 'page has active sub tab', 'Wiki' end context 'on project Members' do @@ -105,7 +108,8 @@ RSpec.describe 'Project active tab', feature_category: :groups_and_projects do visit project_project_members_path(project) end - it_behaves_like 'page has active tab', 'Members' + it_behaves_like 'page has active tab', 'Manage' + it_behaves_like 'page has active sub tab', 'Members' end context 'on project Settings' do @@ -132,23 +136,23 @@ RSpec.describe 'Project active tab', feature_category: :groups_and_projects do end end - context 'on project Analytics' do + context 'on project Analyze' do before do visit project_cycle_analytics_path(project) end - context 'on project Analytics/Value stream Analytics' do - it_behaves_like 'page has active tab', _('Analytics') + context 'on project Analyze/Value stream Analyze' do + it_behaves_like 'page has active tab', _('Analyze') it_behaves_like 'page has active sub tab', _('Value stream') end - context 'on project Analytics/"CI/CD"' do + context 'on project Analyze/"CI/CD"' do before do click_tab(_('CI/CD')) end - it_behaves_like 'page has active tab', _('Analytics') - it_behaves_like 'page has active sub tab', _('CI/CD') + it_behaves_like 'page has active tab', _('Analyze') + it_behaves_like 'page has active sub tab', _('CI/CD analytics') end end @@ -161,7 +165,7 @@ RSpec.describe 'Project active tab', feature_category: :groups_and_projects do visit project_pipeline_path(project, pipeline) end - it_behaves_like 'page has active tab', _('CI/CD') + it_behaves_like 'page has active tab', _('Build') it_behaves_like 'page has active sub tab', _('Pipelines') end @@ -170,7 +174,7 @@ RSpec.describe 'Project active tab', feature_category: :groups_and_projects do visit dag_project_pipeline_path(project, pipeline) end - it_behaves_like 'page has active tab', _('CI/CD') + it_behaves_like 'page has active tab', _('Build') it_behaves_like 'page has active sub tab', _('Pipelines') end @@ -179,7 +183,7 @@ RSpec.describe 'Project active tab', feature_category: :groups_and_projects do visit builds_project_pipeline_path(project, pipeline) end - it_behaves_like 'page has active tab', _('CI/CD') + it_behaves_like 'page has active tab', _('Build') it_behaves_like 'page has active sub tab', _('Pipelines') end @@ -188,7 +192,7 @@ RSpec.describe 'Project active tab', feature_category: :groups_and_projects do visit failures_project_pipeline_path(project, pipeline) end - it_behaves_like 'page has active tab', _('CI/CD') + it_behaves_like 'page has active tab', _('Build') it_behaves_like 'page has active sub tab', _('Pipelines') end @@ -197,7 +201,7 @@ RSpec.describe 'Project active tab', feature_category: :groups_and_projects do visit test_report_project_pipeline_path(project, pipeline) end - it_behaves_like 'page has active tab', _('CI/CD') + it_behaves_like 'page has active tab', _('Build') it_behaves_like 'page has active sub tab', _('Pipelines') end end diff --git a/spec/frontend/ci/runner/admin_new_runner_app/admin_new_runner_app_spec.js b/spec/frontend/ci/runner/admin_new_runner_app/admin_new_runner_app_spec.js index 75bca68b888..03958381d75 100644 --- a/spec/frontend/ci/runner/admin_new_runner_app/admin_new_runner_app_spec.js +++ b/spec/frontend/ci/runner/admin_new_runner_app/admin_new_runner_app_spec.js @@ -6,7 +6,6 @@ import { createAlert, VARIANT_SUCCESS } from '~/alert'; import AdminNewRunnerApp from '~/ci/runner/admin_new_runner/admin_new_runner_app.vue'; import RegistrationCompatibilityAlert from '~/ci/runner/components/registration/registration_compatibility_alert.vue'; -import RegistrationFeedbackBanner from '~/ci/runner/components/registration/registration_feedback_banner.vue'; import { saveAlertToLocalStorage } from '~/ci/runner/local_storage_alert/save_alert_to_local_storage'; import RunnerPlatformsRadioGroup from '~/ci/runner/components/runner_platforms_radio_group.vue'; import { @@ -32,7 +31,6 @@ describe('AdminNewRunnerApp', () => { let wrapper; const findRunnerPlatformsRadioGroup = () => wrapper.findComponent(RunnerPlatformsRadioGroup); - const findRegistrationFeedbackBanner = () => wrapper.findComponent(RegistrationFeedbackBanner); const findRegistrationCompatibilityAlert = () => wrapper.findComponent(RegistrationCompatibilityAlert); const findRunnerCreateForm = () => wrapper.findComponent(RunnerCreateForm); @@ -49,10 +47,6 @@ describe('AdminNewRunnerApp', () => { createComponent(); }); - it('shows a registration feedback banner', () => { - expect(findRegistrationFeedbackBanner().exists()).toBe(true); - }); - it('shows a registration compatibility alert', () => { expect(findRegistrationCompatibilityAlert().props('alertKey')).toBe(INSTANCE_TYPE); }); diff --git a/spec/frontend/ci/runner/components/registration/registration_feedback_banner_spec.js b/spec/frontend/ci/runner/components/registration/registration_feedback_banner_spec.js deleted file mode 100644 index fa6b7ad7c63..00000000000 --- a/spec/frontend/ci/runner/components/registration/registration_feedback_banner_spec.js +++ /dev/null @@ -1,52 +0,0 @@ -import { GlBanner } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; -import RegistrationFeedbackBanner from '~/ci/runner/components/registration/registration_feedback_banner.vue'; -import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue'; -import { makeMockUserCalloutDismisser } from 'helpers/mock_user_callout_dismisser'; - -describe('Runner registration feeback banner', () => { - let wrapper; - let userCalloutDismissSpy; - - const findUserCalloutDismisser = () => wrapper.findComponent(UserCalloutDismisser); - const findBanner = () => wrapper.findComponent(GlBanner); - - const createComponent = ({ shouldShowCallout = true } = {}) => { - userCalloutDismissSpy = jest.fn(); - - wrapper = shallowMount(RegistrationFeedbackBanner, { - stubs: { - UserCalloutDismisser: makeMockUserCalloutDismisser({ - dismiss: userCalloutDismissSpy, - shouldShowCallout, - }), - }, - }); - }; - - it('banner is shown', () => { - createComponent(); - - expect(findBanner().exists()).toBe(true); - }); - - it('dismisses the callout when closed', () => { - createComponent(); - - findBanner().vm.$emit('close'); - - expect(userCalloutDismissSpy).toHaveBeenCalled(); - }); - - it('sets feature name to create_runner_workflow_banner', () => { - createComponent(); - - expect(findUserCalloutDismisser().props('featureName')).toBe('create_runner_workflow_banner'); - }); - - it('is not displayed once it has been dismissed', () => { - createComponent({ shouldShowCallout: false }); - - expect(findBanner().exists()).toBe(false); - }); -}); diff --git a/spec/frontend/ci/runner/group_new_runner_app/group_new_runner_app_spec.js b/spec/frontend/ci/runner/group_new_runner_app/group_new_runner_app_spec.js index 177fd9bcd9a..623a8f1c5a1 100644 --- a/spec/frontend/ci/runner/group_new_runner_app/group_new_runner_app_spec.js +++ b/spec/frontend/ci/runner/group_new_runner_app/group_new_runner_app_spec.js @@ -6,7 +6,6 @@ import { createAlert, VARIANT_SUCCESS } from '~/alert'; import GroupRunnerRunnerApp from '~/ci/runner/group_new_runner/group_new_runner_app.vue'; import RegistrationCompatibilityAlert from '~/ci/runner/components/registration/registration_compatibility_alert.vue'; -import RegistrationFeedbackBanner from '~/ci/runner/components/registration/registration_feedback_banner.vue'; import { saveAlertToLocalStorage } from '~/ci/runner/local_storage_alert/save_alert_to_local_storage'; import RunnerPlatformsRadioGroup from '~/ci/runner/components/runner_platforms_radio_group.vue'; import { @@ -34,7 +33,6 @@ describe('GroupRunnerRunnerApp', () => { let wrapper; const findRunnerPlatformsRadioGroup = () => wrapper.findComponent(RunnerPlatformsRadioGroup); - const findRegistrationFeedbackBanner = () => wrapper.findComponent(RegistrationFeedbackBanner); const findRegistrationCompatibilityAlert = () => wrapper.findComponent(RegistrationCompatibilityAlert); const findRunnerCreateForm = () => wrapper.findComponent(RunnerCreateForm); @@ -54,10 +52,6 @@ describe('GroupRunnerRunnerApp', () => { createComponent(); }); - it('shows a registration feedback banner', () => { - expect(findRegistrationFeedbackBanner().exists()).toBe(true); - }); - it('shows a registration compatibility alert', () => { expect(findRegistrationCompatibilityAlert().props('alertKey')).toBe(mockGroupId); }); diff --git a/spec/frontend/ci/runner/project_new_runner_app/project_new_runner_app_spec.js b/spec/frontend/ci/runner/project_new_runner_app/project_new_runner_app_spec.js index 22d8e243f7b..3e12f3911a0 100644 --- a/spec/frontend/ci/runner/project_new_runner_app/project_new_runner_app_spec.js +++ b/spec/frontend/ci/runner/project_new_runner_app/project_new_runner_app_spec.js @@ -6,7 +6,6 @@ import { createAlert, VARIANT_SUCCESS } from '~/alert'; import ProjectRunnerRunnerApp from '~/ci/runner/project_new_runner/project_new_runner_app.vue'; import RegistrationCompatibilityAlert from '~/ci/runner/components/registration/registration_compatibility_alert.vue'; -import RegistrationFeedbackBanner from '~/ci/runner/components/registration/registration_feedback_banner.vue'; import { saveAlertToLocalStorage } from '~/ci/runner/local_storage_alert/save_alert_to_local_storage'; import RunnerPlatformsRadioGroup from '~/ci/runner/components/runner_platforms_radio_group.vue'; import { @@ -34,7 +33,6 @@ describe('ProjectRunnerRunnerApp', () => { let wrapper; const findRunnerPlatformsRadioGroup = () => wrapper.findComponent(RunnerPlatformsRadioGroup); - const findRegistrationFeedbackBanner = () => wrapper.findComponent(RegistrationFeedbackBanner); const findRegistrationCompatibilityAlert = () => wrapper.findComponent(RegistrationCompatibilityAlert); const findRunnerCreateForm = () => wrapper.findComponent(RunnerCreateForm); @@ -55,10 +53,6 @@ describe('ProjectRunnerRunnerApp', () => { createComponent(); }); - it('shows a registration feedback banner', () => { - expect(findRegistrationFeedbackBanner().exists()).toBe(true); - }); - it('shows a registration compatibility alert', () => { expect(findRegistrationCompatibilityAlert().props('alertKey')).toBe(mockProjectId); }); diff --git a/spec/frontend/search/sidebar/components/merge_requests_filters_spec.js b/spec/frontend/search/sidebar/components/merge_requests_filters_spec.js index 278249c2660..b02228a418f 100644 --- a/spec/frontend/search/sidebar/components/merge_requests_filters_spec.js +++ b/spec/frontend/search/sidebar/components/merge_requests_filters_spec.js @@ -17,10 +17,7 @@ describe('GlobalSearch MergeRequestsFilters', () => { currentScope: () => 'merge_requests', }; - const createComponent = ({ - initialState = {}, - searchMergeRequestsHideArchivedProjects = true, - } = {}) => { + const createComponent = (initialState = {}) => { const store = new Vuex.Store({ state: { urlQuery: MOCK_QUERY, @@ -33,11 +30,6 @@ describe('GlobalSearch MergeRequestsFilters', () => { wrapper = shallowMount(MergeRequestsFilters, { store, - provide: { - glFeatures: { - searchMergeRequestsHideArchivedProjects, - }, - }, }); }; @@ -45,34 +37,23 @@ describe('GlobalSearch MergeRequestsFilters', () => { const findArchivedFilter = () => wrapper.findComponent(ArchivedFilter); const findDividers = () => wrapper.findAll('hr'); - describe.each` - description | searchMergeRequestsHideArchivedProjects - ${'Renders correctly with Archived Filter disabled'} | ${false} - ${'Renders correctly with Archived Filter enabled'} | ${true} - `('$description', ({ searchMergeRequestsHideArchivedProjects }) => { + describe('Renders correctly with Archived Filter', () => { beforeEach(() => { - createComponent({ - searchMergeRequestsHideArchivedProjects, - }); + createComponent(); }); it('renders StatusFilter', () => { expect(findStatusFilter().exists()).toBe(true); }); - it(`renders correctly ArchivedFilter when searchMergeRequestsHideArchivedProjects is ${searchMergeRequestsHideArchivedProjects}`, () => { - expect(findArchivedFilter().exists()).toBe(searchMergeRequestsHideArchivedProjects); - }); - it('renders divider correctly', () => { - const dividersCount = searchMergeRequestsHideArchivedProjects ? 1 : 0; - expect(findDividers()).toHaveLength(dividersCount); + expect(findDividers()).toHaveLength(1); }); }); describe('Renders correctly with basic search', () => { beforeEach(() => { - createComponent({ initialState: { searchType: SEARCH_TYPE_BASIC } }); + createComponent({ searchType: SEARCH_TYPE_BASIC }); }); it('renders StatusFilter', () => { @@ -91,11 +72,8 @@ describe('GlobalSearch MergeRequestsFilters', () => { describe('Renders correctly in new nav', () => { beforeEach(() => { createComponent({ - initialState: { - searchType: SEARCH_TYPE_ADVANCED, - useSidebarNavigation: true, - }, - searchMergeRequestsHideArchivedProjects: true, + searchType: SEARCH_TYPE_ADVANCED, + useSidebarNavigation: true, }); }); it('renders StatusFilter', () => { diff --git a/spec/lib/bulk_imports/clients/graphql_spec.rb b/spec/lib/bulk_imports/clients/graphql_spec.rb index 9bb37a7c438..16f98ed462e 100644 --- a/spec/lib/bulk_imports/clients/graphql_spec.rb +++ b/spec/lib/bulk_imports/clients/graphql_spec.rb @@ -8,13 +8,13 @@ RSpec.describe BulkImports::Clients::Graphql, feature_category: :importers do subject { described_class.new(url: config.url, token: config.access_token) } describe '#execute' do - let(:graphql_client_double) { double } let(:response_double) { double } describe 'network errors' do before do allow(Gitlab::HTTP) .to receive(:post) + .with(an_instance_of(String), a_hash_including(timeout: 60)) .and_return(response_double) end diff --git a/spec/lib/gitlab/usage/metric_definition_spec.rb b/spec/lib/gitlab/usage/metric_definition_spec.rb index d57159b8a57..871891d864a 100644 --- a/spec/lib/gitlab/usage/metric_definition_spec.rb +++ b/spec/lib/gitlab/usage/metric_definition_spec.rb @@ -194,6 +194,134 @@ RSpec.describe Gitlab::Usage::MetricDefinition, feature_category: :service_ping described_class.new(path, attributes).validate! end end + + context 'when metric has removed status' do + before do + attributes[:status] = 'removed' + end + + it 'raise dev exception when removed_by_url is not provided' do + attributes.delete(:removed_by_url) + + expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).at_least(:once).with(instance_of(Gitlab::Usage::MetricDefinition::InvalidError)) + + described_class.new(path, attributes).validate! + end + + it 'raises dev exception when milestone_removed is not provided' do + attributes.delete(:milestone_removed) + + expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).at_least(:once).with(instance_of(Gitlab::Usage::MetricDefinition::InvalidError)) + + described_class.new(path, attributes).validate! + end + end + + context 'internal metric' do + before do + attributes[:data_source] = 'internal_events' + end + + where(:instrumentation_class, :options, :events, :is_valid) do + 'TotalCountMetric' | {} | [] | true + 'AnotherClass' | { events: ['a'] } | [{ name: 'a', unique: 'user.id' }] | false + nil | { events: ['a'] } | [{ name: 'a', unique: 'user.id' }] | false + 'RedisHLLMetric' | { events: ['a'] } | [{ name: 'a', unique: 'user.id' }] | true + 'RedisHLLMetric' | { events: ['a'] } | nil | false + 'RedisHLLMetric' | nil | [{ name: 'a', unique: 'user.id' }] | false + 'RedisHLLMetric' | { events: ['a'] } | [{ name: 'a', unique: 'a' }] | false + 'RedisHLLMetric' | { events: 'a' } | [{ name: 'a', unique: 'user.id' }] | false + 'RedisHLLMetric' | { events: [2] } | [{ name: 'a', unique: 'user.id' }] | false + 'RedisHLLMetric' | { events: ['a'], a: 'b' } | [{ name: 'a', unique: 'user.id' }] | false + 'RedisHLLMetric' | { events: ['a'] } | [{ name: 'a', unique: 'user.id', b: 'c' }] | false + 'RedisHLLMetric' | { events: ['a'] } | [{ name: 'a' }] | false + 'RedisHLLMetric' | { events: ['a'] } | [{ unique: 'user.id' }] | false + end + + with_them do + it 'raises dev exception when invalid' do + attributes[:instrumentation_class] = instrumentation_class if instrumentation_class + attributes[:options] = options if options + attributes[:events] = events if events + + if is_valid + expect(Gitlab::ErrorTracking).not_to receive(:track_and_raise_for_dev_exception) + else + expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).at_least(:once).with(instance_of(Gitlab::Usage::MetricDefinition::InvalidError)) + end + + described_class.new(path, attributes).validate! + end + end + end + + context 'Redis metric' do + before do + attributes[:data_source] = 'redis' + end + + where(:instrumentation_class, :options, :is_valid) do + 'AnotherClass' | { event: 'a', widget: 'b' } | false + 'MergeRequestWidgetExtensionMetric' | { event: 'a', widget: 'b' } | true + 'MergeRequestWidgetExtensionMetric' | { event: 'a', widget: 2 } | false + 'MergeRequestWidgetExtensionMetric' | { event: 'a', widget: 'b', c: 'd' } | false + 'MergeRequestWidgetExtensionMetric' | { event: 'a' } | false + 'MergeRequestWidgetExtensionMetric' | { widget: 'b' } | false + 'RedisMetric' | { event: 'a', prefix: 'b', include_usage_prefix: true } | true + 'RedisMetric' | { event: 'a', prefix: nil, include_usage_prefix: true } | true + 'RedisMetric' | { event: 'a', prefix: 'b', include_usage_prefix: 2 } | false + 'RedisMetric' | { event: 'a', prefix: 'b', include_usage_prefix: true, c: 'd' } | false + 'RedisMetric' | { prefix: 'b', include_usage_prefix: true } | false + 'RedisMetric' | { event: 'a', include_usage_prefix: true } | false + 'RedisMetric' | { event: 'a', prefix: 'b' } | true + end + + with_them do + it 'validates properly' do + attributes[:instrumentation_class] = instrumentation_class + attributes[:options] = options + + if is_valid + expect(Gitlab::ErrorTracking).not_to receive(:track_and_raise_for_dev_exception) + else + expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).at_least(:once).with(instance_of(Gitlab::Usage::MetricDefinition::InvalidError)) + end + + described_class.new(path, attributes).validate! + end + end + end + + context 'RedisHLL metric' do + before do + attributes[:data_source] = 'redis_hll' + end + + where(:instrumentation_class, :options, :is_valid) do + 'AnotherClass' | { events: ['a'] } | false + 'RedisHLLMetric' | { events: ['a'] } | true + 'RedisHLLMetric' | { events: ['a'], b: 'c' } | false + 'RedisHLLMetric' | { events: [2] } | false + 'RedisHLLMetric' | { events: 'a' } | false + 'RedisHLLMetric' | { event: ['a'] } | false + 'AggregatedMetric' | {} | true + end + + with_them do + it 'validates properly' do + attributes[:instrumentation_class] = instrumentation_class + attributes[:options] = options + + if is_valid + expect(Gitlab::ErrorTracking).not_to receive(:track_and_raise_for_dev_exception) + else + expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).at_least(:once).with(instance_of(Gitlab::Usage::MetricDefinition::InvalidError)) + end + + described_class.new(path, attributes).validate! + end + end + end end end @@ -213,10 +341,10 @@ RSpec.describe Gitlab::Usage::MetricDefinition, feature_category: :service_ping end context 'when metric is using new format' do - let(:attributes) { { events: [{ name: 'my_event', unique: 'user_id' }] } } + let(:attributes) { { events: [{ name: 'my_event', unique: 'user.id' }] } } it 'returns a correct hash' do - expect(definition.events).to eq({ 'my_event' => :user_id }) + expect(definition.events).to eq({ 'my_event' => :'user.id' }) end end diff --git a/spec/support/shared_examples/features/nav_sidebar_shared_examples.rb b/spec/support/shared_examples/features/nav_sidebar_shared_examples.rb index 34821fb9eda..8c668ae9a87 100644 --- a/spec/support/shared_examples/features/nav_sidebar_shared_examples.rb +++ b/spec/support/shared_examples/features/nav_sidebar_shared_examples.rb @@ -2,15 +2,16 @@ RSpec.shared_examples 'page has active tab' do |title| it "activates #{title} tab" do - expect(page).to have_selector('.sidebar-top-level-items > li.active', count: 1) - expect(find('.sidebar-top-level-items > li.active')).to have_content(title) + within_testid('super-sidebar') do + expect(page).to have_selector('button[aria-expanded="true"]', text: title) + end end end RSpec.shared_examples 'page has active sub tab' do |title| it "activates #{title} sub tab" do - expect(page).to have_selector('.sidebar-sub-level-items > li.active:not(.fly-out-top-item)', count: 1) - expect(find('.sidebar-sub-level-items > li.active:not(.fly-out-top-item)')) - .to have_content(title) + within_testid('super-sidebar') do + expect(page).to have_selector('a[aria-current="page"]', text: title) + end end end diff --git a/yarn.lock b/yarn.lock index ccdf9749b90..673a80a7597 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1274,10 +1274,10 @@ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.69.0.tgz#bf76b8ffbe72a783807761a38abe8aaedcfe8c12" integrity sha512-Zu8Fcjhi3Bk26jZOptcD5F4SHWC7/KuAe00NULViCeswKdoda1k19B+9oCSbsbxY7vMoFuD20kiCJdBCpxb3HA== -"@gitlab/ui@66.37.0": - version "66.37.0" - resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-66.37.0.tgz#0b785b5f4380b37fb4021246a102c7eca2e0bab5" - integrity sha512-yTyV9Ht5YPtofRHLfOtab08kNFG0Z+VK5/ZtVur/HmgZSMAZv20FfPAo3VqYaieVRYAkTgtLlxpXRO9S2pMpHg== +"@gitlab/ui@67.3.0": + version "67.3.0" + resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-67.3.0.tgz#e106c742591595c78282244dcf0632157c81e75f" + integrity sha512-PSb/gpxRMRpZ99glO9u8hqWKA5vn+fKImS+0s1R3OuQOKIY36t4pYVtlZ/HD6eSQQzc92gx3GSpdfDdjPPmI7w== dependencies: "@floating-ui/dom" "1.2.9" bootstrap-vue "2.23.1" |