Commit cf8ba6b1 authored by Mayra Cabrera's avatar Mayra Cabrera

Merge branch '39-count-unique-users-for-more-accurate-smau-reporting-verify' into 'master'

Count unique users for more accurate SMAU reporting - Verify

See merge request gitlab-org/gitlab!15747
parents 131c34d1 83d2c61c
......@@ -86,3 +86,5 @@ module Ci
end
end
end
Ci::PipelineSchedule.prepend_if_ee('EE::Ci::PipelineSchedule')
......@@ -45,3 +45,5 @@ module Ci
end
end
end
Ci::Trigger.prepend_if_ee('EE::Ci::Trigger')
......@@ -64,3 +64,5 @@ module Clusters
end
end
end
Clusters::Concerns::ApplicationCore.prepend_if_ee('EE::Clusters::Concerns::ApplicationCore')
......@@ -17,6 +17,8 @@ module EE
}.with_indifferent_access.freeze
prepended do
include UsageStatistics
after_save :stick_build_if_status_changed
delegate :service_specification, to: :runner_session, allow_nil: true
......
......@@ -13,6 +13,8 @@ module EE
}.freeze
prepended do
include UsageStatistics
has_many :job_artifacts, through: :builds
has_many :vulnerabilities_occurrence_pipelines, class_name: 'Vulnerabilities::OccurrencePipeline'
has_many :vulnerabilities, source: :occurrence, through: :vulnerabilities_occurrence_pipelines, class_name: 'Vulnerabilities::Occurrence'
......
# frozen_string_literal: true
module EE
module Ci
module PipelineSchedule
extend ActiveSupport::Concern
prepended do
include UsageStatistics
end
end
end
end
# frozen_string_literal: true
module EE
module Ci
module Trigger
extend ActiveSupport::Concern
prepended do
include UsageStatistics
end
end
end
end
# frozen_string_literal: true
module EE
module Clusters
module Concerns
module ApplicationCore
extend ActiveSupport::Concern
prepended do
include UsageStatistics
class_methods do
def distinct_by_user
available.joins(:cluster).distinct_count_by(:user_id)
end
end
end
end
end
end
end
......@@ -118,6 +118,7 @@ module EE
scope :with_security_reports_stored, -> { where('EXISTS (?)', ::Vulnerabilities::Occurrence.scoped_project.select(1)) }
scope :with_security_reports, -> { where('EXISTS (?)', ::Ci::JobArtifact.security_reports.scoped_project.select(1)) }
scope :with_github_service_pipeline_events, -> { joins(:github_service).merge(GithubService.pipeline_hooks) }
delegate :shared_runners_minutes, :shared_runners_seconds, :shared_runners_seconds_last_reset,
to: :statistics, allow_nil: true
......
......@@ -185,7 +185,8 @@ module EE
usage_activity_by_stage: {
create: usage_activity_by_stage_create,
manage: usage_activity_by_stage_manage,
plan: usage_activity_by_stage_plan
plan: usage_activity_by_stage_plan,
verify: usage_activity_by_stage_verify
}
}
end
......@@ -235,6 +236,22 @@ module EE
todos: ::Todo.distinct_count_by(:author_id)
}
end
# Omitted because no user, creator or author associated: `ci_runners`
def usage_activity_by_stage_verify
{
ci_builds: ::Ci::Build.distinct_count_by(:user_id),
ci_external_pipelines: ::Ci::Pipeline.external.distinct_count_by(:user_id),
ci_internal_pipelines: ::Ci::Pipeline.internal.distinct_count_by(:user_id),
ci_pipeline_config_auto_devops: ::Ci::Pipeline.auto_devops_source.distinct_count_by(:user_id),
ci_pipeline_config_repository: ::Ci::Pipeline.repository_source.distinct_count_by(:user_id),
ci_pipeline_schedules: ::Ci::PipelineSchedule.distinct_count_by(:owner_id),
ci_pipelines: ::Ci::Pipeline.distinct_count_by(:user_id),
ci_triggers: ::Ci::Trigger.distinct_count_by(:owner_id),
clusters_applications_runner: ::Clusters::Applications::Runner.distinct_by_user,
projects_reporting_ci_cd_back_to_github: ::Project.with_github_service_pipeline_events.distinct_count_by(:creator_id)
}
end
end
end
end
......
......@@ -16,4 +16,11 @@ FactoryBot.define do
active { false }
end
end
factory :github_service do
project
active { true }
token { 'github-token' }
type { 'GithubService' }
end
end
......@@ -54,7 +54,36 @@ describe Gitlab::UsageData do
end
end
context 'for Plan' do
context 'for create' do
it 'includes accurate usage_activity_by_stage data' do
user = create(:user)
project = create(:project, :repository_private, :requiring_code_owner_approval, :github_imported,
:test_repo, :remote_mirror, creator: user)
create(:deploy_key, user: user)
create(:key, user: user)
create(:merge_request, source_project: project)
create(:project, creator: user)
create(:protected_branch, project: project)
create(:remote_mirror, project: project)
create(:snippet, author: user)
create(:suggestion, note: create(:note, project: project))
expect(described_class.uncached_data[:usage_activity_by_stage][:create]).to eq(
deploy_keys: 1,
keys: 1,
merge_requests: 1,
projects_enforcing_code_owner_approval: 1,
projects_imported_from_github: 1,
projects_with_repositories_enabled: 1,
protected_branches: 1,
remote_mirrors: 1,
snippets: 1,
suggestions: 1
)
end
end
context 'for plan' do
it 'includes accurate usage_activity_by_stage data' do
stub_licensed_features(board_assignee_lists: true, board_milestone_lists: true)
......@@ -89,31 +118,30 @@ describe Gitlab::UsageData do
end
end
context 'for create' do
context 'for verify' do
it 'includes accurate usage_activity_by_stage data' do
user = create(:user)
project = create(:project, :repository_private, :requiring_code_owner_approval, :github_imported,
:test_repo, :remote_mirror, creator: user)
create(:deploy_key, user: user)
create(:key, user: user)
create(:merge_request, source_project: project)
create(:project, creator: user)
create(:protected_branch, project: project)
create(:remote_mirror, project: project)
create(:snippet, author: user)
create(:suggestion, note: create(:note, project: project))
create(:ci_build, user: user)
create(:ci_empty_pipeline, source: :external, user: user)
create(:ci_empty_pipeline, user: user)
create(:ci_pipeline, :auto_devops_source, user: user)
create(:ci_pipeline, :repository_source, user: user)
create(:ci_pipeline_schedule, owner: user)
create(:ci_trigger, owner: user)
create(:clusters_applications_runner, :installed)
create(:github_service)
expect(described_class.uncached_data[:usage_activity_by_stage][:create]).to eq(
deploy_keys: 1,
keys: 1,
merge_requests: 1,
projects_enforcing_code_owner_approval: 1,
projects_imported_from_github: 1,
projects_with_repositories_enabled: 1,
protected_branches: 1,
remote_mirrors: 1,
snippets: 1,
suggestions: 1
expect(described_class.uncached_data[:usage_activity_by_stage][:verify]).to eq(
ci_builds: 1,
ci_external_pipelines: 1,
ci_internal_pipelines: 1,
ci_pipeline_config_auto_devops: 1,
ci_pipeline_config_repository: 1,
ci_pipeline_schedules: 1,
ci_pipelines: 1,
ci_triggers: 1,
clusters_applications_runner: 1,
projects_reporting_ci_cd_back_to_github: 1
)
end
end
......
......@@ -142,6 +142,16 @@ describe Project do
expect(described_class.with_repositories_enabled).not_to include(project_with_repositories_disabled)
end
end
describe '.with_github_service_pipeline_events' do
it 'returns the correct project' do
project_with_github_service_pipeline_events = create(:project, github_service: create(:github_service))
project_without_github_service_pipeline_events = create(:project)
expect(described_class.with_github_service_pipeline_events).to include(project_with_github_service_pipeline_events)
expect(described_class.with_github_service_pipeline_events).not_to include(project_without_github_service_pipeline_events)
end
end
end
describe 'validations' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment