Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-08-19 12:08:42 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-08-19 12:08:42 +0300
commitb76ae638462ab0f673e5915986070518dd3f9ad3 (patch)
treebdab0533383b52873be0ec0eb4d3c66598ff8b91 /spec/services/ci
parent434373eabe7b4be9593d18a585fb763f1e5f1a6f (diff)
Add latest changes from gitlab-org/gitlab@14-2-stable-eev14.2.0-rc42
Diffstat (limited to 'spec/services/ci')
-rw-r--r--spec/services/ci/after_requeue_job_service_spec.rb22
-rw-r--r--spec/services/ci/append_build_trace_service_spec.rb20
-rw-r--r--spec/services/ci/build_cancel_service_spec.rb52
-rw-r--r--spec/services/ci/build_unschedule_service_spec.rb52
-rw-r--r--spec/services/ci/create_downstream_pipeline_service_spec.rb1
-rw-r--r--spec/services/ci/create_pipeline_service/cache_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service/creation_errors_and_warnings_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service/cross_project_pipeline_spec.rb8
-rw-r--r--spec/services/ci/create_pipeline_service/custom_config_content_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service/custom_yaml_tags_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service/dry_run_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service/environment_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service/evaluate_runner_tags_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service/include_spec.rb95
-rw-r--r--spec/services/ci/create_pipeline_service/merge_requests_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service/needs_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service/parallel_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service/parameter_content_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service/pre_post_stages_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service/rules_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb307
-rw-r--r--spec/services/ci/daily_build_group_report_result_service_spec.rb34
-rw-r--r--spec/services/ci/destroy_pipeline_service_spec.rb12
-rw-r--r--spec/services/ci/drop_pipeline_service_spec.rb2
-rw-r--r--spec/services/ci/external_pull_requests/create_pipeline_service_spec.rb42
-rw-r--r--spec/services/ci/extract_sections_from_build_trace_service_spec.rb57
-rw-r--r--spec/services/ci/pipeline_processing/shared_processing_service.rb2
-rw-r--r--spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb2
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_test_manual_same_and_different_stage_needs.yml54
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_test_manual_same_stage_needs.yml70
-rw-r--r--spec/services/ci/pipeline_trigger_service_spec.rb6
-rw-r--r--spec/services/ci/pipelines/add_job_service_spec.rb35
-rw-r--r--spec/services/ci/register_job_service_spec.rb62
-rw-r--r--spec/services/ci/resource_groups/assign_resource_from_resource_group_service_spec.rb20
-rw-r--r--spec/services/ci/retry_build_service_spec.rb2
-rw-r--r--spec/services/ci/stop_environments_service_spec.rb253
37 files changed, 700 insertions, 538 deletions
diff --git a/spec/services/ci/after_requeue_job_service_spec.rb b/spec/services/ci/after_requeue_job_service_spec.rb
index f8c49060ce0..df5ddcafb37 100644
--- a/spec/services/ci/after_requeue_job_service_spec.rb
+++ b/spec/services/ci/after_requeue_job_service_spec.rb
@@ -8,37 +8,41 @@ RSpec.describe Ci::AfterRequeueJobService do
let(:pipeline) { create(:ci_pipeline, project: project) }
+ let!(:build) { create(:ci_build, pipeline: pipeline, stage_idx: 0, name: 'build') }
let!(:test1) { create(:ci_build, :success, pipeline: pipeline, stage_idx: 1) }
let!(:test2) { create(:ci_build, :skipped, pipeline: pipeline, stage_idx: 1) }
- let!(:build) { create(:ci_build, pipeline: pipeline, stage_idx: 0, name: 'build') }
+ let!(:test3) { create(:ci_build, :skipped, :dependent, pipeline: pipeline, stage_idx: 1, needed: build) }
+ let!(:deploy) { create(:ci_build, :skipped, :dependent, pipeline: pipeline, stage_idx: 2, needed: test3) }
subject(:execute_service) { described_class.new(project, user).execute(build) }
it 'marks subsequent skipped jobs as processable' do
expect(test1.reload).to be_success
expect(test2.reload).to be_skipped
+ expect(test3.reload).to be_skipped
+ expect(deploy.reload).to be_skipped
execute_service
expect(test1.reload).to be_success
expect(test2.reload).to be_created
+ expect(test3.reload).to be_created
+ expect(deploy.reload).to be_created
end
context 'when there is a job need from the same stage' do
- let!(:test3) do
+ let!(:test4) do
create(:ci_build,
:skipped,
+ :dependent,
pipeline: pipeline,
stage_idx: 0,
- scheduling_type: :dag)
- end
-
- before do
- create(:ci_build_need, build: test3, name: 'build')
+ scheduling_type: :dag,
+ needed: build)
end
it 'marks subsequent skipped jobs as processable' do
- expect { execute_service }.to change { test3.reload.status }.from('skipped').to('created')
+ expect { execute_service }.to change { test4.reload.status }.from('skipped').to('created')
end
context 'with ci_same_stage_job_needs FF disabled' do
@@ -47,7 +51,7 @@ RSpec.describe Ci::AfterRequeueJobService do
end
it 'does nothing with the build' do
- expect { execute_service }.not_to change { test3.reload.status }
+ expect { execute_service }.not_to change { test4.reload.status }
end
end
end
diff --git a/spec/services/ci/append_build_trace_service_spec.rb b/spec/services/ci/append_build_trace_service_spec.rb
index b251f00158f..487dbacbe90 100644
--- a/spec/services/ci/append_build_trace_service_spec.rb
+++ b/spec/services/ci/append_build_trace_service_spec.rb
@@ -75,25 +75,5 @@ RSpec.describe Ci::AppendBuildTraceService do
expect(build.reload).to be_failed
expect(build.failure_reason).to eq 'trace_size_exceeded'
end
-
- context 'when the feature flag is disabled' do
- before do
- stub_feature_flags(ci_jobs_trace_size_limit: false)
- end
-
- it 'appends trace chunks' do
- stream_size = 1.25.megabytes
- body_data = 'x' * stream_size
- content_range = "0-#{stream_size}"
-
- result = described_class
- .new(build, content_range: content_range)
- .execute(body_data)
-
- expect(result.status).to eq 202
- expect(result.stream_size).to eq stream_size
- expect(build.trace_chunks.count).to eq 10
- end
- end
end
end
diff --git a/spec/services/ci/build_cancel_service_spec.rb b/spec/services/ci/build_cancel_service_spec.rb
new file mode 100644
index 00000000000..fe036dc1368
--- /dev/null
+++ b/spec/services/ci/build_cancel_service_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::BuildCancelService do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+
+ describe '#execute' do
+ subject(:execute) { described_class.new(build, user).execute }
+
+ context 'when user is authorized to cancel the build' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ context 'when build is cancelable' do
+ let!(:build) { create(:ci_build, :cancelable, pipeline: pipeline) }
+
+ it 'transits build to canceled', :aggregate_failures do
+ response = execute
+
+ expect(response).to be_success
+ expect(response.payload.reload).to be_canceled
+ end
+ end
+
+ context 'when build is not cancelable' do
+ let!(:build) { create(:ci_build, :canceled, pipeline: pipeline) }
+
+ it 'responds with unprocessable entity', :aggregate_failures do
+ response = execute
+
+ expect(response).to be_error
+ expect(response.http_status).to eq(:unprocessable_entity)
+ end
+ end
+ end
+
+ context 'when user is not authorized to cancel the build' do
+ let!(:build) { create(:ci_build, :cancelable, pipeline: pipeline) }
+
+ it 'responds with forbidden', :aggregate_failures do
+ response = execute
+
+ expect(response).to be_error
+ expect(response.http_status).to eq(:forbidden)
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/build_unschedule_service_spec.rb b/spec/services/ci/build_unschedule_service_spec.rb
new file mode 100644
index 00000000000..d784d9a2754
--- /dev/null
+++ b/spec/services/ci/build_unschedule_service_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::BuildUnscheduleService do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+
+ describe '#execute' do
+ subject(:execute) { described_class.new(build, user).execute }
+
+ context 'when user is authorized to unschedule the build' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ context 'when build is scheduled' do
+ let!(:build) { create(:ci_build, :scheduled, pipeline: pipeline) }
+
+ it 'transits build to manual' do
+ response = execute
+
+ expect(response).to be_success
+ expect(response.payload.reload).to be_manual
+ end
+ end
+
+ context 'when build is not scheduled' do
+ let!(:build) { create(:ci_build, pipeline: pipeline) }
+
+ it 'responds with unprocessable entity', :aggregate_failures do
+ response = execute
+
+ expect(response).to be_error
+ expect(response.http_status).to eq(:unprocessable_entity)
+ end
+ end
+ end
+
+ context 'when user is not authorized to unschedule the build' do
+ let!(:build) { create(:ci_build, :scheduled, pipeline: pipeline) }
+
+ it 'responds with forbidden', :aggregate_failures do
+ response = execute
+
+ expect(response).to be_error
+ expect(response.http_status).to eq(:forbidden)
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/create_downstream_pipeline_service_spec.rb b/spec/services/ci/create_downstream_pipeline_service_spec.rb
index 18bd59a17f0..2237fd76d07 100644
--- a/spec/services/ci/create_downstream_pipeline_service_spec.rb
+++ b/spec/services/ci/create_downstream_pipeline_service_spec.rb
@@ -624,6 +624,7 @@ RSpec.describe Ci::CreateDownstreamPipelineService, '#execute' do
let(:primary_pipeline) do
Ci::CreatePipelineService.new(upstream_project, upstream_project.owner, { ref: 'master' })
.execute(:push, save_on_errors: false)
+ .payload
end
let(:bridge) { primary_pipeline.processables.find_by(name: 'bridge-job') }
diff --git a/spec/services/ci/create_pipeline_service/cache_spec.rb b/spec/services/ci/create_pipeline_service/cache_spec.rb
index f9767a794db..f5f162e4578 100644
--- a/spec/services/ci/create_pipeline_service/cache_spec.rb
+++ b/spec/services/ci/create_pipeline_service/cache_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Ci::CreatePipelineService do
let(:ref) { 'refs/heads/master' }
let(:source) { :push }
let(:service) { described_class.new(project, user, { ref: ref }) }
- let(:pipeline) { service.execute(source) }
+ let(:pipeline) { service.execute(source).payload }
let(:job) { pipeline.builds.find_by(name: 'job') }
before do
diff --git a/spec/services/ci/create_pipeline_service/creation_errors_and_warnings_spec.rb b/spec/services/ci/create_pipeline_service/creation_errors_and_warnings_spec.rb
index a42770aae20..c69c91593ae 100644
--- a/spec/services/ci/create_pipeline_service/creation_errors_and_warnings_spec.rb
+++ b/spec/services/ci/create_pipeline_service/creation_errors_and_warnings_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Ci::CreatePipelineService do
let(:ref) { 'refs/heads/master' }
let(:source) { :push }
let(:service) { described_class.new(project, user, { ref: ref }) }
- let(:pipeline) { service.execute(source) }
+ let(:pipeline) { service.execute(source).payload }
before do
stub_ci_pipeline_yaml_file(config)
diff --git a/spec/services/ci/create_pipeline_service/cross_project_pipeline_spec.rb b/spec/services/ci/create_pipeline_service/cross_project_pipeline_spec.rb
index b3b8e34dd8e..e1d60ed57ef 100644
--- a/spec/services/ci/create_pipeline_service/cross_project_pipeline_spec.rb
+++ b/spec/services/ci/create_pipeline_service/cross_project_pipeline_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
let_it_be(:group) { create(:group, name: 'my-organization') }
let(:upstream_project) { create(:project, :repository, name: 'upstream', group: group) }
- let(:downstram_project) { create(:project, :repository, name: 'downstream', group: group) }
+ let(:downstream_project) { create(:project, :repository, name: 'downstream', group: group) }
let(:user) { create(:user) }
let(:service) do
@@ -15,9 +15,9 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
before do
upstream_project.add_developer(user)
- downstram_project.add_developer(user)
+ downstream_project.add_developer(user)
create_gitlab_ci_yml(upstream_project, upstream_config)
- create_gitlab_ci_yml(downstram_project, downstream_config)
+ create_gitlab_ci_yml(downstream_project, downstream_config)
end
context 'with resource group', :aggregate_failures do
@@ -79,7 +79,7 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
end
def create_pipeline!
- service.execute(:push)
+ service.execute(:push).payload
end
def create_gitlab_ci_yml(project, content)
diff --git a/spec/services/ci/create_pipeline_service/custom_config_content_spec.rb b/spec/services/ci/create_pipeline_service/custom_config_content_spec.rb
index 42c3f52541b..f150a4f8b51 100644
--- a/spec/services/ci/create_pipeline_service/custom_config_content_spec.rb
+++ b/spec/services/ci/create_pipeline_service/custom_config_content_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe Ci::CreatePipelineService do
let(:upstream_pipeline) { create(:ci_pipeline, project: project) }
let(:bridge) { create(:ci_bridge, pipeline: upstream_pipeline) }
- subject { service.execute(:push, bridge: bridge) }
+ subject { service.execute(:push, bridge: bridge).payload }
context 'custom config content' do
let(:bridge) do
diff --git a/spec/services/ci/create_pipeline_service/custom_yaml_tags_spec.rb b/spec/services/ci/create_pipeline_service/custom_yaml_tags_spec.rb
index 5dceb9f57f0..026111d59f1 100644
--- a/spec/services/ci/create_pipeline_service/custom_yaml_tags_spec.rb
+++ b/spec/services/ci/create_pipeline_service/custom_yaml_tags_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Ci::CreatePipelineService do
let(:ref) { 'refs/heads/master' }
let(:source) { :push }
let(:service) { described_class.new(project, user, { ref: ref }) }
- let(:pipeline) { service.execute(source) }
+ let(:pipeline) { service.execute(source).payload }
before do
stub_ci_pipeline_yaml_file(config)
diff --git a/spec/services/ci/create_pipeline_service/dry_run_spec.rb b/spec/services/ci/create_pipeline_service/dry_run_spec.rb
index 01df7772eef..ae43c63b516 100644
--- a/spec/services/ci/create_pipeline_service/dry_run_spec.rb
+++ b/spec/services/ci/create_pipeline_service/dry_run_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Ci::CreatePipelineService do
let(:ref) { 'refs/heads/master' }
let(:service) { described_class.new(project, user, { ref: ref }) }
- subject { service.execute(:push, dry_run: true) }
+ subject { service.execute(:push, dry_run: true).payload }
before do
stub_ci_pipeline_yaml_file(config)
diff --git a/spec/services/ci/create_pipeline_service/environment_spec.rb b/spec/services/ci/create_pipeline_service/environment_spec.rb
index e77591298ad..43b5220334c 100644
--- a/spec/services/ci/create_pipeline_service/environment_spec.rb
+++ b/spec/services/ci/create_pipeline_service/environment_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Ci::CreatePipelineService do
end
describe '#execute' do
- subject { service.execute(:push) }
+ subject { service.execute(:push).payload }
context 'with deployment tier' do
before do
diff --git a/spec/services/ci/create_pipeline_service/evaluate_runner_tags_spec.rb b/spec/services/ci/create_pipeline_service/evaluate_runner_tags_spec.rb
index df881c1ac8f..9add096d782 100644
--- a/spec/services/ci/create_pipeline_service/evaluate_runner_tags_spec.rb
+++ b/spec/services/ci/create_pipeline_service/evaluate_runner_tags_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Ci::CreatePipelineService do
let_it_be(:user) { create(:user) }
let(:service) { described_class.new(project, user, ref: 'master') }
- let(:pipeline) { service.execute(:push) }
+ let(:pipeline) { service.execute(:push).payload }
let(:job) { pipeline.builds.find_by(name: 'job') }
before do
diff --git a/spec/services/ci/create_pipeline_service/include_spec.rb b/spec/services/ci/create_pipeline_service/include_spec.rb
new file mode 100644
index 00000000000..46271ee36c0
--- /dev/null
+++ b/spec/services/ci/create_pipeline_service/include_spec.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::CreatePipelineService do
+ context 'include:' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { project.owner }
+
+ let(:ref) { 'refs/heads/master' }
+ let(:source) { :push }
+ let(:service) { described_class.new(project, user, { ref: ref }) }
+ let(:pipeline) { service.execute(source).payload }
+
+ let(:file_location) { 'spec/fixtures/gitlab/ci/external_files/.gitlab-ci-template-1.yml' }
+
+ before do
+ allow(project.repository)
+ .to receive(:blob_data_at).with(project.commit.id, '.gitlab-ci.yml')
+ .and_return(config)
+
+ allow(project.repository)
+ .to receive(:blob_data_at).with(project.commit.id, file_location)
+ .and_return(File.read(Rails.root.join(file_location)))
+ end
+
+ context 'with a local file' do
+ let(:config) do
+ <<~EOY
+ include: #{file_location}
+ job:
+ script: exit 0
+ EOY
+ end
+
+ it 'includes the job in the file' do
+ expect(pipeline).to be_created_successfully
+ expect(pipeline.processables.pluck(:name)).to contain_exactly('job', 'rspec')
+ end
+ end
+
+ context 'with a local file with rules' do
+ let(:config) do
+ <<~EOY
+ include:
+ - local: #{file_location}
+ rules:
+ - if: $CI_PROJECT_ID == "#{project_id}"
+ job:
+ script: exit 0
+ EOY
+ end
+
+ context 'when the rules matches' do
+ let(:project_id) { project.id }
+
+ it 'includes the job in the file' do
+ expect(pipeline).to be_created_successfully
+ expect(pipeline.processables.pluck(:name)).to contain_exactly('job', 'rspec')
+ end
+
+ context 'when the FF ci_include_rules is disabled' do
+ before do
+ stub_feature_flags(ci_include_rules: false)
+ end
+
+ it 'includes the job in the file' do
+ expect(pipeline).to be_created_successfully
+ expect(pipeline.processables.pluck(:name)).to contain_exactly('job', 'rspec')
+ end
+ end
+ end
+
+ context 'when the rules does not match' do
+ let(:project_id) { non_existing_record_id }
+
+ it 'does not include the job in the file' do
+ expect(pipeline).to be_created_successfully
+ expect(pipeline.processables.pluck(:name)).to contain_exactly('job')
+ end
+
+ context 'when the FF ci_include_rules is disabled' do
+ before do
+ stub_feature_flags(ci_include_rules: false)
+ end
+
+ it 'includes the job in the file' do
+ expect(pipeline).to be_created_successfully
+ expect(pipeline.processables.pluck(:name)).to contain_exactly('job', 'rspec')
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/create_pipeline_service/merge_requests_spec.rb b/spec/services/ci/create_pipeline_service/merge_requests_spec.rb
index e5347faed6a..a1f85faa69f 100644
--- a/spec/services/ci/create_pipeline_service/merge_requests_spec.rb
+++ b/spec/services/ci/create_pipeline_service/merge_requests_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Ci::CreatePipelineService do
let(:ref) { 'refs/heads/feature' }
let(:source) { :push }
let(:service) { described_class.new(project, user, { ref: ref }) }
- let(:pipeline) { service.execute(source) }
+ let(:pipeline) { service.execute(source).payload }
before do
stub_ci_pipeline_yaml_file <<-EOS
diff --git a/spec/services/ci/create_pipeline_service/needs_spec.rb b/spec/services/ci/create_pipeline_service/needs_spec.rb
index d096db10d0b..9070d86f7f6 100644
--- a/spec/services/ci/create_pipeline_service/needs_spec.rb
+++ b/spec/services/ci/create_pipeline_service/needs_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Ci::CreatePipelineService do
let(:ref) { 'refs/heads/master' }
let(:source) { :push }
let(:service) { described_class.new(project, user, { ref: ref }) }
- let(:pipeline) { service.execute(source) }
+ let(:pipeline) { service.execute(source).payload }
before do
stub_ci_pipeline_yaml_file(config)
diff --git a/spec/services/ci/create_pipeline_service/parallel_spec.rb b/spec/services/ci/create_pipeline_service/parallel_spec.rb
index 5e34a67d376..6b455bf4874 100644
--- a/spec/services/ci/create_pipeline_service/parallel_spec.rb
+++ b/spec/services/ci/create_pipeline_service/parallel_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Ci::CreatePipelineService do
let_it_be(:user) { project.owner }
let(:service) { described_class.new(project, user, { ref: 'master' }) }
- let(:pipeline) { service.execute(:push) }
+ let(:pipeline) { service.execute(:push).payload }
before do
stub_ci_pipeline_yaml_file(config)
diff --git a/spec/services/ci/create_pipeline_service/parameter_content_spec.rb b/spec/services/ci/create_pipeline_service/parameter_content_spec.rb
index 94500a550c6..761504ffb58 100644
--- a/spec/services/ci/create_pipeline_service/parameter_content_spec.rb
+++ b/spec/services/ci/create_pipeline_service/parameter_content_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe Ci::CreatePipelineService do
describe '#execute' do
context 'when source is a dangling build' do
- subject { service.execute(:ondemand_dast_scan, content: content) }
+ subject { service.execute(:ondemand_dast_scan, content: content).payload }
context 'parameter config content' do
it 'creates a pipeline' do
diff --git a/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb b/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb
index 7a6535ed3fa..6eb1315fff4 100644
--- a/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb
+++ b/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb
@@ -369,6 +369,6 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
end
def create_pipeline!
- service.execute(:push)
+ service.execute(:push).payload
end
end
diff --git a/spec/services/ci/create_pipeline_service/pre_post_stages_spec.rb b/spec/services/ci/create_pipeline_service/pre_post_stages_spec.rb
index c84d9a53973..5e34eeb99db 100644
--- a/spec/services/ci/create_pipeline_service/pre_post_stages_spec.rb
+++ b/spec/services/ci/create_pipeline_service/pre_post_stages_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Ci::CreatePipelineService do
let(:source) { :push }
let(:service) { described_class.new(project, user, { ref: ref }) }
- let(:pipeline) { service.execute(source) }
+ let(:pipeline) { service.execute(source).payload }
let(:config) do
<<~YAML
diff --git a/spec/services/ci/create_pipeline_service/rules_spec.rb b/spec/services/ci/create_pipeline_service/rules_spec.rb
index acdf38bbc13..d0915f099de 100644
--- a/spec/services/ci/create_pipeline_service/rules_spec.rb
+++ b/spec/services/ci/create_pipeline_service/rules_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Ci::CreatePipelineService do
let(:ref) { 'refs/heads/master' }
let(:source) { :push }
let(:service) { described_class.new(project, user, { ref: ref }) }
- let(:pipeline) { service.execute(source) }
+ let(:pipeline) { service.execute(source).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
context 'job:rules' do
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index 56bfeda3bff..2fdb0ed3c0d 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -19,7 +19,6 @@ RSpec.describe Ci::CreatePipelineService do
def execute_service(
source: :push,
after: project.commit.id,
- message: 'Message',
ref: ref_name,
trigger_request: nil,
variables_attributes: nil,
@@ -32,7 +31,6 @@ RSpec.describe Ci::CreatePipelineService do
params = { ref: ref,
before: '00000000',
after: after,
- commits: [{ message: message }],
variables_attributes: variables_attributes,
push_options: push_options,
source_sha: source_sha,
@@ -49,12 +47,16 @@ RSpec.describe Ci::CreatePipelineService do
# rubocop:enable Metrics/ParameterLists
context 'valid params' do
- let(:pipeline) { execute_service }
+ let(:pipeline) { execute_service.payload }
let(:pipeline_on_previous_commit) do
execute_service(
after: previous_commit_sha_from_ref('master')
- )
+ ).payload
+ end
+
+ it 'responds with success' do
+ expect(execute_service).to be_success
end
it 'creates a pipeline' do
@@ -128,7 +130,7 @@ RSpec.describe Ci::CreatePipelineService do
merge_request_1
merge_request_2
- head_pipeline = execute_service(ref: 'feature', after: nil)
+ head_pipeline = execute_service(ref: 'feature', after: nil).payload
expect(merge_request_1.reload.head_pipeline).to eq(head_pipeline)
expect(merge_request_2.reload.head_pipeline).to eq(head_pipeline)
@@ -157,7 +159,7 @@ RSpec.describe Ci::CreatePipelineService do
target_branch: "branch_1",
source_project: project)
- head_pipeline = execute_service
+ head_pipeline = execute_service.payload
expect(merge_request.reload.head_pipeline).not_to eq(head_pipeline)
end
@@ -178,7 +180,7 @@ RSpec.describe Ci::CreatePipelineService do
source_project: project,
target_project: target_project)
- head_pipeline = execute_service(ref: 'feature', after: nil)
+ head_pipeline = execute_service(ref: 'feature', after: nil).payload
expect(merge_request.reload.head_pipeline).to eq(head_pipeline)
end
@@ -209,7 +211,7 @@ RSpec.describe Ci::CreatePipelineService do
target_branch: 'feature',
source_project: project)
- head_pipeline = execute_service
+ head_pipeline = execute_service.payload
expect(head_pipeline).to be_persisted
expect(head_pipeline.yaml_errors).to be_present
@@ -230,7 +232,7 @@ RSpec.describe Ci::CreatePipelineService do
target_branch: 'feature',
source_project: project)
- head_pipeline = execute_service
+ head_pipeline = execute_service.payload
expect(head_pipeline).to be_skipped
expect(head_pipeline).to be_persisted
@@ -260,7 +262,7 @@ RSpec.describe Ci::CreatePipelineService do
it 'cancels running outdated pipelines', :sidekiq_inline do
pipeline_on_previous_commit.reload.run
- head_pipeline = execute_service
+ head_pipeline = execute_service.payload
expect(pipeline_on_previous_commit.reload).to have_attributes(status: 'canceled', auto_canceled_by_id: head_pipeline.id)
end
@@ -276,7 +278,8 @@ RSpec.describe Ci::CreatePipelineService do
new_pipeline = execute_service(
ref: 'refs/heads/feature',
after: previous_commit_sha_from_ref('feature')
- )
+ ).payload
+
pipeline
expect(new_pipeline.reload).to have_attributes(status: 'created', auto_canceled_by_id: nil)
@@ -290,7 +293,7 @@ RSpec.describe Ci::CreatePipelineService do
end
it 'is cancelable' do
- pipeline = execute_service
+ pipeline = execute_service.payload
expect(pipeline.builds.find_by(name: 'rspec').interruptible).to be_nil
end
@@ -303,7 +306,7 @@ RSpec.describe Ci::CreatePipelineService do
end
it 'is cancelable' do
- pipeline = execute_service
+ pipeline = execute_service.payload
expect(pipeline.builds.find_by(name: 'rspec').interruptible).to be_truthy
end
@@ -316,7 +319,7 @@ RSpec.describe Ci::CreatePipelineService do
end
it 'is not cancelable' do
- pipeline = execute_service
+ pipeline = execute_service.payload
expect(pipeline.builds.find_by(name: 'rspec').interruptible).to be_falsy
end
@@ -476,21 +479,25 @@ RSpec.describe Ci::CreatePipelineService do
context "skip tag if there is no build for it" do
it "creates commit if there is appropriate job" do
- expect(execute_service).to be_persisted
+ expect(execute_service.payload).to be_persisted
end
it "creates commit if there is no appropriate job but deploy job has right ref setting" do
config = YAML.dump({ deploy: { script: "ls", only: ["master"] } })
stub_ci_pipeline_yaml_file(config)
- expect(execute_service).to be_persisted
+ expect(execute_service.payload).to be_persisted
end
end
- it 'skips creating pipeline for refs without .gitlab-ci.yml' do
+ it 'skips creating pipeline for refs without .gitlab-ci.yml', :aggregate_failures do
stub_ci_pipeline_yaml_file(nil)
- expect(execute_service).not_to be_persisted
+ response = execute_service
+
+ expect(response).to be_error
+ expect(response.message).to eq('Missing CI config file')
+ expect(response.payload).not_to be_persisted
expect(Ci::Pipeline.count).to eq(0)
expect(Namespaces::OnboardingPipelineCreatedWorker).not_to receive(:perform_async)
end
@@ -499,7 +506,7 @@ RSpec.describe Ci::CreatePipelineService do
it 'creates failed pipeline' do
stub_ci_pipeline_yaml_file(ci_yaml)
- pipeline = execute_service(message: message)
+ pipeline = execute_service.payload
expect(pipeline).to be_persisted
expect(pipeline.builds.any?).to be false
@@ -516,7 +523,7 @@ RSpec.describe Ci::CreatePipelineService do
end
it 'pull it from the repository' do
- pipeline = execute_service
+ pipeline = execute_service.payload
expect(pipeline).to be_repository_source
expect(pipeline.builds.map(&:name)).to eq ['rspec']
end
@@ -530,7 +537,7 @@ RSpec.describe Ci::CreatePipelineService do
end
it 'pull it from Auto-DevOps' do
- pipeline = execute_service
+ pipeline = execute_service.payload
expect(pipeline).to be_auto_devops_source
expect(pipeline.builds.map(&:name)).to match_array(%w[brakeman-sast build code_quality eslint-sast secret_detection semgrep-sast test])
end
@@ -541,11 +548,12 @@ RSpec.describe Ci::CreatePipelineService do
stub_ci_pipeline_yaml_file(nil)
end
- it 'attaches errors to the pipeline' do
- pipeline = execute_service
+ it 'responds with error message', :aggregate_failures do
+ response = execute_service
- expect(pipeline.errors.full_messages).to eq ['Missing CI config file']
- expect(pipeline).not_to be_persisted
+ expect(response).to be_error
+ expect(response.message).to eq('Missing CI config file')
+ expect(response.payload).not_to be_persisted
end
end
@@ -556,7 +564,7 @@ RSpec.describe Ci::CreatePipelineService do
end
it 'saves error in pipeline' do
- pipeline = execute_service
+ pipeline = execute_service.payload
expect(pipeline.yaml_errors).to include('Undefined error')
end
@@ -648,7 +656,7 @@ RSpec.describe Ci::CreatePipelineService do
end
it 'saves error in pipeline' do
- pipeline = execute_service
+ pipeline = execute_service.payload
expect(pipeline.yaml_errors).to include('Undefined error')
end
@@ -661,26 +669,18 @@ RSpec.describe Ci::CreatePipelineService do
end
context 'when commit contains a [ci skip] directive' do
- let(:message) { "some message[ci skip]" }
-
- ci_messages = [
- "some message[ci skip]",
- "some message[skip ci]",
- "some message[CI SKIP]",
- "some message[SKIP CI]",
- "some message[ci_skip]",
- "some message[skip_ci]",
- "some message[ci-skip]",
- "some message[skip-ci]"
- ]
+ shared_examples 'creating a pipeline' do
+ it 'does not skip pipeline creation' do
+ pipeline = execute_service.payload
- before do
- allow_any_instance_of(Ci::Pipeline).to receive(:git_commit_message) { message }
+ expect(pipeline).to be_persisted
+ expect(pipeline.builds.first.name).to eq("rspec")
+ end
end
- ci_messages.each do |ci_message|
- it "skips builds creation if the commit message is #{ci_message}" do
- pipeline = execute_service(message: ci_message)
+ shared_examples 'skipping a pipeline' do
+ it 'skips pipeline creation' do
+ pipeline = execute_service.payload
expect(pipeline).to be_persisted
expect(pipeline.builds.any?).to be false
@@ -688,14 +688,26 @@ RSpec.describe Ci::CreatePipelineService do
end
end
- shared_examples 'creating a pipeline' do
- it 'does not skip pipeline creation' do
- allow_any_instance_of(Ci::Pipeline).to receive(:git_commit_message) { commit_message }
+ before do
+ allow_any_instance_of(Ci::Pipeline).to receive(:git_commit_message) { commit_message }
+ end
+
+ skip_commit_messages = [
+ "some message[ci skip]",
+ "some message[skip ci]",
+ "some message[CI SKIP]",
+ "some message[SKIP CI]",
+ "some message[ci_skip]",
+ "some message[skip_ci]",
+ "some message[ci-skip]",
+ "some message[skip-ci]"
+ ]
- pipeline = execute_service(message: commit_message)
+ skip_commit_messages.each do |skip_commit_message|
+ context "when the commit message is #{skip_commit_message}" do
+ let(:commit_message) { skip_commit_message }
- expect(pipeline).to be_persisted
- expect(pipeline.builds.first.name).to eq("rspec")
+ it_behaves_like 'skipping a pipeline'
end
end
@@ -712,9 +724,14 @@ RSpec.describe Ci::CreatePipelineService do
end
context 'when there is [ci skip] tag in commit message and yaml is invalid' do
+ let(:commit_message) { 'some message [ci skip]' }
let(:ci_yaml) { 'invalid: file: fiile' }
- it_behaves_like 'a failed pipeline'
+ before do
+ stub_ci_pipeline_yaml_file(ci_yaml)
+ end
+
+ it_behaves_like 'skipping a pipeline'
end
end
@@ -724,7 +741,7 @@ RSpec.describe Ci::CreatePipelineService do
end
it 'creates a pipline in the skipped state' do
- pipeline = execute_service(push_options: push_options)
+ pipeline = execute_service(push_options: push_options).payload
# TODO: DRY these up with "skips builds creation if the commit message"
expect(pipeline).to be_persisted
@@ -739,10 +756,12 @@ RSpec.describe Ci::CreatePipelineService do
stub_ci_pipeline_yaml_file(config)
end
- it 'does not create a new pipeline' do
+ it 'does not create a new pipeline', :aggregate_failures do
result = execute_service
- expect(result).not_to be_persisted
+ expect(result).to be_error
+ expect(result.message).to eq('No stages / jobs for this pipeline.')
+ expect(result.payload).not_to be_persisted
expect(Ci::Build.all).to be_empty
expect(Ci::Pipeline.count).to eq(0)
end
@@ -757,10 +776,11 @@ RSpec.describe Ci::CreatePipelineService do
.and_call_original
end
- it 'rewinds iid' do
+ it 'rewinds iid', :aggregate_failures do
result = execute_service
- expect(result).not_to be_persisted
+ expect(result).to be_error
+ expect(result.payload).not_to be_persisted
expect(internal_id.last_value).to eq(0)
end
end
@@ -773,7 +793,7 @@ RSpec.describe Ci::CreatePipelineService do
end
it 'does not create a new pipeline', :sidekiq_inline do
- result = execute_service
+ result = execute_service.payload
expect(result).to be_persisted
expect(result.manual_actions).not_to be_empty
@@ -793,7 +813,7 @@ RSpec.describe Ci::CreatePipelineService do
end
it 'creates the environment with tags' do
- result = execute_service
+ result = execute_service.payload
expect(result).to be_persisted
expect(Environment.find_by(name: "review/master")).to be_present
@@ -815,7 +835,7 @@ RSpec.describe Ci::CreatePipelineService do
end
it 'creates the environment with auto stop in' do
- result = execute_service
+ result = execute_service.payload
expect(result).to be_persisted
expect(result.builds.first.options[:environment][:auto_stop_in]).to eq('1 day')
@@ -835,7 +855,7 @@ RSpec.describe Ci::CreatePipelineService do
end
it 'skipps persisted variables in environment name' do
- result = execute_service
+ result = execute_service.payload
expect(result).to be_persisted
expect(Environment.find_by(name: "review/id1/id2")).to be_present
@@ -860,7 +880,7 @@ RSpec.describe Ci::CreatePipelineService do
end
it 'stores the requested namespace' do
- result = execute_service
+ result = execute_service.payload
build = result.builds.first
expect(result).to be_persisted
@@ -876,7 +896,7 @@ RSpec.describe Ci::CreatePipelineService do
it 'does not create an environment' do
expect do
- result = execute_service
+ result = execute_service.payload
expect(result).to be_persisted
end.not_to change { Environment.count }
@@ -896,7 +916,7 @@ RSpec.describe Ci::CreatePipelineService do
end
it 'creates a pipeline with the environment' do
- result = execute_service
+ result = execute_service.payload
expect(result).to be_persisted
expect(Environment.find_by(name: 'production')).to be_present
@@ -906,7 +926,7 @@ RSpec.describe Ci::CreatePipelineService do
end
context 'when builds with auto-retries are configured' do
- let(:pipeline) { execute_service }
+ let(:pipeline) { execute_service.payload }
let(:rspec_job) { pipeline.builds.find_by(name: 'rspec') }
before do
@@ -946,7 +966,7 @@ RSpec.describe Ci::CreatePipelineService do
let(:resource_group_key) { 'iOS' }
it 'persists the association correctly' do
- result = execute_service
+ result = execute_service.payload
deploy_job = result.builds.find_by_name!(:test)
resource_group = project.resource_groups.find_by_key!(resource_group_key)
@@ -962,7 +982,7 @@ RSpec.describe Ci::CreatePipelineService do
let(:resource_group_key) { '$CI_COMMIT_REF_NAME-$CI_JOB_NAME' }
it 'interpolates the variables into the key correctly' do
- result = execute_service
+ result = execute_service.payload
expect(result).to be_persisted
expect(project.resource_groups.exists?(key: 'master-test')).to eq(true)
@@ -979,7 +999,7 @@ RSpec.describe Ci::CreatePipelineService do
end
it 'correctly creates builds with custom timeout value configured' do
- pipeline = execute_service
+ pipeline = execute_service.payload
expect(pipeline).to be_persisted
expect(pipeline.builds.find_by(name: 'rspec').options[:job_timeout]).to eq 123
@@ -994,7 +1014,7 @@ RSpec.describe Ci::CreatePipelineService do
end
it 'is valid config' do
- pipeline = execute_service
+ pipeline = execute_service.payload
build = pipeline.builds.first
expect(pipeline).to be_kind_of(Ci::Pipeline)
expect(pipeline).to be_valid
@@ -1059,14 +1079,14 @@ RSpec.describe Ci::CreatePipelineService do
project.add_developer(user)
end
- it 'does not create a pipeline' do
- expect(execute_service).not_to be_persisted
+ it 'does not create a pipeline', :aggregate_failures do
+ expect(execute_service.payload).not_to be_persisted
expect(Ci::Pipeline.count).to eq(0)
end
end
context 'when user is maintainer' do
- let(:pipeline) { execute_service }
+ let(:pipeline) { execute_service.payload }
before do
project.add_maintainer(user)
@@ -1083,9 +1103,11 @@ RSpec.describe Ci::CreatePipelineService do
let(:user) {}
let(:trigger_request) { create(:ci_trigger_request) }
- it 'does not create a pipeline' do
- expect(execute_service(trigger_request: trigger_request))
- .not_to be_persisted
+ it 'does not create a pipeline', :aggregate_failures do
+ response = execute_service(trigger_request: trigger_request)
+
+ expect(response).to be_error
+ expect(response.payload).not_to be_persisted
expect(Ci::Pipeline.count).to eq(0)
end
end
@@ -1099,9 +1121,11 @@ RSpec.describe Ci::CreatePipelineService do
project.add_developer(user)
end
- it 'does not create a pipeline' do
- expect(execute_service(trigger_request: trigger_request))
- .not_to be_persisted
+ it 'does not create a pipeline', :aggregate_failures do
+ response = execute_service(trigger_request: trigger_request)
+
+ expect(response).to be_error
+ expect(response.payload).not_to be_persisted
expect(Ci::Pipeline.count).to eq(0)
end
end
@@ -1116,7 +1140,7 @@ RSpec.describe Ci::CreatePipelineService do
end
it 'creates a pipeline' do
- expect(execute_service(trigger_request: trigger_request))
+ expect(execute_service(trigger_request: trigger_request).payload)
.to be_persisted
expect(Ci::Pipeline.count).to eq(1)
end
@@ -1150,7 +1174,7 @@ RSpec.describe Ci::CreatePipelineService do
end
it 'creates a tagged pipeline' do
- pipeline = execute_service(ref: 'v1.0.0')
+ pipeline = execute_service(ref: 'v1.0.0').payload
expect(pipeline.tag?).to be true
end
@@ -1161,7 +1185,7 @@ RSpec.describe Ci::CreatePipelineService do
let(:ref_name) { 'refs/heads/nonexistant-branch' }
- let(:pipeline) { execute_service }
+ let(:pipeline) { execute_service.payload }
it 'does not create the pipeline' do
expect(pipeline).not_to be_created_successfully
@@ -1185,7 +1209,7 @@ RSpec.describe Ci::CreatePipelineService do
# v1.1.0 is on the test repo as branch and tag
let(:ref_name) { 'refs/heads/v1.1.0' }
- let(:pipeline) { execute_service }
+ let(:pipeline) { execute_service.payload }
it 'creates the pipeline for the branch' do
expect(pipeline).to be_created_successfully
@@ -1200,7 +1224,7 @@ RSpec.describe Ci::CreatePipelineService do
# v1.1.0 is on the test repo as branch and tag
let(:ref_name) { 'refs/tags/v1.1.0' }
- let(:pipeline) { execute_service }
+ let(:pipeline) { execute_service.payload }
it 'creates the pipeline for the tag' do
expect(pipeline).to be_created_successfully
@@ -1215,7 +1239,7 @@ RSpec.describe Ci::CreatePipelineService do
# v1.1.0 is on the test repo as branch and tag
let(:ref_name) { 'v1.1.0' }
- let(:pipeline) { execute_service }
+ let(:pipeline) { execute_service.payload }
it 'does not create the pipeline' do
expect(pipeline).not_to be_created_successfully
@@ -1229,16 +1253,16 @@ RSpec.describe Ci::CreatePipelineService do
{ key: 'second', secret_value: 'second_world' }]
end
- subject { execute_service(variables_attributes: variables_attributes) }
+ subject(:pipeline) { execute_service(variables_attributes: variables_attributes).payload }
it 'creates a pipeline with specified variables' do
- expect(subject.variables.map { |var| var.slice(:key, :secret_value) })
+ expect(pipeline.variables.map { |var| var.slice(:key, :secret_value) })
.to eq variables_attributes.map(&:with_indifferent_access)
end
end
context 'when pipeline has a job with environment' do
- let(:pipeline) { execute_service }
+ let(:pipeline) { execute_service.payload }
before do
stub_ci_pipeline_yaml_file(YAML.dump(config))
@@ -1286,7 +1310,7 @@ RSpec.describe Ci::CreatePipelineService do
end
describe 'Pipeline for external pull requests' do
- let(:pipeline) do
+ let(:response) do
execute_service(source: source,
external_pull_request: pull_request,
ref: ref_name,
@@ -1294,6 +1318,8 @@ RSpec.describe Ci::CreatePipelineService do
target_sha: target_sha)
end
+ let(:pipeline) { response.payload }
+
before do
stub_ci_pipeline_yaml_file(YAML.dump(config))
end
@@ -1342,9 +1368,11 @@ RSpec.describe Ci::CreatePipelineService do
context 'when ref is tag' do
let(:ref_name) { 'refs/tags/v1.1.0' }
- it 'does not create an extrnal pull request pipeline' do
+ it 'does not create an extrnal pull request pipeline', :aggregate_failures do
+ expect(response).to be_error
+ expect(response.message).to eq('Tag is not included in the list and Failed to build the pipeline!')
expect(pipeline).not_to be_persisted
- expect(pipeline.errors[:tag]).to eq(["is not included in the list"])
+ expect(pipeline.errors[:tag]).to eq(['is not included in the list'])
end
end
@@ -1363,9 +1391,11 @@ RSpec.describe Ci::CreatePipelineService do
}
end
- it 'does not create a detached merge request pipeline' do
+ it 'does not create a detached merge request pipeline', :aggregate_failures do
+ expect(response).to be_error
+ expect(response.message).to eq('No stages / jobs for this pipeline.')
expect(pipeline).not_to be_persisted
- expect(pipeline.errors[:base]).to eq(["No stages / jobs for this pipeline."])
+ expect(pipeline.errors[:base]).to eq(['No stages / jobs for this pipeline.'])
end
end
end
@@ -1373,7 +1403,9 @@ RSpec.describe Ci::CreatePipelineService do
context 'when external pull request is not specified' do
let(:pull_request) { nil }
- it 'does not create an external pull request pipeline' do
+ it 'does not create an external pull request pipeline', :aggregate_failures do
+ expect(response).to be_error
+ expect(response.message).to eq("External pull request can't be blank and Failed to build the pipeline!")
expect(pipeline).not_to be_persisted
expect(pipeline.errors[:external_pull_request]).to eq(["can't be blank"])
end
@@ -1420,11 +1452,11 @@ RSpec.describe Ci::CreatePipelineService do
context 'when external pull request is not specified' do
let(:pull_request) { nil }
- it 'does not create an external pull request pipeline' do
+ it 'does not create an external pull request pipeline', :aggregate_failures do
+ expect(response).to be_error
+ expect(response.message).to eq("External pull request can't be blank and Failed to build the pipeline!")
expect(pipeline).not_to be_persisted
-
- expect(pipeline.errors[:base])
- .to eq(['Failed to build the pipeline!'])
+ expect(pipeline.errors[:base]).to eq(['Failed to build the pipeline!'])
end
end
end
@@ -1432,7 +1464,7 @@ RSpec.describe Ci::CreatePipelineService do
end
describe 'Pipelines for merge requests' do
- let(:pipeline) do
+ let(:response) do
execute_service(source: source,
merge_request: merge_request,
ref: ref_name,
@@ -1440,6 +1472,8 @@ RSpec.describe Ci::CreatePipelineService do
target_sha: target_sha)
end
+ let(:pipeline) { response.payload }
+
before do
stub_ci_pipeline_yaml_file(YAML.dump(config))
end
@@ -1522,9 +1556,11 @@ RSpec.describe Ci::CreatePipelineService do
context 'when ref is tag' do
let(:ref_name) { 'refs/tags/v1.1.0' }
- it 'does not create a merge request pipeline' do
+ it 'does not create a merge request pipeline', :aggregate_failures do
+ expect(response).to be_error
+ expect(response.message).to eq('Tag is not included in the list and Failed to build the pipeline!')
expect(pipeline).not_to be_persisted
- expect(pipeline.errors[:tag]).to eq(["is not included in the list"])
+ expect(pipeline.errors[:tag]).to eq(['is not included in the list'])
end
end
@@ -1564,9 +1600,10 @@ RSpec.describe Ci::CreatePipelineService do
}
end
- it 'does not create a detached merge request pipeline' do
+ it 'does not create a detached merge request pipeline', :aggregate_failures do
+ expect(response).to be_error
+ expect(response.message).to eq('No stages / jobs for this pipeline.')
expect(pipeline).not_to be_persisted
- expect(pipeline.errors[:base]).to eq(["No stages / jobs for this pipeline."])
end
end
end
@@ -1599,11 +1636,10 @@ RSpec.describe Ci::CreatePipelineService do
target_branch: 'master')
end
- it 'does not create a detached merge request pipeline' do
+ it 'does not create a detached merge request pipeline', :aggregate_failures do
+ expect(response).to be_error
+ expect(response.message).to eq('No stages / jobs for this pipeline.')
expect(pipeline).not_to be_persisted
-
- expect(pipeline.errors[:base])
- .to eq(['No stages / jobs for this pipeline.'])
end
end
end
@@ -1628,11 +1664,10 @@ RSpec.describe Ci::CreatePipelineService do
target_branch: 'master')
end
- it 'does not create a detached merge request pipeline' do
+ it 'does not create a detached merge request pipeline', :aggregate_failures do
+ expect(response).to be_error
+ expect(response.message).to eq('No stages / jobs for this pipeline.')
expect(pipeline).not_to be_persisted
-
- expect(pipeline.errors[:base])
- .to eq(['No stages / jobs for this pipeline.'])
end
end
end
@@ -1659,11 +1694,10 @@ RSpec.describe Ci::CreatePipelineService do
target_branch: 'master')
end
- it 'does not create a detached merge request pipeline' do
+ it 'does not create a detached merge request pipeline', :aggregate_failures do
+ expect(response).to be_error
+ expect(response.message).to eq('No stages / jobs for this pipeline.')
expect(pipeline).not_to be_persisted
-
- expect(pipeline.errors[:base])
- .to eq(['No stages / jobs for this pipeline.'])
end
end
end
@@ -1688,11 +1722,10 @@ RSpec.describe Ci::CreatePipelineService do
target_branch: 'master')
end
- it 'does not create a detached merge request pipeline' do
+ it 'does not create a detached merge request pipeline', :aggregate_failures do
+ expect(response).to be_error
+ expect(response.message).to eq('No stages / jobs for this pipeline.')
expect(pipeline).not_to be_persisted
-
- expect(pipeline.errors[:base])
- .to eq(['No stages / jobs for this pipeline.'])
end
end
end
@@ -1733,7 +1766,8 @@ RSpec.describe Ci::CreatePipelineService do
end
context 'when needs is used' do
- let(:pipeline) { execute_service }
+ let(:response) { execute_service }
+ let(:pipeline) { response.payload }
let(:config) do
{
@@ -1779,7 +1813,7 @@ RSpec.describe Ci::CreatePipelineService do
let(:ref_name) { 'refs/heads/feature' }
shared_examples 'has errors' do
- it 'contains the expected errors' do
+ it 'contains the expected errors', :aggregate_failures do
expect(pipeline.builds).to be_empty
error_message = "'test_a' job needs 'build_a' job, but 'build_a' is not in any previous stage"
@@ -1790,9 +1824,12 @@ RSpec.describe Ci::CreatePipelineService do
end
context 'when save_on_errors is enabled' do
- let(:pipeline) { execute_service(save_on_errors: true) }
+ let(:response) { execute_service(save_on_errors: true) }
+ let(:pipeline) { response.payload }
- it 'does create a pipeline as test_a depends on build_a' do
+ it 'does create a pipeline as test_a depends on build_a', :aggregate_failures do
+ expect(response).to be_error
+ expect(response.message).to eq("'test_a' job needs 'build_a' job, but 'build_a' is not in any previous stage")
expect(pipeline).to be_persisted
end
@@ -1800,9 +1837,11 @@ RSpec.describe Ci::CreatePipelineService do
end
context 'when save_on_errors is disabled' do
- let(:pipeline) { execute_service(save_on_errors: false) }
+ let(:response) { execute_service(save_on_errors: false) }
+ let(:pipeline) { response.payload }
- it 'does not create a pipeline as test_a depends on build_a' do
+ it 'does not create a pipeline as test_a depends on build_a', :aggregate_failures do
+ expect(response).to be_error
expect(pipeline).not_to be_persisted
end
@@ -1822,7 +1861,8 @@ RSpec.describe Ci::CreatePipelineService do
context 'when rules are used' do
let(:ref_name) { 'refs/heads/master' }
- let(:pipeline) { execute_service }
+ let(:response) { execute_service }
+ let(:pipeline) { response.payload }
let(:build_names) { pipeline.builds.pluck(:name) }
let(:regular_job) { find_job('regular-job') }
let(:rules_job) { find_job('rules-job') }
@@ -2379,8 +2419,9 @@ RSpec.describe Ci::CreatePipelineService do
end
context 'when inside freeze period' do
- it 'does not create the pipeline' do
+ it 'does not create the pipeline', :aggregate_failures do
Timecop.freeze(2020, 4, 10, 23, 1) do
+ expect(response).to be_error
expect(pipeline).not_to be_persisted
end
end
@@ -2410,7 +2451,8 @@ RSpec.describe Ci::CreatePipelineService do
context 'with no matches' do
let(:ref_name) { 'refs/heads/feature' }
- it 'does not create a pipeline' do
+ it 'does not create a pipeline', :aggregate_failures do
+ expect(response).to be_error
expect(pipeline).not_to be_persisted
end
end
@@ -2418,7 +2460,7 @@ RSpec.describe Ci::CreatePipelineService do
context 'with workflow rules with pipeline variables' do
let(:pipeline) do
- execute_service(variables_attributes: variables_attributes)
+ execute_service(variables_attributes: variables_attributes).payload
end
let(:config) do
@@ -2446,7 +2488,8 @@ RSpec.describe Ci::CreatePipelineService do
context 'with no matches' do
let(:variables_attributes) { {} }
- it 'does not create a pipeline' do
+ it 'does not create a pipeline', :aggregate_failures do
+ expect(response).to be_error
expect(pipeline).not_to be_persisted
end
end
@@ -2456,7 +2499,7 @@ RSpec.describe Ci::CreatePipelineService do
let(:pipeline) do
execute_service do |pipeline|
pipeline.variables.build(variables)
- end
+ end.payload
end
let(:config) do
@@ -2514,7 +2557,8 @@ RSpec.describe Ci::CreatePipelineService do
context 'with no matches' do
let(:variables) { {} }
- it 'does not create a pipeline' do
+ it 'does not create a pipeline', :aggregate_failures do
+ expect(response).to be_error
expect(pipeline).not_to be_persisted
end
@@ -2542,7 +2586,8 @@ RSpec.describe Ci::CreatePipelineService do
EOY
end
- it 'does not create a pipeline' do
+ it 'does not create a pipeline', :aggregate_failures do
+ expect(response).to be_error
expect(pipeline).not_to be_persisted
end
end
diff --git a/spec/services/ci/daily_build_group_report_result_service_spec.rb b/spec/services/ci/daily_build_group_report_result_service_spec.rb
index e58a5de26a1..32651247adb 100644
--- a/spec/services/ci/daily_build_group_report_result_service_spec.rb
+++ b/spec/services/ci/daily_build_group_report_result_service_spec.rb
@@ -41,6 +41,17 @@ RSpec.describe Ci::DailyBuildGroupReportResultService, '#execute' do
expect(Ci::DailyBuildGroupReportResult.find_by(group_name: 'extra')).to be_nil
end
+ it 'creates a project_ci_feature_usage record for the pipeline project' do
+ described_class.new.execute(pipeline)
+
+ expect(Projects::CiFeatureUsage.count).to eq(1)
+ expect(Projects::CiFeatureUsage.first).to have_attributes(
+ project_id: pipeline.project.id,
+ feature: 'code_coverage',
+ default_branch: false
+ )
+ end
+
context 'when there are multiple builds with the same group name that report coverage' do
let!(:test_job_1) { create(:ci_build, pipeline: pipeline, name: 'test 1/2', coverage: 70) }
let!(:test_job_2) { create(:ci_build, pipeline: pipeline, name: 'test 2/2', coverage: 80) }
@@ -99,6 +110,16 @@ RSpec.describe Ci::DailyBuildGroupReportResultService, '#execute' do
data: { 'coverage' => new_karma_job.coverage }
)
end
+
+ it 'does not create a new project_ci_feature_usage record for the pipeline project' do
+ expect { described_class.new.execute(pipeline) }.not_to change { Projects::CiFeatureUsage.count }
+
+ expect(Projects::CiFeatureUsage.first).to have_attributes(
+ project_id: pipeline.project.id,
+ feature: 'code_coverage',
+ default_branch: false
+ )
+ end
end
context 'when the ID of the pipeline is older than the last_pipeline_id' do
@@ -161,6 +182,8 @@ RSpec.describe Ci::DailyBuildGroupReportResultService, '#execute' do
it 'does nothing' do
expect { described_class.new.execute(new_pipeline) }.not_to raise_error
+ expect(Ci::DailyBuildGroupReportResult.count).to eq(0)
+ expect(Projects::CiFeatureUsage.count).to eq(0)
end
end
@@ -178,6 +201,17 @@ RSpec.describe Ci::DailyBuildGroupReportResultService, '#execute' do
expect(coverage.default_branch).to be_truthy
end
end
+
+ it 'creates a project_ci_feature_usage record for the pipeline project for default branch' do
+ described_class.new.execute(pipeline)
+
+ expect(Projects::CiFeatureUsage.count).to eq(1)
+ expect(Projects::CiFeatureUsage.first).to have_attributes(
+ project_id: pipeline.project.id,
+ feature: 'code_coverage',
+ default_branch: true
+ )
+ end
end
context 'when pipeline ref_path is not the project default branch' do
diff --git a/spec/services/ci/destroy_pipeline_service_spec.rb b/spec/services/ci/destroy_pipeline_service_spec.rb
index 588ff0b1762..6c1c02b2875 100644
--- a/spec/services/ci/destroy_pipeline_service_spec.rb
+++ b/spec/services/ci/destroy_pipeline_service_spec.rb
@@ -78,18 +78,6 @@ RSpec.describe ::Ci::DestroyPipelineService do
subject
end
-
- context 'when cancel_pipelines_prior_to_destroy is disabled' do
- before do
- stub_feature_flags(cancel_pipelines_prior_to_destroy: false)
- end
-
- it "doesn't cancel the pipeline" do
- expect(pipeline).not_to receive(:cancel_running)
-
- subject
- end
- end
end
end
diff --git a/spec/services/ci/drop_pipeline_service_spec.rb b/spec/services/ci/drop_pipeline_service_spec.rb
index 4adbb99b9e2..c6a118c6083 100644
--- a/spec/services/ci/drop_pipeline_service_spec.rb
+++ b/spec/services/ci/drop_pipeline_service_spec.rb
@@ -9,8 +9,10 @@ RSpec.describe Ci::DropPipelineService do
let!(:cancelable_pipeline) { create(:ci_pipeline, :running, user: user) }
let!(:running_build) { create(:ci_build, :running, pipeline: cancelable_pipeline) }
+ let!(:commit_status_running) { create(:commit_status, :running, pipeline: cancelable_pipeline) }
let!(:success_pipeline) { create(:ci_pipeline, :success, user: user) }
let!(:success_build) { create(:ci_build, :success, pipeline: success_pipeline) }
+ let!(:commit_status_success) { create(:commit_status, :success, pipeline: cancelable_pipeline) }
describe '#execute_async_for_all' do
subject { described_class.new.execute_async_for_all(user.pipelines, failure_reason, user) }
diff --git a/spec/services/ci/external_pull_requests/create_pipeline_service_spec.rb b/spec/services/ci/external_pull_requests/create_pipeline_service_spec.rb
index e25dd351bb3..2b310443b37 100644
--- a/spec/services/ci/external_pull_requests/create_pipeline_service_spec.rb
+++ b/spec/services/ci/external_pull_requests/create_pipeline_service_spec.rb
@@ -6,14 +6,13 @@ RSpec.describe Ci::ExternalPullRequests::CreatePipelineService do
describe '#execute' do
let_it_be(:project) { create(:project, :auto_devops, :repository) }
let_it_be(:user) { create(:user) }
-
- let(:pull_request) { create(:external_pull_request, project: project) }
+ let_it_be_with_reload(:pull_request) { create(:external_pull_request, project: project) }
before do
project.add_maintainer(user)
end
- subject { described_class.new(project, user).execute(pull_request) }
+ subject(:response) { described_class.new(project, user).execute(pull_request) }
context 'when pull request is open' do
before do
@@ -28,17 +27,20 @@ RSpec.describe Ci::ExternalPullRequests::CreatePipelineService do
pull_request.update!(source_branch: source_branch.name, source_sha: source_branch.target)
end
- it 'creates a pipeline for external pull request' do
- expect(subject).to be_valid
- expect(subject).to be_persisted
- expect(subject).to be_external_pull_request_event
- expect(subject).to eq(project.ci_pipelines.last)
- expect(subject.external_pull_request).to eq(pull_request)
- expect(subject.user).to eq(user)
- expect(subject.status).to eq('created')
- expect(subject.ref).to eq(pull_request.source_branch)
- expect(subject.sha).to eq(pull_request.source_sha)
- expect(subject.source_sha).to eq(pull_request.source_sha)
+ it 'creates a pipeline for external pull request', :aggregate_failures do
+ pipeline = response.payload
+
+ expect(response).to be_success
+ expect(pipeline).to be_valid
+ expect(pipeline).to be_persisted
+ expect(pipeline).to be_external_pull_request_event
+ expect(pipeline).to eq(project.ci_pipelines.last)
+ expect(pipeline.external_pull_request).to eq(pull_request)
+ expect(pipeline.user).to eq(user)
+ expect(pipeline.status).to eq('created')
+ expect(pipeline.ref).to eq(pull_request.source_branch)
+ expect(pipeline.sha).to eq(pull_request.source_sha)
+ expect(pipeline.source_sha).to eq(pull_request.source_sha)
end
end
@@ -50,10 +52,12 @@ RSpec.describe Ci::ExternalPullRequests::CreatePipelineService do
pull_request.update!(source_branch: source_branch.name, source_sha: commit.sha)
end
- it 'does nothing' do
+ it 'does nothing', :aggregate_failures do
expect(Ci::CreatePipelineService).not_to receive(:new)
- expect(subject).to be_nil
+ expect(response).to be_error
+ expect(response.message).to eq('The source sha is not the head of the source branch')
+ expect(response.payload).to be_nil
end
end
end
@@ -63,10 +67,12 @@ RSpec.describe Ci::ExternalPullRequests::CreatePipelineService do
pull_request.update!(status: :closed)
end
- it 'does nothing' do
+ it 'does nothing', :aggregate_failures do
expect(Ci::CreatePipelineService).not_to receive(:new)
- expect(subject).to be_nil
+ expect(response).to be_error
+ expect(response.message).to eq('The pull request is not opened')
+ expect(response.payload).to be_nil
end
end
end
diff --git a/spec/services/ci/extract_sections_from_build_trace_service_spec.rb b/spec/services/ci/extract_sections_from_build_trace_service_spec.rb
deleted file mode 100644
index c6ffcdcc6a8..00000000000
--- a/spec/services/ci/extract_sections_from_build_trace_service_spec.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Ci::ExtractSectionsFromBuildTraceService, '#execute' do
- let(:user) { create(:user) }
- let(:project) { create(:project) }
- let(:build) { create(:ci_build, project: project) }
-
- subject { described_class.new(project, user) }
-
- shared_examples 'build trace has sections markers' do
- before do
- build.trace.set(File.read(expand_fixture_path('trace/trace_with_sections')))
- end
-
- it 'saves the correct extracted sections' do
- expect(build.trace_sections).to be_empty
- expect(subject.execute(build)).to be(true)
- expect(build.trace_sections).not_to be_empty
- end
-
- it "fails if trace_sections isn't empty" do
- expect(subject.execute(build)).to be(true)
- expect(build.trace_sections).not_to be_empty
-
- expect(subject.execute(build)).to be(false)
- expect(build.trace_sections).not_to be_empty
- end
- end
-
- shared_examples 'build trace has no sections markers' do
- before do
- build.trace.set('no markerts')
- end
-
- it 'extracts no sections' do
- expect(build.trace_sections).to be_empty
- expect(subject.execute(build)).to be(true)
- expect(build.trace_sections).to be_empty
- end
- end
-
- context 'when the build has no user' do
- it_behaves_like 'build trace has sections markers'
- it_behaves_like 'build trace has no sections markers'
- end
-
- context 'when the build has a valid user' do
- before do
- build.user = user
- end
-
- it_behaves_like 'build trace has sections markers'
- it_behaves_like 'build trace has no sections markers'
- end
-end
diff --git a/spec/services/ci/pipeline_processing/shared_processing_service.rb b/spec/services/ci/pipeline_processing/shared_processing_service.rb
index 5089f8d5dba..a4bc8e68b2d 100644
--- a/spec/services/ci/pipeline_processing/shared_processing_service.rb
+++ b/spec/services/ci/pipeline_processing/shared_processing_service.rb
@@ -871,7 +871,7 @@ RSpec.shared_examples 'Pipeline Processing Service' do
end
let(:pipeline) do
- Ci::CreatePipelineService.new(project, user, { ref: 'master' }).execute(:push)
+ Ci::CreatePipelineService.new(project, user, { ref: 'master' }).execute(:push).payload
end
before do
diff --git a/spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb b/spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb
index 572808cd2db..b4ad2512593 100644
--- a/spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb
+++ b/spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb
@@ -10,7 +10,7 @@ RSpec.shared_context 'Pipeline Processing Service Tests With Yaml' do
with_them do
let(:test_file) { YAML.load_file(test_file_path) }
- let(:pipeline) { Ci::CreatePipelineService.new(project, user, ref: 'master').execute(:pipeline) }
+ let(:pipeline) { Ci::CreatePipelineService.new(project, user, ref: 'master').execute(:pipeline).payload }
before do
stub_ci_pipeline_yaml_file(YAML.dump(test_file['config']))
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_same_and_different_stage_needs.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_same_and_different_stage_needs.yml
new file mode 100644
index 00000000000..115258c656e
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_same_and_different_stage_needs.yml
@@ -0,0 +1,54 @@
+config:
+ stages: [first, second, third]
+
+ job_a:
+ when: manual
+ stage: first
+ script:
+ - echo
+
+ job_b:
+ when: manual
+ stage: second
+ script:
+ - echo
+
+ job_c:
+ needs: ["job_b"]
+ stage: third
+ script:
+ - echo
+
+ job_d:
+ needs: ["job_a"]
+ stage: third
+ script:
+ - echo
+
+init:
+ expect:
+ pipeline: skipped
+ stages:
+ first: skipped
+ second: skipped
+ third: skipped
+ jobs:
+ job_a: manual
+ job_b: manual
+ job_c: skipped
+ job_d: skipped
+
+transitions:
+ - event: play
+ jobs: [job_b]
+ expect:
+ pipeline: pending
+ stages:
+ first: skipped
+ second: pending
+ third: pending
+ jobs:
+ job_a: manual
+ job_b: pending
+ job_c: created
+ job_d: skipped
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_same_stage_needs.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_same_stage_needs.yml
new file mode 100644
index 00000000000..fd15f7d1b57
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_same_stage_needs.yml
@@ -0,0 +1,70 @@
+config:
+ stages: [first, second, third, fourth]
+
+ first_job:
+ stage: first
+ script:
+ - echo
+
+ second_job:
+ stage: second
+ script:
+ - echo
+ when: manual
+
+ third_job:
+ stage: third
+ needs: ["second_job"]
+ script:
+ - echo
+
+ fourth_job:
+ stage: fourth
+ needs: ["third_job"]
+ script:
+ - echo
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ first: pending
+ second: created
+ third: created
+ fourth: created
+ jobs:
+ first_job: pending
+ second_job: created
+ third_job: created
+ fourth_job: created
+
+transitions:
+ - event: success
+ jobs: [first_job]
+ expect:
+ pipeline: success
+ stages:
+ first: success
+ second: skipped
+ third: skipped
+ fourth: skipped
+ jobs:
+ first_job: success
+ second_job: manual
+ third_job: skipped
+ fourth_job: skipped
+
+ - event: play
+ jobs: [second_job]
+ expect:
+ pipeline: running
+ stages:
+ first: success
+ second: pending
+ third: skipped
+ fourth: skipped
+ jobs:
+ first_job: success
+ second_job: pending
+ third_job: created
+ fourth_job: created
diff --git a/spec/services/ci/pipeline_trigger_service_spec.rb b/spec/services/ci/pipeline_trigger_service_spec.rb
index 080ca1cf0cd..2f93b1ecd3c 100644
--- a/spec/services/ci/pipeline_trigger_service_spec.rb
+++ b/spec/services/ci/pipeline_trigger_service_spec.rb
@@ -24,9 +24,11 @@ RSpec.describe Ci::PipelineTriggerService do
context 'when the pipeline was not created successfully' do
let(:fail_pipeline) do
receive(:execute).and_wrap_original do |original, *args|
- pipeline = original.call(*args)
+ response = original.call(*args)
+ pipeline = response.payload
pipeline.update!(failure_reason: 'unknown_failure')
- pipeline
+
+ response
end
end
diff --git a/spec/services/ci/pipelines/add_job_service_spec.rb b/spec/services/ci/pipelines/add_job_service_spec.rb
index a72ffbfdc87..bdf7e577fa8 100644
--- a/spec/services/ci/pipelines/add_job_service_spec.rb
+++ b/spec/services/ci/pipelines/add_job_service_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Ci::Pipelines::AddJobService do
+ include ExclusiveLeaseHelpers
+
let_it_be(:pipeline) { create(:ci_pipeline) }
let(:job) { build(:ci_build) }
@@ -68,5 +70,38 @@ RSpec.describe Ci::Pipelines::AddJobService do
execute
end
end
+
+ context 'exclusive lock' do
+ let(:lock_uuid) { 'test' }
+ let(:lock_key) { "ci:pipelines:#{pipeline.id}:add-job" }
+ let(:lock_timeout) { 1.minute }
+
+ before do
+ # "Please stub a default value first if message might be received with other args as well."
+ allow(Gitlab::ExclusiveLease).to receive(:new).and_call_original
+ end
+
+ it 'uses exclusive lock' do
+ lease = stub_exclusive_lease(lock_key, lock_uuid, timeout: lock_timeout)
+ expect(lease).to receive(:try_obtain)
+ expect(lease).to receive(:cancel)
+
+ expect(execute).to be_success
+ expect(execute.payload[:job]).to eq(job)
+ end
+
+ context 'when the FF ci_pipeline_add_job_with_lock is disabled' do
+ before do
+ stub_feature_flags(ci_pipeline_add_job_with_lock: false)
+ end
+
+ it 'does not use exclusive lock' do
+ expect(Gitlab::ExclusiveLease).not_to receive(:new).with(lock_key, timeout: lock_timeout)
+
+ expect(execute).to be_success
+ expect(execute.payload[:job]).to eq(job)
+ end
+ end
+ end
end
end
diff --git a/spec/services/ci/register_job_service_spec.rb b/spec/services/ci/register_job_service_spec.rb
index 6e5d7725a7a..2f37d0ea42d 100644
--- a/spec/services/ci/register_job_service_spec.rb
+++ b/spec/services/ci/register_job_service_spec.rb
@@ -5,8 +5,8 @@ require 'spec_helper'
module Ci
RSpec.describe RegisterJobService do
let_it_be(:group) { create(:group) }
- let_it_be(:project, reload: true) { create(:project, group: group, shared_runners_enabled: false, group_runners_enabled: false) }
- let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+ let_it_be_with_reload(:project) { create(:project, group: group, shared_runners_enabled: false, group_runners_enabled: false) }
+ let_it_be_with_reload(:pipeline) { create(:ci_pipeline, project: project) }
let!(:shared_runner) { create(:ci_runner, :instance) }
let!(:specific_runner) { create(:ci_runner, :project, projects: [project]) }
@@ -14,7 +14,7 @@ module Ci
let!(:pending_job) { create(:ci_build, :pending, :queued, pipeline: pipeline) }
describe '#execute' do
- context 'checks database loadbalancing stickiness' do
+ context 'checks database loadbalancing stickiness', :db_load_balancing do
subject { described_class.new(shared_runner).execute }
before do
@@ -22,9 +22,6 @@ module Ci
end
it 'result is valid if replica did caught-up' do
- allow(Gitlab::Database::LoadBalancing).to receive(:enable?)
- .and_return(true)
-
expect(Gitlab::Database::LoadBalancing::Sticking).to receive(:all_caught_up?)
.with(:runner, shared_runner.id) { true }
@@ -32,9 +29,6 @@ module Ci
end
it 'result is invalid if replica did not caught-up' do
- allow(Gitlab::Database::LoadBalancing).to receive(:enable?)
- .and_return(true)
-
expect(Gitlab::Database::LoadBalancing::Sticking).to receive(:all_caught_up?)
.with(:runner, shared_runner.id) { false }
@@ -96,6 +90,9 @@ module Ci
context 'allow shared runners' do
before do
project.update!(shared_runners_enabled: true)
+ pipeline.reload
+ pending_job.reload
+ pending_job.create_queuing_entry!
end
context 'for multiple builds' do
@@ -470,13 +467,27 @@ module Ci
context 'when depended job has not been completed yet' do
let!(:pre_stage_job) { create(:ci_build, :pending, :queued, :manual, pipeline: pipeline, name: 'test', stage_idx: 0) }
- it { expect(subject).to eq(pending_job) }
+ it { is_expected.to eq(pending_job) }
end
context 'when artifacts of depended job has been expired' do
let!(:pre_stage_job) { create(:ci_build, :success, :expired, pipeline: pipeline, name: 'test', stage_idx: 0) }
- it_behaves_like 'not pick'
+ context 'when the pipeline is locked' do
+ before do
+ pipeline.artifacts_locked!
+ end
+
+ it { is_expected.to eq(pending_job) }
+ end
+
+ context 'when the pipeline is unlocked' do
+ before do
+ pipeline.unlocked!
+ end
+
+ it_behaves_like 'not pick'
+ end
end
context 'when artifacts of depended job has been erased' do
@@ -493,8 +504,12 @@ module Ci
let!(:pre_stage_job) { create(:ci_build, :success, :expired, pipeline: pipeline, name: 'test', stage_idx: 0) }
before do
- allow_any_instance_of(Ci::Build).to receive(:drop!)
- .and_raise(ActiveRecord::StaleObjectError.new(pending_job, :drop!))
+ pipeline.unlocked!
+
+ allow_next_instance_of(Ci::Build) do |build|
+ expect(build).to receive(:drop!)
+ .and_raise(ActiveRecord::StaleObjectError.new(pending_job, :drop!))
+ end
end
it 'does not drop nor pick' do
@@ -709,7 +724,21 @@ module Ci
stub_feature_flags(ci_pending_builds_queue_source: true)
end
- include_examples 'handles runner assignment'
+ context 'with ci_queueing_denormalize_shared_runners_information enabled' do
+ before do
+ stub_feature_flags(ci_queueing_denormalize_shared_runners_information: true)
+ end
+
+ include_examples 'handles runner assignment'
+ end
+
+ context 'with ci_queueing_denormalize_shared_runners_information disabled' do
+ before do
+ stub_feature_flags(ci_queueing_denormalize_shared_runners_information: false)
+ end
+
+ include_examples 'handles runner assignment'
+ end
end
context 'when not using pending builds table' do
@@ -783,6 +812,11 @@ module Ci
end
context 'when shared runner is used' do
+ before do
+ pending_job.reload
+ pending_job.create_queuing_entry!
+ end
+
let(:runner) { create(:ci_runner, :instance, tag_list: %w(tag1 tag2)) }
let(:expected_shared_runner) { true }
let(:expected_shard) { ::Gitlab::Ci::Queue::Metrics::DEFAULT_METRICS_SHARD }
diff --git a/spec/services/ci/resource_groups/assign_resource_from_resource_group_service_spec.rb b/spec/services/ci/resource_groups/assign_resource_from_resource_group_service_spec.rb
index a741e3b49e7..53aa842bc28 100644
--- a/spec/services/ci/resource_groups/assign_resource_from_resource_group_service_spec.rb
+++ b/spec/services/ci/resource_groups/assign_resource_from_resource_group_service_spec.rb
@@ -51,14 +51,32 @@ RSpec.describe Ci::ResourceGroups::AssignResourceFromResourceGroupService do
end
context 'when there are no available resources' do
+ let!(:other_build) { create(:ci_build) }
+
before do
- resource_group.assign_resource_to(create(:ci_build))
+ resource_group.assign_resource_to(other_build)
end
it 'does not request resource' do
expect_any_instance_of(Ci::Build).not_to receive(:enqueue_waiting_for_resource)
subject
+
+ expect(build.reload).to be_waiting_for_resource
+ end
+
+ context 'when there is a stale build assigned to a resource' do
+ before do
+ other_build.doom!
+ other_build.update_column(:updated_at, 10.minutes.ago)
+ end
+
+ it 'releases the resource from the stale build and assignes to the waiting build' do
+ subject
+
+ expect(build.reload).to be_pending
+ expect(build.resource).to be_present
+ end
end
end
end
diff --git a/spec/services/ci/retry_build_service_spec.rb b/spec/services/ci/retry_build_service_spec.rb
index 42d6e66b38b..ce2e6ba5e15 100644
--- a/spec/services/ci/retry_build_service_spec.rb
+++ b/spec/services/ci/retry_build_service_spec.rb
@@ -60,7 +60,7 @@ RSpec.describe Ci::RetryBuildService do
artifacts_file artifacts_metadata artifacts_size commands
resource resource_group_id processed security_scans author
pipeline_id report_results pending_state pages_deployments
- queuing_entry runtime_metadata].freeze
+ queuing_entry runtime_metadata trace_metadata].freeze
shared_examples 'build duplication' do
let_it_be(:another_pipeline) { create(:ci_empty_pipeline, project: project) }
diff --git a/spec/services/ci/stop_environments_service_spec.rb b/spec/services/ci/stop_environments_service_spec.rb
deleted file mode 100644
index d5ef67c871c..00000000000
--- a/spec/services/ci/stop_environments_service_spec.rb
+++ /dev/null
@@ -1,253 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Ci::StopEnvironmentsService do
- include CreateEnvironmentsHelpers
-
- let(:project) { create(:project, :private, :repository) }
- let(:user) { create(:user) }
-
- let(:service) { described_class.new(project, user) }
-
- describe '#execute' do
- context 'when environment with review app exists' do
- before do
- create(:environment, :with_review_app, project: project,
- ref: 'feature')
- end
-
- context 'when user has permission to stop environment' do
- before do
- project.add_developer(user)
- end
-
- context 'when environment is associated with removed branch' do
- it 'stops environment' do
- expect_environment_stopped_on('feature')
- end
- end
-
- context 'when environment is associated with different branch' do
- it 'does not stop environment' do
- expect_environment_not_stopped_on('master')
- end
- end
-
- context 'when specified branch does not exist' do
- it 'does not stop environment' do
- expect_environment_not_stopped_on('non/existent/branch')
- end
- end
-
- context 'when no branch not specified' do
- it 'does not stop environment' do
- expect_environment_not_stopped_on(nil)
- end
- end
-
- context 'when environment is not stopped' do
- before do
- allow_any_instance_of(Environment)
- .to receive(:state).and_return(:stopped)
- end
-
- it 'does not stop environment' do
- expect_environment_not_stopped_on('feature')
- end
- end
- end
-
- context 'when user does not have permission to stop environment' do
- context 'when user has no access to manage deployments' do
- before do
- project.add_guest(user)
- end
-
- it 'does not stop environment' do
- expect_environment_not_stopped_on('master')
- end
- end
- end
-
- context 'when branch for stop action is protected' do
- before do
- project.add_developer(user)
- create(:protected_branch, :no_one_can_push,
- name: 'master', project: project)
- end
-
- it 'does not stop environment' do
- expect_environment_not_stopped_on('master')
- end
- end
- end
-
- context 'when there is no environment associated with review app' do
- before do
- create(:environment, project: project)
- end
-
- context 'when user has permission to stop environments' do
- before do
- project.add_maintainer(user)
- end
-
- it 'does not stop environment' do
- expect_environment_not_stopped_on('master')
- end
- end
- end
-
- context 'when environment does not exist' do
- it 'does not raise error' do
- expect { service.execute('master') }
- .not_to raise_error
- end
- end
- end
-
- describe '#execute_for_merge_request' do
- subject { service.execute_for_merge_request(merge_request) }
-
- let(:merge_request) { create(:merge_request, source_branch: 'feature', target_branch: 'master') }
- let(:project) { merge_request.project }
- let(:user) { create(:user) }
-
- let(:pipeline) do
- create(:ci_pipeline,
- source: :merge_request_event,
- merge_request: merge_request,
- project: project,
- sha: merge_request.diff_head_sha,
- merge_requests_as_head_pipeline: [merge_request])
- end
-
- let!(:review_job) { create(:ci_build, :with_deployment, :start_review_app, pipeline: pipeline, project: project) }
- let!(:stop_review_job) { create(:ci_build, :with_deployment, :stop_review_app, :manual, pipeline: pipeline, project: project) }
-
- before do
- review_job.deployment.success!
- end
-
- it 'has active environment at first' do
- expect(pipeline.environments.first).to be_available
- end
-
- context 'when user is a developer' do
- before do
- project.add_developer(user)
- end
-
- it 'stops the active environment' do
- subject
-
- expect(pipeline.environments.first).to be_stopped
- end
- end
-
- context 'when user is a reporter' do
- before do
- project.add_reporter(user)
- end
-
- it 'does not stop the active environment' do
- subject
-
- expect(pipeline.environments.first).to be_available
- end
- end
-
- context 'when pipeline is not associated with environments' do
- let!(:job) { create(:ci_build, pipeline: pipeline, project: project) }
-
- it 'does not raise exception' do
- expect { subject }.not_to raise_exception
- end
- end
-
- context 'when pipeline is not a pipeline for merge request' do
- let(:pipeline) do
- create(:ci_pipeline,
- project: project,
- ref: 'feature',
- sha: merge_request.diff_head_sha,
- merge_requests_as_head_pipeline: [merge_request])
- end
-
- it 'does not stop the active environment' do
- subject
-
- expect(pipeline.environments.first).to be_available
- end
- end
- end
-
- describe '.execute_in_batch' do
- subject { described_class.execute_in_batch(environments) }
-
- let_it_be(:project) { create(:project, :repository) }
- let_it_be(:user) { create(:user) }
-
- let(:environments) { Environment.available }
-
- before_all do
- project.add_developer(user)
- project.repository.add_branch(user, 'review/feature-1', 'master')
- project.repository.add_branch(user, 'review/feature-2', 'master')
- end
-
- before do
- create_review_app(user, project, 'review/feature-1')
- create_review_app(user, project, 'review/feature-2')
- end
-
- it 'stops environments' do
- expect { subject }
- .to change { project.environments.all.map(&:state).uniq }
- .from(['available']).to(['stopped'])
-
- expect(project.environments.all.map(&:auto_stop_at).uniq).to eq([nil])
- end
-
- it 'plays stop actions' do
- expect { subject }
- .to change { Ci::Build.where(name: 'stop_review_app').map(&:status).uniq }
- .from(['manual']).to(['pending'])
- end
-
- context 'when user does not have a permission to play the stop action' do
- before do
- project.team.truncate
- end
-
- it 'tracks the exception' do
- expect(Gitlab::ErrorTracking)
- .to receive(:track_exception)
- .with(Gitlab::Access::AccessDeniedError, anything)
- .twice
- .and_call_original
-
- subject
- end
-
- after do
- project.add_developer(user)
- end
- end
- end
-
- def expect_environment_stopped_on(branch)
- expect_any_instance_of(Environment)
- .to receive(:stop!)
-
- service.execute(branch)
- end
-
- def expect_environment_not_stopped_on(branch)
- expect_any_instance_of(Environment)
- .not_to receive(:stop!)
-
- service.execute(branch)
- end
-end