Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2025-06-13 00:10:47 +00:00
parent 645c20e091
commit b3bd59a59d
39 changed files with 1703 additions and 368 deletions

View File

@ -404,7 +404,7 @@ gem 'gitlab-schema-validation', path: 'gems/gitlab-schema-validation', feature_c
gem 'gitlab-http', path: 'gems/gitlab-http', feature_category: :shared
gem 'premailer-rails', '~> 1.12.0', feature_category: :notifications
gem 'gitlab-labkit', '~> 0.39.0', feature_category: :shared
gem 'gitlab-labkit', '~> 0.37.0', feature_category: :shared
gem 'thrift', '>= 0.16.0', feature_category: :shared
# I18n

View File

@ -231,7 +231,7 @@
{"name":"gitlab-glfm-markdown","version":"0.0.31","platform":"x86_64-linux-gnu","checksum":"c2c4c8f77d078f2afb1420289e32f444e91ece48d8f76a78e43f5b69f5d2248c"},
{"name":"gitlab-glfm-markdown","version":"0.0.31","platform":"x86_64-linux-musl","checksum":"cc3e8529f8eaf6be9bfa71509a58396540bb7c2b025e5dd9615a73ad0cf2a6b3"},
{"name":"gitlab-kas-grpc","version":"17.11.3","platform":"ruby","checksum":"f8b4917c23cae65b4faeb9c2bad6b7aa388317766bf76ca2386dc49359305f53"},
{"name":"gitlab-labkit","version":"0.39.0","platform":"ruby","checksum":"ee81fc360aced98ab7929b5072b0f352b9444f5ff8f79e57faaf4a6bd191571e"},
{"name":"gitlab-labkit","version":"0.37.0","platform":"ruby","checksum":"d2dd0a60db2149a9a8eebf2975dc23f54ac3ceb01bdba732eb1b26b86dfffa70"},
{"name":"gitlab-license","version":"2.6.0","platform":"ruby","checksum":"2c1f8ae73835640ec77bf758c1d0c9730635043c01cf77902f7976e826d7d016"},
{"name":"gitlab-mail_room","version":"0.0.27","platform":"ruby","checksum":"05c07db892094cf5747ea00afb0a95c5a5406e05f34ae779f4388f2ddf962316"},
{"name":"gitlab-markup","version":"2.0.0","platform":"ruby","checksum":"951a1c871463a8f329e6c002b2da337cd547febcc1e33d84df4a212419fba02e"},

View File

@ -770,15 +770,13 @@ GEM
rb_sys (~> 0.9.109)
gitlab-kas-grpc (17.11.3)
grpc (~> 1.0)
gitlab-labkit (0.39.0)
gitlab-labkit (0.37.0)
actionpack (>= 5.0.0, < 8.1.0)
activesupport (>= 5.0.0, < 8.1.0)
google-protobuf (~> 3)
grpc (>= 1.62)
jaeger-client (~> 1.1.0)
opentracing (~> 0.4)
pg_query (>= 6.1.0, < 7.0)
prometheus-client-mmap (~> 1.2.9)
pg_query (>= 5.1.0, < 7.0)
redis (> 3.0.0, < 6.0.0)
gitlab-license (2.6.0)
gitlab-mail_room (0.0.27)
@ -2170,7 +2168,7 @@ DEPENDENCIES
gitlab-housekeeper!
gitlab-http!
gitlab-kas-grpc (~> 17.11.0)
gitlab-labkit (~> 0.39.0)
gitlab-labkit (~> 0.37.0)
gitlab-license (~> 2.6)
gitlab-mail_room (~> 0.0.24)
gitlab-markup (~> 2.0.0)

View File

@ -231,7 +231,7 @@
{"name":"gitlab-glfm-markdown","version":"0.0.31","platform":"x86_64-linux-gnu","checksum":"c2c4c8f77d078f2afb1420289e32f444e91ece48d8f76a78e43f5b69f5d2248c"},
{"name":"gitlab-glfm-markdown","version":"0.0.31","platform":"x86_64-linux-musl","checksum":"cc3e8529f8eaf6be9bfa71509a58396540bb7c2b025e5dd9615a73ad0cf2a6b3"},
{"name":"gitlab-kas-grpc","version":"17.11.3","platform":"ruby","checksum":"f8b4917c23cae65b4faeb9c2bad6b7aa388317766bf76ca2386dc49359305f53"},
{"name":"gitlab-labkit","version":"0.39.0","platform":"ruby","checksum":"ee81fc360aced98ab7929b5072b0f352b9444f5ff8f79e57faaf4a6bd191571e"},
{"name":"gitlab-labkit","version":"0.37.0","platform":"ruby","checksum":"d2dd0a60db2149a9a8eebf2975dc23f54ac3ceb01bdba732eb1b26b86dfffa70"},
{"name":"gitlab-license","version":"2.6.0","platform":"ruby","checksum":"2c1f8ae73835640ec77bf758c1d0c9730635043c01cf77902f7976e826d7d016"},
{"name":"gitlab-mail_room","version":"0.0.27","platform":"ruby","checksum":"05c07db892094cf5747ea00afb0a95c5a5406e05f34ae779f4388f2ddf962316"},
{"name":"gitlab-markup","version":"2.0.0","platform":"ruby","checksum":"951a1c871463a8f329e6c002b2da337cd547febcc1e33d84df4a212419fba02e"},

View File

@ -764,15 +764,13 @@ GEM
rb_sys (~> 0.9.109)
gitlab-kas-grpc (17.11.3)
grpc (~> 1.0)
gitlab-labkit (0.39.0)
gitlab-labkit (0.37.0)
actionpack (>= 5.0.0, < 8.1.0)
activesupport (>= 5.0.0, < 8.1.0)
google-protobuf (~> 3)
grpc (>= 1.62)
jaeger-client (~> 1.1.0)
opentracing (~> 0.4)
pg_query (>= 6.1.0, < 7.0)
prometheus-client-mmap (~> 1.2.9)
pg_query (>= 5.1.0, < 7.0)
redis (> 3.0.0, < 6.0.0)
gitlab-license (2.6.0)
gitlab-mail_room (0.0.27)
@ -2165,7 +2163,7 @@ DEPENDENCIES
gitlab-housekeeper!
gitlab-http!
gitlab-kas-grpc (~> 17.11.0)
gitlab-labkit (~> 0.39.0)
gitlab-labkit (~> 0.37.0)
gitlab-license (~> 2.6)
gitlab-mail_room (~> 0.0.24)
gitlab-markup (~> 2.0.0)

