diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 5c29d5e28c4ccd7e32f8ab7c84fe2eea511b09fe..0616540c0c2b61494baa56882a383b18f9b22ae3 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -1248,11 +1248,7 @@ def track_ci_secrets_management_id_tokens_usage def track_ci_build_created_event return unless Feature.enabled?(:track_ci_build_created_internal_event, project, type: :gitlab_com_derisk) - if user - Gitlab::InternalEvents.track_event('create_ci_build', project: project, user: user) - else - Gitlab::InternalEvents.track_event('create_ci_build', project: project) - end + Gitlab::InternalEvents.track_event('create_ci_build', project: project, user: user) end def partition_id_prefix_in_16_bit_encode diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index a3520df68d50e425089025d64392a3f22ded3d15..f976069f8069e2a27e08349a9dcf1d52c1417420 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -165,6 +165,7 @@ class Pipeline < Ci::ApplicationRecord validates :source, exclusion: { in: %w[unknown], unless: :importing? }, on: :create after_create :keep_around_commits, unless: :importing? + after_commit :track_ci_pipeline_created_event, on: :create, if: :internal_pipeline? after_find :observe_age_in_minutes, unless: :importing? use_fast_destroy :job_artifacts @@ -1462,6 +1463,16 @@ def object_hierarchy(options = {}) ::Gitlab::Ci::PipelineObjectHierarchy .new(self.class.unscoped.where(id: id), options: options) end + + def internal_pipeline? + source != "external" + end + + def track_ci_pipeline_created_event + return unless Feature.enabled?(:track_ci_pipeline_created_event, project, type: :gitlab_com_derisk) + + Gitlab::InternalEvents.track_event('create_ci_internal_pipeline', project: project, user: user) + end end end diff --git a/config/events/create_ci_build.yml b/config/events/create_ci_build.yml index c845d4f38f5d4110f2b4d1a283faca78ed433af5..72f80e4f591a931434a00c20385933347c96dbfe 100644 --- a/config/events/create_ci_build.yml +++ b/config/events/create_ci_build.yml @@ -1,5 +1,5 @@ --- -description: Ci Build created +description: Tracks the number of Ci Builds created category: InternalEventTracking action: create_ci_build identifiers: diff --git a/config/events/create_ci_internal_pipeline.yml b/config/events/create_ci_internal_pipeline.yml new file mode 100644 index 0000000000000000000000000000000000000000..6224cc8bfac21f003e759c874bb7f745bdc0e325 --- /dev/null +++ b/config/events/create_ci_internal_pipeline.yml @@ -0,0 +1,20 @@ +--- +description: Tracks the number of internal Ci pipelines created +category: InternalEventTracking +action: create_ci_internal_pipeline +identifiers: +- project +- namespace +- user +product_section: ci +product_stage: verify +product_group: pipeline_execution +milestone: '16.9' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/142356 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate diff --git a/config/feature_flags/gitlab_com_derisk/track_ci_pipeline_created_event.yml b/config/feature_flags/gitlab_com_derisk/track_ci_pipeline_created_event.yml new file mode 100644 index 0000000000000000000000000000000000000000..4a7379156ae42fec33092594b6c5e0d73fc3520b --- /dev/null +++ b/config/feature_flags/gitlab_com_derisk/track_ci_pipeline_created_event.yml @@ -0,0 +1,9 @@ +--- +name: track_ci_pipeline_created_event +feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/429065 +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/142356 +rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/production/-/issues/17445 +milestone: '16.9' +group: group::pipeline execution +type: gitlab_com_derisk +default_enabled: false diff --git a/config/metrics/counts_28d/count_distinct_user_id_from_create_ci_internal_pipeline_monthly.yml b/config/metrics/counts_28d/count_distinct_user_id_from_create_ci_internal_pipeline_monthly.yml new file mode 100644 index 0000000000000000000000000000000000000000..69aea76743d5111d0578f5acf6ecd87f6870873d --- /dev/null +++ b/config/metrics/counts_28d/count_distinct_user_id_from_create_ci_internal_pipeline_monthly.yml @@ -0,0 +1,27 @@ +--- +key_path: redis_hll_counters.count_distinct_user_id_from_create_ci_internal_pipeline_monthly +description: Monthly count of unique users who triggered internal pipelines +product_section: ci +product_stage: verify +product_group: pipeline_execution +performance_indicator_type: [] +value_type: number +status: active +milestone: '16.9' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/142356 +time_frame: 28d +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +options: + events: + - create_ci_internal_pipeline +events: +- name: create_ci_internal_pipeline + unique: user.id diff --git a/config/metrics/counts_28d/count_total_create_ci_internal_pipeline_monthly.yml b/config/metrics/counts_28d/count_total_create_ci_internal_pipeline_monthly.yml new file mode 100644 index 0000000000000000000000000000000000000000..a11f53499a3213582d5f2447e69ce0fe421d2a7e --- /dev/null +++ b/config/metrics/counts_28d/count_total_create_ci_internal_pipeline_monthly.yml @@ -0,0 +1,26 @@ +--- +key_path: counts.count_total_create_ci_internal_pipeline_monthly +description: Monthly count of internal Ci Pipelines created +product_section: ci +product_stage: verify +product_group: pipeline_execution +performance_indicator_type: [] +value_type: number +status: active +milestone: '16.9' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/142356 +time_frame: 28d +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +options: + events: + - create_ci_internal_pipeline +events: +- name: create_ci_internal_pipeline diff --git a/config/metrics/counts_all/count_total_create_ci_internal_pipeline.yml b/config/metrics/counts_all/count_total_create_ci_internal_pipeline.yml new file mode 100644 index 0000000000000000000000000000000000000000..3de3d3d780ec265cef6f23de19ce7b6dfaad0945 --- /dev/null +++ b/config/metrics/counts_all/count_total_create_ci_internal_pipeline.yml @@ -0,0 +1,26 @@ +--- +key_path: counts.count_total_create_ci_internal_pipeline +description: Total count of created internal Ci pipelines +product_section: ci +product_stage: verify +product_group: pipeline_execution +performance_indicator_type: [] +value_type: number +status: active +milestone: '16.9' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/142356 +time_frame: all +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +options: + events: + - create_ci_internal_pipeline +events: +- name: create_ci_internal_pipeline diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 100a9d2d6ee4322ac49c9e6ea508316528ea2d77..a66e7e260d67d20476e072c2e553943fd8268e27 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -91,31 +91,16 @@ end context 'when running after_commit callbacks' do - context 'without user present' do - it 'tracks creation event' do - build = FactoryBot.build(:ci_build) + it 'tracks creation event' do + build = FactoryBot.build(:ci_build, user: create(:user)) - expect(Gitlab::InternalEvents).to receive(:track_event).with( - 'create_ci_build', - project: build.project - ) - - build.save! - end - end - - context 'with user present' do - it 'tracks creation event' do - build = FactoryBot.build(:ci_build, user: create(:user)) - - expect(Gitlab::InternalEvents).to receive(:track_event).with( - 'create_ci_build', - project: build.project, - user: build.user - ) + expect(Gitlab::InternalEvents).to receive(:track_event).with( + 'create_ci_build', + project: build.project, + user: build.user + ) - build.save! - end + build.save! end context 'with FF track_ci_build_created_internal_event disabled' do diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 52c3792ac93a740ec186fa3464f15a1edc7dbbbf..9e93333245a8aaf845925b3eadb397c2163ea305 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -158,6 +158,40 @@ end end + describe 'callbacks' do + describe '.track_ci_pipeline_created_event' do + let(:pipeline) { build(:ci_pipeline, user: user) } + + it 'tracks the creation event with user information' do + expect(Gitlab::InternalEvents).to receive(:track_event).with('create_ci_internal_pipeline', project: project, user: user) + + pipeline.save! + end + + context 'when pipeline is external' do + let(:pipeline) { build(:ci_pipeline, source: :external) } + + it 'does not track creation event' do + expect(Gitlab::InternalEvents).not_to receive(:track_event) + + pipeline.save! + end + end + + context 'with FF track_ci_pipeline_created_event disabled' do + before do + stub_feature_flags(track_ci_pipeline_created_event: false) + end + + it 'does not track the creation event' do + expect(Gitlab::InternalEvents).not_to receive(:track_event) + + pipeline.save! + end + end + end + end + describe 'unlocking pipelines based on state transition' do let(:ci_ref) { create(:ci_ref) } let(:unlock_previous_pipelines_worker_spy) { class_spy(::Ci::Refs::UnlockPreviousPipelinesWorker) }