Commit 63914718 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 34b881842ee0
......@@ -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 @@ class Pipeline < ApplicationRecord
include FromUnion
include UpdatedAtFilterable
BridgeStatusError = Class.new(StandardError)
sha_attribute :source_sha
sha_attribute :target_sha
......@@ -64,6 +66,7 @@ class Pipeline < ApplicationRecord
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 @@ class Pipeline < ApplicationRecord
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 @@ def same_family_pipeline_ids
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 @@ class Pipeline < ApplicationRecord
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 @@ class Pipeline < ApplicationRecord
end
end
end
::Ci::Sources::Pipeline.prepend_if_ee('::EE::Ci::Sources::Pipeline')
# 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:
......
# 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 @@ def create_build(name, status)
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 @@ def create_build(name, stage_idx)
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 @@
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) }
......
# 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
# 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
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