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/models/ci')
-rw-r--r--spec/models/ci/build_spec.rb209
-rw-r--r--spec/models/ci/build_trace_metadata_spec.rb10
-rw-r--r--spec/models/ci/build_trace_section_name_spec.rb14
-rw-r--r--spec/models/ci/build_trace_section_spec.rb13
-rw-r--r--spec/models/ci/build_trace_spec.rb10
-rw-r--r--spec/models/ci/pending_build_spec.rb28
-rw-r--r--spec/models/ci/pipeline_spec.rb50
-rw-r--r--spec/models/ci/resource_spec.rb52
-rw-r--r--spec/models/ci/runner_namespace_spec.rb6
-rw-r--r--spec/models/ci/runner_project_spec.rb6
10 files changed, 239 insertions, 159 deletions
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 0c344270e0b..26abc98656e 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -20,7 +20,6 @@ RSpec.describe Ci::Build do
it { is_expected.to belong_to(:trigger_request) }
it { is_expected.to belong_to(:erased_by) }
- it { is_expected.to have_many(:trace_sections) }
it { is_expected.to have_many(:needs) }
it { is_expected.to have_many(:sourced_pipelines) }
it { is_expected.to have_many(:job_variables) }
@@ -29,6 +28,7 @@ RSpec.describe Ci::Build do
it { is_expected.to have_one(:deployment) }
it { is_expected.to have_one(:runner_session) }
+ it { is_expected.to have_one(:trace_metadata) }
it { is_expected.to validate_presence_of(:ref) }
@@ -345,12 +345,9 @@ RSpec.describe Ci::Build do
end
describe '#stick_build_if_status_changed' do
- it 'sticks the build if the status changed' do
+ it 'sticks the build if the status changed', :db_load_balancing do
job = create(:ci_build, :pending)
- allow(Gitlab::Database::LoadBalancing).to receive(:enable?)
- .and_return(true)
-
expect(Gitlab::Database::LoadBalancing::Sticking).to receive(:stick)
.with(:build, job.id)
@@ -1105,17 +1102,6 @@ RSpec.describe Ci::Build do
end
end
- describe '#parse_trace_sections!' do
- it 'calls ExtractSectionsFromBuildTraceService' do
- expect(Ci::ExtractSectionsFromBuildTraceService)
- .to receive(:new).with(project, build.user).once.and_call_original
- expect_any_instance_of(Ci::ExtractSectionsFromBuildTraceService)
- .to receive(:execute).with(build).once
-
- build.parse_trace_sections!
- end
- end
-
describe '#trace' do
subject { build.trace }
@@ -1955,17 +1941,7 @@ RSpec.describe Ci::Build do
described_class.retry(build, user)
end
- context 'when prevent_retry_of_retried_jobs feature flag is enabled' do
- it { is_expected.not_to be_retryable }
- end
-
- context 'when prevent_retry_of_retried_jobs feature flag is disabled' do
- before do
- stub_feature_flags(prevent_retry_of_retried_jobs: false)
- end
-
- it { is_expected.to be_retryable }
- end
+ it { is_expected.not_to be_retryable }
end
end
end
@@ -2214,34 +2190,12 @@ RSpec.describe Ci::Build do
expect(build.options['image']).to be_nil
end
- context 'when ci_build_metadata_config is set' do
- before do
- stub_feature_flags(ci_build_metadata_config: true)
- end
-
- it 'persist data in build metadata' do
- expect(build.metadata.read_attribute(:config_options)).to eq(options.symbolize_keys)
- end
-
- it 'does not persist data in build' do
- expect(build.read_attribute(:options)).to be_nil
- end
+ it 'persist data in build metadata' do
+ expect(build.metadata.read_attribute(:config_options)).to eq(options.symbolize_keys)
end
- context 'when ci_build_metadata_config is disabled' do
- let(:build) { create(:ci_build, pipeline: pipeline) }
-
- before do
- stub_feature_flags(ci_build_metadata_config: false)
- end
-
- it 'persist data in build' do
- expect(build.read_attribute(:options)).to eq(options.symbolize_keys)
- end
-
- it 'does not persist data in build metadata' do
- expect(build.metadata.read_attribute(:config_options)).to be_nil
- end
+ it 'does not persist data in build' do
+ expect(build.read_attribute(:options)).to be_nil
end
context 'when options include artifacts:expose_as' do
@@ -2668,6 +2622,7 @@ RSpec.describe Ci::Build do
{ key: 'CI_PROJECT_URL', value: project.web_url, public: true, masked: false },
{ key: 'CI_PROJECT_VISIBILITY', value: 'private', public: true, masked: false },
{ key: 'CI_PROJECT_REPOSITORY_LANGUAGES', value: project.repository_languages.map(&:name).join(',').downcase, public: true, masked: false },
+ { key: 'CI_PROJECT_CLASSIFICATION_LABEL', value: project.external_authorization_classification_label, public: true, masked: false },
{ key: 'CI_DEFAULT_BRANCH', value: project.default_branch, public: true, masked: false },
{ key: 'CI_CONFIG_PATH', value: project.ci_config_path_or_default, public: true, masked: false },
{ key: 'CI_PAGES_DOMAIN', value: Gitlab.config.pages.host, public: true, masked: false },
@@ -3195,6 +3150,17 @@ RSpec.describe Ci::Build do
end
context 'when container registry is enabled' do
+ let_it_be_with_reload(:project) { create(:project, :public, :repository, group: group) }
+
+ let_it_be_with_reload(:pipeline) do
+ create(:ci_pipeline, project: project,
+ sha: project.commit.id,
+ ref: project.default_branch,
+ status: 'success')
+ end
+
+ let_it_be_with_refind(:build) { create(:ci_build, pipeline: pipeline) }
+
let(:container_registry_enabled) { true }
let(:ci_registry) do
{ key: 'CI_REGISTRY', value: 'registry.example.com', public: true, masked: false }
@@ -3206,7 +3172,7 @@ RSpec.describe Ci::Build do
context 'and is disabled for project' do
before do
- project.update!(container_registry_enabled: false)
+ project.project_feature.update_column(:container_registry_access_level, ProjectFeature::DISABLED)
end
it { is_expected.to include(ci_registry) }
@@ -3215,7 +3181,16 @@ RSpec.describe Ci::Build do
context 'and is enabled for project' do
before do
- project.update!(container_registry_enabled: true)
+ project.project_feature.update_column(:container_registry_access_level, ProjectFeature::ENABLED)
+ end
+
+ it { is_expected.to include(ci_registry) }
+ it { is_expected.to include(ci_registry_image) }
+ end
+
+ context 'and is private for project' do
+ before do
+ project.project_feature.update_column(:container_registry_access_level, ProjectFeature::PRIVATE)
end
it { is_expected.to include(ci_registry) }
@@ -3613,36 +3588,14 @@ RSpec.describe Ci::Build do
end
end
- context 'when ci_build_metadata_config is set' do
- before do
- stub_feature_flags(ci_build_metadata_config: true)
- end
-
- it_behaves_like 'having consistent representation'
-
- it 'persist data in build metadata' do
- expect(build.metadata.read_attribute(:config_variables)).not_to be_nil
- end
+ it_behaves_like 'having consistent representation'
- it 'does not persist data in build' do
- expect(build.read_attribute(:yaml_variables)).to be_nil
- end
+ it 'persist data in build metadata' do
+ expect(build.metadata.read_attribute(:config_variables)).not_to be_nil
end
- context 'when ci_build_metadata_config is disabled' do
- before do
- stub_feature_flags(ci_build_metadata_config: false)
- end
-
- it_behaves_like 'having consistent representation'
-
- it 'persist data in build' do
- expect(build.read_attribute(:yaml_variables)).not_to be_nil
- end
-
- it 'does not persist data in build metadata' do
- expect(build.metadata.read_attribute(:config_variables)).to be_nil
- end
+ it 'does not persist data in build' do
+ expect(build.read_attribute(:yaml_variables)).to be_nil
end
end
@@ -3727,7 +3680,7 @@ RSpec.describe Ci::Build do
it 'ensures that it is not run in database transaction' do
expect(job.pipeline.persistent_ref).to receive(:create) do
- expect(Gitlab::Database).not_to be_inside_transaction
+ expect(Gitlab::Database.main).not_to be_inside_transaction
end
run_job_without_exception
@@ -3792,7 +3745,21 @@ RSpec.describe Ci::Build do
context 'when artifacts of depended job has been expired' do
let!(:pre_stage_job) { create(:ci_build, :success, :expired, pipeline: pipeline, name: 'test', stage_idx: 0) }
- it { expect(job).not_to have_valid_build_dependencies }
+ context 'when pipeline is not locked' do
+ before do
+ build.pipeline.unlocked!
+ end
+
+ it { expect(job).not_to have_valid_build_dependencies }
+ end
+
+ context 'when pipeline is locked' do
+ before do
+ build.pipeline.artifacts_locked!
+ end
+
+ it { expect(job).to have_valid_build_dependencies }
+ end
end
context 'when artifacts of depended job has been erased' do
@@ -4788,51 +4755,21 @@ RSpec.describe Ci::Build do
subject { build.send(:write_metadata_attribute, :options, :config_options, options) }
- context 'when ci_build_metadata_config is set' do
+ context 'when data in build is already set' do
before do
- stub_feature_flags(ci_build_metadata_config: true)
+ build.write_attribute(:options, existing_options)
end
- context 'when data in build is already set' do
- before do
- build.write_attribute(:options, existing_options)
- end
-
- it 'does set metadata options' do
- subject
-
- expect(build.metadata.read_attribute(:config_options)).to eq(options)
- end
-
- it 'does reset build options' do
- subject
-
- expect(build.read_attribute(:options)).to be_nil
- end
- end
- end
+ it 'does set metadata options' do
+ subject
- context 'when ci_build_metadata_config is disabled' do
- before do
- stub_feature_flags(ci_build_metadata_config: false)
+ expect(build.metadata.read_attribute(:config_options)).to eq(options)
end
- context 'when data in build metadata is already set' do
- before do
- build.ensure_metadata.write_attribute(:config_options, existing_options)
- end
-
- it 'does set metadata options' do
- subject
-
- expect(build.read_attribute(:options)).to eq(options)
- end
-
- it 'does reset build options' do
- subject
+ it 'does reset build options' do
+ subject
- expect(build.metadata.read_attribute(:config_options)).to be_nil
- end
+ expect(build.read_attribute(:options)).to be_nil
end
end
end
@@ -4842,8 +4779,24 @@ RSpec.describe Ci::Build do
let!(:pre_stage_job_invalid) { create(:ci_build, :success, :expired, pipeline: pipeline, name: 'test2', stage_idx: 1) }
let!(:job) { create(:ci_build, :pending, pipeline: pipeline, stage_idx: 2, options: { dependencies: %w(test1 test2) }) }
- it 'returns invalid dependencies' do
- expect(job.invalid_dependencies).to eq([pre_stage_job_invalid])
+ context 'when pipeline is locked' do
+ before do
+ build.pipeline.unlocked!
+ end
+
+ it 'returns invalid dependencies when expired' do
+ expect(job.invalid_dependencies).to eq([pre_stage_job_invalid])
+ end
+ end
+
+ context 'when pipeline is not locked' do
+ before do
+ build.pipeline.artifacts_locked!
+ end
+
+ it 'returns no invalid dependencies when expired' do
+ expect(job.invalid_dependencies).to eq([])
+ end
end
end
@@ -5267,6 +5220,14 @@ RSpec.describe Ci::Build do
end
end
+ describe '.with_project_and_metadata' do
+ it 'does not join across databases' do
+ with_cross_joins_prevented do
+ ::Ci::Build.with_project_and_metadata.to_a
+ end
+ end
+ end
+
describe '.without_coverage' do
let!(:build_with_coverage) { create(:ci_build, pipeline: pipeline, coverage: 100.0) }
diff --git a/spec/models/ci/build_trace_metadata_spec.rb b/spec/models/ci/build_trace_metadata_spec.rb
new file mode 100644
index 00000000000..42b9d5d34b6
--- /dev/null
+++ b/spec/models/ci/build_trace_metadata_spec.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::BuildTraceMetadata do
+ it { is_expected.to belong_to(:build) }
+ it { is_expected.to belong_to(:trace_artifact) }
+
+ it { is_expected.to validate_presence_of(:build) }
+end
diff --git a/spec/models/ci/build_trace_section_name_spec.rb b/spec/models/ci/build_trace_section_name_spec.rb
deleted file mode 100644
index b220e67d48e..00000000000
--- a/spec/models/ci/build_trace_section_name_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Ci::BuildTraceSectionName, model: true do
- subject { build(:ci_build_trace_section_name) }
-
- it { is_expected.to belong_to(:project) }
- it { is_expected.to have_many(:trace_sections)}
-
- it { is_expected.to validate_presence_of(:project) }
- it { is_expected.to validate_presence_of(:name) }
- it { is_expected.to validate_uniqueness_of(:name).scoped_to(:project_id) }
-end
diff --git a/spec/models/ci/build_trace_section_spec.rb b/spec/models/ci/build_trace_section_spec.rb
deleted file mode 100644
index 640bd202b3a..00000000000
--- a/spec/models/ci/build_trace_section_spec.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Ci::BuildTraceSection, model: true do
- it { is_expected.to belong_to(:build)}
- it { is_expected.to belong_to(:project)}
- it { is_expected.to belong_to(:section_name)}
-
- it { is_expected.to validate_presence_of(:section_name) }
- it { is_expected.to validate_presence_of(:build) }
- it { is_expected.to validate_presence_of(:project) }
-end
diff --git a/spec/models/ci/build_trace_spec.rb b/spec/models/ci/build_trace_spec.rb
index 3beca0565c6..bd24e8be1ac 100644
--- a/spec/models/ci/build_trace_spec.rb
+++ b/spec/models/ci/build_trace_spec.rb
@@ -32,4 +32,14 @@ RSpec.describe Ci::BuildTrace do
{ offset: 0, content: [{ text: 'the-stream' }] }
])
end
+
+ context 'with invalid UTF-8 data' do
+ let(:data) { StringIO.new("UTF-8 dashes here: ā”€ā”€ā”€\nšŸ¤šŸ¤šŸ¤šŸ¤\xF0\x9F\x90\n") }
+
+ it 'returns valid UTF-8 data', :aggregate_failures do
+ expect(subject.lines[0]).to eq({ offset: 0, content: [{ text: 'UTF-8 dashes here: ā”€ā”€ā”€' }] } )
+ # Each of the dashes is 3 bytes, so we get 19 + 9 + 1 = 29
+ expect(subject.lines[1]).to eq({ offset: 29, content: [{ text: 'šŸ¤šŸ¤šŸ¤šŸ¤ļæ½' }] } )
+ end
+ end
end
diff --git a/spec/models/ci/pending_build_spec.rb b/spec/models/ci/pending_build_spec.rb
index b64f3999232..0518c9a1652 100644
--- a/spec/models/ci/pending_build_spec.rb
+++ b/spec/models/ci/pending_build_spec.rb
@@ -8,6 +8,34 @@ RSpec.describe Ci::PendingBuild do
let(:build) { create(:ci_build, :created, pipeline: pipeline) }
+ describe 'associations' do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to belong_to :build }
+ it { is_expected.to belong_to :namespace }
+ end
+
+ describe 'scopes' do
+ describe '.with_instance_runners' do
+ subject(:pending_builds) { described_class.with_instance_runners }
+
+ let!(:pending_build_1) { create(:ci_pending_build, instance_runners_enabled: false) }
+
+ context 'when pending builds cannot be picked up by runner' do
+ it 'returns an empty collection of pending builds' do
+ expect(pending_builds).to be_empty
+ end
+ end
+
+ context 'when pending builds can be picked up by runner' do
+ let!(:pending_build_2) { create(:ci_pending_build) }
+
+ it 'returns matching pending builds' do
+ expect(pending_builds).to contain_exactly(pending_build_2)
+ end
+ end
+ end
+ end
+
describe '.upsert_from_build!' do
context 'another pending entry does not exist' do
it 'creates a new pending entry' do
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 74a476a6422..da89eccc3b2 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -263,6 +263,20 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
end
+ describe '.with_pipeline_source' do
+ subject { described_class.with_pipeline_source(source) }
+
+ let(:source) { 'web' }
+
+ let_it_be(:push_pipeline) { create(:ci_pipeline, source: :push) }
+ let_it_be(:web_pipeline) { create(:ci_pipeline, source: :web) }
+ let_it_be(:api_pipeline) { create(:ci_pipeline, source: :api) }
+
+ it 'contains pipelines created due to specified source' do
+ expect(subject).to contain_exactly(web_pipeline)
+ end
+ end
+
describe '.ci_sources' do
subject { described_class.ci_sources }
@@ -2263,18 +2277,38 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '.latest_successful_for_refs' do
- let!(:latest_successful_pipeline1) do
- create_pipeline(:success, 'ref1', 'D')
- end
+ subject(:latest_successful_for_refs) { described_class.latest_successful_for_refs(refs) }
- let!(:latest_successful_pipeline2) do
- create_pipeline(:success, 'ref2', 'D')
+ context 'when refs are specified' do
+ let(:refs) { %w(first_ref second_ref third_ref) }
+
+ before do
+ create(:ci_empty_pipeline, id: 1001, status: :success, ref: 'first_ref', sha: 'sha')
+ create(:ci_empty_pipeline, id: 1002, status: :success, ref: 'second_ref', sha: 'sha')
+ end
+
+ let!(:latest_successful_pipeline_for_first_ref) do
+ create(:ci_empty_pipeline, id: 2001, status: :success, ref: 'first_ref', sha: 'sha')
+ end
+
+ let!(:latest_successful_pipeline_for_second_ref) do
+ create(:ci_empty_pipeline, id: 2002, status: :success, ref: 'second_ref', sha: 'sha')
+ end
+
+ it 'returns the latest successful pipeline for both refs' do
+ expect(latest_successful_for_refs).to eq({
+ 'first_ref' => latest_successful_pipeline_for_first_ref,
+ 'second_ref' => latest_successful_pipeline_for_second_ref
+ })
+ end
end
- it 'returns the latest successful pipeline for both refs' do
- refs = %w(ref1 ref2 ref3)
+ context 'when no refs are specified' do
+ let(:refs) { [] }
- expect(described_class.latest_successful_for_refs(refs)).to eq({ 'ref1' => latest_successful_pipeline1, 'ref2' => latest_successful_pipeline2 })
+ it 'returns an empty relation whenno refs are specified' do
+ expect(latest_successful_for_refs).to be_empty
+ end
end
end
end
diff --git a/spec/models/ci/resource_spec.rb b/spec/models/ci/resource_spec.rb
index 5574f6f82b2..e883d704768 100644
--- a/spec/models/ci/resource_spec.rb
+++ b/spec/models/ci/resource_spec.rb
@@ -15,6 +15,22 @@ RSpec.describe Ci::Resource do
end
end
+ describe '.retained' do
+ subject { described_class.retained }
+
+ it "returns the resource if it's retained" do
+ resource = create(:ci_resource, processable: create(:ci_build))
+
+ is_expected.to eq([resource])
+ end
+
+ it "returns empty if it's not retained" do
+ create(:ci_resource, processable: nil)
+
+ is_expected.to be_empty
+ end
+ end
+
describe '.retained_by' do
subject { described_class.retained_by(build) }
@@ -25,4 +41,40 @@ RSpec.describe Ci::Resource do
is_expected.to eq([resource])
end
end
+
+ describe '.stale_processables' do
+ subject { resource_group.resources.stale_processables }
+
+ let!(:resource_group) { create(:ci_resource_group) }
+ let!(:resource) { create(:ci_resource, processable: build, resource_group: resource_group) }
+
+ context 'when the processable is running' do
+ let!(:build) { create(:ci_build, :running, resource_group: resource_group) }
+
+ before do
+ # Creating unrelated builds to make sure the `retained` scope is working
+ create(:ci_build, :running, resource_group: resource_group)
+ end
+
+ it 'returns empty' do
+ is_expected.to be_empty
+ end
+
+ context 'and doomed' do
+ before do
+ build.doom!
+ end
+
+ it 'returns empty' do
+ is_expected.to be_empty
+ end
+
+ it 'returns the stale prosessable a few minutes later' do
+ travel_to(10.minutes.since) do
+ is_expected.to eq([build])
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/models/ci/runner_namespace_spec.rb b/spec/models/ci/runner_namespace_spec.rb
index 41d805adb9f..4e7cf7a3cb3 100644
--- a/spec/models/ci/runner_namespace_spec.rb
+++ b/spec/models/ci/runner_namespace_spec.rb
@@ -4,6 +4,12 @@ require 'spec_helper'
RSpec.describe Ci::RunnerNamespace do
it_behaves_like 'includes Limitable concern' do
+ before do
+ skip_default_enabled_yaml_check
+
+ stub_feature_flags(ci_runner_limits_override: false)
+ end
+
subject { build(:ci_runner_namespace, group: create(:group, :nested), runner: create(:ci_runner, :group)) }
end
end
diff --git a/spec/models/ci/runner_project_spec.rb b/spec/models/ci/runner_project_spec.rb
index 13369dba2cf..fef1416a84a 100644
--- a/spec/models/ci/runner_project_spec.rb
+++ b/spec/models/ci/runner_project_spec.rb
@@ -4,6 +4,12 @@ require 'spec_helper'
RSpec.describe Ci::RunnerProject do
it_behaves_like 'includes Limitable concern' do
+ before do
+ skip_default_enabled_yaml_check
+
+ stub_feature_flags(ci_runner_limits_override: false)
+ end
+
subject { build(:ci_runner_project, project: create(:project), runner: create(:ci_runner, :project)) }
end
end