diff options
97 files changed, 926 insertions, 573 deletions
diff --git a/.rubocop_todo/layout/line_continuation_leading_space.yml b/.rubocop_todo/layout/line_continuation_leading_space.yml index 3c39768b481..c1384bf3663 100644 --- a/.rubocop_todo/layout/line_continuation_leading_space.yml +++ b/.rubocop_todo/layout/line_continuation_leading_space.yml @@ -60,8 +60,6 @@ Layout/LineContinuationLeadingSpace: - 'spec/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_total_metric_spec.rb' - 'spec/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_direct_installations_count_metric_spec.rb' - 'spec/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_proxy_installations_count_metric_spec.rb' - - 'spec/lib/gitlab/usage/metrics/instrumentations/in_product_marketing_email_cta_clicked_metric_spec.rb' - - 'spec/lib/gitlab/usage/metrics/instrumentations/in_product_marketing_email_sent_metric_spec.rb' - 'spec/lib/system_check/incoming_email/imap_authentication_check_spec.rb' - 'spec/models/integrations/chat_message/pipeline_message_spec.rb' - 'spec/services/feature_flags/update_service_spec.rb' diff --git a/.rubocop_todo/layout/line_continuation_spacing.yml b/.rubocop_todo/layout/line_continuation_spacing.yml index 355ef3f3ff8..721d7c56942 100644 --- a/.rubocop_todo/layout/line_continuation_spacing.yml +++ b/.rubocop_todo/layout/line_continuation_spacing.yml @@ -165,8 +165,6 @@ Layout/LineContinuationSpacing: - 'spec/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_total_metric_spec.rb' - 'spec/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_direct_installations_count_metric_spec.rb' - 'spec/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_proxy_installations_count_metric_spec.rb' - - 'spec/lib/gitlab/usage/metrics/instrumentations/in_product_marketing_email_cta_clicked_metric_spec.rb' - - 'spec/lib/gitlab/usage/metrics/instrumentations/in_product_marketing_email_sent_metric_spec.rb' - 'spec/lib/gitlab/utils/gzip_spec.rb' - 'spec/lib/system_check/incoming_email/imap_authentication_check_spec.rb' - 'spec/mailers/emails/identity_verification_spec.rb' diff --git a/.rubocop_todo/layout/line_end_string_concatenation_indentation.yml b/.rubocop_todo/layout/line_end_string_concatenation_indentation.yml index 0253613849e..8aacd956734 100644 --- a/.rubocop_todo/layout/line_end_string_concatenation_indentation.yml +++ b/.rubocop_todo/layout/line_end_string_concatenation_indentation.yml @@ -280,8 +280,6 @@ Layout/LineEndStringConcatenationIndentation: - 'spec/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_total_metric_spec.rb' - 'spec/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_direct_installations_count_metric_spec.rb' - 'spec/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_proxy_installations_count_metric_spec.rb' - - 'spec/lib/gitlab/usage/metrics/instrumentations/in_product_marketing_email_cta_clicked_metric_spec.rb' - - 'spec/lib/gitlab/usage/metrics/instrumentations/in_product_marketing_email_sent_metric_spec.rb' - 'spec/lib/gitlab/utils/gzip_spec.rb' - 'spec/mailers/emails/identity_verification_spec.rb' - 'spec/mailers/emails/projects_spec.rb' diff --git a/.rubocop_todo/layout/line_length.yml b/.rubocop_todo/layout/line_length.yml index 9fd3d47d8f0..b8e90f38ce5 100644 --- a/.rubocop_todo/layout/line_length.yml +++ b/.rubocop_todo/layout/line_length.yml @@ -4299,7 +4299,6 @@ Layout/LineLength: - 'spec/models/uploads/fog_spec.rb' - 'spec/models/user_detail_spec.rb' - 'spec/models/user_spec.rb' - - 'spec/models/users/in_product_marketing_email_spec.rb' - 'spec/models/wiki_page_spec.rb' - 'spec/models/x509_certificate_spec.rb' - 'spec/policies/ci/build_policy_spec.rb' diff --git a/.rubocop_todo/layout/space_in_lambda_literal.yml b/.rubocop_todo/layout/space_in_lambda_literal.yml index 54ed188fd26..0d2b0c9a722 100644 --- a/.rubocop_todo/layout/space_in_lambda_literal.yml +++ b/.rubocop_todo/layout/space_in_lambda_literal.yml @@ -101,7 +101,6 @@ Layout/SpaceInLambdaLiteral: - 'app/models/user.rb' - 'app/models/user_highest_role.rb' - 'app/models/users/callout.rb' - - 'app/models/users/in_product_marketing_email.rb' - 'app/models/users/phone_number_validation.rb' - 'app/models/users_star_project.rb' - 'app/models/zoom_meeting.rb' diff --git a/.rubocop_todo/rspec/context_wording.yml b/.rubocop_todo/rspec/context_wording.yml index fc7a105179e..840efa82a2b 100644 --- a/.rubocop_todo/rspec/context_wording.yml +++ b/.rubocop_todo/rspec/context_wording.yml @@ -2268,7 +2268,6 @@ RSpec/ContextWording: - 'spec/models/uploads/local_spec.rb' - 'spec/models/user_preference_spec.rb' - 'spec/models/user_spec.rb' - - 'spec/models/users/in_product_marketing_email_spec.rb' - 'spec/models/wiki_page/meta_spec.rb' - 'spec/models/wiki_page/slug_spec.rb' - 'spec/models/wiki_page_spec.rb' diff --git a/.rubocop_todo/rspec/instance_variable.yml b/.rubocop_todo/rspec/instance_variable.yml index a5a0cec68d4..5196c190bf8 100644 --- a/.rubocop_todo/rspec/instance_variable.yml +++ b/.rubocop_todo/rspec/instance_variable.yml @@ -129,7 +129,6 @@ RSpec/InstanceVariable: - 'spec/models/postgresql/replication_slot_spec.rb' - 'spec/models/project_spec.rb' - 'spec/models/user_spec.rb' - - 'spec/models/users/in_product_marketing_email_spec.rb' - 'spec/rack_servers/puma_spec.rb' - 'spec/requests/api/admin/plan_limits_spec.rb' - 'spec/requests/api/users_spec.rb' diff --git a/app/assets/javascripts/super_sidebar/components/super_sidebar_toggle.vue b/app/assets/javascripts/super_sidebar/components/super_sidebar_toggle.vue index 30ee18cc369..049a61e17c7 100644 --- a/app/assets/javascripts/super_sidebar/components/super_sidebar_toggle.vue +++ b/app/assets/javascripts/super_sidebar/components/super_sidebar_toggle.vue @@ -14,59 +14,75 @@ export default { }, mixins: [Tracking.mixin()], props: { - tooltipContainer: { + type: { type: String, required: false, - default: null, - }, - tooltipPlacement: { - type: String, - required: false, - default: 'right', + default: 'expand', }, }, i18n: { - collapseSidebar: __('Hide sidebar'), - expandSidebar: __('Keep sidebar visible'), primaryNavigationSidebar: __('Primary navigation sidebar'), }, + tooltipCollapse: { + placement: 'bottom', + container: 'super-sidebar', + title: __('Hide sidebar'), + }, + tooltipExpand: { + placement: 'right', + title: __('Keep sidebar visible'), + }, data() { return sidebarState; }, computed: { - canOpen() { - return this.isCollapsed || this.isPeek || this.isHoverPeek; + isTypeCollapse() { + return this.type === 'collapse'; }, - tooltipTitle() { - return this.canOpen ? this.$options.i18n.expandSidebar : this.$options.i18n.collapseSidebar; + isTypeExpand() { + return this.type === 'expand'; }, tooltip() { - return { - placement: this.tooltipPlacement, - container: this.tooltipContainer, - title: this.tooltipTitle, - }; + return this.isTypeExpand ? this.$options.tooltipExpand : this.$options.tooltipCollapse; }, ariaExpanded() { - return String(!this.canOpen); + return String(this.isTypeCollapse); }, }, + mounted() { + this.$root.$on('bv::tooltip::show', this.onTooltipShow); + }, + beforeUnmount() { + this.$root.$off('bv::tooltip::show', this.onTooltipShow); + }, methods: { toggle() { - this.track(this.canOpen ? 'nav_show' : 'nav_hide', { + this.track(this.isTypeExpand ? 'nav_show' : 'nav_hide', { label: 'nav_toggle', property: 'nav_sidebar', }); - toggleSuperSidebarCollapsed(!this.canOpen, true); + toggleSuperSidebarCollapsed(!this.isTypeExpand, true); this.focusOtherToggle(); }, focusOtherToggle() { this.$nextTick(() => { - const classSelector = this.canOpen ? JS_TOGGLE_EXPAND_CLASS : JS_TOGGLE_COLLAPSE_CLASS; + const classSelector = this.isTypeExpand ? JS_TOGGLE_COLLAPSE_CLASS : JS_TOGGLE_EXPAND_CLASS; const otherToggle = document.querySelector(`.${classSelector}`); otherToggle?.focus(); }); }, + onTooltipShow(bvEvent) { + if ( + bvEvent.target !== this.$el || + (this.isTypeCollapse && !this.isCollapsed) || + (this.isTypeExpand && this.isCollapsed) || + this.isPeek || + this.isHoverPeek + ) + return; + + bvEvent.preventDefault(); + }, }, }; </script> diff --git a/app/assets/javascripts/super_sidebar/components/user_bar.vue b/app/assets/javascripts/super_sidebar/components/user_bar.vue index 49aee4f3470..ea634d43a96 100644 --- a/app/assets/javascripts/super_sidebar/components/user_bar.vue +++ b/app/assets/javascripts/super_sidebar/components/user_bar.vue @@ -126,9 +126,8 @@ export default { <super-sidebar-toggle v-if="hasCollapseButton" :class="$options.JS_TOGGLE_COLLAPSE_CLASS" - tooltip-placement="bottom" - tooltip-container="super-sidebar" data-testid="super-sidebar-collapse-button" + type="collapse" /> <create-menu v-if="sidebarData.is_logged_in && sidebarData.create_new_menu_groups.length > 0" diff --git a/app/controllers/import/bulk_imports_controller.rb b/app/controllers/import/bulk_imports_controller.rb index d7d7ad84bc8..a8ec738caf4 100644 --- a/app/controllers/import/bulk_imports_controller.rb +++ b/app/controllers/import/bulk_imports_controller.rb @@ -152,7 +152,7 @@ class Import::BulkImportsController < ApplicationController allow_local_network: allow_local_requests?, schemes: %w[http https] ) - rescue Gitlab::UrlBlocker::BlockedUrlError => e + rescue Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError => e clear_session_data redirect_to new_group_path(anchor: 'import-group-pane'), alert: _('Specified URL cannot be used: "%{reason}"') % { reason: e.message } diff --git a/app/controllers/import/fogbugz_controller.rb b/app/controllers/import/fogbugz_controller.rb index 9ee8e59053f..34fdf513313 100644 --- a/app/controllers/import/fogbugz_controller.rb +++ b/app/controllers/import/fogbugz_controller.rb @@ -128,7 +128,7 @@ class Import::FogbugzController < Import::BaseController allow_local_network: allow_local_requests?, schemes: %w[http https] ) - rescue Gitlab::UrlBlocker::BlockedUrlError => e + rescue Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError => e redirect_to new_import_fogbugz_url, alert: _('Specified URL cannot be used: "%{reason}"') % { reason: e.message } end diff --git a/app/controllers/import/gitea_controller.rb b/app/controllers/import/gitea_controller.rb index 2778b97419a..a7497710dc0 100644 --- a/app/controllers/import/gitea_controller.rb +++ b/app/controllers/import/gitea_controller.rb @@ -99,7 +99,7 @@ class Import::GiteaController < Import::GithubController allow_local_network: allow_local_requests?, schemes: %w[http https] ) - rescue Gitlab::UrlBlocker::BlockedUrlError => e + rescue Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError => e session[access_token_key] = nil redirect_to new_import_url, alert: _('Specified URL cannot be used: "%{reason}"') % { reason: e.message } diff --git a/app/graphql/types/ci/detailed_status_type.rb b/app/graphql/types/ci/detailed_status_type.rb index e18770c2708..6882a495259 100644 --- a/app/graphql/types/ci/detailed_status_type.rb +++ b/app/graphql/types/ci/detailed_status_type.rb @@ -16,20 +16,34 @@ module Types field :favicon, GraphQL::Types::String, null: true, description: 'Favicon of the status.' field :group, GraphQL::Types::String, null: true, - description: 'Group of the status.' + description: 'Group of the status.', + deprecated: { + reason: 'The `group` attribute is deprecated. Use `name` instead', + milestone: '16.4' + } field :has_details, GraphQL::Types::Boolean, null: true, description: 'Indicates if the status has further details.', method: :has_details? field :icon, GraphQL::Types::String, null: true, - description: 'Icon of the status.' + description: 'Icon of the status.', + deprecated: { + reason: 'The `icon` attribute is deprecated. Use `name` to ' \ + 'identify the status to display instead', + milestone: '16.4' + } field :id, GraphQL::Types::String, null: false, description: 'ID for a detailed status.', extras: [:parent] field :label, GraphQL::Types::String, null: true, - calls_gitaly: true, - description: 'Label of the status.' + description: 'Human-readable label of the status (e.g. success).' + field :name, GraphQL::Types::String, null: true, + description: 'Machine-readable status name (e.g. SUCCESS).' field :text, GraphQL::Types::String, null: true, - description: 'Text of the status.' + description: 'Text of the status.', + deprecated: { + reason: 'The `text` attribute is being deprecated. Use `label` instead', + milestone: '16.4' + } field :tooltip, GraphQL::Types::String, null: true, description: 'Tooltip associated with the status.', method: :status_tooltip diff --git a/app/models/abuse_report.rb b/app/models/abuse_report.rb index bf25c539830..adaa057098f 100644 --- a/app/models/abuse_report.rb +++ b/app/models/abuse_report.rb @@ -200,7 +200,7 @@ class AbuseReport < ApplicationRecord format(_('contains URLs that exceed the %{limit} character limit'), limit: MAX_CHAR_LIMIT_URL) ) end - rescue ::Gitlab::UrlBlocker::BlockedUrlError + rescue ::Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError errors.add(:links_to_spam, _('only supports valid HTTP(S) URLs')) end diff --git a/app/models/application_record.rb b/app/models/application_record.rb index 7058bfd5650..15e44296635 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -6,7 +6,7 @@ class ApplicationRecord < ActiveRecord::Base include LegacyBulkInsert include CrossDatabaseModification include SensitiveSerializableHash - include ResetOnUnionError + include ResetOnColumnErrors self.abstract_class = true diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 153257636ba..8ddb2ead37e 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -970,7 +970,7 @@ class ApplicationSetting < MainClusterwide::ApplicationRecord def parsed_kroki_url @parsed_kroki_url ||= Gitlab::UrlBlocker.validate!(kroki_url, schemes: %w[http https], enforce_sanitization: true)[0] - rescue Gitlab::UrlBlocker::BlockedUrlError => e + rescue Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError => e self.errors.add( :kroki_url, "is not valid. #{e}" diff --git a/app/models/clusters/concerns/prometheus_client.rb b/app/models/clusters/concerns/prometheus_client.rb index d2f69b813aa..b4234e9cc0a 100644 --- a/app/models/clusters/concerns/prometheus_client.rb +++ b/app/models/clusters/concerns/prometheus_client.rb @@ -35,7 +35,7 @@ module Clusters def configured? kube_client.present? && available? - rescue Gitlab::UrlBlocker::BlockedUrlError + rescue Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError false end diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb index 5efbec45561..6ae0cd8e3fd 100644 --- a/app/models/clusters/platforms/kubernetes.rb +++ b/app/models/clusters/platforms/kubernetes.rb @@ -12,7 +12,7 @@ module Clusters REQUIRED_K8S_MIN_VERSION = 23 IGNORED_CONNECTION_EXCEPTIONS = [ - Gitlab::UrlBlocker::BlockedUrlError, + Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError, Kubeclient::HttpError, Errno::ECONNREFUSED, URI::InvalidURIError, diff --git a/app/models/concerns/reset_on_column_errors.rb b/app/models/concerns/reset_on_column_errors.rb new file mode 100644 index 00000000000..8786b5d4f4b --- /dev/null +++ b/app/models/concerns/reset_on_column_errors.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +module ResetOnColumnErrors + extend ActiveSupport::Concern + + MAX_RESET_PERIOD = 10.minutes + + included do |base| + base.rescue_from ActiveRecord::StatementInvalid, with: :reset_on_union_error + base.rescue_from ActiveModel::UnknownAttributeError, with: :reset_on_unknown_attribute_error + + base.class_attribute :previous_reset_columns_from_error + end + + class_methods do + def do_reset(exception) + class_to_be_reset = base_class + + class_to_be_reset.reset_column_information + Gitlab::ErrorTracking.log_exception(exception, { reset_model_name: class_to_be_reset.name }) + + class_to_be_reset.previous_reset_columns_from_error = Time.current + end + + def reset_on_union_error(exception) + if exception.message.include?("each UNION query must have the same number of columns") && should_reset? + do_reset(exception) + end + + raise + end + + def should_reset? + return false if base_class.previous_reset_columns_from_error? && + base_class.previous_reset_columns_from_error > MAX_RESET_PERIOD.ago + + Feature.enabled?(:reset_column_information_on_statement_invalid, type: :ops) + end + end + + def reset_on_unknown_attribute_error(exception) + self.class.do_reset(exception) if self.class.should_reset? + + raise + end +end diff --git a/app/models/concerns/reset_on_union_error.rb b/app/models/concerns/reset_on_union_error.rb deleted file mode 100644 index 42e350b0bed..00000000000 --- a/app/models/concerns/reset_on_union_error.rb +++ /dev/null @@ -1,37 +0,0 @@ -# frozen_string_literal: true - -module ResetOnUnionError - extend ActiveSupport::Concern - - MAX_RESET_PERIOD = 10.minutes - - included do |base| - base.rescue_from ActiveRecord::StatementInvalid, with: :reset_on_union_error - - base.class_attribute :previous_reset_columns_from_error - end - - class_methods do - def reset_on_union_error(exception) - if reset_on_statement_invalid?(exception) - class_to_be_reset = base_class - - class_to_be_reset.reset_column_information - Gitlab::ErrorTracking.log_exception(exception, { reset_model_name: class_to_be_reset.name }) - - class_to_be_reset.previous_reset_columns_from_error = Time.current - end - - raise - end - - def reset_on_statement_invalid?(exception) - return false unless exception.message.include?("each UNION query must have the same number of columns") - - return false if base_class.previous_reset_columns_from_error? && - base_class.previous_reset_columns_from_error > MAX_RESET_PERIOD.ago - - Feature.enabled?(:reset_column_information_on_statement_invalid, type: :ops) - end - end -end diff --git a/app/models/service_desk/custom_email_credential.rb b/app/models/service_desk/custom_email_credential.rb index 8ccdd6f2261..5986ac8a43f 100644 --- a/app/models/service_desk/custom_email_credential.rb +++ b/app/models/service_desk/custom_email_credential.rb @@ -59,7 +59,7 @@ module ServiceDesk allow_localhost: false, allow_local_network: false ) - rescue Gitlab::UrlBlocker::BlockedUrlError => e + rescue Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError => e errors.add(:smtp_address, e) end end diff --git a/app/models/ssh_host_key.rb b/app/models/ssh_host_key.rb index daa64f4e087..672a6d64127 100644 --- a/app/models/ssh_host_key.rb +++ b/app/models/ssh_host_key.rb @@ -157,7 +157,7 @@ class SshHostKey url.port = url.inferred_port [url, ip] - rescue Gitlab::UrlBlocker::BlockedUrlError + rescue Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError raise ArgumentError, "Invalid URL" end diff --git a/app/models/users/in_product_marketing_email.rb b/app/models/users/in_product_marketing_email.rb index f220cfd17c5..a62dfaf02c3 100644 --- a/app/models/users/in_product_marketing_email.rb +++ b/app/models/users/in_product_marketing_email.rb @@ -44,16 +44,16 @@ module Users INACTIVE_TRACK_NAMES = %w[invite_team experience].freeze ACTIVE_TRACKS = tracks.except(*INACTIVE_TRACK_NAMES) - scope :for_user_with_track_and_series, -> (user, track, series) do + scope :for_user_with_track_and_series, ->(user, track, series) do where(user: user, track: track, series: series) end - scope :without_track_and_series, -> (track, series) do + scope :without_track_and_series, ->(track, series) do join_condition = for_user.and(for_track_and_series(track, series)) users_without_records(join_condition) end - scope :without_campaign, -> (campaign) do + scope :without_campaign, ->(campaign) do join_condition = for_user.and(for_campaign(campaign)) users_without_records(join_condition) end diff --git a/app/services/clusters/cleanup/project_namespace_service.rb b/app/services/clusters/cleanup/project_namespace_service.rb index f6ac06d0594..3d5a4f85d10 100644 --- a/app/services/clusters/cleanup/project_namespace_service.rb +++ b/app/services/clusters/cleanup/project_namespace_service.rb @@ -40,7 +40,7 @@ module Clusters cluster.kubeclient&.delete_namespace(kubernetes_namespace.namespace) rescue Kubeclient::ResourceNotFoundError # The resources have already been deleted, possibly on a previous attempt that timed out - rescue Gitlab::UrlBlocker::BlockedUrlError + rescue Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError # User gave an invalid cluster from the start, or deleted the endpoint before this job ran end end diff --git a/app/services/clusters/cleanup/service_account_service.rb b/app/services/clusters/cleanup/service_account_service.rb index 0ce4bf9bb9c..0358a5412b3 100644 --- a/app/services/clusters/cleanup/service_account_service.rb +++ b/app/services/clusters/cleanup/service_account_service.rb @@ -22,7 +22,7 @@ module Clusters ) rescue Kubeclient::ResourceNotFoundError # The resources have already been deleted, possibly on a previous attempt that timed out - rescue Gitlab::UrlBlocker::BlockedUrlError + rescue Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError # User gave an invalid cluster from the start, or deleted the endpoint before this job ran rescue Kubeclient::HttpError => e # unauthorized, forbidden: GitLab's access has been revoked diff --git a/app/services/projects/import_service.rb b/app/services/projects/import_service.rb index e22b728cea3..fde56d8429e 100644 --- a/app/services/projects/import_service.rb +++ b/app/services/projects/import_service.rb @@ -29,7 +29,7 @@ module Projects after_execute_hook success - rescue Gitlab::UrlBlocker::BlockedUrlError, StandardError => e + rescue Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError, StandardError => e Gitlab::Import::ImportFailureService.track( project_id: project.id, error_source: self.class.name, @@ -76,7 +76,7 @@ module Projects if project.external_import? && !unknown_url? begin @resolved_address = get_resolved_address - rescue Gitlab::UrlBlocker::BlockedUrlError => e + rescue Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError => e raise e, s_("ImportProjects|Blocked import URL: %{message}") % { message: e.message } end end diff --git a/app/validators/addressable_url_validator.rb b/app/validators/addressable_url_validator.rb index 6dcc089fa73..af7be326f51 100644 --- a/app/validators/addressable_url_validator.rb +++ b/app/validators/addressable_url_validator.rb @@ -84,7 +84,7 @@ class AddressableUrlValidator < ActiveModel::EachValidator value = strip_value!(record, attribute, value) Gitlab::UrlBlocker.validate!(value, **blocker_args) - rescue Gitlab::UrlBlocker::BlockedUrlError => e + rescue Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError => e record.errors.add(attribute, options.fetch(:blocked_message) % { exception_message: e.message }) end diff --git a/app/views/layouts/nav/_top_bar.html.haml b/app/views/layouts/nav/_top_bar.html.haml index 73b253e18bd..59bfd8dd0dd 100644 --- a/app/views/layouts/nav/_top_bar.html.haml +++ b/app/views/layouts/nav/_top_bar.html.haml @@ -8,7 +8,7 @@ %div{ class: top_bar_class, data: { testid: 'top-bar' } } .top-bar-container.gl-display-flex.gl-align-items-center.gl-gap-2{ :class => top_bar_container_class } - if show_super_sidebar? - = render Pajamas::ButtonComponent.new(icon: 'sidebar', category: :tertiary, button_options: { class: 'js-super-sidebar-toggle-expand super-sidebar-toggle gl-ml-n3', title: _('Expand sidebar'), aria: { controls: 'super-sidebar', expanded: 'false', label: _('Navigation sidebar') } }) + = render Pajamas::ButtonComponent.new(icon: 'sidebar', category: :tertiary, button_options: { class: 'js-super-sidebar-toggle-expand super-sidebar-toggle gl-ml-n3', aria: { controls: 'super-sidebar', expanded: 'false', label: _('Primary navigation sidebar') } }) - elsif defined?(@left_sidebar) = render Pajamas::ButtonComponent.new(icon: 'sidebar', category: :tertiary, button_options: { class: 'toggle-mobile-nav gl-ml-n3', data: { testid: 'toggle_mobile_nav_button' }, aria: { label: _('Open sidebar') } }) = render "layouts/nav/breadcrumbs/breadcrumbs" diff --git a/app/workers/integrations/irker_worker.rb b/app/workers/integrations/irker_worker.rb index 3152d68b372..4c1f0df0fc7 100644 --- a/app/workers/integrations/irker_worker.rb +++ b/app/workers/integrations/irker_worker.rb @@ -58,7 +58,7 @@ module Integrations allow_local_network: allow_local_requests?, schemes: ['irc']) @socket = TCPSocket.new ip_address, irker_port - rescue Errno::ECONNREFUSED, Gitlab::UrlBlocker::BlockedUrlError => e + rescue Errno::ECONNREFUSED, Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError => e logger.fatal "Can't connect to Irker daemon: #{e}" return false end diff --git a/config/initializers/rest-client-hostname_override.rb b/config/initializers/rest-client-hostname_override.rb index b647fe9cac8..41988fad282 100644 --- a/config/initializers/rest-client-hostname_override.rb +++ b/config/initializers/rest-client-hostname_override.rb @@ -13,7 +13,7 @@ module RestClient schemes: %w[http https]) self.hostname_override = hostname_override - rescue Gitlab::UrlBlocker::BlockedUrlError => e + rescue Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError => e raise ArgumentError, "URL is blocked: #{e.message}" end diff --git a/config/metrics/counts_all/20210510201537_in_product_marketing_email_create_0_sent.yml b/config/metrics/counts_all/20210510201537_in_product_marketing_email_create_0_sent.yml index d4d17a6a2b4..8e16f073757 100644 --- a/config/metrics/counts_all/20210510201537_in_product_marketing_email_create_0_sent.yml +++ b/config/metrics/counts_all/20210510201537_in_product_marketing_email_create_0_sent.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: create series: 0 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210510201919_in_product_marketing_email_create_0_cta_clicked.yml b/config/metrics/counts_all/20210510201919_in_product_marketing_email_create_0_cta_clicked.yml index 0b61624c409..68f0629928c 100644 --- a/config/metrics/counts_all/20210510201919_in_product_marketing_email_create_0_cta_clicked.yml +++ b/config/metrics/counts_all/20210510201919_in_product_marketing_email_create_0_cta_clicked.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: create series: 0 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210510202148_in_product_marketing_email_create_1_sent.yml b/config/metrics/counts_all/20210510202148_in_product_marketing_email_create_1_sent.yml index c7a38b6a57d..1be199da16b 100644 --- a/config/metrics/counts_all/20210510202148_in_product_marketing_email_create_1_sent.yml +++ b/config/metrics/counts_all/20210510202148_in_product_marketing_email_create_1_sent.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: create series: 1 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210510202356_in_product_marketing_email_create_1_cta_clicked.yml b/config/metrics/counts_all/20210510202356_in_product_marketing_email_create_1_cta_clicked.yml index 7408554e50f..b631a50eea7 100644 --- a/config/metrics/counts_all/20210510202356_in_product_marketing_email_create_1_cta_clicked.yml +++ b/config/metrics/counts_all/20210510202356_in_product_marketing_email_create_1_cta_clicked.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: create series: 1 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210510202604_in_product_marketing_email_create_2_sent.yml b/config/metrics/counts_all/20210510202604_in_product_marketing_email_create_2_sent.yml index 74a7b179acf..21b3f78552c 100644 --- a/config/metrics/counts_all/20210510202604_in_product_marketing_email_create_2_sent.yml +++ b/config/metrics/counts_all/20210510202604_in_product_marketing_email_create_2_sent.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: create series: 2 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210510202724_in_product_marketing_email_create_2_cta_clicked.yml b/config/metrics/counts_all/20210510202724_in_product_marketing_email_create_2_cta_clicked.yml index 221c16450fc..b0edc023a51 100644 --- a/config/metrics/counts_all/20210510202724_in_product_marketing_email_create_2_cta_clicked.yml +++ b/config/metrics/counts_all/20210510202724_in_product_marketing_email_create_2_cta_clicked.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: create series: 2 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210510202807_in_product_marketing_email_verify_0_sent.yml b/config/metrics/counts_all/20210510202807_in_product_marketing_email_verify_0_sent.yml index 2ca26cca60a..06d8c20596e 100644 --- a/config/metrics/counts_all/20210510202807_in_product_marketing_email_verify_0_sent.yml +++ b/config/metrics/counts_all/20210510202807_in_product_marketing_email_verify_0_sent.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: verify series: 0 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210510202943_in_product_marketing_email_verify_0_cta_clicked.yml b/config/metrics/counts_all/20210510202943_in_product_marketing_email_verify_0_cta_clicked.yml index 403e58a0bb9..0ec0ff54c07 100644 --- a/config/metrics/counts_all/20210510202943_in_product_marketing_email_verify_0_cta_clicked.yml +++ b/config/metrics/counts_all/20210510202943_in_product_marketing_email_verify_0_cta_clicked.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: verify series: 0 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210510202955_in_product_marketing_email_verify_1_sent.yml b/config/metrics/counts_all/20210510202955_in_product_marketing_email_verify_1_sent.yml index b1370f700a2..170f8ff6c8a 100644 --- a/config/metrics/counts_all/20210510202955_in_product_marketing_email_verify_1_sent.yml +++ b/config/metrics/counts_all/20210510202955_in_product_marketing_email_verify_1_sent.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: verify series: 1 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210510203005_in_product_marketing_email_verify_1_cta_clicked.yml b/config/metrics/counts_all/20210510203005_in_product_marketing_email_verify_1_cta_clicked.yml index eac2a9fd27f..0d53136ec67 100644 --- a/config/metrics/counts_all/20210510203005_in_product_marketing_email_verify_1_cta_clicked.yml +++ b/config/metrics/counts_all/20210510203005_in_product_marketing_email_verify_1_cta_clicked.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: verify series: 1 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210510203015_in_product_marketing_email_verify_2_sent.yml b/config/metrics/counts_all/20210510203015_in_product_marketing_email_verify_2_sent.yml index f8541ab06e7..57ae962b75b 100644 --- a/config/metrics/counts_all/20210510203015_in_product_marketing_email_verify_2_sent.yml +++ b/config/metrics/counts_all/20210510203015_in_product_marketing_email_verify_2_sent.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: verify series: 2 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210510203025_in_product_marketing_email_verify_2_cta_clicked.yml b/config/metrics/counts_all/20210510203025_in_product_marketing_email_verify_2_cta_clicked.yml index 9344152603f..43aa1ea6cff 100644 --- a/config/metrics/counts_all/20210510203025_in_product_marketing_email_verify_2_cta_clicked.yml +++ b/config/metrics/counts_all/20210510203025_in_product_marketing_email_verify_2_cta_clicked.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: verify series: 2 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210510203035_in_product_marketing_email_trial_0_sent.yml b/config/metrics/counts_all/20210510203035_in_product_marketing_email_trial_0_sent.yml index f2e5aa5d861..dd037658198 100644 --- a/config/metrics/counts_all/20210510203035_in_product_marketing_email_trial_0_sent.yml +++ b/config/metrics/counts_all/20210510203035_in_product_marketing_email_trial_0_sent.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: trial series: 0 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210510203044_in_product_marketing_email_trial_0_cta_clicked.yml b/config/metrics/counts_all/20210510203044_in_product_marketing_email_trial_0_cta_clicked.yml index 3330c77accf..d2df99c0cce 100644 --- a/config/metrics/counts_all/20210510203044_in_product_marketing_email_trial_0_cta_clicked.yml +++ b/config/metrics/counts_all/20210510203044_in_product_marketing_email_trial_0_cta_clicked.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: trial series: 0 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210510203054_in_product_marketing_email_trial_1_sent.yml b/config/metrics/counts_all/20210510203054_in_product_marketing_email_trial_1_sent.yml index 22ed95ec462..666065045f3 100644 --- a/config/metrics/counts_all/20210510203054_in_product_marketing_email_trial_1_sent.yml +++ b/config/metrics/counts_all/20210510203054_in_product_marketing_email_trial_1_sent.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: trial series: 1 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210510203104_in_product_marketing_email_trial_1_cta_clicked.yml b/config/metrics/counts_all/20210510203104_in_product_marketing_email_trial_1_cta_clicked.yml index d75875d60f6..fb2505fc30a 100644 --- a/config/metrics/counts_all/20210510203104_in_product_marketing_email_trial_1_cta_clicked.yml +++ b/config/metrics/counts_all/20210510203104_in_product_marketing_email_trial_1_cta_clicked.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: trial series: 1 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210510203114_in_product_marketing_email_trial_2_sent.yml b/config/metrics/counts_all/20210510203114_in_product_marketing_email_trial_2_sent.yml index 31d6c45b180..31f4e8154ef 100644 --- a/config/metrics/counts_all/20210510203114_in_product_marketing_email_trial_2_sent.yml +++ b/config/metrics/counts_all/20210510203114_in_product_marketing_email_trial_2_sent.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: trial series: 2 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210510203124_in_product_marketing_email_trial_2_cta_clicked.yml b/config/metrics/counts_all/20210510203124_in_product_marketing_email_trial_2_cta_clicked.yml index 09269c37e88..f69e61b9a85 100644 --- a/config/metrics/counts_all/20210510203124_in_product_marketing_email_trial_2_cta_clicked.yml +++ b/config/metrics/counts_all/20210510203124_in_product_marketing_email_trial_2_cta_clicked.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: trial series: 2 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210510203134_in_product_marketing_email_team_0_sent.yml b/config/metrics/counts_all/20210510203134_in_product_marketing_email_team_0_sent.yml index 165af6ee5a9..3ebd0e96074 100644 --- a/config/metrics/counts_all/20210510203134_in_product_marketing_email_team_0_sent.yml +++ b/config/metrics/counts_all/20210510203134_in_product_marketing_email_team_0_sent.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: team series: 0 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210510203143_in_product_marketing_email_team_0_cta_clicked.yml b/config/metrics/counts_all/20210510203143_in_product_marketing_email_team_0_cta_clicked.yml index f40cfd85c4f..a6533d7abc8 100644 --- a/config/metrics/counts_all/20210510203143_in_product_marketing_email_team_0_cta_clicked.yml +++ b/config/metrics/counts_all/20210510203143_in_product_marketing_email_team_0_cta_clicked.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: team series: 0 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210510203153_in_product_marketing_email_team_1_sent.yml b/config/metrics/counts_all/20210510203153_in_product_marketing_email_team_1_sent.yml index 47ab4dcd046..0750bfae82d 100644 --- a/config/metrics/counts_all/20210510203153_in_product_marketing_email_team_1_sent.yml +++ b/config/metrics/counts_all/20210510203153_in_product_marketing_email_team_1_sent.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: team series: 1 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210510203203_in_product_marketing_email_team_1_cta_clicked.yml b/config/metrics/counts_all/20210510203203_in_product_marketing_email_team_1_cta_clicked.yml index 03c15303678..3a74dd6870a 100644 --- a/config/metrics/counts_all/20210510203203_in_product_marketing_email_team_1_cta_clicked.yml +++ b/config/metrics/counts_all/20210510203203_in_product_marketing_email_team_1_cta_clicked.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: team series: 1 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210510203213_in_product_marketing_email_team_2_sent.yml b/config/metrics/counts_all/20210510203213_in_product_marketing_email_team_2_sent.yml index d0a6eeb8fb8..351c4649003 100644 --- a/config/metrics/counts_all/20210510203213_in_product_marketing_email_team_2_sent.yml +++ b/config/metrics/counts_all/20210510203213_in_product_marketing_email_team_2_sent.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: team series: 2 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210510203223_in_product_marketing_email_team_2_cta_clicked.yml b/config/metrics/counts_all/20210510203223_in_product_marketing_email_team_2_cta_clicked.yml index 8bee7df8fbf..a8cf20317f7 100644 --- a/config/metrics/counts_all/20210510203223_in_product_marketing_email_team_2_cta_clicked.yml +++ b/config/metrics/counts_all/20210510203223_in_product_marketing_email_team_2_cta_clicked.yml @@ -6,8 +6,10 @@ product_section: 'TBD' product_stage: growth product_group: activation value_type: number -status: active -milestone: "13.12" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: track: team series: 2 distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210727095918_in_product_marketing_email_team_short_0_cta_clicked.yml b/config/metrics/counts_all/20210727095918_in_product_marketing_email_team_short_0_cta_clicked.yml index 42eee999b46..70f486412f2 100644 --- a/config/metrics/counts_all/20210727095918_in_product_marketing_email_team_short_0_cta_clicked.yml +++ b/config/metrics/counts_all/20210727095918_in_product_marketing_email_team_short_0_cta_clicked.yml @@ -5,8 +5,10 @@ product_section: growth product_stage: growth product_group: activation value_type: number -status: active -milestone: "14.2" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '14.2' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66854 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: series: 0 data_category: optional distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210727095923_in_product_marketing_email_team_short_0_sent.yml b/config/metrics/counts_all/20210727095923_in_product_marketing_email_team_short_0_sent.yml index 5b4ce9572d4..62d4196d39a 100644 --- a/config/metrics/counts_all/20210727095923_in_product_marketing_email_team_short_0_sent.yml +++ b/config/metrics/counts_all/20210727095923_in_product_marketing_email_team_short_0_sent.yml @@ -5,8 +5,10 @@ product_section: growth product_stage: growth product_group: activation value_type: number -status: active -milestone: "14.2" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '14.2' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66854 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: series: 0 data_category: optional distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210727170553_in_product_marketing_email_trial_short_0_cta_clicked.yml b/config/metrics/counts_all/20210727170553_in_product_marketing_email_trial_short_0_cta_clicked.yml index 5949772adb7..260c2b9bb33 100644 --- a/config/metrics/counts_all/20210727170553_in_product_marketing_email_trial_short_0_cta_clicked.yml +++ b/config/metrics/counts_all/20210727170553_in_product_marketing_email_trial_short_0_cta_clicked.yml @@ -5,8 +5,10 @@ product_section: growth product_stage: growth product_group: activation value_type: number -status: active -milestone: "14.2" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '14.2' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66943 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: series: 0 data_category: optional distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210727170558_in_product_marketing_email_trial_short_0_sent.yml b/config/metrics/counts_all/20210727170558_in_product_marketing_email_trial_short_0_sent.yml index 42370e5b267..41f2d30f3c6 100644 --- a/config/metrics/counts_all/20210727170558_in_product_marketing_email_trial_short_0_sent.yml +++ b/config/metrics/counts_all/20210727170558_in_product_marketing_email_trial_short_0_sent.yml @@ -5,8 +5,10 @@ product_section: growth product_stage: growth product_group: activation value_type: number -status: active -milestone: "14.2" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '14.2' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66943 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: series: 0 data_category: optional distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210729140021_in_product_marketing_email_admin_verify_0_cta_clicked.yml b/config/metrics/counts_all/20210729140021_in_product_marketing_email_admin_verify_0_cta_clicked.yml index 425b2346eff..1d5c3a07d07 100644 --- a/config/metrics/counts_all/20210729140021_in_product_marketing_email_admin_verify_0_cta_clicked.yml +++ b/config/metrics/counts_all/20210729140021_in_product_marketing_email_admin_verify_0_cta_clicked.yml @@ -5,8 +5,10 @@ product_section: growth product_stage: growth product_group: activation value_type: number -status: active -milestone: "14.2" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '14.2' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67147 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: series: 0 data_category: optional distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/config/metrics/counts_all/20210729140423_in_product_marketing_email_admin_verify_0_sent.yml b/config/metrics/counts_all/20210729140423_in_product_marketing_email_admin_verify_0_sent.yml index 1df94f95732..a594335f068 100644 --- a/config/metrics/counts_all/20210729140423_in_product_marketing_email_admin_verify_0_sent.yml +++ b/config/metrics/counts_all/20210729140423_in_product_marketing_email_admin_verify_0_sent.yml @@ -5,8 +5,10 @@ product_section: growth product_stage: growth product_group: activation value_type: number -status: active -milestone: "14.2" +status: removed +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131860 +milestone_removed: '16.5' +milestone: '14.2' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67147 time_frame: all data_source: database @@ -16,9 +18,9 @@ options: series: 0 data_category: optional distribution: -- ce -- ee + - ce + - ee tier: -- free -- premium -- ultimate + - free + - premium + - ultimate diff --git a/db/post_migrate/20230924134453_cleanup_uuid_type_migration_on_vulnerability_occurrences.rb b/db/post_migrate/20230924134453_cleanup_uuid_type_migration_on_vulnerability_occurrences.rb new file mode 100644 index 00000000000..192fa854502 --- /dev/null +++ b/db/post_migrate/20230924134453_cleanup_uuid_type_migration_on_vulnerability_occurrences.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +class CleanupUuidTypeMigrationOnVulnerabilityOccurrences < Gitlab::Database::Migration[2.1] + TABLE = :vulnerability_occurrences + TRIGGER_NAME = "trigger_1a857e8db6cd" + COLUMN_NAME = "uuid" + TEMP_COLUMN_NAME = "uuid_convert_string_to_uuid" + + disable_ddl_transaction! + + def up + # Unfortunately I can't use cleanup_concurrent_column_type_change + # because it's not working with disable_ddl_transaction! + # In addition, it doesn't perform cleanup correctly because the original + # trigger was created using UnidirectionalCopyTrigger so it fails to remove + # the actual trigger + # rubocop:disable Migration/WithLockRetriesDisallowedMethod + with_lock_retries do + check_trigger_permissions!(TABLE) + remove_rename_triggers(TABLE, TRIGGER_NAME) + remove_column(TABLE, COLUMN_NAME) + + rename_column(TABLE, TEMP_COLUMN_NAME, COLUMN_NAME) + end + # rubocop:enable Migration/WithLockRetriesDisallowedMethod + end + + def down + undo_cleanup_concurrent_column_type_change( + TABLE, + COLUMN_NAME, + :string, + limit: 36, + temp_column: TEMP_COLUMN_NAME + ) + change_column_null(TABLE, COLUMN_NAME, true) + end +end diff --git a/db/post_migrate/20230924154419_drop_temporary_index_on_uuid_for_type_migration.rb b/db/post_migrate/20230924154419_drop_temporary_index_on_uuid_for_type_migration.rb new file mode 100644 index 00000000000..57bb176f39e --- /dev/null +++ b/db/post_migrate/20230924154419_drop_temporary_index_on_uuid_for_type_migration.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +class DropTemporaryIndexOnUuidForTypeMigration < Gitlab::Database::Migration[2.1] + disable_ddl_transaction! + + INDEX_NAME = "tmp_idx_vulns_on_converted_uuid" + + def up + remove_concurrent_index_by_name( + :vulnerability_occurrences, + INDEX_NAME + ) + end + + def down + # no-op, the table is too big so we need to create the index asynchronously + end +end diff --git a/db/schema_migrations/20230924134453 b/db/schema_migrations/20230924134453 new file mode 100644 index 00000000000..d0e3dbe288e --- /dev/null +++ b/db/schema_migrations/20230924134453 @@ -0,0 +1 @@ +207d8827fcf5749f8cc5d717ee73b114810b7064f072818ec388ba897bb25501
\ No newline at end of file diff --git a/db/schema_migrations/20230924154419 b/db/schema_migrations/20230924154419 new file mode 100644 index 00000000000..7371e780e42 --- /dev/null +++ b/db/schema_migrations/20230924154419 @@ -0,0 +1 @@ +56c0eb18400723d64dcb74ebfe5ad6e5ff9121cadf82210387df051574ff17ca
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 8b7eae7eb47..9f07c5a4f85 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -298,15 +298,6 @@ BEGIN END; $$; -CREATE FUNCTION trigger_1a857e8db6cd() RETURNS trigger - LANGUAGE plpgsql - AS $$ -BEGIN - NEW."uuid_convert_string_to_uuid" := NEW."uuid"; - RETURN NEW; -END; -$$; - CREATE FUNCTION trigger_1bd97da9c1a4() RETURNS trigger LANGUAGE plpgsql AS $$ @@ -25003,7 +24994,6 @@ CREATE TABLE vulnerability_occurrences ( primary_identifier_id bigint NOT NULL, project_fingerprint bytea NOT NULL, location_fingerprint bytea NOT NULL, - uuid character varying(36) NOT NULL, name character varying NOT NULL, metadata_version character varying NOT NULL, raw_metadata text NOT NULL, @@ -25014,7 +25004,7 @@ CREATE TABLE vulnerability_occurrences ( cve text, location jsonb, detection_method smallint DEFAULT 0 NOT NULL, - uuid_convert_string_to_uuid uuid DEFAULT '00000000-0000-0000-0000-000000000000'::uuid NOT NULL, + uuid uuid DEFAULT '00000000-0000-0000-0000-000000000000'::uuid NOT NULL, CONSTRAINT check_4a3a60f2ba CHECK ((char_length(solution) <= 7000)), CONSTRAINT check_ade261da6b CHECK ((char_length(description) <= 15000)), CONSTRAINT check_f602da68dd CHECK ((char_length(cve) <= 48400)) @@ -34251,9 +34241,7 @@ COMMENT ON INDEX index_verification_codes_on_phone_and_visitor_id_code IS 'JiHu- CREATE INDEX index_vs_code_settings_on_user_id ON vs_code_settings USING btree (user_id); -CREATE UNIQUE INDEX index_vuln_findings_on_uuid_including_vuln_id ON vulnerability_occurrences USING btree (uuid) INCLUDE (vulnerability_id); - -CREATE UNIQUE INDEX index_vuln_findings_on_uuid_including_vuln_id_1 ON vulnerability_occurrences USING btree (uuid_convert_string_to_uuid) INCLUDE (vulnerability_id); +CREATE UNIQUE INDEX index_vuln_findings_on_uuid_including_vuln_id_1 ON vulnerability_occurrences USING btree (uuid) INCLUDE (vulnerability_id); CREATE UNIQUE INDEX index_vuln_historical_statistics_on_project_id_and_date ON vulnerability_historical_statistics USING btree (project_id, date); @@ -34373,9 +34361,7 @@ CREATE INDEX index_vulnerability_occurrences_on_project_fingerprint ON vulnerabi CREATE INDEX index_vulnerability_occurrences_on_scanner_id ON vulnerability_occurrences USING btree (scanner_id); -CREATE UNIQUE INDEX index_vulnerability_occurrences_on_uuid ON vulnerability_occurrences USING btree (uuid); - -CREATE UNIQUE INDEX index_vulnerability_occurrences_on_uuid_1 ON vulnerability_occurrences USING btree (uuid_convert_string_to_uuid); +CREATE UNIQUE INDEX index_vulnerability_occurrences_on_uuid_1 ON vulnerability_occurrences USING btree (uuid); CREATE INDEX index_vulnerability_occurrences_on_vulnerability_id ON vulnerability_occurrences USING btree (vulnerability_id); @@ -34613,8 +34599,6 @@ CREATE INDEX tmp_idx_orphaned_approval_project_rules ON approval_project_rules U CREATE INDEX tmp_idx_packages_on_project_id_when_npm_not_pending_destruction ON packages_packages USING btree (project_id) WHERE ((package_type = 2) AND (status <> 4)); -CREATE INDEX tmp_idx_vulns_on_converted_uuid ON vulnerability_occurrences USING btree (id, uuid_convert_string_to_uuid) WHERE (uuid_convert_string_to_uuid = '00000000-0000-0000-0000-000000000000'::uuid); - CREATE INDEX tmp_index_ci_job_artifacts_on_expire_at_where_locked_unknown ON ci_job_artifacts USING btree (expire_at, job_id) WHERE ((locked = 2) AND (expire_at IS NOT NULL)); CREATE INDEX tmp_index_cis_vulnerability_reads_on_id ON vulnerability_reads USING btree (id) WHERE (report_type = 7); @@ -34635,8 +34619,6 @@ CREATE INDEX tmp_index_project_statistics_updated_at ON project_statistics USING CREATE INDEX tmp_index_vulnerability_dismissal_info ON vulnerabilities USING btree (id) WHERE ((state = 2) AND ((dismissed_at IS NULL) OR (dismissed_by_id IS NULL))); -CREATE INDEX tmp_index_vulnerability_occurrences_uuid_cast ON vulnerability_occurrences USING btree (((uuid)::uuid)); - CREATE INDEX tmp_index_vulnerability_overlong_title_html ON vulnerabilities USING btree (id) WHERE (length(title_html) > 800); CREATE UNIQUE INDEX u_project_compliance_standards_adherence_for_reporting ON project_compliance_standards_adherence USING btree (project_id, check_name, standard); @@ -36349,8 +36331,6 @@ CREATE TRIGGER tags_loose_fk_trigger AFTER DELETE ON tags REFERENCING OLD TABLE CREATE TRIGGER trigger_07bc3c48f407 BEFORE INSERT OR UPDATE ON ci_stages FOR EACH ROW EXECUTE FUNCTION trigger_07bc3c48f407(); -CREATE TRIGGER trigger_1a857e8db6cd BEFORE INSERT OR UPDATE ON vulnerability_occurrences FOR EACH ROW EXECUTE FUNCTION trigger_1a857e8db6cd(); - CREATE TRIGGER trigger_1bd97da9c1a4 BEFORE INSERT OR UPDATE ON ci_pipelines FOR EACH ROW EXECUTE FUNCTION trigger_1bd97da9c1a4(); CREATE TRIGGER trigger_239c8032a8d6 BEFORE INSERT OR UPDATE ON ci_pipeline_chat_data FOR EACH ROW EXECUTE FUNCTION trigger_239c8032a8d6(); diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 3f9638093ae..243b29100bc 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -16106,12 +16106,13 @@ four standard [pagination arguments](#connection-pagination-arguments): | <a id="detailedstatusaction"></a>`action` | [`StatusAction`](#statusaction) | Action information for the status. This includes method, button title, icon, path, and title. | | <a id="detailedstatusdetailspath"></a>`detailsPath` | [`String`](#string) | Path of the details for the status. | | <a id="detailedstatusfavicon"></a>`favicon` | [`String`](#string) | Favicon of the status. | -| <a id="detailedstatusgroup"></a>`group` | [`String`](#string) | Group of the status. | +| <a id="detailedstatusgroup"></a>`group` **{warning-solid}** | [`String`](#string) | **Deprecated** in 16.4. The `group` attribute is deprecated. Use `name` instead. | | <a id="detailedstatushasdetails"></a>`hasDetails` | [`Boolean`](#boolean) | Indicates if the status has further details. | -| <a id="detailedstatusicon"></a>`icon` | [`String`](#string) | Icon of the status. | +| <a id="detailedstatusicon"></a>`icon` **{warning-solid}** | [`String`](#string) | **Deprecated** in 16.4. The `icon` attribute is deprecated. Use `name` to identify the status to display instead. | | <a id="detailedstatusid"></a>`id` | [`String!`](#string) | ID for a detailed status. | -| <a id="detailedstatuslabel"></a>`label` | [`String`](#string) | Label of the status. | -| <a id="detailedstatustext"></a>`text` | [`String`](#string) | Text of the status. | +| <a id="detailedstatuslabel"></a>`label` | [`String`](#string) | Human-readable label of the status (e.g. success). | +| <a id="detailedstatusname"></a>`name` | [`String`](#string) | Machine-readable status name (e.g. SUCCESS). | +| <a id="detailedstatustext"></a>`text` **{warning-solid}** | [`String`](#string) | **Deprecated** in 16.4. The `text` attribute is being deprecated. Use `label` instead. | | <a id="detailedstatustooltip"></a>`tooltip` | [`String`](#string) | Tooltip associated with the status. | ### `DevopsAdoptionEnabledNamespace` diff --git a/doc/architecture/blueprints/secret_manager/index.md b/doc/architecture/blueprints/secret_manager/index.md new file mode 100644 index 00000000000..7cc042466e7 --- /dev/null +++ b/doc/architecture/blueprints/secret_manager/index.md @@ -0,0 +1,78 @@ +--- +status: proposed +creation-date: "2023-08-07" +authors: [ "@alberts-gitlab" ] +coach: [ "@grzesiek" ] +approvers: [ "@jocelynjane", "@shampton" ] +owning-stage: "~devops::verify" +participating-stages: [] +--- + +<!-- Blueprints often contain forward-looking statements --> +<!-- vale gitlab.FutureTense = NO --> + +# GitLab Secret Manager + +## Summary + +GitLab users need a secure and easy-to-use solution to +store their sensitive credentials that should be kept confidential ("secret"). +GitLab Secrets Manager is the desired system that provides GitLab users +to meet that need without having to access third party tools. + +## Motivation + +The current de-facto approach used by many to store a sensitive credential in GitLab is +using a [Masked Variable](../../../ci/variables/index.md#mask-a-cicd-variable) or a +[File Variable](../../../ci/variables/index.md#use-file-type-cicd-variables). +However, data stored in variables (masked or file variables) can be inadvertently exposed even with masking. +A more secure solution would be to use native integration +with external secret managers such as HashiCorp Vault or Azure Key Vault. + +Integration with external secret managers requires GitLab to maintain the integration +with the third-party products and to assist customers in troubleshooting configuration issues. +In addition, customer's engineering teams using these external secret managers +may need to maintain these systems themselves, adding to the operational burden. + +Having a GitLab native secret manager would provide customers a secure method to store and access secrets +without the overhead of third party tools as well as to leverage the tight integration with other GitLab features. + +### Goals + +Provide GitLab users with a way to: + +- Securely store secrets in GitLab +- Use the stored secrets in GitLab components (for example, CI Runner) +- Use the stored secrets in external environments (for example, production infrastructure). +- Manage access to secrets across a root namespace, subgroups and projects. +- Seal/unseal secrets vault on demand. + +#### Non-functional requirements + +- Security +- Compliance +- Auditability + +### Non-Goals + +This blueprint does not cover the following: + +- Secrets such as access tokens created within GitLab to allow external resources to access GitLab, e.g personal access tokens. + +## Proposal + +The proposal is still actively being shaped. It will be updated in subsequent Merge Requests. + +## Alternative Solutions + +Other solutions we have explored: + +- Separating secrets from CI/CD variables as a separate model with limited access, to avoid unintended exposure of the secret. +- [Secure Files](../../../ci/secure_files/index.md) + +## References + +The following links provide additional information that may be relevant to secret management concepts. + +- [OWASP Secrets Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html) +- [OWASP Key Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Key_Management_Cheat_Sheet.html) diff --git a/doc/integration/jira/troubleshooting.md b/doc/integration/jira/troubleshooting.md index ec6d41affb0..9483c7e809e 100644 --- a/doc/integration/jira/troubleshooting.md +++ b/doc/integration/jira/troubleshooting.md @@ -126,14 +126,22 @@ Check [`production.log`](../../administration/logs/index.md#productionlog) to se If that's the case, ensure the [**Due date** field is visible for issues](https://confluence.atlassian.com/jirakb/due-date-field-is-missing-189431917.html) in the integrated Jira project. -## `An error occurred while requesting data from Jira` when viewing the Jira issues list in GitLab +## `An error occurred while requesting data from Jira` when viewing the Jira issue list in GitLab -You might see a `An error occurred while requesting data from Jira` message when you attempt to view the Jira issues list in GitLab. +When you try to view the Jira issue list in GitLab, you might see this message: -You can see this error when the authentication details in the Jira integration settings are incomplete or incorrect. +```plaintext +An error occurred while requesting data from Jira +``` + +This error occurs when the authentication for the Jira issue integration is not complete or correct. + +To resolve this issue, [configure the Jira issue integration](configure.md#configure-the-integration) again. +Ensure the authentication details are correct, enter your API token or password again, and save your changes. -To attempt to resolve this error, try [configuring the integration](configure.md#configure-the-integration) again. Verify that the -authentication details are correct, re-enter your API token or password, and save your changes. +The Jira issue list does not load if the project key contains a reserved JQL word. +For more information, see [issue 426176](https://gitlab.com/gitlab-org/gitlab/-/issues/426176). +Your Jira project key must not have [restricted words and characters](https://confluence.atlassian.com/jirasoftwareserver/advanced-searching-939938733.html#Advancedsearching-restrictionsRestrictedwordsandcharacters). ## GitLab cannot link to a Jira issue diff --git a/gems/activerecord-gitlab/lib/active_record/gitlab_patches/rescue_from.rb b/gems/activerecord-gitlab/lib/active_record/gitlab_patches/rescue_from.rb index faabddd2686..eaaa90ec52b 100644 --- a/gems/activerecord-gitlab/lib/active_record/gitlab_patches/rescue_from.rb +++ b/gems/activerecord-gitlab/lib/active_record/gitlab_patches/rescue_from.rb @@ -7,6 +7,7 @@ module ActiveRecord # # - `ActiveRecord::Relation#load`, and other methods that call # `ActiveRecord::Relation#exec_queries`. + # - `ActiveModel::UnknownAttributeError` as a result of `ActiveRecord::Base#assign_attributes` # # class ApplicationRecord < ActiveRecord::Base # rescue_from MyException, with: :my_handler @@ -29,13 +30,23 @@ module ActiveRecord def exec_queries super rescue StandardError => e + # Method klass is defined in ActiveRecord gem lib/active_record/relation.rb klass.rescue_with_handler(e) || raise end end + + module AssignAttributesRescueWithHandler + def _assign_attributes(...) + super(...) + rescue StandardError => e + rescue_with_handler(e) || raise + end + end end end ActiveSupport.on_load(:active_record) do ActiveRecord::Relation.prepend(ActiveRecord::GitlabPatches::ExecQueriesRescueWithHandler) + ActiveRecord::Base.prepend(ActiveRecord::GitlabPatches::AssignAttributesRescueWithHandler) ActiveRecord::Base.prepend(ActiveRecord::GitlabPatches::RescueFrom) end diff --git a/gems/activerecord-gitlab/spec/active_record/gitlab_patches/rescue_from_spec.rb b/gems/activerecord-gitlab/spec/active_record/gitlab_patches/rescue_from_spec.rb index 22729edb014..0a70c4dddaf 100644 --- a/gems/activerecord-gitlab/spec/active_record/gitlab_patches/rescue_from_spec.rb +++ b/gems/activerecord-gitlab/spec/active_record/gitlab_patches/rescue_from_spec.rb @@ -4,10 +4,13 @@ RSpec.describe ActiveRecord::GitlabPatches::RescueFrom do let(:model_with_rescue_from) do Class.new(Project) do rescue_from ActiveRecord::StatementInvalid, with: :handle_exception + rescue_from ActiveRecord::UnknownAttributeError, with: :handle_attr_exception class << self def handle_exception(exception); end end + + def handle_attr_exception(exc); end end end @@ -26,4 +29,19 @@ RSpec.describe ActiveRecord::GitlabPatches::RescueFrom do expect { model_without_rescue_from.where('BADQUERY').load }.to raise_error(ActiveRecord::StatementInvalid) end end + + context 'for errors from ActiveRecord::Base.assign_attributes' do + it 'triggers rescue_from' do + model_instance = model_with_rescue_from.new + + expect(model_instance).to receive(:handle_attr_exception) + + expect { model_instance.assign_attributes(nonexistent_column: "some value") }.not_to raise_error + end + + it 'does not trigger rescue_from' do + expect { model_without_rescue_from.new.assign_attributes(nonexistent_column: "some value") } + .to raise_error(ActiveRecord::UnknownAttributeError) + end + end end diff --git a/gems/gitlab-http/.rubocop.yml b/gems/gitlab-http/.rubocop.yml index 73ea5f610b3..262bef44e6a 100644 --- a/gems/gitlab-http/.rubocop.yml +++ b/gems/gitlab-http/.rubocop.yml @@ -5,9 +5,6 @@ Naming/ClassAndModuleCamelCase: AllowedNames: - HTTP_V2 -Performance/RegexpMatch: - Enabled: false - Style/SpecialGlobalVars: Enabled: false diff --git a/gems/gitlab-http/lib/gitlab/http_v2/url_blocker.rb b/gems/gitlab-http/lib/gitlab/http_v2/url_blocker.rb index a794ab2f443..878daf42d8a 100644 --- a/gems/gitlab-http/lib/gitlab/http_v2/url_blocker.rb +++ b/gems/gitlab-http/lib/gitlab/http_v2/url_blocker.rb @@ -188,7 +188,7 @@ module Gitlab # # @param uri [Addressable::URI] # - # @raise [Gitlab::UrlBlocker::BlockedUrlError, ArgumentError] - BlockedUrlError raised if host is too long. + # @raise [Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError, ArgumentError] raised if host is too long. # # @return [Array<Addrinfo>] def get_address_info(uri) @@ -271,7 +271,7 @@ module Gitlab def multiline_blocked?(parsed_url) url = parsed_url.to_s - return true if url =~ /\n|\r/ + return true if /\n|\r/.match?(url) # Google Cloud Storage uses a multi-line, encoded Signature query string return false if %w[http https].include?(parsed_url.scheme&.downcase) @@ -295,7 +295,7 @@ module Gitlab def validate_user(value) return if value.blank? - return if value =~ /\A\p{Alnum}/ + return if /\A\p{Alnum}/.match?(value) raise BlockedUrlError, "Username needs to start with an alphanumeric character" end @@ -303,7 +303,7 @@ module Gitlab def validate_hostname(value) return if value.blank? return if IPAddress.valid?(value) - return if value =~ /\A\p{Alnum}/ + return if /\A\p{Alnum}/.match?(value) raise BlockedUrlError, "Hostname or IP address invalid" end diff --git a/lib/gitlab/ci/status/core.rb b/lib/gitlab/ci/status/core.rb index f60f5243666..c5306de830b 100644 --- a/lib/gitlab/ci/status/core.rb +++ b/lib/gitlab/ci/status/core.rb @@ -38,6 +38,10 @@ module Gitlab raise NotImplementedError end + def name + self.class.name.demodulize.underscore.upcase + end + def group self.class.name.demodulize.underscore end diff --git a/lib/gitlab/ci/status/success_warning.rb b/lib/gitlab/ci/status/success_warning.rb index 84a0e52f518..a19a85a2e28 100644 --- a/lib/gitlab/ci/status/success_warning.rb +++ b/lib/gitlab/ci/status/success_warning.rb @@ -20,6 +20,10 @@ module Gitlab 'status_warning' end + def name + 'SUCCESS_WITH_WARNINGS' + end + def group 'success-with-warnings' end diff --git a/lib/gitlab/ci/status/waiting_for_resource.rb b/lib/gitlab/ci/status/waiting_for_resource.rb index 9ced0aadb88..edfd7516b25 100644 --- a/lib/gitlab/ci/status/waiting_for_resource.rb +++ b/lib/gitlab/ci/status/waiting_for_resource.rb @@ -20,6 +20,10 @@ module Gitlab 'favicon_status_pending' end + def name + 'WAITING_FOR_RESOURCE' + end + def group 'waiting-for-resource' end diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb index 60cec12b4b5..83108b8ea29 100644 --- a/lib/gitlab/database/migration_helpers.rb +++ b/lib/gitlab/database/migration_helpers.rb @@ -567,8 +567,8 @@ module Gitlab # table - The table containing the column. # column - The name of the column to change. # new_type - The new column type. - def cleanup_concurrent_column_type_change(table, column) - temp_column = "#{column}_for_type_change" + def cleanup_concurrent_column_type_change(table, column, temp_column: nil) + temp_column ||= "#{column}_for_type_change" transaction do # This has to be performed in a transaction as otherwise we might have @@ -586,10 +586,10 @@ module Gitlab # type_cast_function - Required if the conversion back to the original type is not automatic # batch_column_name - option for tables without a primary key, in this case # another unique integer column can be used. Example: :user_id - def undo_cleanup_concurrent_column_type_change(table, column, old_type, type_cast_function: nil, batch_column_name: :id, limit: nil) + def undo_cleanup_concurrent_column_type_change(table, column, old_type, type_cast_function: nil, batch_column_name: :id, limit: nil, temp_column: nil) Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas.require_ddl_mode! - temp_column = "#{column}_for_type_change" + temp_column ||= "#{column}_for_type_change" # Using a descriptive name that includes orinal column's name risks # taking us above the 63 character limit, so we use a hash @@ -909,6 +909,11 @@ module Gitlab name = index.name.gsub(old, new) + if name.length > 63 + digest = Digest::SHA256.hexdigest(name).first(10) + name = "idx_copy_#{digest}" + end + options = { unique: index.unique, name: name, diff --git a/lib/gitlab/http_connection_adapter.rb b/lib/gitlab/http_connection_adapter.rb index 822b8a9f8d9..8e9a63a9f7f 100644 --- a/lib/gitlab/http_connection_adapter.rb +++ b/lib/gitlab/http_connection_adapter.rb @@ -56,7 +56,7 @@ module Gitlab allow_object_storage: allow_object_storage?, dns_rebind_protection: dns_rebind_protection?, schemes: %w[http https]) - rescue Gitlab::UrlBlocker::BlockedUrlError => e + rescue Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError => e raise Gitlab::HTTP::BlockedUrlError, "URL is blocked: #{e.message}" end diff --git a/lib/gitlab/url_blocker.rb b/lib/gitlab/url_blocker.rb index 57d3b3ec6f9..8f2dfce67bb 100644 --- a/lib/gitlab/url_blocker.rb +++ b/lib/gitlab/url_blocker.rb @@ -1,12 +1,16 @@ # frozen_string_literal: true +# +# IMPORTANT: With the new development of the 'gitlab-http' gem (https://gitlab.com/gitlab-org/gitlab/-/issues/415686), +# no additional change should be implemented in this class. This class will be removed after migrating all +# the usages to the new gem. +# + require 'resolv' require 'ipaddress' module Gitlab class UrlBlocker - BlockedUrlError = Class.new(StandardError) - DENY_ALL_REQUESTS_EXCEPT_ALLOWED_DEFAULT = proc { deny_all_requests_except_allowed_app_setting }.freeze # Result stores the validation result: @@ -77,7 +81,7 @@ module Gitlab return Result.new(uri, nil, proxy_in_use) unless enforce_address_info_retrievable?(uri, dns_rebind_protection, deny_all_requests_except_allowed) - raise BlockedUrlError, 'Host cannot be resolved or invalid' + raise Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError, 'Host cannot be resolved or invalid' end ip_address = ip_address(address_info) @@ -112,7 +116,7 @@ module Gitlab validate!(url, **kwargs) false - rescue BlockedUrlError + rescue Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError true end @@ -173,7 +177,7 @@ module Gitlab # # @param uri [Addressable::URI] # - # @raise [Gitlab::UrlBlocker::BlockedUrlError, ArgumentError] - BlockedUrlError raised if host is too long. + # @raise [Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError, ArgumentError] - raised if host is too long. # # @return [Array<Addrinfo>] def get_address_info(uri) @@ -184,7 +188,7 @@ module Gitlab # Addrinfo.getaddrinfo errors if the domain exceeds 1024 characters. raise unless error.message.include?('hostname too long') - raise BlockedUrlError, "Host is too long (maximum is 1024 characters)" + raise Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError, "Host is too long (maximum is 1024 characters)" end def enforce_address_info_retrievable?(uri, dns_rebind_protection, deny_all_requests_except_allowed) @@ -232,7 +236,7 @@ module Gitlab netmask = IPAddr.new('100.64.0.0/10') return unless addrs_info.any? { |addr| netmask.include?(addr.ip_address) } - raise BlockedUrlError, "Requests to the shared address space are not allowed" + raise Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError, "Requests to the shared address space are not allowed" end def get_port(uri) @@ -243,7 +247,7 @@ module Gitlab uri_str = uri.to_s sanitized_uri = ActionController::Base.helpers.sanitize(uri_str, tags: []) if sanitized_uri != uri_str - raise BlockedUrlError, 'HTML/CSS/JS tags are not allowed' + raise Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError, 'HTML/CSS/JS tags are not allowed' end end @@ -252,7 +256,7 @@ module Gitlab raise Addressable::URI::InvalidURIError if multiline_blocked?(parsed_url) end rescue Addressable::URI::InvalidURIError, URI::InvalidURIError - raise BlockedUrlError, 'URI is invalid' + raise Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError, 'URI is invalid' end def multiline_blocked?(parsed_url) @@ -271,12 +275,13 @@ module Gitlab return if port >= 1024 return if ports.include?(port) - raise BlockedUrlError, "Only allowed ports are #{ports.join(', ')}, and any over 1024" + raise Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError, + "Only allowed ports are #{ports.join(', ')}, and any over 1024" end def validate_scheme(scheme, schemes) if scheme.blank? || (schemes.any? && schemes.exclude?(scheme)) - raise BlockedUrlError, "Only allowed schemes are #{schemes.join(', ')}" + raise Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError, "Only allowed schemes are #{schemes.join(', ')}" end end @@ -284,7 +289,7 @@ module Gitlab return if value.blank? return if /\A\p{Alnum}/.match?(value) - raise BlockedUrlError, "Username needs to start with an alphanumeric character" + raise Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError, "Username needs to start with an alphanumeric character" end def validate_hostname(value) @@ -292,13 +297,13 @@ module Gitlab return if IPAddress.valid?(value) return if /\A\p{Alnum}/.match?(value) - raise BlockedUrlError, "Hostname or IP address invalid" + raise Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError, "Hostname or IP address invalid" end def validate_unicode_restriction(uri) return if uri.to_s.ascii_only? - raise BlockedUrlError, "URI must be ascii only #{uri.to_s.dump}" + raise Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError, "URI must be ascii only #{uri.to_s.dump}" end def validate_localhost(addrs_info) @@ -307,38 +312,39 @@ module Gitlab return if (local_ips & addrs_info.map(&:ip_address)).empty? - raise BlockedUrlError, "Requests to localhost are not allowed" + raise Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError, "Requests to localhost are not allowed" end def validate_loopback(addrs_info) return unless addrs_info.any? { |addr| addr.ipv4_loopback? || addr.ipv6_loopback? } - raise BlockedUrlError, "Requests to loopback addresses are not allowed" + raise Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError, "Requests to loopback addresses are not allowed" end def validate_local_network(addrs_info) return unless addrs_info.any? { |addr| addr.ipv4_private? || addr.ipv6_sitelocal? || addr.ipv6_unique_local? } - raise BlockedUrlError, "Requests to the local network are not allowed" + raise Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError, "Requests to the local network are not allowed" end def validate_link_local(addrs_info) netmask = IPAddr.new('169.254.0.0/16') return unless addrs_info.any? { |addr| addr.ipv6_linklocal? || netmask.include?(addr.ip_address) } - raise BlockedUrlError, "Requests to the link local network are not allowed" + raise Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError, "Requests to the link local network are not allowed" end - # Raises a BlockedUrlError if the instance is configured to deny all requests. + # Raises a Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError if the instance is configured to deny all requests. # # This should only be called after allow list checks have been made. def validate_deny_all_requests_except_allowed!(should_deny) return unless deny_all_requests_except_allowed?(should_deny) - raise BlockedUrlError, "Requests to hosts and IP addresses not on the Allow List are denied" + raise Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError, + "Requests to hosts and IP addresses not on the Allow List are denied" end - # Raises a BlockedUrlError if any IP in `addrs_info` is the limited + # Raises a Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError if any IP in `addrs_info` is the limited # broadcast address. # https://datatracker.ietf.org/doc/html/rfc919#section-7 def validate_limited_broadcast_address(addrs_info) @@ -346,7 +352,7 @@ module Gitlab return if (blocked_ips & addrs_info.map(&:ip_address)).empty? - raise BlockedUrlError, "Requests to the limited broadcast address are not allowed" + raise Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError, "Requests to the limited broadcast address are not allowed" end def internal?(uri) diff --git a/locale/gitlab.pot b/locale/gitlab.pot index a94d945c40a..268b3861a21 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -30807,9 +30807,6 @@ msgstr "" msgid "Navigation bar" msgstr "" -msgid "Navigation sidebar" -msgstr "" - msgid "NavigationTheme|Blue" msgstr "" diff --git a/spec/frontend/super_sidebar/components/super_sidebar_toggle_spec.js b/spec/frontend/super_sidebar/components/super_sidebar_toggle_spec.js index 1f2e5602d10..974eb529113 100644 --- a/spec/frontend/super_sidebar/components/super_sidebar_toggle_spec.js +++ b/spec/frontend/super_sidebar/components/super_sidebar_toggle_spec.js @@ -18,13 +18,8 @@ describe('SuperSidebarToggle component', () => { const findButton = () => wrapper.findComponent(GlButton); const getTooltip = () => getBinding(wrapper.element, 'gl-tooltip').value; - const createWrapper = ({ props = {}, sidebarState = {} } = {}) => { + const createWrapper = (props = {}) => { wrapper = shallowMountExtended(SuperSidebarToggle, { - data() { - return { - ...sidebarState, - }; - }, directives: { GlTooltip: createMockDirective('gl-tooltip'), }, @@ -40,18 +35,15 @@ describe('SuperSidebarToggle component', () => { expect(findButton().attributes('aria-controls')).toBe('super-sidebar'); }); - it('has aria-expanded as true when expanded', () => { - createWrapper(); + it('has aria-expanded as true when type is collapse', () => { + createWrapper({ type: 'collapse' }); expect(findButton().attributes('aria-expanded')).toBe('true'); }); - it.each(['isCollapsed', 'isPeek', 'isHoverPeek'])( - 'has aria-expanded as false when %s is `true`', - (stateProp) => { - createWrapper({ sidebarState: { [stateProp]: true } }); - expect(findButton().attributes('aria-expanded')).toBe('false'); - }, - ); + it('has aria-expanded as false when type is expand', () => { + createWrapper(); + expect(findButton().attributes('aria-expanded')).toBe('false'); + }); it('has aria-label attribute', () => { createWrapper(); @@ -60,13 +52,13 @@ describe('SuperSidebarToggle component', () => { }); describe('tooltip', () => { - it('displays collapse when expanded', () => { - createWrapper(); + it('displays "Hide sidebar" when type is collapse', () => { + createWrapper({ type: 'collapse' }); expect(getTooltip().title).toBe('Hide sidebar'); }); - it('displays expand when collapsed', () => { - createWrapper({ sidebarState: { isCollapsed: true } }); + it('displays "Keep sidebar visible" when type is expand', () => { + createWrapper(); expect(getTooltip().title).toBe('Keep sidebar visible'); }); }); @@ -88,13 +80,11 @@ describe('SuperSidebarToggle component', () => { }); it('collapses the sidebar and focuses the other toggle', async () => { - createWrapper(); + createWrapper({ type: 'collapse' }); findButton().vm.$emit('click'); await nextTick(); expect(toggleSuperSidebarCollapsed).toHaveBeenCalledWith(true, true); - expect(document.activeElement).toEqual( - document.querySelector(`.${JS_TOGGLE_COLLAPSE_CLASS}`), - ); + expect(document.activeElement).toEqual(document.querySelector(`.${JS_TOGGLE_EXPAND_CLASS}`)); expect(trackingSpy).toHaveBeenCalledWith(undefined, 'nav_hide', { label: 'nav_toggle', property: 'nav_sidebar', @@ -102,11 +92,13 @@ describe('SuperSidebarToggle component', () => { }); it('expands the sidebar and focuses the other toggle', async () => { - createWrapper({ sidebarState: { isCollapsed: true } }); + createWrapper(); findButton().vm.$emit('click'); await nextTick(); expect(toggleSuperSidebarCollapsed).toHaveBeenCalledWith(false, true); - expect(document.activeElement).toEqual(document.querySelector(`.${JS_TOGGLE_EXPAND_CLASS}`)); + expect(document.activeElement).toEqual( + document.querySelector(`.${JS_TOGGLE_COLLAPSE_CLASS}`), + ); expect(trackingSpy).toHaveBeenCalledWith(undefined, 'nav_show', { label: 'nav_toggle', property: 'nav_sidebar', diff --git a/spec/graphql/types/ci/detailed_status_type_spec.rb b/spec/graphql/types/ci/detailed_status_type_spec.rb index 81ab1b52552..f622f571986 100644 --- a/spec/graphql/types/ci/detailed_status_type_spec.rb +++ b/spec/graphql/types/ci/detailed_status_type_spec.rb @@ -12,7 +12,8 @@ RSpec.describe Types::Ci::DetailedStatusType do it 'has all fields' do expect(described_class).to have_graphql_fields(:id, :group, :icon, :favicon, :details_path, :has_details, - :label, :text, :tooltip, :action) + :label, :name, :text, :tooltip, + :action) end describe 'id field' do diff --git a/spec/lib/gitlab/ci/status/success_warning_spec.rb b/spec/lib/gitlab/ci/status/success_warning_spec.rb index 1725f90a0cf..b44bd00c812 100644 --- a/spec/lib/gitlab/ci/status/success_warning_spec.rb +++ b/spec/lib/gitlab/ci/status/success_warning_spec.rb @@ -25,6 +25,10 @@ RSpec.describe Gitlab::Ci::Status::SuccessWarning, feature_category: :continuous it { expect(subject.group).to eq 'success-with-warnings' } end + describe '#name' do + it { expect(subject.name).to eq 'SUCCESS_WITH_WARNINGS' } + end + describe '.matches?' do let(:matchable) { double('matchable') } diff --git a/spec/lib/gitlab/ci/status/waiting_for_resource_spec.rb b/spec/lib/gitlab/ci/status/waiting_for_resource_spec.rb index 6f5ab77a358..ea553d235db 100644 --- a/spec/lib/gitlab/ci/status/waiting_for_resource_spec.rb +++ b/spec/lib/gitlab/ci/status/waiting_for_resource_spec.rb @@ -27,6 +27,10 @@ RSpec.describe Gitlab::Ci::Status::WaitingForResource do it { expect(subject.group).to eq 'waiting-for-resource' } end + describe '#name' do + it { expect(subject.name).to eq 'WAITING_FOR_RESOURCE' } + end + describe '#details_path' do it { expect(subject.details_path).to be_nil } end diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb index f3c181db3aa..cd789adddf4 100644 --- a/spec/lib/gitlab/database/migration_helpers_spec.rb +++ b/spec/lib/gitlab/database/migration_helpers_spec.rb @@ -1774,6 +1774,35 @@ RSpec.describe Gitlab::Database::MigrationHelpers, feature_category: :database d end describe '#copy_indexes' do + context 'when index name is too long' do + it 'does not fail' do + index = double(:index, + columns: %w(uuid), + name: 'index_vuln_findings_on_uuid_including_vuln_id_1', + using: nil, + where: nil, + opclasses: {}, + unique: true, + lengths: [], + orders: []) + + allow(model).to receive(:indexes_for).with(:vulnerability_occurrences, 'uuid') + .and_return([index]) + + expect(model).to receive(:add_concurrent_index) + .with(:vulnerability_occurrences, + %w(tmp_undo_cleanup_column_8cbf300838), + { + unique: true, + name: 'idx_copy_191a1af1a0', + length: [], + order: [] + }) + + model.copy_indexes(:vulnerability_occurrences, :uuid, :tmp_undo_cleanup_column_8cbf300838) + end + end + context 'using a regular index using a single column' do it 'copies the index' do index = double(:index, diff --git a/spec/lib/gitlab/github_gists_import/importer/gist_importer_spec.rb b/spec/lib/gitlab/github_gists_import/importer/gist_importer_spec.rb index cbcd9b83c15..b098a151660 100644 --- a/spec/lib/gitlab/github_gists_import/importer/gist_importer_spec.rb +++ b/spec/lib/gitlab/github_gists_import/importer/gist_importer_spec.rb @@ -174,9 +174,9 @@ RSpec.describe Gitlab::GithubGistsImport::Importer::GistImporter, feature_catego .to receive(:validate!) .with(url, ports: [80, 443], schemes: %w[http https git], allow_localhost: true, allow_local_network: true) - .and_raise(Gitlab::UrlBlocker::BlockedUrlError) + .and_raise(Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError) - expect { subject.execute }.to raise_error(Gitlab::UrlBlocker::BlockedUrlError) + expect { subject.execute }.to raise_error(Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError) end end @@ -191,9 +191,9 @@ RSpec.describe Gitlab::GithubGistsImport::Importer::GistImporter, feature_catego .to receive(:validate!) .with(url, ports: [80, 443], schemes: %w[http https git], allow_localhost: false, allow_local_network: false) - .and_raise(Gitlab::UrlBlocker::BlockedUrlError) + .and_raise(Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError) - expect { subject.execute }.to raise_error(Gitlab::UrlBlocker::BlockedUrlError) + expect { subject.execute }.to raise_error(Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError) end end end diff --git a/spec/lib/gitlab/http_spec.rb b/spec/lib/gitlab/http_spec.rb index 9d89167bf81..ce29208dc30 100644 --- a/spec/lib/gitlab/http_spec.rb +++ b/spec/lib/gitlab/http_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::HTTP do +RSpec.describe Gitlab::HTTP, feature_category: :shared do include StubRequests let(:default_options) { described_class::DEFAULT_TIMEOUT_OPTIONS } diff --git a/spec/lib/gitlab/kubernetes/kube_client_spec.rb b/spec/lib/gitlab/kubernetes/kube_client_spec.rb index d0b89afccdc..5fcbecfe6e1 100644 --- a/spec/lib/gitlab/kubernetes/kube_client_spec.rb +++ b/spec/lib/gitlab/kubernetes/kube_client_spec.rb @@ -106,7 +106,7 @@ RSpec.describe Gitlab::Kubernetes::KubeClient do describe '#initialize' do shared_examples 'local address' do it 'blocks local addresses' do - expect { client }.to raise_error(Gitlab::UrlBlocker::BlockedUrlError) + expect { client }.to raise_error(Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError) end context 'when local requests are allowed' do @@ -136,7 +136,7 @@ RSpec.describe Gitlab::Kubernetes::KubeClient do let(:api_url) { 'ssh://192.168.1.2' } it 'raises an error' do - expect { client }.to raise_error(Gitlab::UrlBlocker::BlockedUrlError) + expect { client }.to raise_error(Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError) end end diff --git a/spec/lib/gitlab/octokit/middleware_spec.rb b/spec/lib/gitlab/octokit/middleware_spec.rb index f7063f2c4f2..07936de9e78 100644 --- a/spec/lib/gitlab/octokit/middleware_spec.rb +++ b/spec/lib/gitlab/octokit/middleware_spec.rb @@ -16,7 +16,7 @@ RSpec.describe Gitlab::Octokit::Middleware, feature_category: :importers do shared_examples 'Blocked URL' do it 'raises an error' do - expect { middleware.call(env) }.to raise_error(Gitlab::UrlBlocker::BlockedUrlError) + expect { middleware.call(env) }.to raise_error(Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError) end end @@ -88,7 +88,7 @@ RSpec.describe Gitlab::Octokit::Middleware, feature_category: :importers do let(:env) { { url: 'ssh://172.16.0.0' } } it 'raises an error' do - expect { middleware.call(env) }.to raise_error(Gitlab::UrlBlocker::BlockedUrlError) + expect { middleware.call(env) }.to raise_error(Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError) end end end diff --git a/spec/lib/gitlab/url_blocker_spec.rb b/spec/lib/gitlab/url_blocker_spec.rb index cfd40fb93b5..0f827921a66 100644 --- a/spec/lib/gitlab/url_blocker_spec.rb +++ b/spec/lib/gitlab/url_blocker_spec.rb @@ -66,7 +66,7 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only, feature_category: :sh include_context 'when instance configured to deny all requests' it 'blocks the request' do - expect { subject }.to raise_error(described_class::BlockedUrlError) + expect { subject }.to raise_error(Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError) end end @@ -83,7 +83,7 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only, feature_category: :sh let(:arg_value) { proc { true } } it 'blocks the request' do - expect { subject }.to raise_error(described_class::BlockedUrlError) + expect { subject }.to raise_error(Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError) end end @@ -99,7 +99,7 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only, feature_category: :sh let(:arg_value) { true } it 'blocks the request' do - expect { subject }.to raise_error(described_class::BlockedUrlError) + expect { subject }.to raise_error(Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError) end end @@ -228,7 +228,7 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only, feature_category: :sh let(:lfs_enabled) { false } it 'raises an error' do - expect { subject }.to raise_error(described_class::BlockedUrlError) + expect { subject }.to raise_error(Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError) end end @@ -236,7 +236,7 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only, feature_category: :sh let(:lfs_enabled) { true } it 'raises an error' do - expect { subject }.to raise_error(described_class::BlockedUrlError) + expect { subject }.to raise_error(Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError) end end end @@ -251,7 +251,7 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only, feature_category: :sh end it 'raises an error' do - expect { subject }.to raise_error(described_class::BlockedUrlError) + expect { subject }.to raise_error(Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError) end end @@ -259,7 +259,7 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only, feature_category: :sh let(:host) { 'http://127.0.0.1:9000' } it 'raises an error' do - expect { subject }.to raise_error(described_class::BlockedUrlError) + expect { subject }.to raise_error(Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError) end end end @@ -290,7 +290,7 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only, feature_category: :sh end it 'raises an error' do - expect { subject }.to raise_error(described_class::BlockedUrlError) + expect { subject }.to raise_error(Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError) end context 'with HTTP_PROXY' do @@ -324,7 +324,7 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only, feature_category: :sh let(:import_url) { "https://example#{'a' * 1024}.com" } it 'raises an error' do - expect { subject }.to raise_error(described_class::BlockedUrlError) + expect { subject }.to raise_error(Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError) end end end @@ -346,7 +346,7 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only, feature_category: :sh it 'raises an error' do stub_env('RSPEC_ALLOW_INVALID_URLS', 'false') - expect { subject }.to raise_error(described_class::BlockedUrlError) + expect { subject }.to raise_error(Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError) end end end diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/in_product_marketing_email_cta_clicked_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/in_product_marketing_email_cta_clicked_metric_spec.rb index cb94da11d58..91ad81c4291 100644 --- a/spec/lib/gitlab/usage/metrics/instrumentations/in_product_marketing_email_cta_clicked_metric_spec.rb +++ b/spec/lib/gitlab/usage/metrics/instrumentations/in_product_marketing_email_cta_clicked_metric_spec.rb @@ -9,10 +9,10 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::InProductMarketingEmail let(:options) { { track: 'verify', series: 0 } } let(:expected_value) { 2 } let(:expected_query) do - 'SELECT COUNT("in_product_marketing_emails"."id") FROM "in_product_marketing_emails"' \ - ' WHERE "in_product_marketing_emails"."cta_clicked_at" IS NOT NULL' \ - ' AND "in_product_marketing_emails"."series" = 0'\ - ' AND "in_product_marketing_emails"."track" = 1' + 'SELECT COUNT("in_product_marketing_emails"."id") FROM "in_product_marketing_emails" ' \ + 'WHERE "in_product_marketing_emails"."cta_clicked_at" IS NOT NULL ' \ + 'AND "in_product_marketing_emails"."series" = 0 ' \ + 'AND "in_product_marketing_emails"."track" = 1' end before do diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/in_product_marketing_email_sent_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/in_product_marketing_email_sent_metric_spec.rb index 0cc82773d56..3c51368f396 100644 --- a/spec/lib/gitlab/usage/metrics/instrumentations/in_product_marketing_email_sent_metric_spec.rb +++ b/spec/lib/gitlab/usage/metrics/instrumentations/in_product_marketing_email_sent_metric_spec.rb @@ -8,9 +8,9 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::InProductMarketingEmail let(:email_attributes) { { track: 'verify', series: 0 } } let(:expected_value) { 2 } let(:expected_query) do - 'SELECT COUNT("in_product_marketing_emails"."id") FROM "in_product_marketing_emails"' \ - ' WHERE "in_product_marketing_emails"."series" = 0'\ - ' AND "in_product_marketing_emails"."track" = 1' + 'SELECT COUNT("in_product_marketing_emails"."id") FROM "in_product_marketing_emails" ' \ + 'WHERE "in_product_marketing_emails"."series" = 0 ' \ + 'AND "in_product_marketing_emails"."track" = 1' end before do diff --git a/spec/models/concerns/reset_on_column_errors_spec.rb b/spec/models/concerns/reset_on_column_errors_spec.rb new file mode 100644 index 00000000000..d7211a751b7 --- /dev/null +++ b/spec/models/concerns/reset_on_column_errors_spec.rb @@ -0,0 +1,186 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe ResetOnColumnErrors, :delete, feature_category: :shared do + let(:test_attribute_table) do + Class.new(ApplicationRecord) do + include FromUnion + + self.table_name = '_test_attribute_table' + + def self.name + 'TestAttributeTable' + end + end + end + + before(:context) do + ApplicationRecord.connection.execute(<<~SQL) + CREATE TABLE _test_attribute_table ( + id serial NOT NULL PRIMARY KEY, + created_at timestamptz NOT NULL + ); + SQL + end + + after(:context) do + ApplicationRecord.connection.execute(<<~SQL) + DROP TABLE _test_attribute_table + SQL + end + + describe 'resetting on union errors' do + let(:expected_error_message) { /must have the same number of columns/ } + + def load_query + scopes = [ + test_attribute_table.select('*'), + test_attribute_table.select(test_attribute_table.column_names.join(',')) + ] + + test_attribute_table.from_union(scopes).load + end + + context 'with mismatched columns due to schema cache' do + before do + load_query + + ApplicationRecord.connection.execute(<<~SQL) + ALTER TABLE _test_attribute_table ADD COLUMN _test_new_column int; + SQL + end + + after do + ApplicationRecord.connection.execute(<<~SQL) + ALTER TABLE _test_attribute_table DROP COLUMN _test_new_column; + SQL + + test_attribute_table.reset_column_information + end + + it 'resets column information when encountering an UNION error' do + expect do + load_query + end.to raise_error(ActiveRecord::StatementInvalid, expected_error_message) + .and change { test_attribute_table.column_names } + .from(%w[id created_at]).to(%w[id created_at _test_new_column]) + + # Subsequent query load from new schema cache, so no more error + expect do + load_query + end.not_to raise_error + end + + it 'logs when column is reset' do + expect(Gitlab::ErrorTracking::Logger).to receive(:error) + .with(hash_including("extra.reset_model_name" => "TestAttributeTable")) + .and_call_original + + expect do + load_query + end.to raise_error(ActiveRecord::StatementInvalid, expected_error_message) + end + end + + context 'with mismatched columns due to coding error' do + def load_mismatched_query + scopes = [ + test_attribute_table.select("id"), + test_attribute_table.select("id, created_at") + ] + + test_attribute_table.from_union(scopes).load + end + + it 'limits reset_column_information calls' do + expect(test_attribute_table).to receive(:reset_column_information).and_call_original + + expect do + load_mismatched_query + end.to raise_error(ActiveRecord::StatementInvalid, expected_error_message) + + expect(test_attribute_table).not_to receive(:reset_column_information) + + expect do + load_mismatched_query + end.to raise_error(ActiveRecord::StatementInvalid, expected_error_message) + end + + it 'does reset_column_information after some time has passed' do + expect do + load_mismatched_query + end.to raise_error(ActiveRecord::StatementInvalid, expected_error_message) + + travel_to(described_class::MAX_RESET_PERIOD.from_now + 1.minute) + expect(test_attribute_table).to receive(:reset_column_information).and_call_original + + expect do + load_mismatched_query + end.to raise_error(ActiveRecord::StatementInvalid, expected_error_message) + end + end + end + + describe 'resetting on missing column error on save' do + let(:expected_error_message) { /unknown attribute '_test_new_column'/ } + + context 'with mismatched columns due to schema cache' do + let!(:attrs) { test_attribute_table.new.attributes } + + def initialize_with_new_column + test_attribute_table.new(attrs.merge(_test_new_column: 123)) + end + + before do + ApplicationRecord.connection.execute(<<~SQL) + ALTER TABLE _test_attribute_table ADD COLUMN _test_new_column int; + SQL + end + + after do + ApplicationRecord.connection.execute(<<~SQL) + ALTER TABLE _test_attribute_table DROP COLUMN _test_new_column; + SQL + + test_attribute_table.reset_column_information + end + + it 'resets column information when encountering an UnknownAttributeError' do + expect do + initialize_with_new_column + end.to raise_error(ActiveModel::UnknownAttributeError, expected_error_message) + .and change { test_attribute_table.column_names } + .from(%w[id created_at]).to(%w[id created_at _test_new_column]) + + # Subsequent query load from new schema cache, so no more error + expect do + initialize_with_new_column + end.not_to raise_error + end + + it 'logs when column is reset' do + expect(Gitlab::ErrorTracking::Logger).to receive(:error) + .with(hash_including("extra.reset_model_name" => "TestAttributeTable")) + .and_call_original + + expect do + initialize_with_new_column + end.to raise_error(ActiveModel::UnknownAttributeError, expected_error_message) + end + + context 'when reset_column_information_on_statement_invalid FF is disabled' do + before do + stub_feature_flags(reset_column_information_on_statement_invalid: false) + end + + it 'does not reset column information' do + expect do + initialize_with_new_column + end.to raise_error(ActiveModel::UnknownAttributeError, expected_error_message) + .and not_change { test_attribute_table.column_names } + end + end + end + end +end diff --git a/spec/models/concerns/reset_on_union_error_spec.rb b/spec/models/concerns/reset_on_union_error_spec.rb deleted file mode 100644 index 70993b92c90..00000000000 --- a/spec/models/concerns/reset_on_union_error_spec.rb +++ /dev/null @@ -1,132 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe ResetOnUnionError, :delete, feature_category: :shared do - let(:test_unioned_model) do - Class.new(ApplicationRecord) do - include FromUnion - - self.table_name = '_test_unioned_model' - - def self.name - 'TestUnion' - end - end - end - - before(:context) do - ApplicationRecord.connection.execute(<<~SQL) - CREATE TABLE _test_unioned_model ( - id serial NOT NULL PRIMARY KEY, - created_at timestamptz NOT NULL - ); - SQL - end - - after(:context) do - ApplicationRecord.connection.execute(<<~SQL) - DROP TABLE _test_unioned_model - SQL - end - - context 'with mismatched columns due to schema cache' do - def load_query - scopes = [ - test_unioned_model.select('*'), - test_unioned_model.select(test_unioned_model.column_names.join(',')) - ] - - test_unioned_model.from_union(scopes).load - end - - before do - load_query - - ApplicationRecord.connection.execute(<<~SQL) - ALTER TABLE _test_unioned_model ADD COLUMN _test_new_column int; - SQL - end - - after do - ApplicationRecord.connection.execute(<<~SQL) - ALTER TABLE _test_unioned_model DROP COLUMN _test_new_column; - SQL - - test_unioned_model.reset_column_information - end - - it 'resets column information when encountering an UNION error' do - expect do - load_query - end.to raise_error(ActiveRecord::StatementInvalid, /must have the same number of columns/) - .and change { test_unioned_model.column_names }.from(%w[id created_at]).to(%w[id created_at _test_new_column]) - - # Subsequent query load from new schema cache, so no more error - expect do - load_query - end.not_to raise_error - end - - it 'logs when column is reset' do - expect(Gitlab::ErrorTracking::Logger).to receive(:error) - .with(hash_including("extra.reset_model_name" => "TestUnion")) - .and_call_original - - expect do - load_query - end.to raise_error(ActiveRecord::StatementInvalid, /must have the same number of columns/) - end - - context 'when reset_column_information_on_statement_invalid FF is disabled' do - before do - stub_feature_flags(reset_column_information_on_statement_invalid: false) - end - - it 'does not reset column information' do - expect do - load_query - end.to raise_error(ActiveRecord::StatementInvalid, /must have the same number of columns/) - .and not_change { test_unioned_model.column_names } - end - end - end - - context 'with mismatched columns due to coding error' do - def load_mismatched_query - scopes = [ - test_unioned_model.select("id"), - test_unioned_model.select("id, created_at") - ] - - test_unioned_model.from_union(scopes).load - end - - it 'limits reset_column_information calls' do - expect(test_unioned_model).to receive(:reset_column_information).and_call_original - - expect do - load_mismatched_query - end.to raise_error(ActiveRecord::StatementInvalid, /must have the same number of columns/) - - expect(test_unioned_model).not_to receive(:reset_column_information) - - expect do - load_mismatched_query - end.to raise_error(ActiveRecord::StatementInvalid, /must have the same number of columns/) - end - - it 'does reset_column_information after some time has passed' do - expect do - load_mismatched_query - end.to raise_error(ActiveRecord::StatementInvalid, /must have the same number of columns/) - - travel_to(described_class::MAX_RESET_PERIOD.from_now + 1.minute) - expect(test_unioned_model).to receive(:reset_column_information).and_call_original - - expect do - load_mismatched_query - end.to raise_error(ActiveRecord::StatementInvalid, /must have the same number of columns/) - end - end -end diff --git a/spec/models/users/in_product_marketing_email_spec.rb b/spec/models/users/in_product_marketing_email_spec.rb index 78de9ad8bdb..21cf50a63ab 100644 --- a/spec/models/users/in_product_marketing_email_spec.rb +++ b/spec/models/users/in_product_marketing_email_spec.rb @@ -15,7 +15,7 @@ RSpec.describe Users::InProductMarketingEmail, type: :model do it { is_expected.to validate_presence_of(:user) } - context 'for a track+series email' do + context 'when track+series email' do it { is_expected.to validate_presence_of(:track) } it { is_expected.to validate_presence_of(:series) } @@ -25,7 +25,7 @@ RSpec.describe Users::InProductMarketingEmail, type: :model do } end - context 'for a campaign email' do + context 'when campaign email' do subject { build(:in_product_marketing_email, :campaign) } it { is_expected.to validate_presence_of(:campaign) } @@ -78,12 +78,9 @@ RSpec.describe Users::InProductMarketingEmail, type: :model do context 'when no track or series for a user exists' do let(:track) { :create } let(:series) { 0 } + let(:other_user) { create(:user) } - before do - @other_user = create(:user) - end - - it { expect(without_track_and_series).to eq [@other_user] } + it { expect(without_track_and_series).to eq [other_user] } end end @@ -112,7 +109,9 @@ RSpec.describe Users::InProductMarketingEmail, type: :model do let_it_be(:user) { create(:user) } let_it_be(:in_product_marketing_email) { create(:in_product_marketing_email, series: 0, track: 0, user: user) } - subject(:for_user_with_track_and_series) { described_class.for_user_with_track_and_series(user, track, series).first } + subject(:for_user_with_track_and_series) do + described_class.for_user_with_track_and_series(user, track, series).first + end context 'when record for user with given track and series exists' do it { is_expected.to eq(in_product_marketing_email) } @@ -165,7 +164,7 @@ RSpec.describe Users::InProductMarketingEmail, type: :model do end end - context 'cta_clicked_at is already set' do + context 'when cta_clicked_at is already set' do it 'does not update' do create(:in_product_marketing_email, user: user, track: track, series: series, cta_clicked_at: Time.zone.now) diff --git a/spec/services/bulk_imports/file_download_service_spec.rb b/spec/services/bulk_imports/file_download_service_spec.rb index 2197b0b4fac..1734ea45507 100644 --- a/spec/services/bulk_imports/file_download_service_spec.rb +++ b/spec/services/bulk_imports/file_download_service_spec.rb @@ -76,7 +76,7 @@ RSpec.describe BulkImports::FileDownloadService, feature_category: :importers do allowed_content_types: allowed_content_types ) - expect { service.execute }.to raise_error(Gitlab::UrlBlocker::BlockedUrlError) + expect { service.execute }.to raise_error(Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError) end end diff --git a/spec/support/rspec_order_todo.yml b/spec/support/rspec_order_todo.yml index 298f4006c3b..37de6bb6957 100644 --- a/spec/support/rspec_order_todo.yml +++ b/spec/support/rspec_order_todo.yml @@ -7975,7 +7975,6 @@ - './spec/models/users/callout_spec.rb' - './spec/models/users/credit_card_validation_spec.rb' - './spec/models/users/group_callout_spec.rb' -- './spec/models/users/in_product_marketing_email_spec.rb' - './spec/models/users/merge_request_interaction_spec.rb' - './spec/models/user_spec.rb' - './spec/models/users/project_callout_spec.rb' @@ -9590,7 +9589,6 @@ - './spec/services/users/dismiss_project_callout_service_spec.rb' - './spec/services/users/email_verification/generate_token_service_spec.rb' - './spec/services/users/email_verification/validate_token_service_spec.rb' -- './spec/services/users/in_product_marketing_email_records_spec.rb' - './spec/services/users/keys_count_service_spec.rb' - './spec/services/users/last_push_event_service_spec.rb' - './spec/services/users/refresh_authorized_projects_service_spec.rb' diff --git a/spec/support/shared_examples/config/metrics/every_metric_definition_shared_examples.rb b/spec/support/shared_examples/config/metrics/every_metric_definition_shared_examples.rb index d9c624a5747..f03a9302bca 100644 --- a/spec/support/shared_examples/config/metrics/every_metric_definition_shared_examples.rb +++ b/spec/support/shared_examples/config/metrics/every_metric_definition_shared_examples.rb @@ -126,10 +126,23 @@ RSpec.shared_examples 'every metric definition' do ].freeze end + let(:removed_classes) do + [ + Gitlab::Usage::Metrics::Instrumentations::InProductMarketingEmailCtaClickedMetric, + Gitlab::Usage::Metrics::Instrumentations::InProductMarketingEmailSentMetric + ].freeze + end + + def metric_not_used?(constant) + parent_metric_classes.include?(constant) || + ignored_classes.include?(constant) || + removed_classes.include?(constant) + end + def assert_uses_all_nested_classes(parent_module) parent_module.constants(false).each do |const_name| constant = parent_module.const_get(const_name, false) - next if parent_metric_classes.include?(constant) || ignored_classes.include?(constant) + next if metric_not_used?(constant) case constant when Class |