Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
4fb40c9fb4
commit
db4d102e60
14 changed files with 270 additions and 2 deletions
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
name: ci_pipeline_creation_step_duration_tracking
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68485
|
||||||
|
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339486
|
||||||
|
milestone: '14.2'
|
||||||
|
type: development
|
||||||
|
group: group::pipeline execution
|
||||||
|
default_enabled: true
|
|
@ -0,0 +1,28 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# See https://docs.gitlab.com/ee/development/migration_style_guide.html
|
||||||
|
# for more information on how to write migrations for GitLab.
|
||||||
|
|
||||||
|
class StealMergeRequestDiffCommitUsersMigration < ActiveRecord::Migration[6.1]
|
||||||
|
include Gitlab::Database::MigrationHelpers
|
||||||
|
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
def up
|
||||||
|
job = Gitlab::Database::BackgroundMigrationJob
|
||||||
|
.for_migration_class('MigrateMergeRequestDiffCommitUsers')
|
||||||
|
.pending
|
||||||
|
.last
|
||||||
|
|
||||||
|
return unless job
|
||||||
|
|
||||||
|
# We schedule in one hour so we don't end up running the migrations while a
|
||||||
|
# deployment is still wrapping up. Not that that really matters, but it
|
||||||
|
# prevents from too much happening during a deployment window.
|
||||||
|
migrate_in(1.hour, 'StealMigrateMergeRequestDiffCommitUsers', job.arguments)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
# no-op
|
||||||
|
end
|
||||||
|
end
|
1
db/schema_migrations/20210823113259
Normal file
1
db/schema_migrations/20210823113259
Normal file
|
@ -0,0 +1 @@
|
||||||
|
06b44a856fc970f52b19ad8eeb38f885182003eff50ef1524ecf30887f4664d9
|
|
@ -78,6 +78,8 @@ module Gitlab
|
||||||
# rubocop: enable Style/Documentation
|
# rubocop: enable Style/Documentation
|
||||||
|
|
||||||
def perform(start_id, stop_id)
|
def perform(start_id, stop_id)
|
||||||
|
return if already_processed?(start_id, stop_id)
|
||||||
|
|
||||||
# This Hash maps user names + emails to their corresponding rows in
|
# This Hash maps user names + emails to their corresponding rows in
|
||||||
# merge_request_diff_commit_users.
|
# merge_request_diff_commit_users.
|
||||||
user_mapping = {}
|
user_mapping = {}
|
||||||
|
@ -94,6 +96,13 @@ module Gitlab
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def already_processed?(start_id, stop_id)
|
||||||
|
Database::BackgroundMigrationJob
|
||||||
|
.for_migration_execution('MigrateMergeRequestDiffCommitUsers', [start_id, stop_id])
|
||||||
|
.succeeded
|
||||||
|
.any?
|
||||||
|
end
|
||||||
|
|
||||||
# Returns the data we'll use to determine what merge_request_diff_commits
|
# Returns the data we'll use to determine what merge_request_diff_commits
|
||||||
# rows to update, and what data to use for populating their
|
# rows to update, and what data to use for populating their
|
||||||
# commit_author_id and committer_id columns.
|
# commit_author_id and committer_id columns.
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Gitlab
|
||||||
|
module BackgroundMigration
|
||||||
|
# A background migration that finished any pending
|
||||||
|
# MigrateMergeRequestDiffCommitUsers jobs, and schedules new jobs itself.
|
||||||
|
#
|
||||||
|
# This migration exists so we can bypass rescheduling issues (e.g. jobs
|
||||||
|
# getting dropped after too many retries) that may occur when
|
||||||
|
# MigrateMergeRequestDiffCommitUsers jobs take longer than expected.
|
||||||
|
class StealMigrateMergeRequestDiffCommitUsers
|
||||||
|
def perform(start_id, stop_id)
|
||||||
|
MigrateMergeRequestDiffCommitUsers.new.perform(start_id, stop_id)
|
||||||
|
schedule_next_job
|
||||||
|
end
|
||||||
|
|
||||||
|
def schedule_next_job
|
||||||
|
# We process jobs in reverse order, so that (hopefully) we are less
|
||||||
|
# likely to process jobs that the regular background migration job is
|
||||||
|
# also processing.
|
||||||
|
next_job = Database::BackgroundMigrationJob
|
||||||
|
.for_migration_class('MigrateMergeRequestDiffCommitUsers')
|
||||||
|
.pending
|
||||||
|
.last
|
||||||
|
|
||||||
|
return unless next_job
|
||||||
|
|
||||||
|
BackgroundMigrationWorker.perform_in(
|
||||||
|
5.minutes,
|
||||||
|
'StealMigrateMergeRequestDiffCommitUsers',
|
||||||
|
next_job.arguments
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -87,6 +87,13 @@ module Gitlab
|
||||||
@metrics ||= ::Gitlab::Ci::Pipeline::Metrics
|
@metrics ||= ::Gitlab::Ci::Pipeline::Metrics
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def observe_step_duration(step_class, duration)
|
||||||
|
if Feature.enabled?(:ci_pipeline_creation_step_duration_tracking, default_enabled: :yaml)
|
||||||
|
metrics.pipeline_creation_step_duration_histogram
|
||||||
|
.observe({ step: step_class.name }, duration.seconds)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def observe_creation_duration(duration)
|
def observe_creation_duration(duration)
|
||||||
metrics.pipeline_creation_duration_histogram
|
metrics.pipeline_creation_duration_histogram
|
||||||
.observe({}, duration.seconds)
|
.observe({}, duration.seconds)
|
||||||
|
|
|
@ -14,9 +14,16 @@ module Gitlab
|
||||||
|
|
||||||
def build!
|
def build!
|
||||||
@sequence.each do |step_class|
|
@sequence.each do |step_class|
|
||||||
|
step_start = ::Gitlab::Metrics::System.monotonic_time
|
||||||
step = step_class.new(@pipeline, @command)
|
step = step_class.new(@pipeline, @command)
|
||||||
|
|
||||||
step.perform!
|
step.perform!
|
||||||
|
|
||||||
|
@command.observe_step_duration(
|
||||||
|
step_class,
|
||||||
|
::Gitlab::Metrics::System.monotonic_time - step_start
|
||||||
|
)
|
||||||
|
|
||||||
break if step.break?
|
break if step.break?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ module Gitlab
|
||||||
module Ci
|
module Ci
|
||||||
module Pipeline
|
module Pipeline
|
||||||
class Metrics
|
class Metrics
|
||||||
|
extend Gitlab::Utils::StrongMemoize
|
||||||
|
|
||||||
def self.pipeline_creation_duration_histogram
|
def self.pipeline_creation_duration_histogram
|
||||||
name = :gitlab_ci_pipeline_creation_duration_seconds
|
name = :gitlab_ci_pipeline_creation_duration_seconds
|
||||||
comment = 'Pipeline creation duration'
|
comment = 'Pipeline creation duration'
|
||||||
|
@ -13,6 +15,17 @@ module Gitlab
|
||||||
::Gitlab::Metrics.histogram(name, comment, labels, buckets)
|
::Gitlab::Metrics.histogram(name, comment, labels, buckets)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.pipeline_creation_step_duration_histogram
|
||||||
|
strong_memoize(:pipeline_creation_step_histogram) do
|
||||||
|
name = :gitlab_ci_pipeline_creation_step_duration_seconds
|
||||||
|
comment = 'Duration of each pipeline creation step'
|
||||||
|
labels = { step: nil }
|
||||||
|
buckets = [0.01, 0.05, 0.1, 0.5, 1.0, 2.0, 5.0, 10.0, 15.0, 20.0, 50.0, 240.0]
|
||||||
|
|
||||||
|
::Gitlab::Metrics.histogram(name, comment, labels, buckets)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def self.pipeline_security_orchestration_policy_processing_duration_histogram
|
def self.pipeline_security_orchestration_policy_processing_duration_histogram
|
||||||
name = :gitlab_ci_pipeline_security_orchestration_policy_processing_duration_seconds
|
name = :gitlab_ci_pipeline_security_orchestration_policy_processing_duration_seconds
|
||||||
comment = 'Pipeline security orchestration policy processing duration'
|
comment = 'Pipeline security orchestration policy processing duration'
|
||||||
|
|
|
@ -91,6 +91,18 @@ RSpec.describe Gitlab::BackgroundMigration::MigrateMergeRequestDiffCommitUsers d
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#perform' do
|
describe '#perform' do
|
||||||
|
it 'skips jobs that have already been completed' do
|
||||||
|
Gitlab::Database::BackgroundMigrationJob.create!(
|
||||||
|
class_name: 'MigrateMergeRequestDiffCommitUsers',
|
||||||
|
arguments: [1, 10],
|
||||||
|
status: :succeeded
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(migration).not_to receive(:get_data_to_update)
|
||||||
|
|
||||||
|
migration.perform(1, 10)
|
||||||
|
end
|
||||||
|
|
||||||
it 'migrates the data in the range' do
|
it 'migrates the data in the range' do
|
||||||
commits.create!(
|
commits.create!(
|
||||||
merge_request_diff_id: diff.id,
|
merge_request_diff_id: diff.id,
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe Gitlab::BackgroundMigration::StealMigrateMergeRequestDiffCommitUsers do
|
||||||
|
let(:migration) { described_class.new }
|
||||||
|
|
||||||
|
describe '#perform' do
|
||||||
|
it 'processes the background migration' do
|
||||||
|
spy = instance_spy(
|
||||||
|
Gitlab::BackgroundMigration::MigrateMergeRequestDiffCommitUsers
|
||||||
|
)
|
||||||
|
|
||||||
|
allow(Gitlab::BackgroundMigration::MigrateMergeRequestDiffCommitUsers)
|
||||||
|
.to receive(:new)
|
||||||
|
.and_return(spy)
|
||||||
|
|
||||||
|
expect(spy).to receive(:perform).with(1, 4)
|
||||||
|
expect(migration).to receive(:schedule_next_job)
|
||||||
|
|
||||||
|
migration.perform(1, 4)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#schedule_next_job' do
|
||||||
|
it 'schedules the next job in reverse order' do
|
||||||
|
Gitlab::Database::BackgroundMigrationJob.create!(
|
||||||
|
class_name: 'MigrateMergeRequestDiffCommitUsers',
|
||||||
|
arguments: [10, 20]
|
||||||
|
)
|
||||||
|
|
||||||
|
Gitlab::Database::BackgroundMigrationJob.create!(
|
||||||
|
class_name: 'MigrateMergeRequestDiffCommitUsers',
|
||||||
|
arguments: [40, 50]
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(BackgroundMigrationWorker)
|
||||||
|
.to receive(:perform_in)
|
||||||
|
.with(5.minutes, 'StealMigrateMergeRequestDiffCommitUsers', [40, 50])
|
||||||
|
|
||||||
|
migration.schedule_next_job
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not schedule any new jobs when there are none' do
|
||||||
|
expect(BackgroundMigrationWorker).not_to receive(:perform_in)
|
||||||
|
|
||||||
|
migration.schedule_next_job
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -341,4 +341,40 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Command do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#observe_step_duration' do
|
||||||
|
context 'when ci_pipeline_creation_step_duration_tracking is enabled' do
|
||||||
|
it 'adds the duration to the step duration histogram' do
|
||||||
|
histogram = double(:histogram)
|
||||||
|
duration = 1.hour
|
||||||
|
|
||||||
|
expect(::Gitlab::Ci::Pipeline::Metrics).to receive(:pipeline_creation_step_duration_histogram)
|
||||||
|
.and_return(histogram)
|
||||||
|
expect(histogram).to receive(:observe)
|
||||||
|
.with({ step: 'Gitlab::Ci::Pipeline::Chain::Build' }, duration.seconds)
|
||||||
|
|
||||||
|
described_class.new.observe_step_duration(
|
||||||
|
Gitlab::Ci::Pipeline::Chain::Build,
|
||||||
|
duration
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when ci_pipeline_creation_step_duration_tracking is disabled' do
|
||||||
|
before do
|
||||||
|
stub_feature_flags(ci_pipeline_creation_step_duration_tracking: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does nothing' do
|
||||||
|
duration = 1.hour
|
||||||
|
|
||||||
|
expect(::Gitlab::Ci::Pipeline::Metrics).not_to receive(:pipeline_creation_step_duration_histogram)
|
||||||
|
|
||||||
|
described_class.new.observe_step_duration(
|
||||||
|
Gitlab::Ci::Pipeline::Chain::Build,
|
||||||
|
duration
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,8 +8,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Sequence do
|
||||||
|
|
||||||
let(:pipeline) { build_stubbed(:ci_pipeline) }
|
let(:pipeline) { build_stubbed(:ci_pipeline) }
|
||||||
let(:command) { Gitlab::Ci::Pipeline::Chain::Command.new(project: project) }
|
let(:command) { Gitlab::Ci::Pipeline::Chain::Command.new(project: project) }
|
||||||
let(:first_step) { spy('first step') }
|
let(:first_step) { spy('first step', name: 'FirstStep') }
|
||||||
let(:second_step) { spy('second step') }
|
let(:second_step) { spy('second step', name: 'SecondStep') }
|
||||||
let(:sequence) { [first_step, second_step] }
|
let(:sequence) { [first_step, second_step] }
|
||||||
let(:histogram) { spy('prometheus metric') }
|
let(:histogram) { spy('prometheus metric') }
|
||||||
|
|
||||||
|
@ -61,6 +61,17 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Sequence do
|
||||||
expect(histogram).to have_received(:observe)
|
expect(histogram).to have_received(:observe)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'adds step sequence duration to duration histogram' do
|
||||||
|
expect(command.metrics)
|
||||||
|
.to receive(:pipeline_creation_step_duration_histogram)
|
||||||
|
.twice
|
||||||
|
.and_return(histogram)
|
||||||
|
expect(histogram).to receive(:observe).with({ step: 'FirstStep' }, any_args).ordered
|
||||||
|
expect(histogram).to receive(:observe).with({ step: 'SecondStep' }, any_args).ordered
|
||||||
|
|
||||||
|
subject.build!
|
||||||
|
end
|
||||||
|
|
||||||
it 'records pipeline size by pipeline source in a histogram' do
|
it 'records pipeline size by pipeline source in a histogram' do
|
||||||
allow(command.metrics)
|
allow(command.metrics)
|
||||||
.to receive(:pipeline_size_histogram)
|
.to receive(:pipeline_size_histogram)
|
||||||
|
|
21
spec/lib/gitlab/ci/pipeline/metrics_spec.rb
Normal file
21
spec/lib/gitlab/ci/pipeline/metrics_spec.rb
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe ::Gitlab::Ci::Pipeline::Metrics do
|
||||||
|
describe '.pipeline_creation_step_duration_histogram' do
|
||||||
|
it 'adds the step to the step duration histogram' do
|
||||||
|
described_class.clear_memoization(:pipeline_creation_step_histogram)
|
||||||
|
|
||||||
|
expect(::Gitlab::Metrics).to receive(:histogram)
|
||||||
|
.with(
|
||||||
|
:gitlab_ci_pipeline_creation_step_duration_seconds,
|
||||||
|
'Duration of each pipeline creation step',
|
||||||
|
{ step: nil },
|
||||||
|
[0.01, 0.05, 0.1, 0.5, 1.0, 2.0, 5.0, 10.0, 15.0, 20.0, 50.0, 240.0]
|
||||||
|
)
|
||||||
|
|
||||||
|
described_class.pipeline_creation_step_duration_histogram
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,29 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
require_migration! 'steal_merge_request_diff_commit_users_migration'
|
||||||
|
|
||||||
|
RSpec.describe StealMergeRequestDiffCommitUsersMigration, :migration do
|
||||||
|
let(:migration) { described_class.new }
|
||||||
|
|
||||||
|
describe '#up' do
|
||||||
|
it 'schedules a job if there are pending jobs' do
|
||||||
|
Gitlab::Database::BackgroundMigrationJob.create!(
|
||||||
|
class_name: 'MigrateMergeRequestDiffCommitUsers',
|
||||||
|
arguments: [10, 20]
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(migration)
|
||||||
|
.to receive(:migrate_in)
|
||||||
|
.with(1.hour, 'StealMigrateMergeRequestDiffCommitUsers', [10, 20])
|
||||||
|
|
||||||
|
migration.up
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not schedule any jobs when all jobs have been completed' do
|
||||||
|
expect(migration).not_to receive(:migrate_in)
|
||||||
|
|
||||||
|
migration.up
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue