Commit f8de35f7 authored by Fabio Pitino's avatar Fabio Pitino

Merge branch '326476-CreatePipelineService-returns-ServiceResponse' into 'master'

Return ServiceResponse from  CreatePipelineService#execute [RUN ALL RSPEC] [RUN AS-IF-FOSS]

See merge request gitlab-org/gitlab!64318
parents 7bc94d1d 47b591b6
......@@ -68,20 +68,22 @@ class Projects::PipelinesController < Projects::ApplicationController
end
def create
@pipeline = Ci::CreatePipelineService
service_response = Ci::CreatePipelineService
.new(project, current_user, create_params)
.execute(:web, ignore_skip_ci: true, save_on_errors: false)
@pipeline = service_response.payload
respond_to do |format|
format.html do
if @pipeline.created_successfully?
if service_response.success?
redirect_to project_pipeline_path(project, @pipeline)
else
render 'new', status: :bad_request
end
end
format.json do
if @pipeline.created_successfully?
if service_response.success?
render json: PipelineSerializer
.new(project: project, current_user: current_user)
.represent(@pipeline),
......
......@@ -33,8 +33,9 @@ module Ci
current_user,
pipeline_params.fetch(:target_revision))
downstream_pipeline = service.execute(
pipeline_params.fetch(:source), **pipeline_params[:execute_params])
downstream_pipeline = service
.execute(pipeline_params.fetch(:source), **pipeline_params[:execute_params])
.payload
downstream_pipeline.tap do |pipeline|
update_bridge_status!(@bridge, pipeline)
......
......@@ -87,12 +87,16 @@ module Ci
if pipeline.persisted?
schedule_head_pipeline_update
create_namespace_onboarding_action
else
# If pipeline is not persisted, try to recover IID
pipeline.reset_project_iid
end
# If pipeline is not persisted, try to recover IID
pipeline.reset_project_iid unless pipeline.persisted?
pipeline
if error_message = pipeline.full_error_messages.presence || pipeline.failure_reason.presence
ServiceResponse.error(message: error_message, payload: pipeline)
else
ServiceResponse.success(payload: pipeline)
end
end
# rubocop: enable Metrics/ParameterLists
......@@ -100,8 +104,8 @@ module Ci
source = args[0]
params = Hash(args[1])
execute(source, **params, &block).tap do |pipeline|
unless pipeline.persisted?
execute(source, **params, &block).tap do |response|
unless response.payload.persisted?
raise CreateError, pipeline.full_error_messages
end
end
......
......@@ -7,7 +7,8 @@ module Ci
module ExternalPullRequests
class CreatePipelineService < BaseService
def execute(pull_request)
return unless pull_request.open? && pull_request.actual_branch_head?
return pull_request_not_open_error unless pull_request.open?
return pull_request_branch_error unless pull_request.actual_branch_head?
create_pipeline_for(pull_request)
end
......@@ -26,6 +27,14 @@ module Ci
target_sha: pull_request.target_sha
}
end
def pull_request_not_open_error
ServiceResponse.error(message: 'The pull request is not opened', payload: nil)
end
def pull_request_branch_error
ServiceResponse.error(message: 'The source sha is not the head of the source branch', payload: nil)
end
end
end
end
......@@ -27,13 +27,13 @@ module Ci
# this check is to not leak the presence of the project if user cannot read it
return unless trigger.project == project
pipeline = Ci::CreatePipelineService
response = Ci::CreatePipelineService
.new(project, trigger.owner, ref: params[:ref], variables_attributes: variables)
.execute(:trigger, ignore_skip_ci: true) do |pipeline|
pipeline.trigger_requests.build(trigger: trigger)
end
pipeline_service_response(pipeline)
pipeline_service_response(response.payload)
end
def pipeline_service_response(pipeline)
......@@ -57,7 +57,7 @@ module Ci
# this check is to not leak the presence of the project if user cannot read it
return unless can?(job.user, :read_project, project)
pipeline = Ci::CreatePipelineService
response = Ci::CreatePipelineService
.new(project, job.user, ref: params[:ref], variables_attributes: variables)
.execute(:pipeline, ignore_skip_ci: true) do |pipeline|
source = job.sourced_pipelines.build(
......@@ -69,7 +69,7 @@ module Ci
pipeline.source_pipeline = source
end
pipeline_service_response(pipeline)
pipeline_service_response(response.payload)
end
def job_from_token
......
......@@ -3,7 +3,7 @@
module MergeRequests
class CreatePipelineService < MergeRequests::BaseService
def execute(merge_request)
return unless can_create_pipeline_for?(merge_request)
return cannot_create_pipeline_error unless can_create_pipeline_for?(merge_request)
create_detached_merge_request_pipeline(merge_request)
end
......@@ -60,6 +60,10 @@ module MergeRequests
::Gitlab::UserAccess.new(current_user, container: merge_request.target_project)
.can_update_branch?(merge_request.source_branch_ref)
end
def cannot_create_pipeline_error
ServiceResponse.error(message: 'Cannot create a pipeline for this merge request.', payload: nil)
end
end
end
......
......@@ -24,7 +24,7 @@ module AppSec
response = create_scan(dast_profile)
return response if response.error?
return error(response.message) if response.error?
success(dast_profile: dast_profile, pipeline_url: response.payload.fetch(:pipeline_url))
end
......
......@@ -7,7 +7,7 @@ module Ci
service = Ci::CreatePipelineService.new(project, current_user, ref: branch)
pipeline = service.execute(:ondemand_dast_scan, content: ci_configuration) do |pipeline|
response = service.execute(:ondemand_dast_scan, content: ci_configuration) do |pipeline|
if dast_profile
pipeline.dast_profile = dast_profile
else
......@@ -16,6 +16,7 @@ module Ci
end
end
pipeline = response.payload
if pipeline.created_successfully?
ServiceResponse.success(payload: pipeline)
else
......
......@@ -7,17 +7,19 @@ module EE
override :execute
def execute(merge_request)
create_merged_result_pipeline_for(merge_request) || super
response = create_merged_result_pipeline_for(merge_request)
return response if response.success?
super
end
def create_merged_result_pipeline_for(merge_request)
return unless can_create_merged_result_pipeline_for?(merge_request)
return cannot_create_pipeline_error unless can_create_merged_result_pipeline_for?(merge_request)
result = ::MergeRequests::MergeabilityCheckService.new(merge_request).execute(recheck: true)
if result.success? &&
merge_request.mergeable_state?(skip_ci_check: true, skip_discussions_check: true)
if result.success? && merge_request.mergeable_state?(skip_ci_check: true, skip_discussions_check: true)
ref_payload = result.payload.fetch(:merge_ref_head)
::Ci::CreatePipelineService.new(merge_request.target_project, current_user,
......@@ -26,6 +28,8 @@ module EE
target_sha: ref_payload[:target_id],
source_sha: ref_payload[:source_id])
.execute(:merge_request_event, merge_request: merge_request)
else
cannot_create_pipeline_error
end
end
......
......@@ -39,16 +39,16 @@ module MergeTrains
end
def create_pipeline(merge_request, merge_status)
pipeline = ::Ci::CreatePipelineService.new(merge_request.target_project, merge_request.merge_user,
response = ::Ci::CreatePipelineService.new(merge_request.target_project, merge_request.merge_user,
ref: merge_request.train_ref_path,
checkout_sha: merge_status[:commit_id],
target_sha: merge_status[:target_id],
source_sha: merge_status[:source_id])
.execute(:merge_request_event, merge_request: merge_request)
return error(pipeline.full_error_messages) unless pipeline.persisted?
return error(response.message) if response.error? && !response.payload.persisted?
success(pipeline: pipeline)
success(pipeline: response.payload)
end
def can_add_to_merge_train?(merge_request)
......
......@@ -29,7 +29,7 @@ RSpec.describe 'Jobs/Browser-Performance-Testing.gitlab-ci.yml' do
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
......@@ -77,7 +77,7 @@ RSpec.describe 'Jobs/Browser-Performance-Testing.gitlab-ci.yml' do
context 'on merge request' do
let(:service) { MergeRequests::CreatePipelineService.new(project: project, current_user: user) }
let(:merge_request) { create(:merge_request, :simple, source_project: project) }
let(:pipeline) { service.execute(merge_request) }
let(:pipeline) { service.execute(merge_request).payload }
it 'has no jobs' do
expect(pipeline).to be_merge_request_event
......
......@@ -32,7 +32,7 @@ RSpec.describe 'Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml' do
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
......
......@@ -29,7 +29,7 @@ RSpec.describe 'Jobs/Load-Performance-Testing.gitlab-ci.yml' do
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
......@@ -75,7 +75,7 @@ RSpec.describe 'Jobs/Load-Performance-Testing.gitlab-ci.yml' do
context 'on merge request' do
let(:service) { MergeRequests::CreatePipelineService.new(project: project, current_user: user) }
let(:merge_request) { create(:merge_request, :simple, source_project: project) }
let(:pipeline) { service.execute(merge_request) }
let(:pipeline) { service.execute(merge_request).payload }
it 'has no jobs' do
expect(pipeline).to be_merge_request_event
......
......@@ -25,7 +25,7 @@ RSpec.describe 'Verify/Browser-Performance.gitlab-ci.yml' do
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
......@@ -66,7 +66,7 @@ RSpec.describe 'Verify/Browser-Performance.gitlab-ci.yml' do
context 'on merge request' do
let(:service) { MergeRequests::CreatePipelineService.new(project: project, current_user: user) }
let(:merge_request) { create(:merge_request, :simple, source_project: project) }
let(:pipeline) { service.execute(merge_request) }
let(:pipeline) { service.execute(merge_request).payload }
it 'has no jobs' do
expect(pipeline).to be_merge_request_event
......
......@@ -25,7 +25,7 @@ RSpec.describe 'Verify/Load-Performance-Testing.gitlab-ci.yml' do
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
......@@ -65,7 +65,7 @@ RSpec.describe 'Verify/Load-Performance-Testing.gitlab-ci.yml' do
context 'on merge request' do
let(:service) { MergeRequests::CreatePipelineService.new(project: project, current_user: user) }
let(:merge_request) { create(:merge_request, :simple, source_project: project) }
let(:pipeline) { service.execute(merge_request) }
let(:pipeline) { service.execute(merge_request).payload }
it 'has no jobs' do
expect(pipeline).to be_merge_request_event
......
......@@ -35,7 +35,7 @@ RSpec.describe 'API-Fuzzing.gitlab-ci.yml' do
let(:pipeline_branch) { default_branch }
let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
context 'when no stages' do
......
......@@ -35,7 +35,7 @@ RSpec.describe 'API-Fuzzing.latest.gitlab-ci.yml' do
let(:pipeline_branch) { default_branch }
let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
context 'when no stages' do
......
......@@ -11,7 +11,7 @@ RSpec.describe 'Cluster-Image-Scanning.gitlab-ci.yml' do
let(:default_branch) { 'master' }
let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: 'master' ) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
......
......@@ -11,7 +11,7 @@ RSpec.describe 'Container-Scanning.gitlab-ci.yml' do
let(:default_branch) { 'master' }
let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: 'master' ) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
......
......@@ -35,7 +35,7 @@ RSpec.describe 'DAST-API.gitlab-ci.yml' do
let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
......
......@@ -11,7 +11,7 @@ RSpec.describe 'DAST.gitlab-ci.yml' do
let(:project) { create(:project, :custom_repo, files: { 'README.txt' => '' }) }
let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
let(:ci_pipeline_yaml) { "stages: [\"dast\"]\n" }
......
......@@ -23,7 +23,7 @@ RSpec.describe 'DAST.latest.gitlab-ci.yml' do
let(:project) { create(:project, :custom_repo, files: { 'README.txt' => '' }) }
let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
let(:ci_pipeline_yaml) { "stages: [\"dast\"]\n" }
......
......@@ -11,7 +11,7 @@ RSpec.describe 'Dependency-Scanning.gitlab-ci.yml' do
let(:project) { create(:project, :custom_repo, files: files) }
let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: 'master') }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
......
......@@ -11,7 +11,7 @@ RSpec.describe 'License-Scanning.gitlab-ci.yml' do
let(:default_branch) { 'master' }
let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: 'master') }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
......
......@@ -11,7 +11,7 @@ RSpec.describe 'SAST.gitlab-ci.yml' do
let(:project) { create(:project, :custom_repo, files: files) }
let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: 'master') }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
......
......@@ -14,7 +14,7 @@ RSpec.describe 'Secure-Binaries.gitlab-ci.yml' do
let(:pipeline_branch) { default_branch }
let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
......
......@@ -32,14 +32,14 @@ RSpec.describe 'Running a DAST Profile' do
end
context 'when pipeline creation fails' do
let(:fake_pipeline) { instance_double('Ci::Pipeline', created_successfully?: false, full_error_messages: 'full error messages') }
let(:fake_service) { instance_double('Ci::CreatePipelineService', execute: ServiceResponse.error(message: 'error message', payload: fake_pipeline)) }
before do
allow_next_instance_of(Ci::Pipeline) do |instance|
allow(instance).to receive(:created_successfully?).and_return(false)
allow(instance).to receive(:full_error_messages).and_return('error message')
end
allow(Ci::CreatePipelineService).to receive(:new).and_return(fake_service)
end
it_behaves_like 'a mutation that returns errors in the response', errors: ['error message']
it_behaves_like 'a mutation that returns errors in the response', errors: ['full error messages']
end
end
end
......@@ -63,12 +63,14 @@ RSpec.describe 'Running a DAST Scan' do
end
context 'when pipeline creation fails' do
let(:fake_pipeline) { instance_double('Ci::Pipeline', created_successfully?: false, full_error_messages: 'full error messages') }
let(:fake_service) { instance_double('Ci::CreatePipelineService', execute: ServiceResponse.error(message: 'error message', payload: fake_pipeline)) }
before do
allow_any_instance_of(Ci::Pipeline).to receive(:created_successfully?).and_return(false)
allow_any_instance_of(Ci::Pipeline).to receive(:full_error_messages).and_return('error message')
allow(Ci::CreatePipelineService).to receive(:new).and_return(fake_service)
end
it_behaves_like 'a mutation that returns errors in the response', errors: ['error message']
it_behaves_like 'a mutation that returns errors in the response', errors: ['full error messages']
end
end
end
......@@ -41,12 +41,16 @@ RSpec.describe Ci::CreatePipelineService do
compliance_project.add_maintainer(project.owner)
end
it 'responds with success' do
is_expected.to be_success
end
it 'persists pipeline' do
is_expected.to be_persisted
expect(execute.payload).to be_persisted
end
it 'sets the correct source' do
expect(execute.config_source).to eq("compliance_source")
expect(execute.payload.config_source).to eq("compliance_source")
end
it 'persists jobs' do
......@@ -54,13 +58,13 @@ RSpec.describe Ci::CreatePipelineService do
end
it do
expect(execute.processables.map(&:name)).to contain_exactly('compliance_build', 'compliance_test')
expect(execute.payload.processables.map(&:name)).to contain_exactly('compliance_build', 'compliance_test')
end
end
context 'when user does not have access to compliance project' do
it 'includes access denied error' do
expect(execute.yaml_errors).to eq "Project `compliance/hippa` not found or access denied!"
expect(execute.payload.yaml_errors).to eq "Project `compliance/hippa` not found or access denied!"
end
it 'does not persist jobs' do
......
......@@ -36,10 +36,10 @@ RSpec.describe Ci::CreatePipelineService do
]
end
let(:build_job) { subject.builds.find_by!(name: :build_job) }
let(:build_job) { subject.payload.builds.find_by!(name: :build_job) }
it 'persists pipeline' do
is_expected.to be_persisted
expect(subject.payload).to be_persisted
end
it 'persists job' do
......@@ -124,10 +124,10 @@ RSpec.describe Ci::CreatePipelineService do
%w[build_job_1]
end
let(:test_job) { subject.builds.find_by!(name: :test_job) }
let(:test_job) { subject.payload.builds.find_by!(name: :test_job) }
it 'persists pipeline' do
is_expected.to be_persisted
expect(subject.payload).to be_persisted
end
it 'persists jobs' do
......@@ -175,11 +175,11 @@ RSpec.describe Ci::CreatePipelineService do
end
it 'persists pipeline' do
is_expected.to be_persisted
expect(subject.payload).to be_persisted
end
it 'has errors' do
expect(subject.yaml_errors)
expect(subject.payload.yaml_errors)
.to include('jobs:build_job:needs:need ref should be a string')
end
end
......
......@@ -50,7 +50,7 @@ RSpec.describe Ci::CreatePipelineService do
.to_runner_variables
end
subject { described_class.new(project, user, ref: 'refs/heads/master').execute(:push) }
subject { described_class.new(project, user, ref: 'refs/heads/master').execute(:push).payload }
before do
stub_ci_pipeline_yaml_file(config)
......
......@@ -126,6 +126,6 @@ RSpec.describe Ci::CreatePipelineService do
end
def create_pipeline!
service.execute(:push)
service.execute(:push).payload
end
end
......@@ -33,8 +33,8 @@ RSpec.describe Ci::CreatePipelineService, :sidekiq_inline do
stub_ci_pipeline_yaml_file(config)
end
it 'drops builds that match shared runners' do
pipeline = create_pipeline!
it 'drops builds that match shared runners', :aggregate_failures do
pipeline = create_pipeline
job1 = pipeline.builds.find_by_name('job1')
job2 = pipeline.builds.find_by_name('job2')
......@@ -49,8 +49,8 @@ RSpec.describe Ci::CreatePipelineService, :sidekiq_inline do
create(:ci_runner, :project, :online, projects: [project])
end
it 'does not drop the builds' do
pipeline = create_pipeline!
it 'does not drop the builds', :aggregate_failures do
pipeline = create_pipeline
job1 = pipeline.builds.find_by_name('job1')
job2 = pipeline.builds.find_by_name('job2')
......@@ -60,7 +60,7 @@ RSpec.describe Ci::CreatePipelineService, :sidekiq_inline do
end
end
def create_pipeline!
service.execute(:push)
def create_pipeline
service.execute(:push).payload
end
end
......@@ -29,9 +29,10 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
describe 'CI/CD Quotas / Limits' do
context 'when there are not limits enabled' do
it 'enqueues a new pipeline' do
pipeline = create_pipeline!
it 'enqueues a new pipeline', :aggregate_failures do
response, pipeline = create_pipeline!
expect(response).to be_success
expect(pipeline).to be_created_successfully
end
end
......@@ -44,9 +45,10 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
create(:ci_pipeline, project: project, status: 'running')
end
it 'drops the pipeline and does not process jobs' do
pipeline = create_pipeline!
it 'drops the pipeline and does not process jobs', :aggregate_failures do
response, pipeline = create_pipeline!
expect(response).to be_error
expect(pipeline).to be_persisted
expect(pipeline).to be_failed
expect(pipeline.statuses).not_to be_empty
......@@ -60,9 +62,10 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
plan_limits.update_column(:ci_pipeline_size, 2)
end
it 'drops pipeline without creating jobs' do
pipeline = create_pipeline!
it 'drops pipeline without creating jobs', :aggregate_failures do
response, pipeline = create_pipeline!
expect(response).to be_error
expect(pipeline).to be_persisted
expect(pipeline).to be_failed
expect(pipeline.statuses).to be_empty
......@@ -85,12 +88,13 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
YAML
end
it 'creates bridge jobs correctly' do
pipeline = create_pipeline!
it 'creates bridge jobs correctly', :aggregate_failures do
response, pipeline = create_pipeline!
test = pipeline.statuses.find_by(name: 'test')
bridge = pipeline.statuses.find_by(name: 'deploy')
expect(response).to be_success
expect(pipeline).to be_persisted
expect(test).to be_a Ci::Build
expect(bridge).to be_a Ci::Bridge
......@@ -124,7 +128,7 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
context 'that include the bridge job' do
it 'persists the bridge job' do
pipeline = create_pipeline!
_, pipeline = create_pipeline!
expect(pipeline.processables.pluck(:name)).to contain_exactly('hello', 'bridge-job')
end
......@@ -134,7 +138,7 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
let(:ref_name) { 'refs/heads/wip' }
it 'does not include the bridge job' do
pipeline = create_pipeline!
_, pipeline = create_pipeline!
expect(pipeline.processables.pluck(:name)).to eq(%w[hello])
end
......@@ -154,9 +158,10 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
YAML
end
it 'persists secrets as job metadata' do
pipeline = create_pipeline!
it 'persists secrets as job metadata', :aggregate_failures do
response, pipeline = create_pipeline!
expect(response).to be_success
expect(pipeline).to be_persisted
build = Ci::Build.find(pipeline.builds.first.id)
......@@ -175,9 +180,10 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
describe 'credit card requirement' do
shared_examples 'creates a successful pipeline' do
it 'creates a successful pipeline' do
pipeline = create_pipeline!
it 'creates a successful pipeline', :aggregate_failures do
response, pipeline = create_pipeline!
expect(response).to be_success
expect(pipeline).to be_created_successfully
end
end
......@@ -200,7 +206,7 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
context 'when user does not have credit card' do
it 'creates a pipeline with errors', :aggregate_failures do
pipeline = create_pipeline!
_, pipeline = create_pipeline!
expect(pipeline).not_to be_created_successfully
expect(pipeline.failure_reason).to eq('user_not_verified')
......@@ -212,8 +218,9 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
end
it 'does not create a pipeline', :aggregate_failures do
pipeline = create_pipeline!
response, pipeline = create_pipeline!
expect(response).to be_error
expect(pipeline).not_to be_persisted
end
end
......@@ -235,6 +242,8 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
end
def create_pipeline!
service.execute(:push)
response = service.execute(:push)
[response, response.payload]
end
end
......@@ -185,19 +185,20 @@ RSpec.describe Ci::RunDastScanService do
end
context 'when the pipeline fails to save' do
let(:fake_pipeline) { instance_double 'Ci::Pipeline', created_successfully?: false, full_error_messages: 'Fake full error messages' }
let(:fake_response) { ServiceResponse.error(message: 'Fake error message', payload: fake_pipeline) }
let(:fake_service) { instance_double "Ci::CreatePipelineService", execute: fake_response }
before do
allow_any_instance_of(Ci::Pipeline).to receive(:created_successfully?).and_return(false)
allow_any_instance_of(Ci::Pipeline).to receive(:full_error_messages).and_return(full_error_messages)
allow(Ci::CreatePipelineService).to receive(:new).and_return(fake_service)
end
let(:full_error_messages) { SecureRandom.hex }
it 'returns an error status' do
expect(status).to eq(:error)
end
it 'populates message' do
expect(message).to eq(full_error_messages)
expect(message).to eq('Fake full error messages')
end
end
......
......@@ -52,6 +52,11 @@ RSpec.describe MergeRequests::CreatePipelineService, :clean_gitlab_redis_shared_
expect(merge_request.all_pipelines.last).not_to be_merged_result_pipeline
expect(merge_request.all_pipelines.last).to be_detached_merge_request_pipeline
end
it 'responds with success', :sidekiq_might_not_need_inline, :aggregate_failures do
expect(subject).to be_success
expect(subject.payload).to eq(Ci::Pipeline.last)
end
end
it 'creates a merge request pipeline', :sidekiq_might_not_need_inline do
......@@ -62,6 +67,11 @@ RSpec.describe MergeRequests::CreatePipelineService, :clean_gitlab_redis_shared_
expect(merge_request.all_pipelines.last).not_to be_detached_merge_request_pipeline
end
it 'responds with success', :sidekiq_might_not_need_inline, :aggregate_failures do
expect(subject).to be_success
expect(subject.payload).to eq(Ci::Pipeline.last)
end
context 'when merge request is WIP' do
before do
merge_request.update!(title: merge_request.wip_title)
......@@ -128,11 +138,16 @@ RSpec.describe MergeRequests::CreatePipelineService, :clean_gitlab_redis_shared_
context 'when .gitlab-ci.yml is invalid' do
let(:ci_yaml) { 'invalid yaml file' }
it 'persists a pipeline with a config error' do
it 'persists a pipeline with a config error', :aggregate_failures do
expect { subject }.to change { Ci::Pipeline.count }.by(1)
expect(merge_request.all_pipelines.last).to be_failed
expect(merge_request.all_pipelines.last).to be_config_error
end
it 'responds with error', :aggregate_failures do
expect(subject).to be_error
expect(subject.message).to eq('Cannot create a pipeline for this merge request.')
end
end
end
end
......@@ -78,12 +78,11 @@ module API
.merge(variables_attributes: params[:variables])
.except(:variables)
new_pipeline = ::Ci::CreatePipelineService.new(user_project,
current_user,
pipeline_params)
.execute(:api, ignore_skip_ci: true, save_on_errors: false)
response = ::Ci::CreatePipelineService.new(user_project, current_user, pipeline_params)
.execute(:api, ignore_skip_ci: true, save_on_errors: false)
new_pipeline = response.payload
if new_pipeline.persisted?
if response.success?
present new_pipeline, with: Entities::Ci::Pipeline
else
render_validation_error!(new_pipeline)
......
......@@ -404,6 +404,7 @@ module API
pipeline = ::MergeRequests::CreatePipelineService
.new(project: user_project, current_user: current_user, params: { allow_duplicate: true })
.execute(find_merge_request_with_access(params[:merge_request_iid]))
.payload
if pipeline.nil?
not_allowed!
......
......@@ -54,10 +54,12 @@ module Gitlab
}
)
service.execute(:chat) do |pipeline|
response = service.execute(:chat) do |pipeline|
build_environment_variables(pipeline)
build_chat_data(pipeline)
end
response.payload
end
# pipeline - The `Ci::Pipeline` to create the environment variables for.
......
......@@ -38,6 +38,7 @@ module Gitlab
pipeline = ::Ci::CreatePipelineService
.new(@project, @current_user, ref: @project.default_branch)
.execute(:push, dry_run: true, content: content)
.payload
Result.new(
jobs: dry_run_convert_to_jobs(pipeline.stages),
......
......@@ -43,12 +43,14 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
let!(:push_pipeline) do
Ci::CreatePipelineService.new(project, user, ref: 'feature')
.execute(:push)
.execute(:push)
.payload
end
let!(:detached_merge_request_pipeline) do
Ci::CreatePipelineService.new(project, user, ref: 'feature')
.execute(:merge_request_event, merge_request: merge_request)
.execute(:merge_request_event, merge_request: merge_request)
.payload
end
before do
......@@ -77,12 +79,14 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
context 'when a user updated a merge request in the parent project', :sidekiq_might_not_need_inline do
let!(:push_pipeline_2) do
Ci::CreatePipelineService.new(project, user, ref: 'feature')
.execute(:push)
.execute(:push)
.payload
end
let!(:detached_merge_request_pipeline_2) do
Ci::CreatePipelineService.new(project, user, ref: 'feature')
.execute(:merge_request_event, merge_request: merge_request)
.execute(:merge_request_event, merge_request: merge_request)
.payload
end
before do
......@@ -222,12 +226,14 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
let!(:push_pipeline) do
Ci::CreatePipelineService.new(forked_project, user2, ref: 'feature')
.execute(:push)
.execute(:push)
.payload
end
let!(:detached_merge_request_pipeline) do
Ci::CreatePipelineService.new(forked_project, user2, ref: 'feature')
.execute(:merge_request_event, merge_request: merge_request)
.execute(:merge_request_event, merge_request: merge_request)
.payload
end
let(:forked_project) { fork_project(project, user2, repository: true) }
......@@ -267,12 +273,14 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
context 'when a user updated a merge request from a forked project to the parent project' do
let!(:push_pipeline_2) do
Ci::CreatePipelineService.new(forked_project, user2, ref: 'feature')
.execute(:push)
.execute(:push)
.payload
end
let!(:detached_merge_request_pipeline_2) do
Ci::CreatePipelineService.new(forked_project, user2, ref: 'feature')
.execute(:merge_request_event, merge_request: merge_request)
.execute(:merge_request_event, merge_request: merge_request)
.payload
end
before do
......
......@@ -245,7 +245,7 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
threads << Thread.new do
Sidekiq::Worker.skipping_transaction_check do
@pipeline = Ci::CreatePipelineService.new(project, user, build_push_data).execute(:push)
@pipeline = Ci::CreatePipelineService.new(project, user, build_push_data).execute(:push).payload
end
end
......
......@@ -12,7 +12,7 @@ RSpec.describe '5-Minute-Production-App.gitlab-ci.yml' do
let(:default_branch) { 'master' }
let(:pipeline_branch) { default_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
......
......@@ -11,7 +11,7 @@ RSpec.describe 'Deploy-ECS.gitlab-ci.yml' do
let(:project) { create(:project, :auto_devops, :custom_repo, files: { 'README.md' => '' }) }
let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
let(:platform_target) { 'ECS' }
......
......@@ -12,7 +12,7 @@ RSpec.describe 'Jobs/Build.gitlab-ci.yml' do
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
......@@ -47,7 +47,7 @@ RSpec.describe 'Jobs/Build.gitlab-ci.yml' do
context 'on merge request' do
let(:service) { MergeRequests::CreatePipelineService.new(project: project, current_user: user) }
let(:merge_request) { create(:merge_request, :simple, source_project: project) }
let(:pipeline) { service.execute(merge_request) }
let(:pipeline) { service.execute(merge_request).payload }
it 'has no jobs' do
expect(pipeline).to be_merge_request_event
......
......@@ -12,7 +12,7 @@ RSpec.describe 'Jobs/Code-Quality.gitlab-ci.yml' do
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
......@@ -47,7 +47,7 @@ RSpec.describe 'Jobs/Code-Quality.gitlab-ci.yml' do
context 'on merge request' do
let(:service) { MergeRequests::CreatePipelineService.new(project: project, current_user: user) }
let(:merge_request) { create(:merge_request, :simple, source_project: project) }
let(:pipeline) { service.execute(merge_request) }
let(:pipeline) { service.execute(merge_request).payload }
it 'has no jobs' do
expect(pipeline).to be_merge_request_event
......
......@@ -33,7 +33,7 @@ RSpec.describe 'Jobs/Deploy.gitlab-ci.yml' do
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
......@@ -210,7 +210,7 @@ RSpec.describe 'Jobs/Deploy.gitlab-ci.yml' do
context 'on merge request' do
let(:service) { MergeRequests::CreatePipelineService.new(project: project, current_user: user) }
let(:merge_request) { create(:merge_request, :simple, source_project: project) }
let(:pipeline) { service.execute(merge_request) }
let(:pipeline) { service.execute(merge_request).payload }
it 'has no jobs' do
expect(pipeline).to be_merge_request_event
......
......@@ -12,7 +12,7 @@ RSpec.describe 'Jobs/Test.gitlab-ci.yml' do
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
......@@ -47,7 +47,7 @@ RSpec.describe 'Jobs/Test.gitlab-ci.yml' do
context 'on merge request' do
let(:service) { MergeRequests::CreatePipelineService.new(project: project, current_user: user) }
let(:merge_request) { create(:merge_request, :simple, source_project: project) }
let(:pipeline) { service.execute(merge_request) }
let(:pipeline) { service.execute(merge_request).payload }
it 'has no jobs' do
expect(pipeline).to be_merge_request_event
......
......@@ -11,7 +11,7 @@ RSpec.describe 'Terraform/Base.latest.gitlab-ci.yml' do
let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
......
......@@ -25,7 +25,7 @@ RSpec.describe 'Verify/Load-Performance-Testing.gitlab-ci.yml' do
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
......@@ -64,7 +64,7 @@ RSpec.describe 'Verify/Load-Performance-Testing.gitlab-ci.yml' do
context 'on merge request' do
let(:service) { MergeRequests::CreatePipelineService.new(project: project, current_user: user) }
let(:merge_request) { create(:merge_request, :simple, source_project: project) }
let(:pipeline) { service.execute(merge_request) }
let(:pipeline) { service.execute(merge_request).payload }
it 'has no jobs' do
expect(pipeline).to be_merge_request_event
......
......@@ -17,7 +17,7 @@ RSpec.describe 'Auto-DevOps.gitlab-ci.yml' do
let(:project) { create(:project, :auto_devops, :custom_repo, files: { 'README.md' => '' }) }
let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
......@@ -264,7 +264,7 @@ RSpec.describe 'Auto-DevOps.gitlab-ci.yml' do
let(:project) { create(:project, :custom_repo, files: files) }
let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: default_branch ) }
let(:pipeline) { service.execute(:push) }
let(:pipeline) { service.execute(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
......
......@@ -10,7 +10,7 @@ RSpec.describe 'Flutter.gitlab-ci.yml' do
let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
......
......@@ -10,7 +10,7 @@ RSpec.describe 'Managed-Cluster-Applications.gitlab-ci.yml' do
let(:project) { create(:project, :custom_repo, namespace: user.namespace, files: { 'README.md' => '' }) }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
let(:default_branch) { project.default_branch_or_main }
let(:pipeline_branch) { default_branch }
......
......@@ -14,7 +14,7 @@ RSpec.describe 'npm.gitlab-ci.yml' do
let(:pipeline_tag) { 'v1.2.1' }
let(:pipeline_ref) { pipeline_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref ) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
def create_branch(name:)
......
......@@ -15,7 +15,7 @@ RSpec.describe 'Terraform.latest.gitlab-ci.yml' do
let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:pipeline) { service.execute!(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
......
......@@ -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') }
......
......@@ -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
......
......@@ -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)
......
......@@ -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)
......
......@@ -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
......
......@@ -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)
......
......@@ -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)
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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)
......
......@@ -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)
......
......@@ -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
......
......@@ -369,6 +369,6 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
end
def create_pipeline!
service.execute(:push)
service.execute(:push).payload
end
end
......@@ -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
......
......@@ -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
......
......@@ -49,12 +49,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 +132,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 +161,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 +182,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 +213,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 +234,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 +264,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 +280,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 +295,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 +308,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 +321,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 +481,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 +508,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(message: message).payload
expect(pipeline).to be_persisted
expect(pipeline.builds.any?).to be false
......@@ -516,7 +525,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 +539,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 +550,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 +566,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 +658,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
......@@ -680,7 +690,7 @@ RSpec.describe Ci::CreatePipelineService do
ci_messages.each do |ci_message|
it "skips builds creation if the commit message is #{ci_message}" do
pipeline = execute_service(message: ci_message)
pipeline = execute_service(message: ci_message).payload
expect(pipeline).to be_persisted
expect(pipeline.builds.any?).to be false
......@@ -692,7 +702,7 @@ RSpec.describe Ci::CreatePipelineService do
it 'does not skip pipeline creation' do
allow_any_instance_of(Ci::Pipeline).to receive(:git_commit_message) { commit_message }
pipeline = execute_service(message: commit_message)
pipeline = execute_service(message: commit_message).payload
expect(pipeline).to be_persisted
expect(pipeline.builds.first.name).to eq("rspec")
......@@ -724,7 +734,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 +749,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 +769,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 +786,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 +806,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 +828,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 +848,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 +873,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 +889,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 +909,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 +919,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 +959,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 +975,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 +992,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 +1007,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 +1072,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 +1096,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 +1114,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 +1133,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 +1167,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
......@@ -1162,16 +1179,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))
......@@ -1219,7 +1236,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,
......@@ -1227,6 +1244,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
......@@ -1275,9 +1294,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
......@@ -1296,9 +1317,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
......@@ -1306,7 +1329,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
......@@ -1353,11 +1378,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
......@@ -1365,7 +1390,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,
......@@ -1373,6 +1398,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
......@@ -1455,9 +1482,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
......@@ -1497,9 +1526,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
......@@ -1532,11 +1562,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
......@@ -1561,11 +1590,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
......@@ -1592,11 +1620,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
......@@ -1621,11 +1648,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
......@@ -1666,7 +1692,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
{
......@@ -1712,7 +1739,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"
......@@ -1723,9 +1750,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
......@@ -1733,9 +1763,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
......@@ -1755,7 +1787,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') }
......@@ -2312,8 +2345,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
......@@ -2343,7 +2377,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
......@@ -2351,7 +2386,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
......@@ -2379,7 +2414,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
......@@ -2389,7 +2425,7 @@ RSpec.describe Ci::CreatePipelineService do
let(:pipeline) do
execute_service do |pipeline|
pipeline.variables.build(variables)
end
end.payload
end
let(:config) do
......@@ -2447,7 +2483,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
......@@ -2475,7 +2512,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
......
......@@ -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
......
......@@ -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
......
......@@ -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']))
......
......@@ -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
......
......@@ -18,7 +18,7 @@ RSpec.describe MergeRequests::CreatePipelineService do
end
describe '#execute' do
subject { service.execute(merge_request) }
subject(:response) { service.execute(merge_request) }
before do
stub_ci_pipeline_yaml_file(YAML.dump(config))
......@@ -39,14 +39,15 @@ RSpec.describe MergeRequests::CreatePipelineService do
let(:source_project) { project }
it 'creates a detached merge request pipeline' do
expect { subject }.to change { Ci::Pipeline.count }.by(1)
expect { response }.to change { Ci::Pipeline.count }.by(1)
expect(subject).to be_persisted
expect(subject).to be_detached_merge_request_pipeline
expect(response).to be_success
expect(response.payload).to be_persisted
expect(response.payload).to be_detached_merge_request_pipeline
end
it 'defaults to merge_request_event' do
expect(subject.source).to eq('merge_request_event')
expect(response.payload.source).to eq('merge_request_event')
end
context 'with fork merge request' do
......@@ -58,7 +59,7 @@ RSpec.describe MergeRequests::CreatePipelineService do
let(:actor) { user }
it 'creates a pipeline in the target project' do
expect(subject.project).to eq(project)
expect(response.payload.project).to eq(project)
end
context 'when source branch is protected' do
......@@ -66,7 +67,7 @@ RSpec.describe MergeRequests::CreatePipelineService do
let!(:protected_branch) { create(:protected_branch, name: '*', project: project) }
it 'creates a pipeline in the source project' do
expect(subject.project).to eq(source_project)
expect(response.payload.project).to eq(source_project)
end
end
......@@ -74,7 +75,7 @@ RSpec.describe MergeRequests::CreatePipelineService do
let!(:protected_branch) { create(:protected_branch, :developers_can_merge, name: '*', project: project) }
it 'creates a pipeline in the target project' do
expect(subject.project).to eq(project)
expect(response.payload.project).to eq(project)
end
end
end
......@@ -85,7 +86,7 @@ RSpec.describe MergeRequests::CreatePipelineService do
end
it 'creates a pipeline in the source project' do
expect(subject.project).to eq(source_project)
expect(response.payload.project).to eq(source_project)
end
end
end
......@@ -99,15 +100,16 @@ RSpec.describe MergeRequests::CreatePipelineService do
end
it 'creates a pipeline in the source project' do
expect(subject.project).to eq(source_project)
expect(response.payload.project).to eq(source_project)
end
end
context 'when actor does not have permission to create pipelines' do
let(:actor) { create(:user) }
it 'returns nothing' do
expect(subject.full_error_messages).to include('Insufficient permissions to create a new pipeline')
it 'responds with error' do
expect(response).to be_error
expect(response.message).to include('Insufficient permissions to create a new pipeline')
end
end
end
......@@ -139,7 +141,7 @@ RSpec.describe MergeRequests::CreatePipelineService do
end
it 'does not create a pipeline' do
expect { subject }.not_to change { Ci::Pipeline.count }
expect { response }.not_to change { Ci::Pipeline.count }
end
end
......@@ -154,7 +156,7 @@ RSpec.describe MergeRequests::CreatePipelineService do
end
it 'does not create a pipeline' do
expect { subject }.not_to change { Ci::Pipeline.count }
expect { response }.not_to change { Ci::Pipeline.count }
end
end
end
......@@ -170,11 +172,12 @@ RSpec.describe MergeRequests::CreatePipelineService do
}
end
it 'creates a detached merge request pipeline' do
expect { subject }.to change { Ci::Pipeline.count }.by(1)
it 'creates a detached merge request pipeline', :aggregate_failures do
expect { response }.to change { Ci::Pipeline.count }.by(1)
expect(subject).to be_persisted
expect(subject).to be_detached_merge_request_pipeline
expect(response).to be_success
expect(response.payload).to be_persisted
expect(response.payload).to be_detached_merge_request_pipeline
end
end
......@@ -188,10 +191,25 @@ RSpec.describe MergeRequests::CreatePipelineService do
}
end
it 'does not create a pipeline' do
expect { subject }.not_to change { Ci::Pipeline.count }
it 'does not create a pipeline', :aggregate_failures do
expect { response }.not_to change { Ci::Pipeline.count }
expect(response).to be_error
end
end
end
context 'when merge request has no commits' do
before do
allow(merge_request).to receive(:has_no_commits?).and_return(true)
end
it 'does not create a pipeline', :aggregate_failures do
expect { response }.not_to change { Ci::Pipeline.count }
expect(response).to be_error
expect(response.message).to eq('Cannot create a pipeline for this merge request.')
expect(response.payload).to be_nil
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