Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
91ed938e3d
commit
6397f0322d
|
@ -34,6 +34,7 @@ cache-repo:
|
|||
- git clone --progress $CI_REPOSITORY_URL $CI_PROJECT_NAME
|
||||
- cd $CI_PROJECT_NAME
|
||||
- gcloud auth activate-service-account --key-file=$CI_REPO_CACHE_CREDENTIALS
|
||||
- git remote rm origin
|
||||
- tar cf $TAR_FILENAME .
|
||||
- gzip $TAR_FILENAME
|
||||
- gsutil cp $TAR_FILENAME.gz gs://gitlab-ci-git-repo-cache/project-$CI_PROJECT_ID/gitlab-master.tar.gz
|
||||
|
|
|
@ -16,6 +16,8 @@ module Ci
|
|||
include FromUnion
|
||||
include UpdatedAtFilterable
|
||||
|
||||
BridgeStatusError = Class.new(StandardError)
|
||||
|
||||
sha_attribute :source_sha
|
||||
sha_attribute :target_sha
|
||||
|
||||
|
@ -64,6 +66,7 @@ module Ci
|
|||
has_one :triggered_by_pipeline, through: :source_pipeline, source: :source_pipeline
|
||||
has_one :parent_pipeline, -> { merge(Ci::Sources::Pipeline.same_project) }, through: :source_pipeline, source: :source_pipeline
|
||||
has_one :source_job, through: :source_pipeline, source: :source_job
|
||||
has_one :source_bridge, through: :source_pipeline, source: :source_bridge
|
||||
|
||||
has_one :pipeline_config, class_name: 'Ci::PipelineConfig', inverse_of: :pipeline
|
||||
|
||||
|
@ -204,6 +207,22 @@ module Ci
|
|||
end
|
||||
end
|
||||
|
||||
after_transition any => ::Ci::Pipeline.completed_statuses do |pipeline|
|
||||
next unless pipeline.bridge_triggered?
|
||||
next unless pipeline.bridge_waiting?
|
||||
|
||||
pipeline.run_after_commit do
|
||||
::Ci::PipelineBridgeStatusWorker.perform_async(pipeline.id)
|
||||
end
|
||||
end
|
||||
|
||||
after_transition created: :pending do |pipeline|
|
||||
next unless pipeline.bridge_triggered?
|
||||
next if pipeline.bridge_waiting?
|
||||
|
||||
pipeline.update_bridge_status!
|
||||
end
|
||||
|
||||
after_transition any => [:success, :failed] do |pipeline|
|
||||
pipeline.run_after_commit do
|
||||
PipelineNotificationWorker.perform_async(pipeline.id)
|
||||
|
@ -722,6 +741,21 @@ module Ci
|
|||
end
|
||||
end
|
||||
|
||||
def update_bridge_status!
|
||||
raise ArgumentError unless bridge_triggered?
|
||||
raise BridgeStatusError unless source_bridge.active?
|
||||
|
||||
source_bridge.success!
|
||||
end
|
||||
|
||||
def bridge_triggered?
|
||||
source_bridge.present?
|
||||
end
|
||||
|
||||
def bridge_waiting?
|
||||
source_bridge&.dependent?
|
||||
end
|
||||
|
||||
def child?
|
||||
parent_pipeline.present?
|
||||
end
|
||||
|
|
|
@ -10,6 +10,7 @@ module Ci
|
|||
|
||||
belongs_to :source_project, class_name: "Project", foreign_key: :source_project_id
|
||||
belongs_to :source_job, class_name: "CommitStatus", foreign_key: :source_job_id
|
||||
belongs_to :source_bridge, class_name: "Ci::Bridge", foreign_key: :source_job_id
|
||||
belongs_to :source_pipeline, class_name: "Ci::Pipeline", foreign_key: :source_pipeline_id
|
||||
|
||||
validates :project, presence: true
|
||||
|
@ -23,5 +24,3 @@ module Ci
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
::Ci::Sources::Pipeline.prepend_if_ee('::EE::Ci::Sources::Pipeline')
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Ci
|
||||
class PipelineBridgeStatusService < ::BaseService
|
||||
def execute(pipeline)
|
||||
return unless pipeline.bridge_triggered?
|
||||
|
||||
pipeline.source_bridge.inherit_status_from_downstream!(pipeline)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Ci::PipelineBridgeStatusService.prepend_if_ee('EE::Ci::PipelineBridgeStatusService')
|
|
@ -531,6 +531,12 @@
|
|||
:latency_sensitive:
|
||||
:resource_boundary: :unknown
|
||||
:weight: 3
|
||||
- :name: pipeline_default:ci_pipeline_bridge_status
|
||||
:feature_category: :continuous_integration
|
||||
:has_external_dependencies:
|
||||
:latency_sensitive: true
|
||||
:resource_boundary: :cpu
|
||||
:weight: 3
|
||||
- :name: pipeline_default:pipeline_metrics
|
||||
:feature_category: :continuous_integration
|
||||
:has_external_dependencies:
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Ci
|
||||
class PipelineBridgeStatusWorker
|
||||
include ::ApplicationWorker
|
||||
include ::PipelineQueue
|
||||
|
||||
latency_sensitive_worker!
|
||||
worker_resource_boundary :cpu
|
||||
|
||||
def perform(pipeline_id)
|
||||
::Ci::Pipeline.find_by_id(pipeline_id).try do |pipeline|
|
||||
::Ci::PipelineBridgeStatusService
|
||||
.new(pipeline.project, pipeline.user)
|
||||
.execute(pipeline)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -221,7 +221,10 @@ with failed showing at the top, skipped next and successful cases last.
|
|||
|
||||
### Enabling the feature
|
||||
|
||||
This feature comes with the `:junit_pipeline_view` feature flag disabled by default.
|
||||
This feature comes with the `:junit_pipeline_view` feature flag disabled by default. This
|
||||
feature is disabled due to some performance issues with very large data sets.
|
||||
When [the performance issue](https://gitlab.com/gitlab-org/gitlab/issues/37725) is resolved, the feature will be enabled by default.
|
||||
|
||||
To enable this feature, ask a GitLab administrator with Rails console access to run the
|
||||
following command:
|
||||
|
||||
|
|
|
@ -1210,6 +1210,32 @@ describe Ci::Pipeline, :mailer do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when pipeline is bridge triggered' do
|
||||
before do
|
||||
pipeline.source_bridge = create(:ci_bridge)
|
||||
end
|
||||
|
||||
context 'when source bridge is dependent on pipeline status' do
|
||||
before do
|
||||
allow(pipeline.source_bridge).to receive(:dependent?).and_return(true)
|
||||
end
|
||||
|
||||
it 'schedules the pipeline bridge worker' do
|
||||
expect(::Ci::PipelineBridgeStatusWorker).to receive(:perform_async)
|
||||
|
||||
pipeline.succeed!
|
||||
end
|
||||
end
|
||||
|
||||
context 'when source bridge is not dependent on pipeline status' do
|
||||
it 'does not schedule the pipeline bridge worker' do
|
||||
expect(::Ci::PipelineBridgeStatusWorker).not_to receive(:perform_async)
|
||||
|
||||
pipeline.succeed!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def auto_devops_pipelines_completed_total(status)
|
||||
Gitlab::Metrics.counter(:auto_devops_pipelines_completed_total, 'Number of completed auto devops pipelines').get(status: status)
|
||||
end
|
||||
|
@ -2883,4 +2909,82 @@ describe Ci::Pipeline, :mailer do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'upstream status interactions' do
|
||||
context 'when a pipeline has an upstream status' do
|
||||
context 'when an upstream status is a bridge' do
|
||||
let(:bridge) { create(:ci_bridge, status: :pending) }
|
||||
|
||||
before do
|
||||
create(:ci_sources_pipeline, pipeline: pipeline, source_job: bridge)
|
||||
end
|
||||
|
||||
describe '#bridge_triggered?' do
|
||||
it 'is a pipeline triggered by a bridge' do
|
||||
expect(pipeline).to be_bridge_triggered
|
||||
end
|
||||
end
|
||||
|
||||
describe '#source_job' do
|
||||
it 'has a correct source job' do
|
||||
expect(pipeline.source_job).to eq bridge
|
||||
end
|
||||
end
|
||||
|
||||
describe '#source_bridge' do
|
||||
it 'has a correct bridge source' do
|
||||
expect(pipeline.source_bridge).to eq bridge
|
||||
end
|
||||
end
|
||||
|
||||
describe '#update_bridge_status!' do
|
||||
it 'can update bridge status if it is running' do
|
||||
pipeline.update_bridge_status!
|
||||
|
||||
expect(bridge.reload).to be_success
|
||||
end
|
||||
|
||||
it 'can not update bridge status if is not active' do
|
||||
bridge.success!
|
||||
|
||||
expect { pipeline.update_bridge_status! }
|
||||
.to raise_error Ci::Pipeline::BridgeStatusError
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when an upstream status is a build' do
|
||||
let(:build) { create(:ci_build) }
|
||||
|
||||
before do
|
||||
create(:ci_sources_pipeline, pipeline: pipeline, source_job: build)
|
||||
end
|
||||
|
||||
describe '#bridge_triggered?' do
|
||||
it 'is a pipeline that has not been triggered by a bridge' do
|
||||
expect(pipeline).not_to be_bridge_triggered
|
||||
end
|
||||
end
|
||||
|
||||
describe '#source_job' do
|
||||
it 'has a correct source job' do
|
||||
expect(pipeline.source_job).to eq build
|
||||
end
|
||||
end
|
||||
|
||||
describe '#source_bridge' do
|
||||
it 'does not have a bridge source' do
|
||||
expect(pipeline.source_bridge).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe '#update_bridge_status!' do
|
||||
it 'can not update upstream job status' do
|
||||
expect { pipeline.update_bridge_status! }
|
||||
.to raise_error ArgumentError
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,6 +8,7 @@ describe Ci::Sources::Pipeline do
|
|||
|
||||
it { is_expected.to belong_to(:source_project) }
|
||||
it { is_expected.to belong_to(:source_job) }
|
||||
it { is_expected.to belong_to(:source_bridge) }
|
||||
it { is_expected.to belong_to(:source_pipeline) }
|
||||
|
||||
it { is_expected.to validate_presence_of(:project) }
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ci::PipelineBridgeStatusService do
|
||||
let(:user) { build(:user) }
|
||||
let(:project) { build(:project) }
|
||||
let(:pipeline) { build(:ci_pipeline, project: project) }
|
||||
|
||||
describe '#execute' do
|
||||
subject { described_class.new(project, user).execute(pipeline) }
|
||||
|
||||
context 'when pipeline has upstream bridge' do
|
||||
let(:bridge) { build(:ci_bridge) }
|
||||
|
||||
before do
|
||||
pipeline.source_bridge = bridge
|
||||
end
|
||||
|
||||
it 'calls inherit_status_from_downstream on upstream bridge' do
|
||||
expect(bridge).to receive(:inherit_status_from_downstream!).with(pipeline)
|
||||
|
||||
subject
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,38 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ci::PipelineBridgeStatusWorker do
|
||||
describe '#perform' do
|
||||
subject { described_class.new.perform(pipeline_id) }
|
||||
|
||||
context 'when pipeline exists' do
|
||||
let(:pipeline) { create(:ci_pipeline) }
|
||||
let(:pipeline_id) { pipeline.id }
|
||||
|
||||
it 'calls the service' do
|
||||
service = double('bridge status service')
|
||||
|
||||
expect(Ci::PipelineBridgeStatusService)
|
||||
.to receive(:new)
|
||||
.with(pipeline.project, pipeline.user)
|
||||
.and_return(service)
|
||||
|
||||
expect(service).to receive(:execute).with(pipeline)
|
||||
|
||||
subject
|
||||
end
|
||||
end
|
||||
|
||||
context 'when pipeline does not exist' do
|
||||
let(:pipeline_id) { 1234 }
|
||||
|
||||
it 'does not call the service' do
|
||||
expect(Ci::PipelineBridgeStatusService)
|
||||
.not_to receive(:new)
|
||||
|
||||
subject
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue