From a060caf3db3090d75284a71a08ab1cf697afad97 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Tue, 5 Jan 2021 09:10:15 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .../components/alerts_service_form.vue | 14 -- .../javascripts/lib/utils/datetime_utility.js | 17 +++ app/views/projects/services/_form.html.haml | 6 +- .../shared/integrations/_index.html.haml | 3 +- ...-be-removed-from-the-integrations-list.yml | 5 + .../deprecate-prometheus-listen-address.yml | 5 + config/gitlab.yml.example | 9 +- config/initializers/1_settings.rb | 12 ++ config/metrics/counts_28d/deployments.yml | 15 +++ ..._management_issue_title_changed_weekly.yml | 16 +++ config/metrics/counts_all/deployments.yml | 15 +++ config/metrics/license/recorded_at.yml | 16 +++ config/metrics/license/uuid.yml | 17 +++ config/metrics/schema.json | 66 ++++++++++ config/metrics/settings/database_adapter.yml | 14 ++ lib/gitlab/danger/commit_linter.rb | 12 +- lib/gitlab/danger/merge_request_linter.rb | 8 +- .../self_monitoring/project/create_service.rb | 12 +- lib/gitlab/prometheus/internal.rb | 28 ++-- lib/gitlab/usage/metric.rb | 43 ++++++ lib/gitlab/usage/metric_definition.rb | 84 ++++++++++++ lib/gitlab/utils/usage_data.rb | 3 +- locale/gitlab.pot | 9 ++ .../services/user_activates_alerts_spec.rb | 6 - .../components/alerts_service_form_spec.js | 12 -- .../lib/utils/datetime_utility_spec.js | 25 ++++ .../project/create_service_spec.rb | 30 ++--- spec/lib/gitlab/prometheus/internal_spec.rb | 48 ++----- .../gitlab/usage/metric_definition_spec.rb | 123 ++++++++++++++++++ spec/lib/gitlab/usage/metric_spec.rb | 29 +++++ spec/lib/gitlab/utils/usage_data_spec.rb | 2 +- .../prometheus_service_spec.rb | 4 +- 32 files changed, 586 insertions(+), 122 deletions(-) create mode 100644 changelogs/unreleased/212925-power-icon-should-be-removed-from-the-integrations-list.yml create mode 100644 changelogs/unreleased/deprecate-prometheus-listen-address.yml create mode 100644 config/metrics/counts_28d/deployments.yml create mode 100644 config/metrics/counts_7d/g_project_management_issue_title_changed_weekly.yml create mode 100644 config/metrics/counts_all/deployments.yml create mode 100644 config/metrics/license/recorded_at.yml create mode 100644 config/metrics/license/uuid.yml create mode 100644 config/metrics/schema.json create mode 100644 config/metrics/settings/database_adapter.yml create mode 100644 lib/gitlab/usage/metric.rb create mode 100644 lib/gitlab/usage/metric_definition.rb create mode 100644 spec/lib/gitlab/usage/metric_definition_spec.rb create mode 100644 spec/lib/gitlab/usage/metric_spec.rb diff --git a/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue b/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue index 576ea2c543a..c0e93d315a4 100644 --- a/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue +++ b/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue @@ -91,21 +91,7 @@ export default { ]; }, }, - watch: { - activated() { - this.updateIcon(); - }, - }, methods: { - updateIcon() { - return document.querySelectorAll('.js-service-active-status').forEach((icon) => { - if (icon.dataset.value === this.activated.toString()) { - icon.classList.remove('d-none'); - } else { - icon.classList.add('d-none'); - } - }); - }, resetKey() { return axios .put(this.formPath, { service: { token: '' } }) diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js index 1be84d9351d..f296f25457a 100644 --- a/app/assets/javascripts/lib/utils/datetime_utility.js +++ b/app/assets/javascripts/lib/utils/datetime_utility.js @@ -806,3 +806,20 @@ export const dateAtFirstDayOfMonth = (date) => new Date(newDate(date).setDate(1) * @return {Boolean} true if the dates match */ export const datesMatch = (date1, date2) => differenceInMilliseconds(date1, date2) === 0; + +/** + * A utility function which computes a formatted 24 hour + * time string from a positive int in the range 0 - 24. + * + * @param {Int} time a positive Int between 0 and 24 + * + * @returns {String} formatted 24 hour time String + */ +export const format24HourTimeStringFromInt = (time) => { + if (!Number.isInteger(time) || time < 0 || time > 24) { + return ''; + } + + const formatted24HourString = time > 9 ? `${time}:00` : `0${time}:00`; + return formatted24HourString; +}; diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml index 2b1e08f4880..59b3afa476f 100644 --- a/app/views/projects/services/_form.html.haml +++ b/app/views/projects/services/_form.html.haml @@ -5,10 +5,8 @@ .col-lg-4 %h3.page-title.gl-mt-0 = @service.title - - [true, false].each do |value| - - hide_class = 'd-none' if @service.operating? != value - %span.js-service-active-status{ class: hide_class, data: { value: value.to_s } } - = boolean_to_icon value + - if @service.operating? + = sprite_icon('check', css_class: 'gl-text-green-500') - if @service.respond_to?(:detailed_description) %p= @service.detailed_description diff --git a/app/views/shared/integrations/_index.html.haml b/app/views/shared/integrations/_index.html.haml index edc85f04d91..ccc2c448f69 100644 --- a/app/views/shared/integrations/_index.html.haml +++ b/app/views/shared/integrations/_index.html.haml @@ -16,7 +16,8 @@ - activated_label = (integration.activated? ? s_("ProjectService|%{service_title}: status on") : s_("ProjectService|%{service_title}: status off")) % { service_title: integration.title } %tr{ role: 'row' } %td{ role: 'cell', 'aria-colindex': 1, 'aria-label': activated_label, title: activated_label } - = boolean_to_icon integration.operating? + - if integration.operating? + = sprite_icon('check', css_class: 'gl-text-green-500') %td{ role: 'cell', 'aria-colindex': 2 } = link_to integration.title, scoped_edit_integration_path(integration), class: 'gl-font-weight-bold', data: { qa_selector: "#{integration.to_param}_link" } %td.d-none.d-sm-table-cell{ role: 'cell', 'aria-colindex': 3 } diff --git a/changelogs/unreleased/212925-power-icon-should-be-removed-from-the-integrations-list.yml b/changelogs/unreleased/212925-power-icon-should-be-removed-from-the-integrations-list.yml new file mode 100644 index 00000000000..fd5e13d8b64 --- /dev/null +++ b/changelogs/unreleased/212925-power-icon-should-be-removed-from-the-integrations-list.yml @@ -0,0 +1,5 @@ +--- +title: Remove inactive integrations indicator in index and show pages +merge_request: 50753 +author: +type: changed diff --git a/changelogs/unreleased/deprecate-prometheus-listen-address.yml b/changelogs/unreleased/deprecate-prometheus-listen-address.yml new file mode 100644 index 00000000000..2c0c0b84663 --- /dev/null +++ b/changelogs/unreleased/deprecate-prometheus-listen-address.yml @@ -0,0 +1,5 @@ +--- +title: Deprecate prometheus.listen_address and prometheus.enable +merge_request: 50500 +author: +type: deprecated diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 57788e55f8f..1cd162f909a 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -1207,10 +1207,7 @@ production: &base # yourself, and then update the values here. # https://docs.gitlab.com/ee/administration/monitoring/prometheus/ prometheus: - # Do not use `enable` and `listen_address` in any new code, as they are deprecated. Use `server_address` instead. - # https://gitlab.com/gitlab-org/gitlab/-/issues/227111 - # enable: true - # listen_address: 'localhost:9090' + # enabled: true # server_address: 'localhost:9090' ## Consul settings @@ -1499,8 +1496,8 @@ test: group_base: 'ou=groups,dc=example,dc=com' admin_group: '' prometheus: - enable: true - listen_address: 'localhost:9090' + enabled: true + server_address: 'localhost:9090' staging: <<: *base diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 97c0e051f1f..752309ff370 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -851,6 +851,18 @@ Settings.monitoring.web_exporter['enabled'] ||= false Settings.monitoring.web_exporter['address'] ||= 'localhost' Settings.monitoring.web_exporter['port'] ||= 8083 +# +# Prometheus settings +# +Settings['prometheus'] ||= Settingslogic.new({}) +# TODO: Remove listen_address and enable in GitLab 14.0 and set default value +# of server_address to be nil and enabled to be false - +# https://gitlab.com/gitlab-org/gitlab/-/issues/296022 +Settings.prometheus['enable'] ||= false +Settings.prometheus['listen_address'] ||= nil +Settings.prometheus['enabled'] = Settings.prometheus['enable'] if Settings.prometheus['enabled'].nil? +Settings.prometheus['server_address'] ||= Settings.prometheus['listen_address'] + # # Shutdown settings # diff --git a/config/metrics/counts_28d/deployments.yml b/config/metrics/counts_28d/deployments.yml new file mode 100644 index 00000000000..dabd50ef5be --- /dev/null +++ b/config/metrics/counts_28d/deployments.yml @@ -0,0 +1,15 @@ +name: deployments +description: Total deployments count for recent 28 days +value_type: integer +stage: release +status: data_available +default_generation: generation_1 +full_path: + generation_1: counts_monthy.deployments +milestone: 13.2 +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35493 +group: 'group::ops release' +time_frame: 28d +data_source: database +distribution: [ee, ce] +tier: ['free', 'starter', 'premium', 'ultimate', 'bronze', 'silver', 'gold'] diff --git a/config/metrics/counts_7d/g_project_management_issue_title_changed_weekly.yml b/config/metrics/counts_7d/g_project_management_issue_title_changed_weekly.yml new file mode 100644 index 00000000000..997263f9e30 --- /dev/null +++ b/config/metrics/counts_7d/g_project_management_issue_title_changed_weekly.yml @@ -0,0 +1,16 @@ +name: g_project_management_issue_title_changed_weekly +description: Distinct users count that changed issue title in a group for last recent week +value_type: integer +product_category: issue_tracking +stage: plan +status: data_available +default_generation: generation_1 +full_path: + generation_1: redis_hll_counters.issues_edit.g_project_management_issue_title_changed_weekly +milestone: 13.6 +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/229918 +group: 'group::project management' +time_frame: 7d +data_source: redis_hll +distribution: [ee, ce] +tier: ['free', 'starter', 'premium', 'ultimate', 'bronze', 'silver', 'gold'] diff --git a/config/metrics/counts_all/deployments.yml b/config/metrics/counts_all/deployments.yml new file mode 100644 index 00000000000..bb78e8d6144 --- /dev/null +++ b/config/metrics/counts_all/deployments.yml @@ -0,0 +1,15 @@ +name: deployments +description: Total deployments count +value_type: integer +stage: release +status: data_available +default_generation: generation_1 +full_path: + generation_1: counts.deployments +milestone: 8.12 +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/735 +group: 'group::ops release' +time_frame: all +data_source: database +distribution: [ee, ce] +tier: ['free', 'starter', 'premium', 'ultimate', 'bronze', 'silver', 'gold'] diff --git a/config/metrics/license/recorded_at.yml b/config/metrics/license/recorded_at.yml new file mode 100644 index 00000000000..5b2b3b37290 --- /dev/null +++ b/config/metrics/license/recorded_at.yml @@ -0,0 +1,16 @@ +name: recorded_at +description: When the Usage Ping computation was started +value_type: string +product_category: collection +stage: growth +status: data_available +default_generation: generation_1 +full_path: + generation_1: recorded_at +milestone: 8.10 +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/557 +group: group::product analytics +time_frame: none +data_source: ruby +distribution: [ee, ce] +tier: ['free', 'starter', 'premium', 'ultimate', 'bronze', 'silver', 'gold'] diff --git a/config/metrics/license/uuid.yml b/config/metrics/license/uuid.yml new file mode 100644 index 00000000000..38e0d74fc22 --- /dev/null +++ b/config/metrics/license/uuid.yml @@ -0,0 +1,17 @@ +name: uuid +description: GitLab instance unique identifier +value_type: string +product_category: collection +stage: growth +status: data_available +default_generation: generation_1 +full_path: + generation_1: uuid + generation_2: license.uuid +milestone: 9.1 +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1521 +group: group::product analytics +time_frame: none +data_source: database +distribution: [ee, ce] +tier: ['free', 'starter', 'premium', 'ultimate', 'bronze', 'silver', 'gold'] diff --git a/config/metrics/schema.json b/config/metrics/schema.json new file mode 100644 index 00000000000..4d1120a7d8d --- /dev/null +++ b/config/metrics/schema.json @@ -0,0 +1,66 @@ +{ + "type": "object", + "required": ["name", "description", "value_type", "status", "default_generation", "full_path", "group", "time_frame", "data_source", "distribution", "tier"], + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "value_type": { + "type": "string", + "enum": ["integer", "string", "number", "boolean"] + }, + "product_category": { + "type": ["string", "null"] + }, + "stage": { + "type": ["string", "null"] + }, + "status": { + "type": ["string"], + "enum": ["data_available", "planned", "in_progress", "implmented"] + }, + "default_generation": { + "type": "string" + }, + "full_path": { + "type": "object" + }, + "milestone": { + "type": ["number", "null"] + }, + "milestone_removed": { + "type": ["number", "null"] + }, + "introduced_by_url": { + "type": ["string", "null"] + }, + "group": { + "type": "string" + }, + "time_frame": { + "type": "string", + "enum": ["7d", "28d", "all", "none"] + }, + "data_source": { + "type": "string", + "enum": ["database", "redis", "redis_hll", "prometheus", "ruby"] + }, + "distribution": { + "type": "array", + "items": { + "type": "string", + "enum": ["ee", "ce"] + } + }, + "tier": { + "type": "array", + "items": { + "type": "string", + "enum": ["free", "starter", "premium", "ultimate", "bronze", "silver", "gold"] + } + } + } +} diff --git a/config/metrics/settings/database_adapter.yml b/config/metrics/settings/database_adapter.yml new file mode 100644 index 00000000000..b24fc933a08 --- /dev/null +++ b/config/metrics/settings/database_adapter.yml @@ -0,0 +1,14 @@ +name: adapter +description: This metric only returns a value of PostgreSQL in supported versions of GitLab. It could be removed from the usage ping. Historically MySQL was also supported. +value_type: string +product_category: collection +stage: growth +status: data_available +default_generation: generation_1 +full_path: + generation_1: database.adapter +group: group::enablement distribution +time_frame: none +data_source: database +distribution: [ee, ce] +tier: ['free', 'starter', 'premium', 'ultimate', 'bronze', 'silver', 'gold'] diff --git a/lib/gitlab/danger/commit_linter.rb b/lib/gitlab/danger/commit_linter.rb index 7e2e0fb0acb..e23f5900433 100644 --- a/lib/gitlab/danger/commit_linter.rb +++ b/lib/gitlab/danger/commit_linter.rb @@ -1,9 +1,15 @@ # frozen_string_literal: true -require_relative 'base_linter' - emoji_checker_path = File.expand_path('emoji_checker', __dir__) -defined?(Rails) ? require_dependency(emoji_checker_path) : require_relative(emoji_checker_path) +base_linter_path = File.expand_path('base_linter', __dir__) + +if defined?(Rails) + require_dependency(base_linter_path) + require_dependency(emoji_checker_path) +else + require_relative(base_linter_path) + require_relative(emoji_checker_path) +end module Gitlab module Danger diff --git a/lib/gitlab/danger/merge_request_linter.rb b/lib/gitlab/danger/merge_request_linter.rb index d401d332aa7..ed354bfc68d 100644 --- a/lib/gitlab/danger/merge_request_linter.rb +++ b/lib/gitlab/danger/merge_request_linter.rb @@ -1,6 +1,12 @@ # frozen_string_literal: true -require_relative 'base_linter' +base_linter_path = File.expand_path('base_linter', __dir__) + +if defined?(Rails) + require_dependency(base_linter_path) +else + require_relative(base_linter_path) +end module Gitlab module Danger diff --git a/lib/gitlab/database_importers/self_monitoring/project/create_service.rb b/lib/gitlab/database_importers/self_monitoring/project/create_service.rb index b1093b2fca4..d1ada8c723e 100644 --- a/lib/gitlab/database_importers/self_monitoring/project/create_service.rb +++ b/lib/gitlab/database_importers/self_monitoring/project/create_service.rb @@ -75,7 +75,7 @@ module Gitlab if response # In the add_prometheus_manual_configuration method, the Prometheus - # listen_address config is saved as an api_url in the PrometheusService + # server_address config is saved as an api_url in the PrometheusService # model. There are validates hooks in the PrometheusService model that # check if the project associated with the PrometheusService is the # self_monitoring project. It checks @@ -105,7 +105,7 @@ module Gitlab def add_prometheus_manual_configuration(result) return success(result) unless prometheus_enabled? - return success(result) unless prometheus_listen_address.present? + return success(result) unless prometheus_server_address.present? service = result[:project].find_or_initialize_service('prometheus') @@ -132,8 +132,8 @@ module Gitlab ::Gitlab::Prometheus::Internal.prometheus_enabled? end - def prometheus_listen_address - ::Gitlab::Prometheus::Internal.listen_address + def prometheus_server_address + ::Gitlab::Prometheus::Internal.server_address end def docs_path @@ -152,13 +152,13 @@ module Gitlab } end - def internal_prometheus_listen_address_uri + def internal_prometheus_server_address_uri ::Gitlab::Prometheus::Internal.uri end def prometheus_service_attributes { - api_url: internal_prometheus_listen_address_uri, + api_url: internal_prometheus_server_address_uri, manual_configuration: true, active: true } diff --git a/lib/gitlab/prometheus/internal.rb b/lib/gitlab/prometheus/internal.rb index c2f4035821e..fe06b97add6 100644 --- a/lib/gitlab/prometheus/internal.rb +++ b/lib/gitlab/prometheus/internal.rb @@ -4,43 +4,39 @@ module Gitlab module Prometheus class Internal def self.uri - return if listen_address.blank? + return if server_address.blank? - if listen_address.starts_with?('0.0.0.0:') + if server_address.starts_with?('0.0.0.0:') # 0.0.0.0:9090 - port = ':' + listen_address.split(':').second + port = ':' + server_address.split(':').second 'http://localhost' + port - elsif listen_address.starts_with?(':') + elsif server_address.starts_with?(':') # :9090 - 'http://localhost' + listen_address + 'http://localhost' + server_address - elsif listen_address.starts_with?('http') + elsif server_address.starts_with?('http') # https://localhost:9090 - listen_address + server_address else # localhost:9090 - 'http://' + listen_address + 'http://' + server_address end end def self.server_address - uri&.strip&.sub(/^http[s]?:\/\//, '') - end - - def self.listen_address - Gitlab.config.prometheus.listen_address.to_s if Gitlab.config.prometheus + Gitlab.config.prometheus.server_address.to_s if Gitlab.config.prometheus rescue Settingslogic::MissingSetting - Gitlab::AppLogger.error('Prometheus listen_address is not present in config/gitlab.yml') + Gitlab::AppLogger.error('Prometheus server_address is not present in config/gitlab.yml') nil end def self.prometheus_enabled? - Gitlab.config.prometheus.enable if Gitlab.config.prometheus + Gitlab.config.prometheus.enabled if Gitlab.config.prometheus rescue Settingslogic::MissingSetting - Gitlab::AppLogger.error('prometheus.enable is not present in config/gitlab.yml') + Gitlab::AppLogger.error('prometheus.enabled is not present in config/gitlab.yml') false end diff --git a/lib/gitlab/usage/metric.rb b/lib/gitlab/usage/metric.rb new file mode 100644 index 00000000000..e1648c78168 --- /dev/null +++ b/lib/gitlab/usage/metric.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +module Gitlab + module Usage + class Metric + include ActiveModel::Model + + InvalidMetricError = Class.new(RuntimeError) + + attr_accessor :default_generation_path, :value + + validates :default_generation_path, presence: true + + def definition + self.class.definitions[default_generation_path] + end + + def unflatten_default_path + unflatten(default_generation_path.split('.'), value) + end + + class << self + def definitions + @definitions ||= Gitlab::Usage::MetricDefinition.definitions + end + + def dictionary + definitions.map { |key, definition| definition.to_dictionary } + end + end + + private + + def unflatten(keys, value) + loop do + value = { keys.pop.to_sym => value } + break if keys.blank? + end + value + end + end + end +end diff --git a/lib/gitlab/usage/metric_definition.rb b/lib/gitlab/usage/metric_definition.rb new file mode 100644 index 00000000000..e57d154e46f --- /dev/null +++ b/lib/gitlab/usage/metric_definition.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: true + +module Gitlab + module Usage + class MetricDefinition + METRIC_SCHEMA_PATH = Rails.root.join('config', 'metrics', 'schema.json') + + attr_reader :path + attr_reader :attributes + + def initialize(path, opts = {}) + @path = path + @attributes = opts + end + + # The key is defined by default_generation and full_path + def key + full_path[default_generation.to_sym] + end + + def to_h + attributes + end + + def validate! + self.class.schemer.validate(attributes.stringify_keys).map do |error| + Gitlab::ErrorTracking.track_and_raise_for_dev_exception(Metric::InvalidMetricError.new("#{error["details"] || error['data_pointer']} for `#{path}`")) + end + end + + alias_method :to_dictionary, :to_h + + class << self + def paths + @paths ||= [Rails.root.join('config', 'metrics', '**', '*.yml')] + end + + def definitions + @definitions ||= load_all! + end + + def schemer + @schemer ||= ::JSONSchemer.schema(Pathname.new(METRIC_SCHEMA_PATH)) + end + + private + + def load_all! + paths.each_with_object({}) do |glob_path, definitions| + load_all_from_path!(definitions, glob_path) + end + end + + def load_from_file(path) + definition = File.read(path) + definition = YAML.safe_load(definition) + definition.deep_symbolize_keys! + + self.new(path, definition).tap(&:validate!) + rescue => e + Gitlab::ErrorTracking.track_and_raise_for_dev_exception(Metric::InvalidMetricError.new(e.message)) + end + + def load_all_from_path!(definitions, glob_path) + Dir.glob(glob_path).each do |path| + definition = load_from_file(path) + + if previous = definitions[definition.key] + Gitlab::ErrorTracking.track_and_raise_for_dev_exception(Metric::InvalidMetricError.new("Metric '#{definition.key}' is already defined in '#{previous.path}'")) + end + + definitions[definition.key] = definition + end + end + end + + private + + def method_missing(method, *args) + attributes[method] || super + end + end + end +end diff --git a/lib/gitlab/utils/usage_data.rb b/lib/gitlab/utils/usage_data.rb index 261fc6fbdbd..9ed0dfde7fe 100644 --- a/lib/gitlab/utils/usage_data.rb +++ b/lib/gitlab/utils/usage_data.rb @@ -145,7 +145,8 @@ module Gitlab def prometheus_server_address if Gitlab::Prometheus::Internal.prometheus_enabled? - Gitlab::Prometheus::Internal.server_address + # Stripping protocol from URI + Gitlab::Prometheus::Internal.uri&.strip&.sub(%r{^https?://}, '') elsif Gitlab::Consul::Internal.api_url Gitlab::Consul::Internal.discover_prometheus_server_address end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index db1f67a8f77..b4d3d0e23cf 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -19535,6 +19535,15 @@ msgstr "" msgid "OnCallSchedules|Sets the default timezone for the schedule, for all participants" msgstr "" +msgid "OnCallSchedules|Successfully created a new rotation" +msgstr "" + +msgid "OnCallSchedules|Successfully edited your rotation" +msgstr "" + +msgid "OnCallSchedules|The rotation could not be updated. Please try again." +msgstr "" + msgid "OnCallSchedules|The schedule could not be deleted. Please try again." msgstr "" diff --git a/spec/features/projects/services/user_activates_alerts_spec.rb b/spec/features/projects/services/user_activates_alerts_spec.rb index 8b0acdf3618..e8eddea8ed0 100644 --- a/spec/features/projects/services/user_activates_alerts_spec.rb +++ b/spec/features/projects/services/user_activates_alerts_spec.rb @@ -22,7 +22,6 @@ RSpec.describe 'User activates Alerts', :js do click_link(service_title) expect(page).to have_callout_message - expect(page).not_to have_active_service expect(page).to have_toggle_active_disabled end end @@ -38,7 +37,6 @@ RSpec.describe 'User activates Alerts', :js do it 'user cannot change settings' do expect(page).to have_callout_message - expect(page).to have_active_service expect(page).to have_toggle_active_disabled expect(page).to have_button_reset_key_disabled end @@ -60,10 +58,6 @@ RSpec.describe 'User activates Alerts', :js do end end - def have_active_service - have_selector('.js-service-active-status[data-value="true"]') - end - def have_toggle_active_disabled have_selector('#activated .project-feature-toggle.is-disabled') end diff --git a/spec/frontend/alerts_service_settings/components/alerts_service_form_spec.js b/spec/frontend/alerts_service_settings/components/alerts_service_form_spec.js index 6ac5380e8d9..346059ed7be 100644 --- a/spec/frontend/alerts_service_settings/components/alerts_service_form_spec.js +++ b/spec/frontend/alerts_service_settings/components/alerts_service_form_spec.js @@ -35,16 +35,9 @@ describe('AlertsServiceForm', () => { const findUrl = () => wrapper.find('#url'); const findAuthorizationKey = () => wrapper.find('#authorization-key'); const findDescription = () => wrapper.find('[data-testid="description"'); - const findActiveStatusIcon = (val) => - document.querySelector(`.js-service-active-status[data-value=${val.toString()}]`); beforeEach(() => { mockAxios = new MockAdapter(axios); - setFixtures(` -
- - -
`); }); afterEach(() => { @@ -124,11 +117,6 @@ describe('AlertsServiceForm', () => { it(`updates toggle button value to ${value}`, () => { expect(wrapper.find(ToggleButton).props('value')).toBe(value); }); - - it('updates visible status icons', () => { - expect(findActiveStatusIcon(!value)).toHaveClass('d-none'); - expect(findActiveStatusIcon(value)).not.toHaveClass('d-none'); - }); }, ); }); diff --git a/spec/frontend/lib/utils/datetime_utility_spec.js b/spec/frontend/lib/utils/datetime_utility_spec.js index 698d6cd277f..5c457fb6d70 100644 --- a/spec/frontend/lib/utils/datetime_utility_spec.js +++ b/spec/frontend/lib/utils/datetime_utility_spec.js @@ -731,3 +731,28 @@ describe('datesMatch', () => { expect(datetimeUtility.datesMatch(date1, date2)).toBe(expected); }); }); + +describe('format24HourTimeStringFromInt', () => { + const expectedFormattedTimes = [ + [0, '00:00'], + [2, '02:00'], + [6, '06:00'], + [9, '09:00'], + [10, '10:00'], + [16, '16:00'], + [22, '22:00'], + [32, ''], + [NaN, ''], + ['Invalid Int', ''], + [null, ''], + [undefined, ''], + ]; + + expectedFormattedTimes.forEach(([timeInt, expectedTimeStringIn24HourNotation]) => { + it(`formats ${timeInt} as ${expectedTimeStringIn24HourNotation}`, () => { + expect(datetimeUtility.format24HourTimeStringFromInt(timeInt)).toBe( + expectedTimeStringIn24HourNotation, + ); + }); + }); +}); diff --git a/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb b/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb index 4048fc69591..417bf3e363a 100644 --- a/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb +++ b/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb @@ -8,8 +8,8 @@ RSpec.describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService let(:prometheus_settings) do { - enable: true, - listen_address: 'localhost:9090' + enabled: true, + server_address: 'localhost:9090' } end @@ -63,13 +63,13 @@ RSpec.describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService application_setting.update(allow_local_requests_from_web_hooks_and_services: true) end - shared_examples 'has prometheus service' do |listen_address| + shared_examples 'has prometheus service' do |server_address| it do expect(result[:status]).to eq(:success) prometheus = project.prometheus_service expect(prometheus).not_to eq(nil) - expect(prometheus.api_url).to eq(listen_address) + expect(prometheus.api_url).to eq(server_address) expect(prometheus.active).to eq(true) expect(prometheus.manual_configuration).to eq(true) end @@ -202,25 +202,25 @@ RSpec.describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService end context 'with non default prometheus address' do - let(:listen_address) { 'https://localhost:9090' } + let(:server_address) { 'https://localhost:9090' } let(:prometheus_settings) do { - enable: true, - listen_address: listen_address + enabled: true, + server_address: server_address } end it_behaves_like 'has prometheus service', 'https://localhost:9090' context 'with :9090 symbol' do - let(:listen_address) { :':9090' } + let(:server_address) { :':9090' } it_behaves_like 'has prometheus service', 'http://localhost:9090' end context 'with 0.0.0.0:9090' do - let(:listen_address) { '0.0.0.0:9090' } + let(:server_address) { '0.0.0.0:9090' } it_behaves_like 'has prometheus service', 'http://localhost:9090' end @@ -251,8 +251,8 @@ RSpec.describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService context 'when prometheus setting is disabled in gitlab.yml' do let(:prometheus_settings) do { - enable: false, - listen_address: 'http://localhost:9090' + enabled: false, + server_address: 'http://localhost:9090' } end @@ -262,8 +262,8 @@ RSpec.describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService end end - context 'when prometheus listen address is blank in gitlab.yml' do - let(:prometheus_settings) { { enable: true, listen_address: '' } } + context 'when prometheus server address is blank in gitlab.yml' do + let(:prometheus_settings) { { enabled: true, server_address: '' } } it 'does not configure prometheus' do expect(result).to include(status: :success) @@ -296,8 +296,8 @@ RSpec.describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService context 'when prometheus manual configuration cannot be saved' do let(:prometheus_settings) do { - enable: true, - listen_address: 'httpinvalid://localhost:9090' + enabled: true, + server_address: 'httpinvalid://localhost:9090' } end diff --git a/spec/lib/gitlab/prometheus/internal_spec.rb b/spec/lib/gitlab/prometheus/internal_spec.rb index 7771d85222a..b08b8813470 100644 --- a/spec/lib/gitlab/prometheus/internal_spec.rb +++ b/spec/lib/gitlab/prometheus/internal_spec.rb @@ -3,12 +3,12 @@ require 'spec_helper' RSpec.describe Gitlab::Prometheus::Internal do - let(:listen_address) { 'localhost:9090' } + let(:server_address) { 'localhost:9090' } let(:prometheus_settings) do { - enable: true, - listen_address: listen_address + enabled: true, + server_address: server_address } end @@ -27,25 +27,25 @@ RSpec.describe Gitlab::Prometheus::Internal do it_behaves_like 'returns valid uri', 'http://localhost:9090' context 'with non default prometheus address' do - let(:listen_address) { 'https://localhost:9090' } + let(:server_address) { 'https://localhost:9090' } it_behaves_like 'returns valid uri', 'https://localhost:9090' context 'with :9090 symbol' do - let(:listen_address) { :':9090' } + let(:server_address) { :':9090' } it_behaves_like 'returns valid uri', 'http://localhost:9090' end context 'with 0.0.0.0:9090' do - let(:listen_address) { '0.0.0.0:9090' } + let(:server_address) { '0.0.0.0:9090' } it_behaves_like 'returns valid uri', 'http://localhost:9090' end end - context 'when listen_address is nil' do - let(:listen_address) { nil } + context 'when server_address is nil' do + let(:server_address) { nil } it 'does not fail' do expect(described_class.uri).to be_nil @@ -53,7 +53,7 @@ RSpec.describe Gitlab::Prometheus::Internal do end context 'when prometheus listen address is blank in gitlab.yml' do - let(:listen_address) { '' } + let(:server_address) { '' } it 'does not configure prometheus' do expect(described_class.uri).to be_nil @@ -61,26 +61,6 @@ RSpec.describe Gitlab::Prometheus::Internal do end end - describe '.server_address' do - context 'self.uri returns valid uri' do - ['http://localhost:9090', 'https://localhost:9090 '].each do |valid_uri| - it 'returns correct server address' do - expect(described_class).to receive(:uri).and_return(valid_uri) - - expect(described_class.server_address).to eq('localhost:9090') - end - end - end - - context 'self.uri returns nil' do - it 'returns nil' do - expect(described_class).to receive(:uri).and_return(nil) - - expect(described_class.server_address).to be_nil - end - end - end - describe '.prometheus_enabled?' do it 'returns correct value' do expect(described_class.prometheus_enabled?).to eq(true) @@ -89,8 +69,8 @@ RSpec.describe Gitlab::Prometheus::Internal do context 'when prometheus setting is disabled in gitlab.yml' do let(:prometheus_settings) do { - enable: false, - listen_address: listen_address + enabled: false, + server_address: server_address } end @@ -110,9 +90,9 @@ RSpec.describe Gitlab::Prometheus::Internal do end end - describe '.listen_address' do + describe '.server_address' do it 'returns correct value' do - expect(described_class.listen_address).to eq(listen_address) + expect(described_class.server_address).to eq(server_address) end context 'when prometheus setting is not present in gitlab.yml' do @@ -121,7 +101,7 @@ RSpec.describe Gitlab::Prometheus::Internal do end it 'does not fail' do - expect(described_class.listen_address).to be_nil + expect(described_class.server_address).to be_nil end end end diff --git a/spec/lib/gitlab/usage/metric_definition_spec.rb b/spec/lib/gitlab/usage/metric_definition_spec.rb new file mode 100644 index 00000000000..e101f837324 --- /dev/null +++ b/spec/lib/gitlab/usage/metric_definition_spec.rb @@ -0,0 +1,123 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Usage::MetricDefinition do + let(:attributes) do + { + name: 'uuid', + description: 'GitLab instance unique identifier', + value_type: 'string', + product_category: 'collection', + stage: 'growth', + status: 'data_available', + default_generation: 'generation_1', + full_path: { + generation_1: 'uuid', + generation_2: 'license.uuid' + }, + group: 'group::product analytics', + time_frame: 'none', + data_source: 'database', + distribution: %w(ee ce), + tier: %w(free starter premium ultimate bronze silver gold) + } + end + + let(:path) { File.join('metrics', 'uuid.yml') } + let(:definition) { described_class.new(path, attributes) } + let(:yaml_content) { attributes.deep_stringify_keys.to_yaml } + + it 'has all definitons valid' do + expect { described_class.definitions }.not_to raise_error(Gitlab::Usage::Metric::InvalidMetricError) + end + + describe '#key' do + subject { definition.key } + + it 'returns a symbol from name' do + is_expected.to eq('uuid') + end + end + + describe '#validate' do + using RSpec::Parameterized::TableSyntax + + where(:attribute, :value) do + :name | nil + :description | nil + :value_type | nil + :value_type | 'test' + :status | nil + :default_generation | nil + :group | nil + :time_frame | nil + :time_frame | '29d' + :data_source | 'other' + :data_source | nil + :distribution | nil + :distribution | 'test' + :tier | %w(test ee) + end + + with_them do + before do + attributes[attribute] = value + end + + it 'raise exception' do + expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).at_least(:once).with(instance_of(Gitlab::Usage::Metric::InvalidMetricError)) + + described_class.new(path, attributes).validate! + end + end + end + + describe '.load_all!' do + let(:metric1) { Dir.mktmpdir('metric1') } + let(:metric2) { Dir.mktmpdir('metric2') } + let(:definitions) { {} } + + before do + allow(described_class).to receive(:paths).and_return( + [ + File.join(metric1, '**', '*.yml'), + File.join(metric2, '**', '*.yml') + ] + ) + end + + subject { described_class.send(:load_all!) } + + it 'has empty list when there are no definition files' do + is_expected.to be_empty + end + + it 'has one metric when there is one file' do + write_metric(metric1, path, yaml_content) + + is_expected.to be_one + end + + it 'when the same meric is defined multiple times raises exception' do + write_metric(metric1, path, yaml_content) + write_metric(metric2, path, yaml_content) + + expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).with(instance_of(Gitlab::Usage::Metric::InvalidMetricError)) + + subject + end + + after do + FileUtils.rm_rf(metric1) + FileUtils.rm_rf(metric2) + end + + def write_metric(metric, path, content) + path = File.join(metric, path) + dir = File.dirname(path) + FileUtils.mkdir_p(dir) + File.write(path, content) + end + end +end diff --git a/spec/lib/gitlab/usage/metric_spec.rb b/spec/lib/gitlab/usage/metric_spec.rb new file mode 100644 index 00000000000..40671d980d6 --- /dev/null +++ b/spec/lib/gitlab/usage/metric_spec.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Usage::Metric do + describe '#definition' do + it 'returns generation_1 metric definiton' do + expect(described_class.new(default_generation_path: 'uuid').definition).to be_an(Gitlab::Usage::MetricDefinition) + end + end + + describe '#unflatten_default_path' do + using RSpec::Parameterized::TableSyntax + + where(:default_generation_path, :value, :expected_hash) do + 'uuid' | nil | { uuid: nil } + 'uuid' | '1111' | { uuid: '1111' } + 'counts.issues' | nil | { counts: { issues: nil } } + 'counts.issues' | 100 | { counts: { issues: 100 } } + 'usage_activity_by_stage.verify.ci_builds' | 100 | { usage_activity_by_stage: { verify: { ci_builds: 100 } } } + end + + with_them do + subject { described_class.new(default_generation_path: default_generation_path, value: value).unflatten_default_path } + + it { is_expected.to eq(expected_hash) } + end + end +end diff --git a/spec/lib/gitlab/utils/usage_data_spec.rb b/spec/lib/gitlab/utils/usage_data_spec.rb index 73cbc4a6041..f801a1f462a 100644 --- a/spec/lib/gitlab/utils/usage_data_spec.rb +++ b/spec/lib/gitlab/utils/usage_data_spec.rb @@ -284,7 +284,7 @@ RSpec.describe Gitlab::Utils::UsageData do context 'when Prometheus server address is available from settings' do before do expect(Gitlab::Prometheus::Internal).to receive(:prometheus_enabled?).and_return(true) - expect(Gitlab::Prometheus::Internal).to receive(:server_address).and_return('prom:9090') + expect(Gitlab::Prometheus::Internal).to receive(:uri).and_return('http://prom:9090') end it_behaves_like 'try to query Prometheus with given address' diff --git a/spec/models/project_services/prometheus_service_spec.rb b/spec/models/project_services/prometheus_service_spec.rb index 76fc5a826c9..8215fb5c336 100644 --- a/spec/models/project_services/prometheus_service_spec.rb +++ b/spec/models/project_services/prometheus_service_spec.rb @@ -95,7 +95,7 @@ RSpec.describe PrometheusService, :use_clean_rails_memory_store_caching, :snowpl service.api_url = 'http://localhost:9090' stub_application_setting(self_monitoring_project_id: project.id) - stub_config(prometheus: { enable: true, listen_address: 'localhost:9090' }) + stub_config(prometheus: { enable: true, server_address: 'localhost:9090' }) end it 'allows self-monitoring project to connect to internal Prometheus' do @@ -242,7 +242,7 @@ RSpec.describe PrometheusService, :use_clean_rails_memory_store_caching, :snowpl stub_config(prometheus: { enable: true, - listen_address: api_url + server_address: api_url }) end