View File

@ -125,10 +125,20 @@ export default {
});
},
nameValuePairs() {
return this.inputsToEmit.map((input) => ({
name: input.name,
value: this.formatInputValue(input),
}));
return this.inputsToEmit.flatMap((input) => {
const baseNameValuePair = {
name: input.name,
value: this.formatInputValue(input),
};
if (input.isSelected) {
return [baseNameValuePair];
}
if (input.savedValue !== undefined) {
return [{ ...baseNameValuePair, destroy: true }];
}
return [];
});
},
inputsList() {
return this.inputs.map((input) => ({ text: input.name, value: input.name }));
@ -217,15 +227,15 @@ export default {
this.$emit('update-inputs', this.nameValuePairs);
},
selectInputs(items) {
const changedInputs = [];
const selectionChangedInputs = [];
this.inputs = this.inputs.map((input) => {
const oldValue = input.value;
const wasSelected = input.isSelected;
const isSelected = items.includes(input.name);
const newValue = isSelected ? input.value : input.default;
if (newValue !== oldValue) {
changedInputs.push(input.name);
if (isSelected !== wasSelected) {
selectionChangedInputs.push(input.name);
}
return {
@ -237,8 +247,8 @@ export default {
this.selectedInputNames = items;
// Note: we need to emit an event from here as the input value of deselected input changed
if (changedInputs.length > 0) {
// Emit events for inputs that had selection changes
if (selectionChangedInputs.length > 0) {
this.emitEvents();
}
},

View File

@ -129,7 +129,9 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
end
def omniauth_login_counter
Gitlab::Auth::OAuth::BeforeRequestPhaseOauthLoginCounterIncrement.counter
@counter ||= Gitlab::Metrics.counter(
:gitlab_omniauth_login_total,
'Counter of OmniAuth login attempts')
end
def log_failed_login(user, provider)

View File

@ -14,6 +14,6 @@ class MetricsService
private
def multiprocess_metrics_path
::Gitlab::Metrics.client.configuration.multiprocess_files_dir
::Prometheus::Client.configuration.multiprocess_files_dir
end
end

View File

@ -7,13 +7,13 @@
"enable_language_server_restrictions": {
"type": "boolean",
"default": false,
"description": "Enables enforcing language server restrictions"
"description": "Enforce restrictions on Language Server"
},
"minimum_language_server_version": {
"type": "string",
"pattern": "^\\d+\\.\\d+\\.\\d+$",
"maxLength": 64,
"description": "Minimum language server version to accept requests from"
"description": "Minimum required Language Server version"
}
}
}

View File

@ -3,7 +3,7 @@
testid: 'admin-editor-extensions-settings',
expanded: expanded_by_default?) do |c|
- c.with_description do
= _('Configure instance-wide Editor Extensions settings')
= _('Configure Editor Extensions settings for your instance')
- c.with_body do
= gitlab_ui_form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-editor-extensions-settings'), html: { class: 'fieldset-form', id: 'editor-extensions-settings' } do |f|
= form_errors(@application_setting)

View File

@ -38,10 +38,10 @@ if puma_master?
# since it must happen prior to any worker processes or the metrics server starting up.
Prometheus::CleanupMultiprocDirService.new(prometheus_metrics_dir).execute
Gitlab::Metrics.client.reinitialize_on_pid_change(force: true)
::Prometheus::Client.reinitialize_on_pid_change(force: true)
end
Gitlab::Metrics.client.configure do |config|
::Prometheus::Client.configure do |config|
config.logger = Gitlab::AppLogger
config.multiprocess_files_dir = prometheus_metrics_dir
@ -79,7 +79,7 @@ rescue IOError => e
end
Gitlab::Cluster::LifecycleEvents.on_worker_start do
defined?(Gitlab::Metrics.client.reinitialize_on_pid_change) && Gitlab::Metrics.client.reinitialize_on_pid_change
defined?(::Prometheus::Client.reinitialize_on_pid_change) && ::Prometheus::Client.reinitialize_on_pid_change
logger = Gitlab::AppLogger
# Since we also run these samplers in the Puma primary, we need to re-create them each time we fork.
# For Sidekiq, this does not make any difference, since there is no primary.

View File

@ -13,13 +13,9 @@ title: Configure Editor Extensions
{{< /details >}}
Configure Editor Extensions settings for your GitLab instance in the Admin area.
Configure Editor Extensions settings for your GitLab instance.
You can enforce the following restrictions on Editor Extensions:
- Enforce a minimum language server version.
## Enforce a minimum language server version
## Require a minimum language server version
{{< history >}}
@ -36,8 +32,9 @@ On GitLab Dedicated, this feature is available.
{{< /alert >}}
By default, any GitLab Language Server version can connect to your GitLab instance when
Personal Access Tokens are enabled. You can configure a minimum language server version and
block requests from clients on older versions. Existing clients will receive an API error
personal access tokens are enabled. To block requests from clients on older versions,
configure a minimum language server version. Clients older than the minimum allowed
Language Server version receive an API error.
Prerequisites:
@ -69,7 +66,8 @@ To allow any GitLab Language Server clients:
{{< alert type="note" >}}
Allowing all requests is **not recommended** because it can cause incompatibility if your GitLab version is ahead of your Editor Extensions.
Updating your Editor Extensions is **recommended** to receive the latest feature improvements, bug fixes, and security fixes.
Allowing all requests is not recommended. It can cause incompatibility if your
GitLab version is ahead of your extension version. You should update your extensions
to receive the latest feature improvements, bug fixes, and security fixes.
{{< /alert >}}

View File

@ -0,0 +1,60 @@
# frozen_string_literal: true
module Gitlab
module ApprovalRules
module V2
class DataMapper
def initialize(v1_rule)
@v1_rule = v1_rule
end
def migrate
return unless v1_rule
return unless Feature.enabled?(:v2_approval_rules, v1_rule.project)
return unless merge_request_level_rule?
ApplicationRecord.transaction do
v2_rule = create_v2_rule
create_merge_request_association(v2_rule)
migrate_user_associations(v2_rule)
v2_rule
end
end
private
attr_reader :v1_rule
def merge_request_level_rule?
v1_rule.is_a?(::ApprovalMergeRequestRule)
end
def create_v2_rule
::MergeRequests::ApprovalRule.create!(
name: v1_rule.name,
approvals_required: v1_rule.approvals_required,
rule_type: v1_rule.rule_type,
origin: :merge_request,
project_id: v1_rule.project.id
)
end
def create_merge_request_association(v2_rule)
::MergeRequests::ApprovalRulesMergeRequest.create!(
approval_rule: v2_rule,
merge_request: v1_rule.merge_request
)
end
def migrate_user_associations(v2_rule)
v1_rule.users.find_each do |user|
::MergeRequests::ApprovalRulesApproverUser.create!(
approval_rule: v2_rule,
user: user
)
end
end
end
end
end
end

View File

@ -4,15 +4,14 @@ module Gitlab
module Auth
module OAuth
module BeforeRequestPhaseOauthLoginCounterIncrement
def self.counter
OMNIAUTH_LOGIN_TOTAL_COUNTER =
Gitlab::Metrics.counter(:gitlab_omniauth_login_total, 'Counter of initiated OmniAuth login attempts')
end
def self.call(env)
provider = current_provider_name_from(env)
return unless provider
counter.increment(omniauth_provider: provider, status: 'initiated')
OMNIAUTH_LOGIN_TOTAL_COUNTER.increment(omniauth_provider: provider, status: 'initiated')
end
private_class_method def self.current_provider_name_from(env)

View File

@ -2,20 +2,20 @@
module Gitlab
module Metrics
# TODO: remove when we move away from Prometheus::Client to Labkit::Metrics::Client completely
# https://gitlab.com/gitlab-com/gl-infra/observability/team/-/issues/4160
if ENV["LABKIT_METRICS_ENABLED"] == "true"
include ::Gitlab::Metrics::Labkit
else
include ::Gitlab::Metrics::Prometheus
end
include Gitlab::Metrics::Prometheus
EXECUTION_MEASUREMENT_BUCKETS = [0.001, 0.01, 0.1, 1].freeze
@error = false
def self.enabled?
prometheus_metrics_enabled?
end
def self.error?
@error
end
def self.record_duration_for_status?(status)
status.to_i.between?(200, 499)
end

View File

@ -46,7 +46,7 @@ module Gitlab
private
def current_context
::Labkit::Context.current
Labkit::Context.current
end
def feature_category

View File

@ -1,15 +1,7 @@
# frozen_string_literal: true
require 'webrick'
RACK_EXPORTER =
if ENV["LABKIT_METRICS_ENABLED"] == "true"
require 'labkit/metrics/rack_exporter'
::Labkit::Metrics::RackExporter
else
require 'prometheus/client/rack/exporter'
::Prometheus::Client::Rack::Exporter
end
require 'prometheus/client/rack/exporter'
module Gitlab
module Metrics
@ -91,8 +83,7 @@ module Gitlab
use Rack::Deflater
use Gitlab::Metrics::Exporter::MetricsMiddleware, pid
use Gitlab::Metrics::Exporter::GcRequestMiddleware if gc_requests
use RACK_EXPORTER if ::Gitlab::Metrics.enabled?
use ::Prometheus::Client::Rack::Exporter if ::Gitlab::Metrics.metrics_folder_present?
run ->(env) { [404, {}, ['']] }
end
end

View File

@ -1,96 +0,0 @@
# frozen_string_literal: true
module Gitlab
module Metrics
module Labkit
extend ActiveSupport::Concern
class_methods do
def client
::Labkit::Metrics::Client
end
alias_method :registry, :client
def null_metric
::Labkit::Metrics::Null.instance
end
def error?
!client.enabled?
end
# TODO: remove when we move away from Prometheus::Client to Labkit::Metrics::Client completely
# https://gitlab.com/gitlab-com/gl-infra/observability/team/-/issues/4160.
#
# This method is kept here for compatibility with the old implementation only:
# lib/gitlab/metrics/prometheus.rb. This is a implementation detail supposed
# to be hidden within Labkit::Metrics::Client.enabled?/disabled? methods.
def metrics_folder_present?
client.enabled?
end
# Used only in specs to reset the error state
#
# TODO: remove when we move away from Prometheus::Client to Labkit::Metrics::Client completely
# https://gitlab.com/gitlab-com/gl-infra/observability/team/-/issues/4160
def reset_registry!
@prometheus_metrics_enabled = nil
client.reset!
end
def counter(name, docstring, base_labels = {})
safe_provide_metric(:counter, name, docstring, base_labels)
end
def summary(name, docstring, base_labels = {})
safe_provide_metric(:summary, name, docstring, base_labels)
end
def gauge(name, docstring, base_labels = {}, multiprocess_mode = :all)
safe_provide_metric(:gauge, name, docstring, base_labels, multiprocess_mode)
end
def histogram(name, docstring, base_labels = {}, buckets = ::Prometheus::Client::Histogram::DEFAULT_BUCKETS)
safe_provide_metric(:histogram, name, docstring, base_labels, buckets)
end
# TODO: remove when we move away from Prometheus::Client to Labkit::Metrics::Client completely
# https://gitlab.com/gitlab-com/gl-infra/observability/team/-/issues/4160
def error_detected!
@prometheus_metrics_enabled = nil
client.disable!
end
# Used only in specs to reset the error state
#
# TODO: remove when we move away from Prometheus::Client to Labkit::Metrics::Client completely
# https://gitlab.com/gitlab-com/gl-infra/observability/team/-/issues/4160
def clear_errors!
@prometheus_metrics_enabled = nil
client.enable!
end
def prometheus_metrics_enabled?
prometheus_metrics_enabled_memoized
end
private
# TODO: remove when we move away from Prometheus::Client to Labkit::Metrics::Client completely
# https://gitlab.com/gitlab-com/gl-infra/observability/team/-/issues/4160
def safe_provide_metric(metric_type, metric_name, *args)
return null_metric unless prometheus_metrics_enabled?
client.send(metric_type, metric_name, *args) # rubocop:disable GitlabSecurity/PublicSend -- temporary workaround, see issue link
end
def prometheus_metrics_enabled_memoized
@prometheus_metrics_enabled ||=
(client.enabled? && Gitlab::CurrentSettings.prometheus_metrics_enabled) || false
end
end
end
end
end

View File

@ -11,22 +11,8 @@ module Gitlab
class_methods do
include Gitlab::Utils::StrongMemoize
@error = false
def error?
@error
end
def client
::Prometheus::Client
end
def null_metric
NullMetric.instance
end
def metrics_folder_present?
multiprocess_files_dir = client.configuration.multiprocess_files_dir
multiprocess_files_dir = ::Prometheus::Client.configuration.multiprocess_files_dir
multiprocess_files_dir &&
::Dir.exist?(multiprocess_files_dir) &&
@ -41,11 +27,10 @@ module Gitlab
def reset_registry!
clear_memoization(:registry)
clear_memoization(:prometheus_metrics_enabled)
REGISTRY_MUTEX.synchronize do
client.cleanup!
client.reset!
::Prometheus::Client.cleanup!
::Prometheus::Client.reset!
end
end
@ -53,7 +38,7 @@ module Gitlab
strong_memoize(:registry) do
REGISTRY_MUTEX.synchronize do
strong_memoize(:registry) do
client.registry
::Prometheus::Client.registry
end
end
end
@ -71,7 +56,7 @@ module Gitlab
safe_provide_metric(:gauge, name, docstring, base_labels, multiprocess_mode)
end
def histogram(name, docstring, base_labels = {}, buckets = client::Histogram::DEFAULT_BUCKETS)
def histogram(name, docstring, base_labels = {}, buckets = ::Prometheus::Client::Histogram::DEFAULT_BUCKETS)
safe_provide_metric(:histogram, name, docstring, base_labels, buckets)
end
@ -93,17 +78,20 @@ module Gitlab
private
def safe_provide_metric(metric_type, metric_name, *args)
def safe_provide_metric(method, name, *args)
metric = provide_metric(name)
return metric if metric
PROVIDER_MUTEX.synchronize do
provide_metric(metric_type, metric_name, *args)
provide_metric(name) || registry.method(method).call(name, *args)
end
end
def provide_metric(metric_type, metric_name, *args)
def provide_metric(name)
if prometheus_metrics_enabled?
registry.get(metric_name) || registry.method(metric_type).call(metric_name, *args)
registry.get(name)
else
null_metric
NullMetric.instance
end
end

View File

@ -3959,6 +3959,14 @@ msgstr ""
msgid "Adds this %{issuable_type} as related to the %{issuable_type} it was created from"
msgstr ""
msgid "AdherenceReport|%{pendingCount}/%{totalCount} control is pending"
msgid_plural "AdherenceReport|%{pendingCount}/%{totalCount} controls are pending"
msgstr[0] ""
msgstr[1] ""
msgid "AdherenceReport|Completed controls"
msgstr ""
msgid "AdherenceReport|Have questions or thoughts on the new improvements we made? %{linkStart}Please provide feedback on your experience%{linkEnd}."
msgstr ""
@ -3968,6 +3976,9 @@ msgstr ""
msgid "AdherenceReport|No statuses found."
msgstr ""
msgid "AdherenceReport|Pending controls"
msgstr ""
msgid "AdherenceReport|Show old report"
msgstr ""
@ -16029,6 +16040,9 @@ msgid_plural "ComplianceStandardsAdherence|%d controls"
msgstr[0] ""
msgstr[1] ""
msgid "ComplianceStandardsAdherence|%{failedCount} failed"
msgstr ""
msgid "ComplianceStandardsAdherence|%{failedCount}/%{totalCount} failed"
msgstr ""
@ -16791,6 +16805,18 @@ msgstr ""
msgid "ComplianceViolations|Your Compliance Violations CSV export for the group %{group_link} has been attached to this email."
msgstr ""
msgid "ComplianceViolation|Detected"
msgstr ""
msgid "ComplianceViolation|Dismissed"
msgstr ""
msgid "ComplianceViolation|In review"
msgstr ""
msgid "ComplianceViolation|Resolved"
msgstr ""
msgid "Compliance|Framework deleted successfully"
msgstr ""
@ -16896,6 +16922,9 @@ msgstr ""
msgid "Configure Dependency Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
msgid "Configure Editor Extensions settings for your instance"
msgstr ""
msgid "Configure Error Tracking"
msgstr ""
@ -16953,9 +16982,6 @@ msgstr ""
msgid "Configure import sources and settings related to import and export features."
msgstr ""
msgid "Configure instance-wide Editor Extensions settings"
msgstr ""
msgid "Configure it later"
msgstr ""
@ -26365,6 +26391,9 @@ msgstr ""
msgid "Failed to update compliance requirement control. Error: %{error_message}"
msgstr ""
msgid "Failed to update compliance violation status. Please try again later."
msgstr ""
msgid "Failed to update framework"
msgstr ""
@ -32322,9 +32351,6 @@ msgstr ""
msgid "In progress, queued for %{queuedDuration} seconds"
msgstr ""
msgid "In review"
msgstr ""
msgid "In the background, we're attempting to connect you again."
msgstr ""

View File

@ -8,22 +8,16 @@ require 'active_support/concern'
require 'active_support/inflector'
require 'active_support/core_ext/numeric/bytes'
require 'gitlab/utils/all'
if ENV["LABKIT_METRICS_ENABLED"] == "true"
require 'gitlab-labkit'
require_relative '../lib/gitlab/metrics/labkit'
else
require 'prometheus/client'
require_relative '../lib/gitlab/metrics/prometheus'
end
require 'prometheus/client'
require 'rack'
require 'gitlab/utils/all'
require_relative 'settings_overrides'
require_relative '../lib/gitlab/daemon'
require_relative '../lib/prometheus/cleanup_multiproc_dir_service'
require_relative '../lib/gitlab/metrics/prometheus'
require_relative '../lib/gitlab/metrics'
require_relative '../lib/gitlab/metrics/system'
require_relative '../lib/gitlab/metrics/memory'

View File

@ -8,7 +8,7 @@ class MetricsServer # rubocop:disable Gitlab/NamespacedClass
class << self
def start_for_puma
metrics_dir = Gitlab::Metrics.client.configuration.multiprocess_files_dir
metrics_dir = ::Prometheus::Client.configuration.multiprocess_files_dir
start_server = proc do
MetricsServer.spawn('puma', metrics_dir: metrics_dir).tap do |pid|
@ -105,7 +105,7 @@ class MetricsServer # rubocop:disable Gitlab/NamespacedClass
end
def start
Gitlab::Metrics.client.configure do |config|
::Prometheus::Client.configure do |config|
config.multiprocess_files_dir = @metrics_dir
config.pid_provider = proc { name }
end

View File

@ -2,7 +2,6 @@
require 'spec_helper'
require_relative '../../../metrics_server/dependencies'
require_relative '../../../metrics_server/metrics_server'
# End-to-end tests for the metrics server process we use to serve metrics

View File

@ -163,7 +163,7 @@ RSpec.describe OmniauthCallbacksController, :with_current_organization, type: :c
Rails.application.env_config['omniauth.auth'] = @original_env_config_omniauth_auth
end
context 'when authentication succeeds', :prometheus do
context 'when authentication succeeds' do
let(:extern_uid) { 'my-uid' }
let(:provider) { :github }
@ -173,8 +173,7 @@ RSpec.describe OmniauthCallbacksController, :with_current_organization, type: :c
change do
Gitlab::Metrics.registry
.get(:gitlab_omniauth_login_total)
&.get(omniauth_provider: 'github', status: 'succeeded')
.to_f
.get(omniauth_provider: 'github', status: 'succeeded')
end.by(1)
)
end
@ -186,7 +185,7 @@ RSpec.describe OmniauthCallbacksController, :with_current_organization, type: :c
end
end
context 'with signed-in user', :prometheus do
context 'with signed-in user' do
before do
sign_in user
end
@ -200,8 +199,7 @@ RSpec.describe OmniauthCallbacksController, :with_current_organization, type: :c
change do
Gitlab::Metrics.registry
.get(:gitlab_omniauth_login_total)
&.get(omniauth_provider: 'github', status: 'succeeded')
.to_f
.get(omniauth_provider: 'github', status: 'succeeded')
end.by(1)
)
end
@ -288,7 +286,7 @@ RSpec.describe OmniauthCallbacksController, :with_current_organization, type: :c
end
end
context 'when sign in fails', :prometheus do
context 'when sign in fails' do
include RoutesHelpers
let(:extern_uid) { 'my-uid' }
@ -314,8 +312,7 @@ RSpec.describe OmniauthCallbacksController, :with_current_organization, type: :c
change do
Gitlab::Metrics.registry
.get(:gitlab_omniauth_login_total)
&.get(omniauth_provider: 'saml', status: 'failed')
.to_f
.get(omniauth_provider: 'saml', status: 'failed')
end.by(1)
)
end

View File

@ -402,10 +402,13 @@ describe('PipelineInputsForm', () => {
await createComponent();
await selectInputs();
const updatedInput = { ...expectedInputs[0], value: 'updated-value' };
// Emits an event on inputs select
expect(wrapper.emitted()['update-inputs']).toHaveLength(1);
const updatedInput = { ...expectedInputs[0], value: 'updated-value', isSelected: true };
findInputsTable().vm.$emit('update', updatedInput);
expect(wrapper.emitted()['update-inputs']).toHaveLength(1);
expect(wrapper.emitted()['update-inputs']).toHaveLength(2);
const expectedEmittedValue = [
{ name: 'deploy_environment', value: 'updated-value' },
@ -413,7 +416,7 @@ describe('PipelineInputsForm', () => {
{ name: 'tags', value: '' },
];
expect(wrapper.emitted()['update-inputs'][0][0]).toEqual(expectedEmittedValue);
expect(wrapper.emitted('update-inputs')[1][0]).toEqual(expectedEmittedValue);
});
it('only emits modified inputs when emitModifiedOnly is true', async () => {
@ -423,16 +426,30 @@ describe('PipelineInputsForm', () => {
const inputs = findInputsTable().props('inputs');
const totalInputsCount = inputs.length;
const inputToModify = { ...inputs[0], value: 'modified-value' };
const inputToModify = { ...inputs[0], value: 'modified-value', isSelected: true };
findInputsTable().vm.$emit('update', inputToModify);
const emittedNameValuePairs = wrapper.emitted()['update-inputs'][0][0];
const emittedNameValuePairs = wrapper.emitted('update-inputs')[1][0];
expect(emittedNameValuePairs).toHaveLength(1);
expect(emittedNameValuePairs.length).toBeLessThan(totalInputsCount);
});
it('when saved input is unselected restores value to default and emits destroy property', async () => {
pipelineInputsHandler = jest.fn().mockResolvedValue(mockPipelineInputsResponse);
const savedInputs = [{ name: 'deploy_environment', value: 'saved-value' }];
await createComponent({ props: { savedInputs } });
await selectInputs([]);
const expectedEmittedValue = [
{ name: 'deploy_environment', value: 'staging', destroy: true },
];
expect(wrapper.emitted('update-inputs')[0][0]).toEqual(expectedEmittedValue);
});
it('converts string values to arrays for ARRAY type inputs', async () => {
pipelineInputsHandler = jest.fn().mockResolvedValue(mockPipelineInputsResponse);
await createComponent();
@ -450,7 +467,7 @@ describe('PipelineInputsForm', () => {
findInputsTable().vm.$emit('update', updatedInput);
// Check that the emitted value contains the converted array
const emittedValues = wrapper.emitted()['update-inputs'][0][0];
const emittedValues = wrapper.emitted('update-inputs')[1][0];
const emittedArrayValue = emittedValues.find((item) => item.name === 'tags').value;
expect(Array.isArray(emittedArrayValue)).toBe(true);
@ -472,22 +489,24 @@ describe('PipelineInputsForm', () => {
findInputsTable().vm.$emit('update', updatedInput);
const emittedValues = wrapper.emitted()['update-inputs'][0][0];
const emittedValues = wrapper.emitted('update-inputs')[1][0];
const emittedArrayValue = emittedValues.find((item) => item.name === 'tags').value;
expect(Array.isArray(emittedArrayValue)).toBe(true);
expect(emittedArrayValue).toEqual([{ key: 'value' }, { another: 'object' }]);
});
it('restores default values when inputs are deselected', async () => {
it('restores input defaults and emits empty array when all inputs are deselected', async () => {
pipelineInputsHandler = jest.fn().mockResolvedValue(mockPipelineInputsResponse);
await createComponent();
await selectInputs();
const updatedInput = { ...expectedInputs[0], value: 'updated-value' };
expect(wrapper.emitted('update-inputs')).toHaveLength(1);
const updatedInput = { ...expectedInputs[0], value: 'updated-value', isSelected: true };
findInputsTable().vm.$emit('update', updatedInput);
expect(wrapper.emitted()['update-inputs']).toHaveLength(1);
expect(wrapper.emitted('update-inputs')).toHaveLength(2);
const expectedEmittedValue = [
{ name: 'deploy_environment', value: 'updated-value' },
@ -495,19 +514,13 @@ describe('PipelineInputsForm', () => {
{ name: 'tags', value: '' },
];
expect(wrapper.emitted()['update-inputs'][0][0]).toEqual(expectedEmittedValue);
expect(wrapper.emitted('update-inputs')[1][0]).toEqual(expectedEmittedValue);
findInputsSelector().vm.$emit('reset');
await nextTick();
// Note: 'staging' is a default value
const newExpectedEmittedValue = [
{ name: 'deploy_environment', value: 'staging' },
{ name: 'api_token', value: '' },
{ name: 'tags', value: '' },
];
expect(wrapper.emitted()['update-inputs']).toHaveLength(2);
expect(wrapper.emitted()['update-inputs'][1][0]).toEqual(newExpectedEmittedValue);
expect(wrapper.emitted('update-inputs')).toHaveLength(3);
expect(wrapper.emitted('update-inputs')[2][0]).toEqual([]);
});
});
@ -519,7 +532,7 @@ describe('PipelineInputsForm', () => {
});
it('emits total available and modified counts when receives the inputs', () => {
expect(wrapper.emitted()['update-inputs-metadata']).toHaveLength(1);
expect(wrapper.emitted()['update-inputs-metadata']).toHaveLength(2);
expect(wrapper.emitted()['update-inputs-metadata'][0][0]).toEqual({
totalAvailable: 3,
totalModified: 0,
@ -531,8 +544,8 @@ describe('PipelineInputsForm', () => {
const updatedInput = { ...inputs[0], savedValue: 'saved-value', value: 'new-updated-value' };
findInputsTable().vm.$emit('update', updatedInput);
expect(wrapper.emitted()['update-inputs-metadata']).toHaveLength(2);
expect(wrapper.emitted()['update-inputs-metadata'][1][0]).toEqual({
expect(wrapper.emitted()['update-inputs-metadata']).toHaveLength(3);
expect(wrapper.emitted()['update-inputs-metadata'][2][0]).toEqual({
totalModified: 1,
newlyModified: 1,
});

View File

@ -1,23 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe "Work items", '(JavaScript fixtures)', type: :request, feature_category: :portfolio_management do
include ApiHelpers
include GraphqlHelpers
include JavaScriptFixturesHelpers
let_it_be(:group) { create(:group, :public) }
let_it_be(:project) { create(:project, :public, namespace: group) }
let_it_be(:user) { create(:user) }
let(:namespace_work_item_types_query_path) { 'work_items/graphql/namespace_work_item_types.query.graphql' }
it 'graphql/work_items/project_namespace_work_item_types.query.graphql.json' do
query = get_graphql_query_as_string(namespace_work_item_types_query_path)
post_graphql(query, current_user: user, variables: { fullPath: project.full_path })
expect_graphql_errors_to_be_empty
end
end

View File

@ -1,6 +1,5 @@
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import namespaceWorkItemTypesQueryResponse from 'test_fixtures/graphql/work_items/project_namespace_work_item_types.query.graphql.json';
import getIssueDetailsQuery from 'ee_else_ce/work_items/graphql/get_issue_details.query.graphql';
import { TEST_HOST } from 'helpers/test_constants';
import createMockApollo from 'helpers/mock_apollo_helper';
@ -18,6 +17,7 @@ import {
createWorkItemMutationErrorResponse,
createWorkItemMutationResponse,
getIssueDetailsResponse,
namespaceWorkItemTypesQueryResponse,
workItemByIidResponseFactory,
} from 'ee_else_ce_jest/work_items/mock_data';
import {

View File

@ -3,7 +3,6 @@ import VueApollo from 'vue-apollo';
import { GlAlert, GlButton, GlFormSelect, GlLink, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { cloneDeep } from 'lodash';
import namespaceWorkItemTypesQueryResponse from 'test_fixtures/graphql/work_items/project_namespace_work_item_types.query.graphql.json';
import { setHTMLFixture } from 'helpers/fixtures';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
@ -42,6 +41,7 @@ import {
createWorkItemMutationResponse,
createWorkItemMutationErrorResponse,
createWorkItemQueryResponse,
namespaceWorkItemTypesQueryResponse,
} from 'ee_else_ce_jest/work_items/mock_data';
jest.mock('~/alert');
@ -223,7 +223,7 @@ describe('Create work item component', () => {
expect(setNewWorkItemCache).toHaveBeenCalledWith({
fullPath: 'full-path',
widgetDefinitions: expectedWorkItemTypeData.widgetDefinitions,
widgetDefinitions: expect.any(Array),
workItemType: expectedWorkItemTypeData.name,
workItemTypeId: expectedWorkItemTypeData.id,
workItemTypeIconName: expectedWorkItemTypeData.iconName,

View File

@ -1,7 +1,6 @@
import { GlDisclosureDropdown, GlModal, GlDisclosureDropdownItem, GlLoadingIcon } from '@gitlab/ui';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import namespaceWorkItemTypesQueryResponse from 'test_fixtures/graphql/work_items/project_namespace_work_item_types.query.graphql.json';
import createMockApollo from 'helpers/mock_apollo_helper';
import { stubComponent } from 'helpers/stub_component';
@ -31,10 +30,11 @@ import namespaceWorkItemTypesQuery from '~/work_items/graphql/namespace_work_ite
import convertWorkItemMutation from '~/work_items/graphql/work_item_convert.mutation.graphql';
import {
convertWorkItemMutationErrorResponse,
convertWorkItemMutationResponse,
namespaceWorkItemTypesQueryResponse,
updateWorkItemMutationResponse,
updateWorkItemNotificationsMutationResponse,
convertWorkItemMutationErrorResponse,
} from 'ee_else_ce_jest/work_items/mock_data';
jest.mock('~/lib/utils/common_utils');

View File

@ -2,7 +2,6 @@ import { GlModal, GlFormSelect } from '@gitlab/ui';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import namespaceWorkItemTypesQueryResponse from 'test_fixtures/graphql/work_items/project_namespace_work_item_types.query.graphql.json';
import createMockApollo from 'helpers/mock_apollo_helper';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
@ -20,6 +19,7 @@ import {
import {
convertWorkItemMutationResponse,
namespaceWorkItemTypesQueryResponse,
workItemChangeTypeWidgets,
workItemQueryResponse,
workItemWithEpicParentQueryResponse,

View File

@ -1,7 +1,6 @@
import Vue, { nextTick } from 'vue';
import { GlForm, GlFormGroup, GlFormInput, GlFormCheckbox, GlTooltip } from '@gitlab/ui';
import VueApollo from 'vue-apollo';
import namespaceWorkItemTypesQueryResponse from 'test_fixtures/graphql/work_items/project_namespace_work_item_types.query.graphql.json';
import { stubComponent } from 'helpers/stub_component';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
@ -24,11 +23,12 @@ import createWorkItemMutation from '~/work_items/graphql/create_work_item.mutati
import updateWorkItemHierarchyMutation from '~/work_items/graphql/update_work_item_hierarchy.mutation.graphql';
import namespaceProjectsForLinksWidgetQuery from '~/work_items/graphql/namespace_projects_for_links_widget.query.graphql';
import {
createWorkItemMutationResponse,
updateWorkItemMutationResponse,
availableWorkItemsResponse,
namespaceProjectsList,
createWorkItemMutationResponse,
generateWorkItemsListWithId,
namespaceProjectsList,
namespaceWorkItemTypesQueryResponse,
updateWorkItemMutationResponse,
} from 'ee_else_ce_jest/work_items/mock_data';
Vue.use(VueApollo);

View File

@ -1,7 +1,6 @@
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import { GlAlert } from '@gitlab/ui';
import namespaceWorkItemTypesQueryResponse from 'test_fixtures/graphql/work_items/project_namespace_work_item_types.query.graphql.json';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@ -32,6 +31,7 @@ import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import * as utils from '~/work_items/utils';
import {
mockRolledUpCountsByType,
namespaceWorkItemTypesQueryResponse,
workItemHierarchyTreeResponse,
workItemHierarchyPaginatedTreeResponse,
workItemHierarchyTreeEmptyResponse,

View File

@ -2,8 +2,6 @@ import { GlButton, GlIcon } from '@gitlab/ui';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import namespaceWorkItemTypesQueryResponse from 'test_fixtures/graphql/work_items/project_namespace_work_item_types.query.graphql.json';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
@ -13,8 +11,10 @@ import toast from '~/vue_shared/plugins/global_toast';
import WorkItemNotificationsWidget from '~/work_items/components/work_item_notifications_widget.vue';
import updateWorkItemNotificationsMutation from '~/work_items/graphql/update_work_item_notifications.mutation.graphql';
import namespaceWorkItemTypesQuery from '~/work_items/graphql/namespace_work_item_types.query.graphql';
import { updateWorkItemNotificationsMutationResponse } from '../mock_data';
import {
namespaceWorkItemTypesQueryResponse,
updateWorkItemNotificationsMutationResponse,
} from '../mock_data';
jest.mock('~/lib/utils/common_utils');
jest.mock('~/vue_shared/plugins/global_toast');

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Auth::OAuth::BeforeRequestPhaseOauthLoginCounterIncrement, :prometheus, feature_category: :system_access do
RSpec.describe Gitlab::Auth::OAuth::BeforeRequestPhaseOauthLoginCounterIncrement, feature_category: :system_access do
describe '.call' do
let(:env) { { 'omniauth.strategy' => omniauth_strategy } }
let(:omniauth_strategy) { instance_double(OmniAuth::Strategies::GoogleOauth2, name: 'google_oauth2') }

View File

@ -1,44 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe ::Gitlab::Metrics::Labkit, :prometheus, feature_category: :scalability do
let(:all_metrics) do
Class.new do
include ::Gitlab::Metrics::Labkit
end
end
let(:client) { all_metrics.client }
after do
all_metrics.clear_errors!
end
describe '#reset_registry!' do
it 'clears existing metrics' do
counter = client.counter(:test, 'test metric')
counter.increment
expect(counter.get).to eq(1)
all_metrics.reset_registry!
expect(counter.get).to eq(0)
end
end
describe '#error_detected!' do
it 'disables Prometheus metrics' do
stub_application_setting(prometheus_metrics_enabled: true)
expect(all_metrics.error?).to be_falsey
expect(all_metrics.prometheus_metrics_enabled?).to be_truthy
all_metrics.error_detected!
expect(all_metrics.prometheus_metrics_enabled?).to be_falsey
expect(all_metrics.error?).to be_truthy
end
end
end

View File

@ -2,13 +2,8 @@
require 'spec_helper'
RSpec.describe ::Gitlab::Metrics::Prometheus, :prometheus, feature_category: :scalability do
let(:all_metrics) do
Class.new do
include ::Gitlab::Metrics::Prometheus
end
end
RSpec.describe Gitlab::Metrics::Prometheus, :prometheus do
let(:all_metrics) { Gitlab::Metrics }
let(:registry) { all_metrics.registry }
after do

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Metrics, :prometheus, feature_category: :scalability do
RSpec.describe Gitlab::Metrics do
include StubENV
describe '.settings' do
@ -17,39 +17,39 @@ RSpec.describe Gitlab::Metrics, :prometheus, feature_category: :scalability do
end
end
describe '.prometheus_metrics_enabled_unmemoized' do
subject { described_class.send(:prometheus_metrics_enabled_unmemoized) }
context 'prometheus metrics enabled in config' do
before do
allow(Gitlab::CurrentSettings).to receive(:prometheus_metrics_enabled).and_return(true)
end
context 'when metrics folder is present' do
before do
allow(described_class).to receive(:metrics_folder_present?).and_return(true)
end
it 'metrics are enabled' do
expect(subject).to eq(true)
end
end
context 'when metrics folder is missing' do
before do
allow(described_class).to receive(:metrics_folder_present?).and_return(false)
end
it 'metrics are disabled' do
expect(subject).to eq(false)
end
end
end
end
describe '.prometheus_metrics_enabled?' do
subject { described_class.prometheus_metrics_enabled? }
it { is_expected.to be_in([true, false]) }
context 'when Gitlab::CurrentSettings.prometheus_metrics_enabled is enabled' do
before do
allow(Gitlab::CurrentSettings).to receive(:prometheus_metrics_enabled).and_return(true)
allow(described_class).to receive(:metrics_folder_present?).and_return(true)
Labkit::Metrics::Client.enable!
end
it { is_expected.to be true }
end
context 'when Gitlab::CurrentSettings.prometheus_metrics_enabled is false' do
before do
allow(Gitlab::CurrentSettings).to receive(:prometheus_metrics_enabled).and_return(false)
allow(described_class).to receive(:metrics_folder_present?).and_return(true)
Labkit::Metrics::Client.enable!
end
it { is_expected.to be false }
end
context 'when metrics are disabled' do
before do
allow(Gitlab::CurrentSettings).to receive(:prometheus_metrics_enabled).and_return(true)
allow(described_class).to receive(:metrics_folder_present?).and_return(false)
Labkit::Metrics::Client.disable!
end
it { is_expected.to be false }
it 'returns a boolean' do
expect(described_class.prometheus_metrics_enabled?).to be_in([true, false])
end
end
@ -207,33 +207,38 @@ RSpec.describe Gitlab::Metrics, :prometheus, feature_category: :scalability do
context 'prometheus metrics disabled' do
before do
allow(described_class).to receive(:prometheus_metrics_enabled?).and_return(false)
Labkit::Metrics::Client.disable!
end
it_behaves_like 'prometheus metrics API'
describe '#null_metric' do
subject { described_class.send(:provide_metric, :test) }
it { is_expected.to be_a(Gitlab::Metrics::NullMetric) }
end
describe '#counter' do
subject { described_class.counter(:counter, 'doc') }
it { is_expected.to eq(described_class.null_metric) }
it { is_expected.to be_a(Gitlab::Metrics::NullMetric) }
end
describe '#summary' do
subject { described_class.summary(:summary, 'doc') }
it { is_expected.to eq(described_class.null_metric) }
it { is_expected.to be_a(Gitlab::Metrics::NullMetric) }
end
describe '#gauge' do
subject { described_class.gauge(:gauge, 'doc') }
it { is_expected.to eq(described_class.null_metric) }
it { is_expected.to be_a(Gitlab::Metrics::NullMetric) }
end
describe '#histogram' do
subject { described_class.histogram(:histogram, 'doc') }
it { is_expected.to eq(described_class.null_metric) }
it { is_expected.to be_a(Gitlab::Metrics::NullMetric) }
end
end
@ -243,33 +248,38 @@ RSpec.describe Gitlab::Metrics, :prometheus, feature_category: :scalability do
before do
stub_const('Prometheus::Client::Multiprocdir', metrics_multiproc_dir)
allow(described_class).to receive(:prometheus_metrics_enabled?).and_return(true)
Labkit::Metrics::Client.enable!
end
it_behaves_like 'prometheus metrics API'
describe '#null_metric' do
subject { described_class.send(:provide_metric, :test) }
it { is_expected.to be_nil }
end
describe '#counter' do
subject { described_class.counter(:name, 'doc') }
it { is_expected.not_to eq(described_class.null_metric) }
it { is_expected.not_to be_a(Gitlab::Metrics::NullMetric) }
end
describe '#summary' do
subject { described_class.summary(:name, 'doc') }
it { is_expected.not_to eq(described_class.null_metric) }
it { is_expected.not_to be_a(Gitlab::Metrics::NullMetric) }
end
describe '#gauge' do
subject { described_class.gauge(:name, 'doc') }
it { is_expected.not_to eq(described_class.null_metric) }
it { is_expected.not_to be_a(Gitlab::Metrics::NullMetric) }
end
describe '#histogram' do
subject { described_class.histogram(:name, 'doc') }
it { is_expected.not_to eq(described_class.null_metric) }
it { is_expected.not_to be_a(Gitlab::Metrics::NullMetric) }
end
end

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe 'OmniAuth Rack middlewares', :prometheus, feature_category: :system_access do
RSpec.describe 'OmniAuth Rack middlewares', feature_category: :system_access do
include SessionHelpers
describe 'OmniAuth before_request_phase callback' do