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:
Diffstat (limited to 'spec/services/ci')
-rw-r--r--spec/services/ci/abort_pipelines_service_spec.rb43
-rw-r--r--spec/services/ci/after_requeue_job_service_spec.rb255
-rw-r--r--spec/services/ci/create_downstream_pipeline_service_spec.rb8
-rw-r--r--spec/services/ci/create_pipeline_service/artifacts_spec.rb67
-rw-r--r--spec/services/ci/create_pipeline_service/parameter_content_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service/tags_spec.rb25
-rw-r--r--spec/services/ci/destroy_secure_file_service_spec.rb32
-rw-r--r--spec/services/ci/job_artifacts/create_service_spec.rb2
-rw-r--r--spec/services/ci/parse_dotenv_artifact_service_spec.rb24
-rw-r--r--spec/services/ci/retry_pipeline_service_spec.rb46
-rw-r--r--spec/services/ci/runners/assign_runner_service_spec.rb40
-rw-r--r--spec/services/ci/runners/register_runner_service_spec.rb (renamed from spec/services/ci/register_runner_service_spec.rb)2
-rw-r--r--spec/services/ci/runners/reset_registration_token_service_spec.rb76
-rw-r--r--spec/services/ci/runners/unassign_runner_service_spec.rb43
-rw-r--r--spec/services/ci/runners/unregister_runner_service_spec.rb (renamed from spec/services/ci/unregister_runner_service_spec.rb)4
-rw-r--r--spec/services/ci/runners/update_runner_service_spec.rb (renamed from spec/services/ci/update_runner_service_spec.rb)2
16 files changed, 558 insertions, 113 deletions
diff --git a/spec/services/ci/abort_pipelines_service_spec.rb b/spec/services/ci/abort_pipelines_service_spec.rb
index e31a45cb123..db25faff70f 100644
--- a/spec/services/ci/abort_pipelines_service_spec.rb
+++ b/spec/services/ci/abort_pipelines_service_spec.rb
@@ -7,24 +7,51 @@ RSpec.describe Ci::AbortPipelinesService do
let_it_be(:project) { create(:project, namespace: user.namespace) }
let_it_be(:cancelable_pipeline, reload: true) { create(:ci_pipeline, :running, project: project, user: user) }
- let_it_be(:manual_pipeline, reload: true) { create(:ci_pipeline, status: :manual, project: project, user: user) } # not cancelable
+ let_it_be(:manual_pipeline, reload: true) { create(:ci_pipeline, status: :manual, project: project, user: user) }
let_it_be(:other_users_pipeline, reload: true) { create(:ci_pipeline, :running, project: project, user: create(:user)) } # not this user's pipeline
+
let_it_be(:cancelable_build, reload: true) { create(:ci_build, :running, pipeline: cancelable_pipeline) }
let_it_be(:non_cancelable_build, reload: true) { create(:ci_build, :success, pipeline: cancelable_pipeline) }
let_it_be(:cancelable_stage, reload: true) { create(:ci_stage_entity, name: 'stageA', status: :running, pipeline: cancelable_pipeline, project: project) }
let_it_be(:non_cancelable_stage, reload: true) { create(:ci_stage_entity, name: 'stageB', status: :success, pipeline: cancelable_pipeline, project: project) }
+ let_it_be(:manual_pipeline_cancelable_build, reload: true) { create(:ci_build, :created, pipeline: manual_pipeline) }
+ let_it_be(:manual_pipeline_non_cancelable_build, reload: true) { create(:ci_build, :manual, pipeline: manual_pipeline) }
+ let_it_be(:manual_pipeline_cancelable_stage, reload: true) { create(:ci_stage_entity, name: 'stageA', status: :created, pipeline: manual_pipeline, project: project) }
+ let_it_be(:manual_pipeline_non_cancelable_stage, reload: true) { create(:ci_stage_entity, name: 'stageB', status: :success, pipeline: manual_pipeline, project: project) }
+
describe '#execute' do
- def expect_correct_cancellations
+ def expect_correct_pipeline_cancellations
expect(cancelable_pipeline.finished_at).not_to be_nil
- expect(cancelable_pipeline.status).to eq('failed')
- expect((cancelable_pipeline.stages - [non_cancelable_stage]).map(&:status)).to all(eq('failed'))
- expect(cancelable_build.status).to eq('failed')
+ expect(cancelable_pipeline).to be_failed
+
+ expect(manual_pipeline.finished_at).not_to be_nil
+ expect(manual_pipeline).to be_failed
+ end
+
+ def expect_correct_stage_cancellations
+ expect(cancelable_pipeline.stages - [non_cancelable_stage]).to all(be_failed)
+ expect(manual_pipeline.stages - [manual_pipeline_non_cancelable_stage]).to all(be_failed)
+
+ expect(non_cancelable_stage).not_to be_failed
+ expect(manual_pipeline_non_cancelable_stage).not_to be_failed
+ end
+
+ def expect_correct_build_cancellations
+ expect(cancelable_build).to be_failed
expect(cancelable_build.finished_at).not_to be_nil
- expect(manual_pipeline.status).not_to eq('failed')
- expect(non_cancelable_stage.status).not_to eq('failed')
- expect(non_cancelable_build.status).not_to eq('failed')
+ expect(manual_pipeline_cancelable_build).to be_failed
+ expect(manual_pipeline_cancelable_build.finished_at).not_to be_nil
+
+ expect(non_cancelable_build).not_to be_failed
+ expect(manual_pipeline_non_cancelable_build).not_to be_failed
+ end
+
+ def expect_correct_cancellations
+ expect_correct_pipeline_cancellations
+ expect_correct_stage_cancellations
+ expect_correct_build_cancellations
end
context 'with project pipelines' do
diff --git a/spec/services/ci/after_requeue_job_service_spec.rb b/spec/services/ci/after_requeue_job_service_spec.rb
index d2acf3ad2f1..2f2baa15945 100644
--- a/spec/services/ci/after_requeue_job_service_spec.rb
+++ b/spec/services/ci/after_requeue_job_service_spec.rb
@@ -2,69 +2,236 @@
require 'spec_helper'
-RSpec.describe Ci::AfterRequeueJobService do
- let_it_be(:project) { create(:project) }
+RSpec.describe Ci::AfterRequeueJobService, :sidekiq_inline do
+ let_it_be(:project) { create(:project, :empty_repo) }
let_it_be(:user) { project.first_owner }
- let(:pipeline) { create(:ci_pipeline, project: project) }
+ before_all do
+ project.repository.create_file(user, 'init', 'init', message: 'init', branch_name: 'master')
+ end
- let!(:build1) { create(:ci_build, name: 'build1', pipeline: pipeline, stage_idx: 0) }
- let!(:test1) { create(:ci_build, :success, name: 'test1', pipeline: pipeline, stage_idx: 1) }
- let!(:test2) { create(:ci_build, :skipped, name: 'test2', pipeline: pipeline, stage_idx: 1) }
- let!(:test3) { create(:ci_build, :skipped, :dependent, name: 'test3', pipeline: pipeline, stage_idx: 1, needed: build1) }
- let!(:deploy) { create(:ci_build, :skipped, :dependent, name: 'deploy', pipeline: pipeline, stage_idx: 2, needed: test3) }
+ subject(:service) { described_class.new(project, user) }
- subject(:execute_service) { described_class.new(project, user).execute(build1) }
+ context 'stage-dag mixed pipeline' do
+ let(:config) do
+ <<-EOY
+ stages: [a, b, c]
- shared_examples 'processing subsequent skipped jobs' do
- 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
+ a1:
+ stage: a
+ script: exit $(($RANDOM % 2))
+
+ a2:
+ stage: a
+ script: exit 0
+ needs: [a1]
- execute_service
+ b1:
+ stage: b
+ script: exit 0
+ needs: []
- expect(test1.reload).to be_success
- expect(test2.reload).to be_created
- expect(test3.reload).to be_created
- expect(deploy.reload).to be_created
+ b2:
+ stage: b
+ script: exit 0
+ needs: [a2]
+
+ c1:
+ stage: c
+ script: exit 0
+ needs: [b2]
+
+ c2:
+ stage: c
+ script: exit 0
+ EOY
end
- end
- it_behaves_like 'processing subsequent skipped jobs'
-
- context 'when there is a job need from the same stage' do
- let!(:build2) do
- create(:ci_build,
- :skipped,
- :dependent,
- name: 'build2',
- pipeline: pipeline,
- stage_idx: 0,
- scheduling_type: :dag,
- needed: build1)
+ let(:pipeline) do
+ Ci::CreatePipelineService.new(project, user, { ref: 'master' }).execute(:push).payload
end
- shared_examples 'processing the same stage job' do
- it 'marks subsequent skipped jobs as processable' do
- expect { execute_service }.to change { build2.reload.status }.from('skipped').to('created')
- end
+ let(:a1) { find_job('a1') }
+ let(:b1) { find_job('b1') }
+
+ before do
+ stub_ci_pipeline_yaml_file(config)
+ check_jobs_statuses(
+ a1: 'pending',
+ a2: 'created',
+ b1: 'pending',
+ b2: 'created',
+ c1: 'created',
+ c2: 'created'
+ )
+
+ b1.success!
+ check_jobs_statuses(
+ a1: 'pending',
+ a2: 'created',
+ b1: 'success',
+ b2: 'created',
+ c1: 'created',
+ c2: 'created'
+ )
+
+ a1.drop!
+ check_jobs_statuses(
+ a1: 'failed',
+ a2: 'skipped',
+ b1: 'success',
+ b2: 'skipped',
+ c1: 'skipped',
+ c2: 'skipped'
+ )
+
+ new_a1 = Ci::RetryBuildService.new(project, user).clone!(a1)
+ new_a1.enqueue!
+ check_jobs_statuses(
+ a1: 'pending',
+ a2: 'skipped',
+ b1: 'success',
+ b2: 'skipped',
+ c1: 'skipped',
+ c2: 'skipped'
+ )
end
- it_behaves_like 'processing subsequent skipped jobs'
- it_behaves_like 'processing the same stage job'
+ it 'marks subsequent skipped jobs as processable' do
+ execute_after_requeue_service(a1)
+
+ check_jobs_statuses(
+ a1: 'pending',
+ a2: 'created',
+ b1: 'success',
+ b2: 'created',
+ c1: 'created',
+ c2: 'created'
+ )
+ end
end
- context 'when the pipeline is a downstream pipeline and the bridge is depended' do
- let!(:trigger_job) { create(:ci_bridge, :strategy_depend, name: 'trigger_job', status: 'success') }
+ context 'stage-dag mixed pipeline with some same-stage needs' do
+ let(:config) do
+ <<-EOY
+ stages: [a, b, c]
+
+ a1:
+ stage: a
+ script: exit $(($RANDOM % 2))
+
+ a2:
+ stage: a
+ script: exit 0
+ needs: [a1]
+
+ b1:
+ stage: b
+ script: exit 0
+ needs: [b2]
+
+ b2:
+ stage: b
+ script: exit 0
+
+ c1:
+ stage: c
+ script: exit 0
+ needs: [b2]
+
+ c2:
+ stage: c
+ script: exit 0
+ EOY
+ end
+
+ let(:pipeline) do
+ Ci::CreatePipelineService.new(project, user, { ref: 'master' }).execute(:push).payload
+ end
+
+ let(:a1) { find_job('a1') }
before do
- create(:ci_sources_pipeline, pipeline: pipeline, source_job: trigger_job)
+ stub_ci_pipeline_yaml_file(config)
+ check_jobs_statuses(
+ a1: 'pending',
+ a2: 'created',
+ b1: 'created',
+ b2: 'created',
+ c1: 'created',
+ c2: 'created'
+ )
+
+ a1.drop!
+ check_jobs_statuses(
+ a1: 'failed',
+ a2: 'skipped',
+ b1: 'skipped',
+ b2: 'skipped',
+ c1: 'skipped',
+ c2: 'skipped'
+ )
+
+ new_a1 = Ci::RetryBuildService.new(project, user).clone!(a1)
+ new_a1.enqueue!
+ check_jobs_statuses(
+ a1: 'pending',
+ a2: 'skipped',
+ b1: 'skipped',
+ b2: 'skipped',
+ c1: 'skipped',
+ c2: 'skipped'
+ )
end
- it 'marks source bridge as pending' do
- expect { execute_service }.to change { trigger_job.reload.status }.from('success').to('pending')
+ it 'marks subsequent skipped jobs as processable' do
+ execute_after_requeue_service(a1)
+
+ check_jobs_statuses(
+ a1: 'pending',
+ a2: 'created',
+ b1: 'created',
+ b2: 'created',
+ c1: 'created',
+ c2: 'created'
+ )
+ end
+
+ context 'when the FF ci_fix_order_of_subsequent_jobs is disabled' do
+ before do
+ stub_feature_flags(ci_fix_order_of_subsequent_jobs: false)
+ end
+
+ it 'does not mark b1 as processable' do
+ execute_after_requeue_service(a1)
+
+ check_jobs_statuses(
+ a1: 'pending',
+ a2: 'created',
+ b1: 'skipped',
+ b2: 'created',
+ c1: 'created',
+ c2: 'created'
+ )
+ end
end
end
+
+ private
+
+ def find_job(name)
+ processables.find_by!(name: name)
+ end
+
+ def check_jobs_statuses(statuses)
+ expect(processables.order(:name).pluck(:name, :status)).to contain_exactly(*statuses.stringify_keys.to_a)
+ end
+
+ def processables
+ pipeline.processables.latest
+ end
+
+ def execute_after_requeue_service(processable)
+ service.execute(processable)
+ 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 43eb57df66c..6142704b00e 100644
--- a/spec/services/ci/create_downstream_pipeline_service_spec.rb
+++ b/spec/services/ci/create_downstream_pipeline_service_spec.rb
@@ -485,14 +485,6 @@ RSpec.describe Ci::CreateDownstreamPipelineService, '#execute' do
end
it_behaves_like 'detects cyclical pipelines'
-
- context 'when ci_drop_cyclical_triggered_pipelines is not enabled' do
- before do
- stub_feature_flags(ci_drop_cyclical_triggered_pipelines: false)
- end
-
- it_behaves_like 'passes cyclical pipeline precondition'
- end
end
context 'when source in the ancestry differ' do
diff --git a/spec/services/ci/create_pipeline_service/artifacts_spec.rb b/spec/services/ci/create_pipeline_service/artifacts_spec.rb
new file mode 100644
index 00000000000..1ec30d68666
--- /dev/null
+++ b/spec/services/ci/create_pipeline_service/artifacts_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Ci::CreatePipelineService do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { project.first_owner }
+
+ let(:ref) { 'refs/heads/master' }
+ let(:source) { :push }
+
+ let(:service) { described_class.new(project, user, { ref: ref }) }
+ let(:pipeline) { service.execute(source).payload }
+
+ describe 'artifacts:' do
+ before do
+ stub_ci_pipeline_yaml_file(config)
+ allow_next_instance_of(Ci::BuildScheduleWorker) do |instance|
+ allow(instance).to receive(:perform).and_return(true)
+ end
+ end
+
+ describe 'reports:' do
+ context 'with valid config' do
+ let(:config) do
+ <<~YAML
+ test-job:
+ script: "echo 'hello world' > cobertura.xml"
+ artifacts:
+ reports:
+ coverage_report:
+ coverage_format: 'cobertura'
+ path: 'cobertura.xml'
+
+ dependency-scanning-job:
+ script: "echo 'hello world' > gl-dependency-scanning-report.json"
+ artifacts:
+ reports:
+ dependency_scanning: 'gl-dependency-scanning-report.json'
+ YAML
+ end
+
+ it 'creates pipeline with builds' do
+ expect(pipeline).to be_persisted
+ expect(pipeline).not_to have_yaml_errors
+ expect(pipeline.builds.pluck(:name)).to contain_exactly('test-job', 'dependency-scanning-job')
+ end
+ end
+
+ context 'with invalid config' do
+ let(:config) do
+ <<~YAML
+ test-job:
+ script: "echo 'hello world' > cobertura.xml"
+ artifacts:
+ reports:
+ foo: 'bar'
+ YAML
+ end
+
+ it 'creates pipeline with yaml errors' do
+ expect(pipeline).to be_persisted
+ expect(pipeline).to have_yaml_errors
+ end
+ end
+ end
+ end
+end
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 c28bc9d8c13..f593707f460 100644
--- a/spec/services/ci/create_pipeline_service/parameter_content_spec.rb
+++ b/spec/services/ci/create_pipeline_service/parameter_content_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe Ci::CreatePipelineService do
variables:
DAST_VERSION: 1
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
+ SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/security-products"
dast:
stage: dast
diff --git a/spec/services/ci/create_pipeline_service/tags_spec.rb b/spec/services/ci/create_pipeline_service/tags_spec.rb
index 61c2415fa33..0774f9fff2a 100644
--- a/spec/services/ci/create_pipeline_service/tags_spec.rb
+++ b/spec/services/ci/create_pipeline_service/tags_spec.rb
@@ -81,31 +81,6 @@ RSpec.describe Ci::CreatePipelineService do
end
end
- context 'when the feature flag is disabled' do
- before do
- stub_feature_flags(ci_bulk_insert_tags: false)
- end
-
- it 'executes N+1s queries' do
- stub_yaml_config(config_without_tags)
-
- # warm up the cached objects so we get a more accurate count
- create_pipeline
-
- control = ActiveRecord::QueryRecorder.new(skip_cached: false) do
- create_pipeline
- end
-
- stub_yaml_config(config)
-
- expect { pipeline }
- .to exceed_all_query_limit(control)
- .with_threshold(4)
-
- expect(pipeline).to be_created_successfully
- end
- end
-
context 'when tags are already persisted' do
it 'does not execute N+1 queries' do
# warm up the cached objects so we get a more accurate count
diff --git a/spec/services/ci/destroy_secure_file_service_spec.rb b/spec/services/ci/destroy_secure_file_service_spec.rb
new file mode 100644
index 00000000000..6a30d33f4ca
--- /dev/null
+++ b/spec/services/ci/destroy_secure_file_service_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Ci::DestroySecureFileService do
+ let_it_be(:maintainer_user) { create(:user) }
+ let_it_be(:developer_user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:secure_file) { create(:ci_secure_file, project: project) }
+ let_it_be(:project_member) { create(:project_member, :maintainer, user: maintainer_user, project: project) }
+ let_it_be(:project_member2) { create(:project_member, :developer, user: developer_user, project: project) }
+
+ subject { described_class.new(project, user).execute(secure_file) }
+
+ context 'user is a maintainer' do
+ let(:user) { maintainer_user }
+
+ it 'destroys the secure file' do
+ subject
+
+ expect { secure_file.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+
+ context 'user is a developer' do
+ let(:user) { developer_user }
+
+ it 'raises an exception' do
+ expect { subject }.to raise_error(Gitlab::Access::AccessDeniedError)
+ end
+ end
+end
diff --git a/spec/services/ci/job_artifacts/create_service_spec.rb b/spec/services/ci/job_artifacts/create_service_spec.rb
index 2d309bfe425..b8487e438a9 100644
--- a/spec/services/ci/job_artifacts/create_service_spec.rb
+++ b/spec/services/ci/job_artifacts/create_service_spec.rb
@@ -175,7 +175,7 @@ RSpec.describe Ci::JobArtifacts::CreateService do
end
expect(subject[:status]).to eq(:success)
- expect(job.job_variables.as_json).to contain_exactly(
+ expect(job.job_variables.as_json(only: [:key, :value, :source])).to contain_exactly(
hash_including('key' => 'KEY1', 'value' => 'VAR1', 'source' => 'dotenv'),
hash_including('key' => 'KEY2', 'value' => 'VAR2', 'source' => 'dotenv'))
end
diff --git a/spec/services/ci/parse_dotenv_artifact_service_spec.rb b/spec/services/ci/parse_dotenv_artifact_service_spec.rb
index 6bf22b7c8b2..aaab849cd93 100644
--- a/spec/services/ci/parse_dotenv_artifact_service_spec.rb
+++ b/spec/services/ci/parse_dotenv_artifact_service_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe Ci::ParseDotenvArtifactService do
it 'parses the artifact' do
expect(subject[:status]).to eq(:success)
- expect(build.job_variables.as_json).to contain_exactly(
+ expect(build.job_variables.as_json(only: [:key, :value])).to contain_exactly(
hash_including('key' => 'KEY1', 'value' => 'VAR1'),
hash_including('key' => 'KEY2', 'value' => 'VAR2'))
end
@@ -57,7 +57,7 @@ RSpec.describe Ci::ParseDotenvArtifactService do
expect(subject[:status]).to eq(:success)
- expect(build.job_variables.as_json).to contain_exactly(
+ expect(build.job_variables.as_json(only: [:key, :value])).to contain_exactly(
hash_including('key' => 'KEY1', 'value' => 'VAR4'),
hash_including('key' => 'KEY2', 'value' => 'VAR3'))
end
@@ -101,7 +101,7 @@ RSpec.describe Ci::ParseDotenvArtifactService do
it 'trims the trailing space' do
subject
- expect(build.job_variables.as_json).to contain_exactly(
+ expect(build.job_variables.as_json(only: [:key, :value])).to contain_exactly(
hash_including('key' => 'KEY1', 'value' => 'VAR1'))
end
end
@@ -112,7 +112,7 @@ RSpec.describe Ci::ParseDotenvArtifactService do
it 'parses the dotenv data' do
subject
- expect(build.job_variables.as_json).to contain_exactly(
+ expect(build.job_variables.as_json(only: [:key, :value])).to contain_exactly(
hash_including('key' => 'KEY', 'value' => 'VARCONTAINING=EQLS'))
end
end
@@ -133,7 +133,7 @@ RSpec.describe Ci::ParseDotenvArtifactService do
it 'parses the dotenv data' do
subject
- expect(build.job_variables.as_json).to contain_exactly(
+ expect(build.job_variables.as_json(only: [:key, :value])).to contain_exactly(
hash_including('key' => 'skateboard', 'value' => '🛹'))
end
end
@@ -154,7 +154,7 @@ RSpec.describe Ci::ParseDotenvArtifactService do
it 'parses the dotenv data' do
subject
- expect(build.job_variables.as_json).to contain_exactly(
+ expect(build.job_variables.as_json(only: [:key, :value])).to contain_exactly(
hash_including('key' => 'KEY1', 'value' => 'V A R 1'))
end
end
@@ -165,7 +165,7 @@ RSpec.describe Ci::ParseDotenvArtifactService do
it 'parses the value as-is' do
subject
- expect(build.job_variables.as_json).to contain_exactly(
+ expect(build.job_variables.as_json(only: [:key, :value])).to contain_exactly(
hash_including('key' => 'KEY1', 'value' => '"VAR1"'))
end
end
@@ -176,7 +176,7 @@ RSpec.describe Ci::ParseDotenvArtifactService do
it 'parses the value as-is' do
subject
- expect(build.job_variables.as_json).to contain_exactly(
+ expect(build.job_variables.as_json(only: [:key, :value])).to contain_exactly(
hash_including('key' => 'KEY1', 'value' => "'VAR1'"))
end
end
@@ -187,7 +187,7 @@ RSpec.describe Ci::ParseDotenvArtifactService do
it 'parses the value as-is' do
subject
- expect(build.job_variables.as_json).to contain_exactly(
+ expect(build.job_variables.as_json(only: [:key, :value])).to contain_exactly(
hash_including('key' => 'KEY1', 'value' => '" VAR1 "'))
end
end
@@ -208,7 +208,7 @@ RSpec.describe Ci::ParseDotenvArtifactService do
it 'parses the dotenv data' do
subject
- expect(build.job_variables.as_json).to contain_exactly(
+ expect(build.job_variables.as_json(only: [:key, :value])).to contain_exactly(
hash_including('key' => 'KEY1', 'value' => ''))
end
end
@@ -250,7 +250,7 @@ RSpec.describe Ci::ParseDotenvArtifactService do
it 'does not support variable expansion in dotenv parser' do
subject
- expect(build.job_variables.as_json).to contain_exactly(
+ expect(build.job_variables.as_json(only: [:key, :value])).to contain_exactly(
hash_including('key' => 'KEY1', 'value' => 'VAR1'),
hash_including('key' => 'KEY2', 'value' => '${KEY1}_Test'))
end
@@ -284,7 +284,7 @@ RSpec.describe Ci::ParseDotenvArtifactService do
it 'does not support comment in dotenv parser' do
subject
- expect(build.job_variables.as_json).to contain_exactly(
+ expect(build.job_variables.as_json(only: [:key, :value])).to contain_exactly(
hash_including('key' => 'KEY1', 'value' => 'VAR1 # This is variable'))
end
end
diff --git a/spec/services/ci/retry_pipeline_service_spec.rb b/spec/services/ci/retry_pipeline_service_spec.rb
index 12106b70969..df1e159b5c0 100644
--- a/spec/services/ci/retry_pipeline_service_spec.rb
+++ b/spec/services/ci/retry_pipeline_service_spec.rb
@@ -137,7 +137,7 @@ RSpec.describe Ci::RetryPipelineService, '#execute' do
end
end
- context 'when the last stage was skipepd' do
+ context 'when the last stage was skipped' do
before do
create_build('build 1', :success, 0)
create_build('test 2', :failed, 1)
@@ -336,12 +336,32 @@ RSpec.describe Ci::RetryPipelineService, '#execute' do
expect(pipeline.reload).to be_running
end
end
+
+ context 'when user is not allowed to retry build' do
+ before do
+ build = create(:ci_build, pipeline: pipeline, status: :failed)
+ allow_next_instance_of(Ci::RetryBuildService) do |service|
+ allow(service).to receive(:can?).with(user, :update_build, build).and_return(false)
+ end
+ end
+
+ it 'returns an error' do
+ response = service.execute(pipeline)
+
+ expect(response.http_status).to eq(:forbidden)
+ expect(response.errors).to include('403 Forbidden')
+ expect(pipeline.reload).not_to be_running
+ end
+ end
end
context 'when user is not allowed to retry pipeline' do
- it 'raises an error' do
- expect { service.execute(pipeline) }
- .to raise_error Gitlab::Access::AccessDeniedError
+ it 'returns an error' do
+ response = service.execute(pipeline)
+
+ expect(response.http_status).to eq(:forbidden)
+ expect(response.errors).to include('403 Forbidden')
+ expect(pipeline.reload).not_to be_running
end
end
@@ -359,9 +379,12 @@ RSpec.describe Ci::RetryPipelineService, '#execute' do
create_build('verify', :canceled, 1)
end
- it 'raises an error' do
- expect { service.execute(pipeline) }
- .to raise_error Gitlab::Access::AccessDeniedError
+ it 'returns an error' do
+ response = service.execute(pipeline)
+
+ expect(response.http_status).to eq(:forbidden)
+ expect(response.errors).to include('403 Forbidden')
+ expect(pipeline.reload).not_to be_running
end
end
@@ -372,9 +395,12 @@ RSpec.describe Ci::RetryPipelineService, '#execute' do
create_build('verify', :canceled, 2)
end
- it 'raises an error' do
- expect { service.execute(pipeline) }
- .to raise_error Gitlab::Access::AccessDeniedError
+ it 'returns an error' do
+ response = service.execute(pipeline)
+
+ expect(response.http_status).to eq(:forbidden)
+ expect(response.errors).to include('403 Forbidden')
+ expect(pipeline.reload).not_to be_running
end
end
end
diff --git a/spec/services/ci/runners/assign_runner_service_spec.rb b/spec/services/ci/runners/assign_runner_service_spec.rb
new file mode 100644
index 00000000000..00b176bb759
--- /dev/null
+++ b/spec/services/ci/runners/assign_runner_service_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Ci::Runners::AssignRunnerService, '#execute' do
+ subject { described_class.new(runner, project, user).execute }
+
+ let_it_be(:runner) { create(:ci_runner, :project, projects: [project]) }
+ let_it_be(:project) { create(:project) }
+
+ context 'without user' do
+ let(:user) { nil }
+
+ it 'does not call assign_to on runner and returns false' do
+ expect(runner).not_to receive(:assign_to)
+
+ is_expected.to eq(false)
+ end
+ end
+
+ context 'with unauthorized user' do
+ let(:user) { build(:user) }
+
+ it 'does not call assign_to on runner and returns false' do
+ expect(runner).not_to receive(:assign_to)
+
+ is_expected.to eq(false)
+ end
+ end
+
+ context 'with admin user', :enable_admin_mode do
+ let(:user) { create_default(:user, :admin) }
+
+ it 'calls assign_to on runner and returns value unchanged' do
+ expect(runner).to receive(:assign_to).with(project, user).once.and_return('assign_to return value')
+
+ is_expected.to eq('assign_to return value')
+ end
+ end
+end
diff --git a/spec/services/ci/register_runner_service_spec.rb b/spec/services/ci/runners/register_runner_service_spec.rb
index 491582bbd13..f43fd823078 100644
--- a/spec/services/ci/register_runner_service_spec.rb
+++ b/spec/services/ci/runners/register_runner_service_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe ::Ci::RegisterRunnerService, '#execute' do
+RSpec.describe ::Ci::Runners::RegisterRunnerService, '#execute' do
let(:registration_token) { 'abcdefg123456' }
let(:token) { }
let(:args) { {} }
diff --git a/spec/services/ci/runners/reset_registration_token_service_spec.rb b/spec/services/ci/runners/reset_registration_token_service_spec.rb
new file mode 100644
index 00000000000..c4bfff51cc8
--- /dev/null
+++ b/spec/services/ci/runners/reset_registration_token_service_spec.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Ci::Runners::ResetRegistrationTokenService, '#execute' do
+ subject { described_class.new(scope, current_user).execute }
+
+ let_it_be(:user) { build(:user) }
+ let_it_be(:admin_user) { create(:user, :admin) }
+
+ shared_examples 'a registration token reset operation' do
+ context 'without user' do
+ let(:current_user) { nil }
+
+ it 'does not reset registration token and returns nil' do
+ expect(scope).not_to receive(token_reset_method_name)
+
+ is_expected.to be_nil
+ end
+ end
+
+ context 'with unauthorized user' do
+ let(:current_user) { user }
+
+ it 'does not reset registration token and returns nil' do
+ expect(scope).not_to receive(token_reset_method_name)
+
+ is_expected.to be_nil
+ end
+ end
+
+ context 'with admin user', :enable_admin_mode do
+ let(:current_user) { admin_user }
+
+ it 'resets registration token and returns value unchanged' do
+ expect(scope).to receive(token_reset_method_name).once do
+ expect(scope).to receive(token_method_name).once.and_return("#{token_method_name} return value")
+ end
+
+ is_expected.to eq("#{token_method_name} return value")
+ end
+ end
+ end
+
+ context 'with instance scope' do
+ let_it_be(:scope) { create(:application_setting) }
+
+ before do
+ allow(ApplicationSetting).to receive(:current).and_return(scope)
+ allow(ApplicationSetting).to receive(:current_without_cache).and_return(scope)
+ end
+
+ it_behaves_like 'a registration token reset operation' do
+ let(:token_method_name) { :runners_registration_token }
+ let(:token_reset_method_name) { :reset_runners_registration_token! }
+ end
+ end
+
+ context 'with group scope' do
+ let_it_be(:scope) { create(:group) }
+
+ it_behaves_like 'a registration token reset operation' do
+ let(:token_method_name) { :runners_token }
+ let(:token_reset_method_name) { :reset_runners_token! }
+ end
+ end
+
+ context 'with project scope' do
+ let_it_be(:scope) { create(:project) }
+
+ it_behaves_like 'a registration token reset operation' do
+ let(:token_method_name) { :runners_token }
+ let(:token_reset_method_name) { :reset_runners_token! }
+ end
+ end
+end
diff --git a/spec/services/ci/runners/unassign_runner_service_spec.rb b/spec/services/ci/runners/unassign_runner_service_spec.rb
new file mode 100644
index 00000000000..3fb6925f4bd
--- /dev/null
+++ b/spec/services/ci/runners/unassign_runner_service_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Ci::Runners::UnassignRunnerService, '#execute' do
+ subject(:service) { described_class.new(runner_project, user).execute }
+
+ let_it_be(:runner) { create(:ci_runner, :project, projects: [project]) }
+ let_it_be(:project) { create(:project) }
+
+ let(:runner_project) { runner.runner_projects.last }
+
+ context 'without user' do
+ let(:user) { nil }
+
+ it 'does not destroy runner_project', :aggregate_failures do
+ expect(runner_project).not_to receive(:destroy)
+ expect { service }.not_to change { runner.runner_projects.count }.from(1)
+
+ is_expected.to eq(false)
+ end
+ end
+
+ context 'with unauthorized user' do
+ let(:user) { build(:user) }
+
+ it 'does not call destroy on runner_project' do
+ expect(runner).not_to receive(:destroy)
+
+ service
+ end
+ end
+
+ context 'with admin user', :enable_admin_mode do
+ let(:user) { create_default(:user, :admin) }
+
+ it 'destroys runner_project' do
+ expect(runner_project).to receive(:destroy).once
+
+ service
+ end
+ end
+end
diff --git a/spec/services/ci/unregister_runner_service_spec.rb b/spec/services/ci/runners/unregister_runner_service_spec.rb
index f427e04f228..df1a0a90067 100644
--- a/spec/services/ci/unregister_runner_service_spec.rb
+++ b/spec/services/ci/runners/unregister_runner_service_spec.rb
@@ -2,8 +2,8 @@
require 'spec_helper'
-RSpec.describe ::Ci::UnregisterRunnerService, '#execute' do
- subject { described_class.new(runner).execute }
+RSpec.describe ::Ci::Runners::UnregisterRunnerService, '#execute' do
+ subject { described_class.new(runner, 'some_token').execute }
let(:runner) { create(:ci_runner) }
diff --git a/spec/services/ci/update_runner_service_spec.rb b/spec/services/ci/runners/update_runner_service_spec.rb
index eee80bfef47..b02ea8f58b0 100644
--- a/spec/services/ci/update_runner_service_spec.rb
+++ b/spec/services/ci/runners/update_runner_service_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Ci::UpdateRunnerService do
+RSpec.describe Ci::Runners::UpdateRunnerService do
let(:runner) { create(:ci_runner) }
describe '#update' do