diff options
Diffstat (limited to 'lib/gitlab')
36 files changed, 366 insertions, 80 deletions
diff --git a/lib/gitlab/analytics/cycle_analytics/average.rb b/lib/gitlab/analytics/cycle_analytics/average.rb new file mode 100644 index 00000000000..a449b71b165 --- /dev/null +++ b/lib/gitlab/analytics/cycle_analytics/average.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +module Gitlab + module Analytics + module CycleAnalytics + class Average + include Gitlab::Utils::StrongMemoize + include StageQueryHelpers + + def initialize(stage:, query:) + @stage = stage + @query = query + end + + def seconds + select_average ? select_average['average'] : nil + end + + def days + seconds ? seconds.fdiv(1.day) : nil + end + + private + + attr_reader :stage + + # rubocop: disable CodeReuse/ActiveRecord + def select_average + strong_memoize(:select_average) do + execute_query(@query.select(average_in_seconds.as('average')).reorder(nil)).first + end + end + # rubocop: enable CodeReuse/ActiveRecord + + def average + Arel::Nodes::NamedFunction.new( + 'AVG', + [duration] + ) + end + + def average_in_seconds + Arel::Nodes::Extract.new(average, :epoch) + end + end + end + end +end diff --git a/lib/gitlab/analytics/cycle_analytics/data_collector.rb b/lib/gitlab/analytics/cycle_analytics/data_collector.rb index 5eca364a697..10a008a76d5 100644 --- a/lib/gitlab/analytics/cycle_analytics/data_collector.rb +++ b/lib/gitlab/analytics/cycle_analytics/data_collector.rb @@ -31,6 +31,12 @@ module Gitlab end end + def average + strong_memoize(:average) do + Average.new(stage: stage, query: query) + end + end + private attr_reader :stage, :params diff --git a/lib/gitlab/analytics/instance_statistics/workers_argument_builder.rb b/lib/gitlab/analytics/usage_trends/workers_argument_builder.rb index 54b3bbb3ce6..a502f46287d 100644 --- a/lib/gitlab/analytics/instance_statistics/workers_argument_builder.rb +++ b/lib/gitlab/analytics/usage_trends/workers_argument_builder.rb @@ -2,7 +2,7 @@ module Gitlab module Analytics - module InstanceStatistics + module UsageTrends class WorkersArgumentBuilder def initialize(measurement_identifiers: [], recorded_at: Time.zone.now) @measurement_identifiers = measurement_identifiers @@ -35,11 +35,11 @@ module Gitlab end def custom_min_max_queries - ::Analytics::InstanceStatistics::Measurement.identifier_min_max_queries + ::Analytics::UsageTrends::Measurement.identifier_min_max_queries end def query_mappings - ::Analytics::InstanceStatistics::Measurement.identifier_query_mapping + ::Analytics::UsageTrends::Measurement.identifier_query_mapping end end end diff --git a/lib/gitlab/application_rate_limiter.rb b/lib/gitlab/application_rate_limiter.rb index 0a69a9c503d..f74edf2b767 100644 --- a/lib/gitlab/application_rate_limiter.rb +++ b/lib/gitlab/application_rate_limiter.rb @@ -47,7 +47,7 @@ module Gitlab # @option scope [Array<ActiveRecord>] Array of ActiveRecord models to scope throttling to a specific request (e.g. per user per project) # @option threshold [Integer] Optional threshold value to override default one registered in `.rate_limits` # @option interval [Integer] Optional interval value to override default one registered in `.rate_limits` - # @option users_allowlist [Array<String>] Optional list of usernames to excepted from the limit. This param will only be functional if Scope includes a current user. + # @option users_allowlist [Array<String>] Optional list of usernames to exclude from the limit. This param will only be functional if Scope includes a current user. # # @return [Boolean] Whether or not a request should be throttled def throttled?(key, **options) diff --git a/lib/gitlab/auth/o_auth/provider.rb b/lib/gitlab/auth/o_auth/provider.rb index 57ff3fcd1f0..ab6ac815601 100644 --- a/lib/gitlab/auth/o_auth/provider.rb +++ b/lib/gitlab/auth/o_auth/provider.rb @@ -5,11 +5,12 @@ module Gitlab module OAuth class Provider LABELS = { - "github" => "GitHub", - "gitlab" => "GitLab.com", - "google_oauth2" => "Google", - "azure_oauth2" => "Azure AD", - 'atlassian_oauth2' => 'Atlassian' + "github" => "GitHub", + "gitlab" => "GitLab.com", + "google_oauth2" => "Google", + "azure_oauth2" => "Azure AD", + "azure_activedirectory_v2" => "Azure AD v2", + 'atlassian_oauth2' => 'Atlassian' }.freeze def self.authentication(user, provider) diff --git a/lib/gitlab/background_migration/set_default_iteration_cadences.rb b/lib/gitlab/background_migration/set_default_iteration_cadences.rb new file mode 100644 index 00000000000..530608144aa --- /dev/null +++ b/lib/gitlab/background_migration/set_default_iteration_cadences.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + # rubocop:disable Style/Documentation + class SetDefaultIterationCadences + class Iteration < ApplicationRecord + self.table_name = 'sprints' + end + + class IterationCadence < ApplicationRecord + self.table_name = 'iterations_cadences' + + include BulkInsertSafe + end + + class Group < ApplicationRecord + self.table_name = 'namespaces' + end + + def perform(*group_ids) + create_iterations_cadences(group_ids) + assign_iterations_cadences(group_ids) + end + + private + + def create_iterations_cadences(group_ids) + groups_with_cadence = IterationCadence.select(:group_id) + new_cadences = Group.where(id: group_ids).where.not(id: groups_with_cadence).map do |group| + last_iteration = Iteration.where(group_id: group.id).order(:start_date)&.last + + next unless last_iteration + + time = Time.now + IterationCadence.new( + group_id: group.id, + title: "#{group.name} Iterations", + start_date: last_iteration.start_date, + last_run_date: last_iteration.start_date, + automatic: false, + created_at: time, + updated_at: time + ) + end + + IterationCadence.bulk_insert!(new_cadences.compact) + end + + def assign_iterations_cadences(group_ids) + IterationCadence.where(group_id: group_ids).each do |cadence| + Iteration.where(iterations_cadence_id: nil).where(group_id: cadence.group_id).update_all(iterations_cadence_id: cadence.id) + end + end + end + end +end diff --git a/lib/gitlab/ci/jwt.rb b/lib/gitlab/ci/jwt.rb index 0870c74053a..af06e124736 100644 --- a/lib/gitlab/ci/jwt.rb +++ b/lib/gitlab/ci/jwt.rb @@ -60,7 +60,7 @@ module Gitlab ref_protected: build.protected.to_s } - if include_environment_claims? + if environment.present? fields.merge!( environment: environment.name, environment_protected: environment_protected?.to_s @@ -119,10 +119,6 @@ module Gitlab def environment_protected? false # Overridden in EE end - - def include_environment_claims? - Feature.enabled?(:ci_jwt_include_environment) && environment.present? - end end end end diff --git a/lib/gitlab/ci/templates/LaTeX.gitlab-ci.yml b/lib/gitlab/ci/templates/LaTeX.gitlab-ci.yml index a4aed36889e..e4ed7fadfaa 100644 --- a/lib/gitlab/ci/templates/LaTeX.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/LaTeX.gitlab-ci.yml @@ -1,11 +1,20 @@ -# use docker image with latex preinstalled -# since there is no official latex image, use https://github.com/blang/latex-docker -# possible alternative: https://github.com/natlownes/docker-latex -image: blang/latex +--- +variables: + # Feel free to choose the image that suits you best. + # blang/latex:latest ... Former image used in this template. No longer maintained by author. + # listx/texlive:2020 ... The default, referring to TexLive 2020. Current at least to 2021-02-02. + + # Additional alternatives with high Docker pull counts: + # thomasweise/docker-texlive-full + # thomasweise/texlive + # adnrv/texlive + LATEX_IMAGE: listx/texlive:2020 build: + image: $LATEX_IMAGE script: - latexmk -pdf + artifacts: paths: - "*.pdf" diff --git a/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml index 135f0df99fe..460cb84460a 100644 --- a/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml @@ -172,6 +172,7 @@ apifuzzer_fuzz_dnd: -e FUZZAPI_HAR \ -e FUZZAPI_OPENAPI \ -e FUZZAPI_POSTMAN_COLLECTION \ + -e FUZZAPI_POSTMAN_COLLECTION_VARIABLES \ -e FUZZAPI_TARGET_URL \ -e FUZZAPI_OVERRIDES_FILE \ -e FUZZAPI_OVERRIDES_ENV \ @@ -214,6 +215,7 @@ apifuzzer_fuzz_dnd: -e FUZZAPI_HAR \ -e FUZZAPI_OPENAPI \ -e FUZZAPI_POSTMAN_COLLECTION \ + -e FUZZAPI_POSTMAN_COLLECTION_VARIABLES \ -e FUZZAPI_TARGET_URL \ -e FUZZAPI_OVERRIDES_FILE \ -e FUZZAPI_OVERRIDES_ENV \ diff --git a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml index 828352743b4..3b166505e0a 100644 --- a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml @@ -140,7 +140,9 @@ gosec-sast: mobsf-android-sast: extends: .sast-analyzer services: - - name: opensecurity/mobile-security-framework-mobsf:latest + # this version must match with analyzer version mentioned in: https://gitlab.com/gitlab-org/security-products/analyzers/mobsf/-/blob/master/Dockerfile + # Unfortunately, we need to keep track of mobsf version in 2 different places for now. + - name: opensecurity/mobile-security-framework-mobsf:v3.2.9 alias: mobsf image: name: "$SAST_ANALYZER_IMAGE" @@ -161,7 +163,9 @@ mobsf-android-sast: mobsf-ios-sast: extends: .sast-analyzer services: - - name: opensecurity/mobile-security-framework-mobsf:latest + # this version must match with analyzer version mentioned in: https://gitlab.com/gitlab-org/security-products/analyzers/mobsf/-/blob/master/Dockerfile + # Unfortunately, we need to keep track of mobsf version in 2 different places for now. + - name: opensecurity/mobile-security-framework-mobsf:v3.2.9 alias: mobsf image: name: "$SAST_ANALYZER_IMAGE" diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb index 0bf41f9dc0d..55f381fcb64 100644 --- a/lib/gitlab/current_settings.rb +++ b/lib/gitlab/current_settings.rb @@ -3,6 +3,10 @@ module Gitlab module CurrentSettings class << self + def signup_disabled? + !signup_enabled? + end + def current_application_settings Gitlab::SafeRequestStore.fetch(:current_application_settings) { ensure_application_settings! } end diff --git a/lib/gitlab/database/migrations/observation.rb b/lib/gitlab/database/migrations/observation.rb index 518c2c560d2..046843824a4 100644 --- a/lib/gitlab/database/migrations/observation.rb +++ b/lib/gitlab/database/migrations/observation.rb @@ -7,7 +7,8 @@ module Gitlab :migration, :walltime, :success, - :total_database_size_change + :total_database_size_change, + :query_statistics ) end end diff --git a/lib/gitlab/database/migrations/observers.rb b/lib/gitlab/database/migrations/observers.rb index 4b931d3c19c..592993aeac5 100644 --- a/lib/gitlab/database/migrations/observers.rb +++ b/lib/gitlab/database/migrations/observers.rb @@ -6,7 +6,8 @@ module Gitlab module Observers def self.all_observers [ - TotalDatabaseSizeChange.new + TotalDatabaseSizeChange.new, + QueryStatistics.new ] end end diff --git a/lib/gitlab/database/migrations/observers/query_statistics.rb b/lib/gitlab/database/migrations/observers/query_statistics.rb new file mode 100644 index 00000000000..466f4724256 --- /dev/null +++ b/lib/gitlab/database/migrations/observers/query_statistics.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +module Gitlab + module Database + module Migrations + module Observers + # This observer gathers statistics from the pg_stat_statements extension. + # Notice that this extension is not installed by default. In case it cannot + # be found, the observer does nothing and doesn't throw an error. + class QueryStatistics < MigrationObserver + include Gitlab::Database::SchemaHelpers + + def before + return unless enabled? + + connection.execute('select pg_stat_statements_reset()') + end + + def record(observation) + return unless enabled? + + observation.query_statistics = connection.execute(<<~SQL) + SELECT query, calls, total_time, max_time, mean_time, rows + FROM pg_stat_statements + ORDER BY total_time DESC + SQL + end + + private + + def enabled? + function_exists?(:pg_stat_statements_reset) && connection.view_exists?(:pg_stat_statements) + end + end + end + end + end +end diff --git a/lib/gitlab/email/handler/service_desk_handler.rb b/lib/gitlab/email/handler/service_desk_handler.rb index d1dd616385d..80e8b726099 100644 --- a/lib/gitlab/email/handler/service_desk_handler.rb +++ b/lib/gitlab/email/handler/service_desk_handler.rb @@ -79,7 +79,7 @@ module Gitlab @issue = Issues::CreateService.new( project, User.support_bot, - title: issue_title, + title: mail.subject, description: message_including_template, confidential: true, external_author: from_address @@ -137,12 +137,6 @@ module Gitlab (mail.reply_to || []).first || mail.from.first || mail.sender end - def issue_title - from = "(from #{from_address})" if from_address - - "Service Desk #{from}: #{mail.subject}" - end - def can_handle_legacy_format? project_path && project_path.include?('/') && !mail_key.include?('+') end diff --git a/lib/gitlab/experimentation.rb b/lib/gitlab/experimentation.rb index 423f238a0a2..337c28f3179 100644 --- a/lib/gitlab/experimentation.rb +++ b/lib/gitlab/experimentation.rb @@ -58,10 +58,6 @@ module Gitlab tracking_category: 'Growth::Conversion::Experiment::ContactSalesInApp', use_backwards_compatible_subject_index: true }, - customize_homepage: { - tracking_category: 'Growth::Expansion::Experiment::CustomizeHomepage', - use_backwards_compatible_subject_index: true - }, group_only_trials: { tracking_category: 'Growth::Conversion::Experiment::GroupOnlyTrials', use_backwards_compatible_subject_index: true @@ -81,7 +77,7 @@ module Gitlab trial_during_signup: { tracking_category: 'Growth::Conversion::Experiment::TrialDuringSignup' }, - ci_syntax_templates: { + ci_syntax_templates_b: { tracking_category: 'Growth::Activation::Experiment::CiSyntaxTemplates', rollout_strategy: :user }, diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb index 3c7fa88977e..e3788814dd5 100644 --- a/lib/gitlab/gitaly_client.rb +++ b/lib/gitlab/gitaly_client.rb @@ -246,9 +246,7 @@ module Gitlab def self.route_to_primary return {} unless Gitlab::SafeRequestStore.active? - return {} unless Gitlab::SafeRequestStore[:gitlab_git_env] - - return {} if Gitlab::SafeRequestStore[:gitlab_git_env].empty? + return {} if Gitlab::SafeRequestStore[:gitlab_git_env].blank? { 'gitaly-route-repository-accessor-policy' => 'primary-only' } end diff --git a/lib/gitlab/gitaly_client/storage_settings.rb b/lib/gitlab/gitaly_client/storage_settings.rb index 5e50ac72965..7edd42f9ef7 100644 --- a/lib/gitlab/gitaly_client/storage_settings.rb +++ b/lib/gitlab/gitaly_client/storage_settings.rb @@ -60,7 +60,8 @@ module Gitlab end def legacy_disk_path - if self.class.disk_access_denied? + # Do not use self.class due to Spring reloading issues + if Gitlab::GitalyClient::StorageSettings.disk_access_denied? raise DirectPathAccessError, "git disk access denied" end diff --git a/lib/gitlab/graphql/docs/helper.rb b/lib/gitlab/graphql/docs/helper.rb index ad9e08e189c..155602740c4 100644 --- a/lib/gitlab/graphql/docs/helper.rb +++ b/lib/gitlab/graphql/docs/helper.rb @@ -28,16 +28,20 @@ module Gitlab end def render_name_and_description(object) - content = "### #{object[:name]}\n" + content = "### #{object[:name].camelcase}\n" if object[:description].present? - content += "\n#{object[:description]}.\n" + content += "\n#{object[:description]}" + content += '.' unless object[:description].ends_with?('.') + content += "\n" end content end def sorted_by_name(objects) + return [] unless objects.present? + objects.sort_by { |o| o[:name] } end @@ -49,6 +53,14 @@ module Gitlab ] end + def render_argument(argument) + '| %s | %s | %s |' % [ + render_name(argument), + render_description(argument), + render_field_type(argument[:type][:info]) + ] + end + def render_enum_value(value) '| %s | %s |' % [ render_name(value), @@ -98,6 +110,10 @@ module Gitlab end end + def queries + graphql_operation_types.find { |type| type[:name] == 'Query' }.to_h[:fields] + end + # We ignore the built-in enum types. def enums graphql_enum_types.select do |enum_type| diff --git a/lib/gitlab/graphql/docs/templates/default.md.haml b/lib/gitlab/graphql/docs/templates/default.md.haml index 9dfb9b090a8..1df1c3a3e58 100644 --- a/lib/gitlab/graphql/docs/templates/default.md.haml +++ b/lib/gitlab/graphql/docs/templates/default.md.haml @@ -21,6 +21,24 @@ \ :plain + ## Queries + + Queries are used to get the resources, filter or query them. + + For more information, visit [Queries and Mutations](https://graphql.org/learn/queries/). +\ + +- sorted_by_name(queries).each do |query| + + = render_name_and_description(query) + - unless query[:arguments].empty? + ~ "| Name | Description | Type |" + ~ "| ----- | ---- | ----------- |" + - sorted_by_name(query[:arguments]).each do |argument| + = render_argument(argument) + \ + +:plain ## Object types Object types represent the resources that the GitLab GraphQL API can return. diff --git a/lib/gitlab/import_export/repo_restorer.rb b/lib/gitlab/import_export/repo_restorer.rb index 8af7b68d78e..998da3e4afb 100644 --- a/lib/gitlab/import_export/repo_restorer.rb +++ b/lib/gitlab/import_export/repo_restorer.rb @@ -42,7 +42,7 @@ module Gitlab def ensure_repository_does_not_exist! if repository.exists? shared.logger.info( - message: %Q{Deleting existing "#{repository.path}" to re-import it.} + message: %Q{Deleting existing "#{repository.disk_path}" to re-import it.} ) Repositories::DestroyService.new(repository).execute diff --git a/lib/gitlab/marginalia.rb b/lib/gitlab/marginalia.rb index 325a8c5c325..c99cf113638 100644 --- a/lib/gitlab/marginalia.rb +++ b/lib/gitlab/marginalia.rb @@ -2,8 +2,6 @@ module Gitlab module Marginalia - cattr_accessor :enabled, default: false - def self.set_application_name ::Marginalia.application_name = Gitlab.process_name end @@ -13,12 +11,5 @@ module Gitlab ::Marginalia::SidekiqInstrumentation.enable! end end - - def self.set_enabled_from_feature_flag - # During db:create and db:bootstrap skip feature query as DB is not available yet. - return false unless Gitlab::Database.cached_table_exists?('features') - - self.enabled = Feature.enabled?(:marginalia, type: :ops) - end end end diff --git a/lib/gitlab/marginalia/active_record_instrumentation.rb b/lib/gitlab/marginalia/active_record_instrumentation.rb deleted file mode 100644 index 452f472bf6a..00000000000 --- a/lib/gitlab/marginalia/active_record_instrumentation.rb +++ /dev/null @@ -1,12 +0,0 @@ -# frozen_string_literal: true - -# Patch to annotate sql only when the feature is enabled. -module Gitlab - module Marginalia - module ActiveRecordInstrumentation - def annotate_sql(sql) - Gitlab::Marginalia.enabled ? super(sql) : sql - end - end - end -end diff --git a/lib/gitlab/metrics/samplers/ruby_sampler.rb b/lib/gitlab/metrics/samplers/ruby_sampler.rb index 76175b465e4..3d29d38fa1f 100644 --- a/lib/gitlab/metrics/samplers/ruby_sampler.rb +++ b/lib/gitlab/metrics/samplers/ruby_sampler.rb @@ -7,7 +7,7 @@ module Gitlab module Samplers class RubySampler < BaseSampler DEFAULT_SAMPLING_INTERVAL_SECONDS = 60 - GC_REPORT_BUCKETS = [0.005, 0.01, 0.02, 0.04, 0.07, 0.1, 0.5].freeze + GC_REPORT_BUCKETS = [0.01, 0.05, 0.1, 0.2, 0.3, 0.5, 1].freeze def initialize(*) GC::Profiler.clear diff --git a/lib/gitlab/metrics/subscribers/active_record.rb b/lib/gitlab/metrics/subscribers/active_record.rb index d725d8d7b29..111aa2cab48 100644 --- a/lib/gitlab/metrics/subscribers/active_record.rb +++ b/lib/gitlab/metrics/subscribers/active_record.rb @@ -9,6 +9,7 @@ module Gitlab IGNORABLE_SQL = %w{BEGIN COMMIT}.freeze DB_COUNTERS = %i{db_count db_write_count db_cached_count}.freeze + SQL_COMMANDS_WITH_COMMENTS_REGEX = /\A(\/\*.*\*\/\s)?((?!(.*[^\w'"](DELETE|UPDATE|INSERT INTO)[^\w'"])))(WITH.*)?(SELECT)((?!(FOR UPDATE|FOR SHARE)).)*$/i.freeze def sql(event) # Mark this thread as requiring a database connection. This is used @@ -37,7 +38,7 @@ module Gitlab private def select_sql_command?(payload) - payload[:sql].match(/\A((?!(.*[^\w'"](DELETE|UPDATE|INSERT INTO)[^\w'"])))(WITH.*)?(SELECT)((?!(FOR UPDATE|FOR SHARE)).)*$/i) + payload[:sql].match(SQL_COMMANDS_WITH_COMMENTS_REGEX) end def increment_db_counters(payload) diff --git a/lib/gitlab/performance_bar/redis_adapter_when_peek_enabled.rb b/lib/gitlab/performance_bar/redis_adapter_when_peek_enabled.rb index 133d777fc32..ac5c907465e 100644 --- a/lib/gitlab/performance_bar/redis_adapter_when_peek_enabled.rb +++ b/lib/gitlab/performance_bar/redis_adapter_when_peek_enabled.rb @@ -17,7 +17,7 @@ module Gitlab # to a structured log # rubocop:disable Gitlab/ModuleWithInstanceVariables def enqueue_stats_job(request_id) - return unless gather_stats? + return unless Feature.enabled?(:performance_bar_stats) @client.sadd(GitlabPerformanceBarStatsWorker::STATS_KEY, request_id) @@ -43,12 +43,6 @@ module Gitlab ) end # rubocop:enable Gitlab/ModuleWithInstanceVariables - - def gather_stats? - return unless Feature.enabled?(:performance_bar_stats) - - Gitlab.com? || Gitlab.staging? || !Rails.env.production? - end end end end diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb index 96f2b7570b3..00739c05386 100644 --- a/lib/gitlab/regex.rb +++ b/lib/gitlab/regex.rb @@ -61,6 +61,10 @@ module Gitlab maven_app_name_regex end + def npm_package_name_regex + @npm_package_name_regex ||= %r{\A(?:@(#{Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX})/)?[-+\.\_a-zA-Z0-9]+\z} + end + def nuget_package_name_regex @nuget_package_name_regex ||= %r{\A[-+\.\_a-zA-Z0-9]+\z}.freeze end diff --git a/lib/gitlab/template/base_template.rb b/lib/gitlab/template/base_template.rb index 0f933a61598..dc006877129 100644 --- a/lib/gitlab/template/base_template.rb +++ b/lib/gitlab/template/base_template.rb @@ -87,11 +87,11 @@ module Gitlab raise NotImplementedError end - def by_category(category, project = nil) + def by_category(category, project = nil, empty_category_title: nil) directory = category_directory(category) files = finder(project).list_files_for(directory) - files.map { |f| new(f, project, category: category) }.sort + files.map { |f| new(f, project, category: category.presence || empty_category_title) }.sort end def category_directory(category) @@ -108,7 +108,7 @@ module Gitlab # Gitaly the actual template names within a given project's repository for all file templates # other than `issue` and `merge request` description templates, which would instead # overwrite the `template_names` method to return a redis cached version, by reading cached values - # from `repository.issue_template_names_by_category` and `repository.merge_request_template_names_by_category` + # from `repository.issue_template_names_hash` and `repository.merge_request_template_names_hash` # methods. def repository_template_names(project) template_names_by_category(self.all(project)) diff --git a/lib/gitlab/template/issue_template.rb b/lib/gitlab/template/issue_template.rb index 3049f43b322..6e579018e45 100644 --- a/lib/gitlab/template/issue_template.rb +++ b/lib/gitlab/template/issue_template.rb @@ -23,7 +23,11 @@ module Gitlab # own caching mechanism to avoid the back and forth call jumps between finder and model. # # follow-up issue: https://gitlab.com/gitlab-org/gitlab/-/issues/300279 - project.repository.issue_template_names_by_category + project.repository.issue_template_names_hash + end + + def by_category(category, project = nil, empty_category_title: nil) + super(category, project, empty_category_title: _('Project Templates')) end end end diff --git a/lib/gitlab/template/merge_request_template.rb b/lib/gitlab/template/merge_request_template.rb index 9442f3b13fb..241a823d870 100644 --- a/lib/gitlab/template/merge_request_template.rb +++ b/lib/gitlab/template/merge_request_template.rb @@ -23,7 +23,11 @@ module Gitlab # own caching mechanism to avoid the back and forth call jumps between finder and model. # # follow-up issue: https://gitlab.com/gitlab-org/gitlab/-/issues/300279 - project.repository.merge_request_template_names_by_category + project.repository.merge_request_template_names_hash + end + + def by_category(category, project = nil, empty_category_title: nil) + super(category, project, empty_category_title: _('Project Templates')) end end end diff --git a/lib/gitlab/tracking/standard_context.rb b/lib/gitlab/tracking/standard_context.rb index 92fdd008249..8ce16c11267 100644 --- a/lib/gitlab/tracking/standard_context.rb +++ b/lib/gitlab/tracking/standard_context.rb @@ -15,10 +15,14 @@ module Gitlab end def environment - return 'production' if Gitlab.com_and_canary? - return 'staging' if Gitlab.staging? + return 'production' if Gitlab.com? + + return 'org' if Gitlab.org? + + return 'self-managed' if Rails.env.production? + 'development' end diff --git a/lib/gitlab/usage/docs/helper.rb b/lib/gitlab/usage/docs/helper.rb index 8483334800b..e090eb65b4b 100644 --- a/lib/gitlab/usage/docs/helper.rb +++ b/lib/gitlab/usage/docs/helper.rb @@ -31,7 +31,9 @@ module Gitlab end def render_description(object) - object.description + return 'Missing description' unless object.attributes[:description].present? + + object.attributes[:description] end def render_attribute_row(key, value) diff --git a/lib/gitlab/usage/docs/value_formatter.rb b/lib/gitlab/usage/docs/value_formatter.rb index a2dc9b081f8..22c5c13fc0f 100644 --- a/lib/gitlab/usage/docs/value_formatter.rb +++ b/lib/gitlab/usage/docs/value_formatter.rb @@ -5,12 +5,14 @@ module Gitlab module Docs class ValueFormatter def self.format(key, value) + return '' unless value.present? + case key when :key_path "**`#{value}`**" when :data_source value.to_s.capitalize - when :product_group + when :product_group, :product_category "`#{value}`" when :introduced_by_url "[Introduced by](#{value})" diff --git a/lib/gitlab/usage_data_counters/aggregated_metrics/code_review.yml b/lib/gitlab/usage_data_counters/aggregated_metrics/code_review.yml new file mode 100644 index 00000000000..4f86d500164 --- /dev/null +++ b/lib/gitlab/usage_data_counters/aggregated_metrics/code_review.yml @@ -0,0 +1,89 @@ +# code_review_extension_category_monthly_active_users +# This is only metrics related to the VS Code Extension for now. +# +# code_review_category_monthly_active_users +# This is the user based metrics. These should only be user based metrics and only be related to the Code Review things inside of GitLab. +# +# code_review_group_monthly_active_users +# This is an aggregation of both of the above aggregations. It's intended to represent all users who interact with our group across all of our categories. +--- +- name: code_review_group_monthly_active_users + operator: OR + feature_flag: usage_data_code_review_aggregation + source: redis + events: [ + 'i_code_review_user_single_file_diffs', + 'i_code_review_user_create_mr', + 'i_code_review_user_close_mr', + 'i_code_review_user_reopen_mr', + 'i_code_review_user_resolve_thread', + 'i_code_review_user_unresolve_thread', + 'i_code_review_edit_mr_title', + 'i_code_review_edit_mr_desc', + 'i_code_review_user_merge_mr', + 'i_code_review_user_create_mr_comment', + 'i_code_review_user_edit_mr_comment', + 'i_code_review_user_remove_mr_comment', + 'i_code_review_user_create_review_note', + 'i_code_review_user_publish_review', + 'i_code_review_user_create_multiline_mr_comment', + 'i_code_review_user_edit_multiline_mr_comment', + 'i_code_review_user_remove_multiline_mr_comment', + 'i_code_review_user_add_suggestion', + 'i_code_review_user_apply_suggestion', + 'i_code_review_user_assigned', + 'i_code_review_user_review_requested', + 'i_code_review_user_approve_mr', + 'i_code_review_user_unapprove_mr', + 'i_code_review_user_marked_as_draft', + 'i_code_review_user_unmarked_as_draft', + 'i_code_review_user_approval_rule_added', + 'i_code_review_user_approval_rule_deleted', + 'i_code_review_user_approval_rule_edited', + 'i_code_review_user_vs_code_api_request', + 'i_code_review_user_toggled_task_item_status', + 'i_code_review_user_create_mr_from_issue' + ] +- name: code_review_category_monthly_active_users + operator: OR + feature_flag: usage_data_code_review_aggregation + source: redis + events: [ + 'i_code_review_user_single_file_diffs', + 'i_code_review_user_create_mr', + 'i_code_review_user_close_mr', + 'i_code_review_user_reopen_mr', + 'i_code_review_user_resolve_thread', + 'i_code_review_user_unresolve_thread', + 'i_code_review_edit_mr_title', + 'i_code_review_edit_mr_desc', + 'i_code_review_user_merge_mr', + 'i_code_review_user_create_mr_comment', + 'i_code_review_user_edit_mr_comment', + 'i_code_review_user_remove_mr_comment', + 'i_code_review_user_create_review_note', + 'i_code_review_user_publish_review', + 'i_code_review_user_create_multiline_mr_comment', + 'i_code_review_user_edit_multiline_mr_comment', + 'i_code_review_user_remove_multiline_mr_comment', + 'i_code_review_user_add_suggestion', + 'i_code_review_user_apply_suggestion', + 'i_code_review_user_assigned', + 'i_code_review_user_review_requested', + 'i_code_review_user_approve_mr', + 'i_code_review_user_unapprove_mr', + 'i_code_review_user_marked_as_draft', + 'i_code_review_user_unmarked_as_draft', + 'i_code_review_user_approval_rule_added', + 'i_code_review_user_approval_rule_deleted', + 'i_code_review_user_approval_rule_edited', + 'i_code_review_user_toggled_task_item_status', + 'i_code_review_user_create_mr_from_issue' + ] +- name: code_review_extension_category_monthly_active_users + operator: OR + feature_flag: usage_data_code_review_aggregation + source: redis + events: [ + 'i_code_review_user_vs_code_api_request' + ] diff --git a/lib/gitlab/usage_data_counters/counter_events/package_events.yml b/lib/gitlab/usage_data_counters/counter_events/package_events.yml index f6bddabdd44..e1648245f3f 100644 --- a/lib/gitlab/usage_data_counters/counter_events/package_events.yml +++ b/lib/gitlab/usage_data_counters/counter_events/package_events.yml @@ -41,6 +41,9 @@ - i_package_pypi_delete_package - i_package_pypi_pull_package - i_package_pypi_push_package +- i_package_rubygems_delete_package +- i_package_rubygems_pull_package +- i_package_rubygems_push_package - i_package_tag_delete_package - i_package_tag_pull_package - i_package_tag_push_package diff --git a/lib/gitlab/usage_data_counters/known_events/package_events.yml b/lib/gitlab/usage_data_counters/known_events/package_events.yml index 78a2a587b34..6cf31ba4db7 100644 --- a/lib/gitlab/usage_data_counters/known_events/package_events.yml +++ b/lib/gitlab/usage_data_counters/known_events/package_events.yml @@ -99,6 +99,16 @@ aggregation: weekly redis_slot: package feature_flag: collect_package_events_redis +- name: i_package_rubygems_deploy_token + category: deploy_token_packages + aggregation: weekly + redis_slot: package + feature_flag: collect_package_events_redis +- name: i_package_rubygems_user + category: user_packages + aggregation: weekly + redis_slot: package + feature_flag: collect_package_events_redis - name: i_package_tag_deploy_token category: deploy_token_packages aggregation: weekly |