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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-03-16 21:18:33 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-03-16 21:18:33 +0300
commitf64a639bcfa1fc2bc89ca7db268f594306edfd7c (patch)
treea2c3c2ebcc3b45e596949db485d6ed18ffaacfa1 /spec/models/ci
parentbfbc3e0d6583ea1a91f627528bedc3d65ba4b10f (diff)
Add latest changes from gitlab-org/gitlab@13-10-stable-eev13.10.0-rc40
Diffstat (limited to 'spec/models/ci')
-rw-r--r--spec/models/ci/bridge_spec.rb6
-rw-r--r--spec/models/ci/build_spec.rb143
-rw-r--r--spec/models/ci/daily_build_group_report_result_spec.rb34
-rw-r--r--spec/models/ci/group_variable_spec.rb12
-rw-r--r--spec/models/ci/pipeline_spec.rb728
-rw-r--r--spec/models/ci/processable_spec.rb4
-rw-r--r--spec/models/ci/runner_spec.rb112
-rw-r--r--spec/models/ci/variable_spec.rb9
8 files changed, 592 insertions, 456 deletions
diff --git a/spec/models/ci/bridge_spec.rb b/spec/models/ci/bridge_spec.rb
index b50e4204e0a..f3029598b02 100644
--- a/spec/models/ci/bridge_spec.rb
+++ b/spec/models/ci/bridge_spec.rb
@@ -41,7 +41,7 @@ RSpec.describe Ci::Bridge do
end
end
- describe '#scoped_variables_hash' do
+ describe '#scoped_variables' do
it 'returns a hash representing variables' do
variables = %w[
CI_JOB_NAME CI_JOB_STAGE CI_COMMIT_SHA CI_COMMIT_SHORT_SHA
@@ -53,7 +53,7 @@ RSpec.describe Ci::Bridge do
CI_COMMIT_TIMESTAMP
]
- expect(bridge.scoped_variables_hash.keys).to include(*variables)
+ expect(bridge.scoped_variables.map { |v| v[:key] }).to include(*variables)
end
context 'when bridge has dependency which has dotenv variable' do
@@ -63,7 +63,7 @@ RSpec.describe Ci::Bridge do
let!(:job_variable) { create(:ci_job_variable, :dotenv_source, job: test) }
it 'includes inherited variable' do
- expect(bridge.scoped_variables_hash).to include(job_variable.key => job_variable.value)
+ expect(bridge.scoped_variables.to_hash).to include(job_variable.key => job_variable.value)
end
end
end
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 4ad7ce70a44..5b07bd8923f 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -581,7 +581,7 @@ RSpec.describe Ci::Build do
end
it 'that cannot handle build' do
- expect_any_instance_of(Ci::Runner).to receive(:can_pick?).and_return(false)
+ expect_any_instance_of(Ci::Runner).to receive(:matches_build?).with(build).and_return(false)
is_expected.to be_falsey
end
end
@@ -817,7 +817,48 @@ RSpec.describe Ci::Build do
end
describe '#cache' do
- let(:options) { { cache: { key: "key", paths: ["public"], policy: "pull-push" } } }
+ let(:options) do
+ { cache: [{ key: "key", paths: ["public"], policy: "pull-push" }] }
+ end
+
+ context 'with multiple_cache_per_job FF disabled' do
+ before do
+ stub_feature_flags(multiple_cache_per_job: false)
+ end
+ let(:options) { { cache: { key: "key", paths: ["public"], policy: "pull-push" } } }
+
+ subject { build.cache }
+
+ context 'when build has cache' do
+ before do
+ allow(build).to receive(:options).and_return(options)
+ end
+
+ context 'when project has jobs_cache_index' do
+ before do
+ allow_any_instance_of(Project).to receive(:jobs_cache_index).and_return(1)
+ end
+
+ it { is_expected.to be_an(Array).and all(include(key: "key-1")) }
+ end
+
+ context 'when project does not have jobs_cache_index' do
+ before do
+ allow_any_instance_of(Project).to receive(:jobs_cache_index).and_return(nil)
+ end
+
+ it { is_expected.to eq([options[:cache]]) }
+ end
+ end
+
+ context 'when build does not have cache' do
+ before do
+ allow(build).to receive(:options).and_return({})
+ end
+
+ it { is_expected.to eq([]) }
+ end
+ end
subject { build.cache }
@@ -826,6 +867,21 @@ RSpec.describe Ci::Build do
allow(build).to receive(:options).and_return(options)
end
+ context 'when build has multiple caches' do
+ let(:options) do
+ { cache: [
+ { key: "key", paths: ["public"], policy: "pull-push" },
+ { key: "key2", paths: ["public"], policy: "pull-push" }
+ ] }
+ end
+
+ before do
+ allow_any_instance_of(Project).to receive(:jobs_cache_index).and_return(1)
+ end
+
+ it { is_expected.to match([a_hash_including(key: "key-1"), a_hash_including(key: "key2-1")]) }
+ end
+
context 'when project has jobs_cache_index' do
before do
allow_any_instance_of(Project).to receive(:jobs_cache_index).and_return(1)
@@ -839,7 +895,7 @@ RSpec.describe Ci::Build do
allow_any_instance_of(Project).to receive(:jobs_cache_index).and_return(nil)
end
- it { is_expected.to eq([options[:cache]]) }
+ it { is_expected.to eq(options[:cache]) }
end
end
@@ -848,7 +904,7 @@ RSpec.describe Ci::Build do
allow(build).to receive(:options).and_return({})
end
- it { is_expected.to eq([nil]) }
+ it { is_expected.to be_empty }
end
end
@@ -1205,6 +1261,21 @@ RSpec.describe Ci::Build do
end
end
+ describe '#environment_deployment_tier' do
+ subject { build.environment_deployment_tier }
+
+ let(:build) { described_class.new(options: options) }
+ let(:options) { { environment: { deployment_tier: 'production' } } }
+
+ it { is_expected.to eq('production') }
+
+ context 'when options does not include deployment_tier' do
+ let(:options) { { environment: { name: 'production' } } }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
describe 'deployment' do
describe '#outdated_deployment?' do
subject { build.outdated_deployment? }
@@ -2367,6 +2438,7 @@ RSpec.describe Ci::Build do
{ key: 'CI_JOB_ID', value: build.id.to_s, public: true, masked: false },
{ key: 'CI_JOB_URL', value: project.web_url + "/-/jobs/#{build.id}", public: true, masked: false },
{ key: 'CI_JOB_TOKEN', value: 'my-token', public: false, masked: true },
+ { key: 'CI_JOB_STARTED_AT', value: build.started_at&.iso8601, public: true, masked: false },
{ key: 'CI_BUILD_ID', value: build.id.to_s, public: true, masked: false },
{ key: 'CI_BUILD_TOKEN', value: 'my-token', public: false, masked: true },
{ key: 'CI_REGISTRY_USER', value: 'gitlab-ci-token', public: true, masked: false },
@@ -2405,17 +2477,18 @@ RSpec.describe Ci::Build do
{ key: 'CI_PROJECT_REPOSITORY_LANGUAGES', value: project.repository_languages.map(&:name).join(',').downcase, public: true, masked: false },
{ key: 'CI_DEFAULT_BRANCH', value: project.default_branch, public: true, masked: false },
{ key: 'CI_PROJECT_CONFIG_PATH', value: project.ci_config_path_or_default, 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 },
{ key: 'CI_PAGES_URL', value: project.pages_url, public: true, masked: false },
- { key: 'CI_DEPENDENCY_PROXY_SERVER', value: "#{Gitlab.config.gitlab.host}:#{Gitlab.config.gitlab.port}", public: true, masked: false },
+ { key: 'CI_DEPENDENCY_PROXY_SERVER', value: Gitlab.host_with_port, public: true, masked: false },
{ key: 'CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX',
- value: "#{Gitlab.config.gitlab.host}:#{Gitlab.config.gitlab.port}/#{project.namespace.root_ancestor.path}#{DependencyProxy::URL_SUFFIX}",
+ value: "#{Gitlab.host_with_port}/#{project.namespace.root_ancestor.path.downcase}#{DependencyProxy::URL_SUFFIX}",
public: true,
masked: false },
{ key: 'CI_API_V4_URL', value: 'http://localhost/api/v4', public: true, masked: false },
{ key: 'CI_PIPELINE_IID', value: pipeline.iid.to_s, public: true, masked: false },
{ key: 'CI_PIPELINE_SOURCE', value: pipeline.source, public: true, masked: false },
- { key: 'CI_CONFIG_PATH', value: pipeline.config_path, public: true, masked: false },
+ { key: 'CI_PIPELINE_CREATED_AT', value: pipeline.created_at.iso8601, public: true, masked: false },
{ key: 'CI_COMMIT_SHA', value: build.sha, public: true, masked: false },
{ key: 'CI_COMMIT_SHORT_SHA', value: build.short_sha, public: true, masked: false },
{ key: 'CI_COMMIT_BEFORE_SHA', value: build.before_sha, public: true, masked: false },
@@ -2440,7 +2513,8 @@ RSpec.describe Ci::Build do
build.yaml_variables = []
end
- it { is_expected.to eq(predefined_variables) }
+ it { is_expected.to be_instance_of(Gitlab::Ci::Variables::Collection) }
+ it { expect(subject.to_runner_variables).to eq(predefined_variables) }
context 'when ci_job_jwt feature flag is disabled' do
before do
@@ -2495,7 +2569,7 @@ RSpec.describe Ci::Build do
end
it 'returns variables in order depending on resource hierarchy' do
- is_expected.to eq(
+ expect(subject.to_runner_variables).to eq(
[dependency_proxy_var,
job_jwt_var,
build_pre_var,
@@ -2525,7 +2599,7 @@ RSpec.describe Ci::Build do
end
it 'matches explicit variables ordering' do
- received_variables = subject.map { |variable| variable.fetch(:key) }
+ received_variables = subject.map { |variable| variable[:key] }
expect(received_variables).to eq expected_variables
end
@@ -2584,14 +2658,14 @@ RSpec.describe Ci::Build do
end
shared_examples 'containing environment variables' do
- it { environment_variables.each { |v| is_expected.to include(v) } }
+ it { is_expected.to include(*environment_variables) }
end
context 'when no URL was set' do
it_behaves_like 'containing environment variables'
it 'does not have CI_ENVIRONMENT_URL' do
- keys = subject.map { |var| var[:key] }
+ keys = subject.pluck(:key)
expect(keys).not_to include('CI_ENVIRONMENT_URL')
end
@@ -2618,7 +2692,7 @@ RSpec.describe Ci::Build do
it_behaves_like 'containing environment variables'
it 'puts $CI_ENVIRONMENT_URL in the last so all other variables are available to be used when runners are trying to expand it' do
- expect(subject.last).to eq(environment_variables.last)
+ expect(subject.to_runner_variables.last).to eq(environment_variables.last)
end
end
end
@@ -2951,7 +3025,7 @@ RSpec.describe Ci::Build do
end
it 'overrides YAML variable using a pipeline variable' do
- variables = subject.reverse.uniq { |variable| variable[:key] }.reverse
+ variables = subject.to_runner_variables.reverse.uniq { |variable| variable[:key] }.reverse
expect(variables)
.not_to include(key: 'MYVAR', value: 'myvar', public: true, masked: false)
@@ -3248,47 +3322,6 @@ RSpec.describe Ci::Build do
end
end
- describe '#scoped_variables_hash' do
- context 'when overriding CI variables' do
- before do
- project.variables.create!(key: 'MY_VAR', value: 'my value 1')
- pipeline.variables.create!(key: 'MY_VAR', value: 'my value 2')
- end
-
- it 'returns a regular hash created using valid ordering' do
- expect(build.scoped_variables_hash).to include('MY_VAR': 'my value 2')
- expect(build.scoped_variables_hash).not_to include('MY_VAR': 'my value 1')
- end
- end
-
- context 'when overriding user-provided variables' do
- let(:build) do
- create(:ci_build, pipeline: pipeline, yaml_variables: [{ key: 'MY_VAR', value: 'myvar', public: true }])
- end
-
- before do
- pipeline.variables.build(key: 'MY_VAR', value: 'pipeline value')
- end
-
- it 'returns a hash including variable with higher precedence' do
- expect(build.scoped_variables_hash).to include('MY_VAR': 'pipeline value')
- expect(build.scoped_variables_hash).not_to include('MY_VAR': 'myvar')
- end
- end
-
- context 'when overriding CI instance variables' do
- before do
- create(:ci_instance_variable, key: 'MY_VAR', value: 'my value 1')
- group.variables.create!(key: 'MY_VAR', value: 'my value 2')
- end
-
- it 'returns a regular hash created using valid ordering' do
- expect(build.scoped_variables_hash).to include('MY_VAR': 'my value 2')
- expect(build.scoped_variables_hash).not_to include('MY_VAR': 'my value 1')
- end
- end
- end
-
describe '#any_unmet_prerequisites?' do
let(:build) { create(:ci_build, :created) }
diff --git a/spec/models/ci/daily_build_group_report_result_spec.rb b/spec/models/ci/daily_build_group_report_result_spec.rb
index f6e6a6a5e02..4e96ec7cecb 100644
--- a/spec/models/ci/daily_build_group_report_result_spec.rb
+++ b/spec/models/ci/daily_build_group_report_result_spec.rb
@@ -162,39 +162,5 @@ RSpec.describe Ci::DailyBuildGroupReportResult do
end
end
end
-
- describe '.by_date' do
- subject(:coverages) { described_class.by_date(start_date) }
-
- let!(:coverage_1) { create(:ci_daily_build_group_report_result, date: 1.week.ago) }
-
- context 'when project has several coverage' do
- let!(:coverage_2) { create(:ci_daily_build_group_report_result, date: 2.weeks.ago) }
- let(:start_date) { 1.week.ago.to_date.to_s }
-
- it 'returns the coverage from the start_date' do
- expect(coverages).to contain_exactly(coverage_1)
- end
- end
-
- context 'when start_date is over 90 days' do
- let!(:coverage_2) { create(:ci_daily_build_group_report_result, date: 90.days.ago) }
- let!(:coverage_3) { create(:ci_daily_build_group_report_result, date: 91.days.ago) }
- let(:start_date) { 1.year.ago.to_date.to_s }
-
- it 'returns the coverage in the last 90 days' do
- expect(coverages).to contain_exactly(coverage_1, coverage_2)
- end
- end
-
- context 'when start_date is not a string' do
- let!(:coverage_2) { create(:ci_daily_build_group_report_result, date: 90.days.ago) }
- let(:start_date) { 1.week.ago }
-
- it 'returns the coverage in the last 90 days' do
- expect(coverages).to contain_exactly(coverage_1, coverage_2)
- end
- end
- end
end
end
diff --git a/spec/models/ci/group_variable_spec.rb b/spec/models/ci/group_variable_spec.rb
index c8eac4d8765..f0eec549da7 100644
--- a/spec/models/ci/group_variable_spec.rb
+++ b/spec/models/ci/group_variable_spec.rb
@@ -9,7 +9,17 @@ RSpec.describe Ci::GroupVariable do
it { is_expected.to include_module(Presentable) }
it { is_expected.to include_module(Ci::Maskable) }
- it { is_expected.to validate_uniqueness_of(:key).scoped_to(:group_id).with_message(/\(\w+\) has already been taken/) }
+ it { is_expected.to include_module(HasEnvironmentScope) }
+ it { is_expected.to validate_uniqueness_of(:key).scoped_to([:group_id, :environment_scope]).with_message(/\(\w+\) has already been taken/) }
+
+ describe '.by_environment_scope' do
+ let!(:matching_variable) { create(:ci_group_variable, environment_scope: 'production ') }
+ let!(:non_matching_variable) { create(:ci_group_variable, environment_scope: 'staging') }
+
+ subject { Ci::GroupVariable.by_environment_scope('production') }
+
+ it { is_expected.to contain_exactly(matching_variable) }
+ end
describe '.unprotected' do
subject { described_class.unprotected }
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 94943fb3644..d57a39d133f 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -8,12 +8,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
include Ci::SourcePipelineHelpers
let_it_be(:user) { create(:user) }
- let_it_be(:namespace) { create_default(:namespace) }
- let_it_be(:project) { create_default(:project, :repository) }
-
- let(:pipeline) do
- create(:ci_empty_pipeline, status: :created, project: project)
- end
+ let_it_be(:namespace) { create_default(:namespace).freeze }
+ let_it_be(:project) { create_default(:project, :repository).freeze }
it_behaves_like 'having unique enum values'
@@ -53,6 +49,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe 'associations' do
+ let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) }
+
it 'has a bidirectional relationship with projects' do
expect(described_class.reflect_on_association(:project).has_inverse?).to eq(:all_pipelines)
expect(Project.reflect_on_association(:all_pipelines).has_inverse?).to eq(:project)
@@ -82,6 +80,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#set_status' do
+ let(:pipeline) { build(:ci_empty_pipeline, :created) }
+
where(:from_status, :to_status) do
from_status_names = described_class.state_machines[:status].states.map(&:name)
to_status_names = from_status_names - [:created] # we never want to transition into created
@@ -105,6 +105,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '.processables' do
+ let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) }
+
before do
create(:ci_build, name: 'build', pipeline: pipeline)
create(:ci_bridge, name: 'bridge', pipeline: pipeline)
@@ -142,7 +144,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
subject { described_class.for_sha(sha) }
let(:sha) { 'abc' }
- let!(:pipeline) { create(:ci_pipeline, sha: 'abc') }
+
+ let_it_be(:pipeline) { create(:ci_pipeline, sha: 'abc') }
it 'returns the pipeline' do
is_expected.to contain_exactly(pipeline)
@@ -170,7 +173,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
subject { described_class.for_source_sha(source_sha) }
let(:source_sha) { 'abc' }
- let!(:pipeline) { create(:ci_pipeline, source_sha: 'abc') }
+
+ let_it_be(:pipeline) { create(:ci_pipeline, source_sha: 'abc') }
it 'returns the pipeline' do
is_expected.to contain_exactly(pipeline)
@@ -228,7 +232,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
subject { described_class.for_branch(branch) }
let(:branch) { 'master' }
- let!(:pipeline) { create(:ci_pipeline, ref: 'master') }
+
+ let_it_be(:pipeline) { create(:ci_pipeline, ref: 'master') }
it 'returns the pipeline' do
is_expected.to contain_exactly(pipeline)
@@ -247,13 +252,16 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '.ci_sources' do
subject { described_class.ci_sources }
- let!(:push_pipeline) { create(:ci_pipeline, source: :push) }
- let!(:web_pipeline) { create(:ci_pipeline, source: :web) }
- let!(:api_pipeline) { create(:ci_pipeline, source: :api) }
- let!(:webide_pipeline) { create(:ci_pipeline, source: :webide) }
- let!(:child_pipeline) { create(:ci_pipeline, source: :parent_pipeline) }
+ let(:push_pipeline) { build(:ci_pipeline, source: :push) }
+ let(:web_pipeline) { build(:ci_pipeline, source: :web) }
+ let(:api_pipeline) { build(:ci_pipeline, source: :api) }
+ let(:webide_pipeline) { build(:ci_pipeline, source: :webide) }
+ let(:child_pipeline) { build(:ci_pipeline, source: :parent_pipeline) }
+ let(:pipelines) { [push_pipeline, web_pipeline, api_pipeline, webide_pipeline, child_pipeline] }
it 'contains pipelines having CI only sources' do
+ pipelines.map(&:save!)
+
expect(subject).to contain_exactly(push_pipeline, web_pipeline, api_pipeline)
end
@@ -365,8 +373,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
end
- describe '#merge_request_pipeline?' do
- subject { pipeline.merge_request_pipeline? }
+ describe '#merged_result_pipeline?' do
+ subject { pipeline.merged_result_pipeline? }
let!(:pipeline) do
create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, target_sha: target_sha)
@@ -387,6 +395,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#merge_request_ref?' do
subject { pipeline.merge_request_ref? }
+ let(:pipeline) { build(:ci_empty_pipeline, :created) }
+
it 'calls MergeRequest#merge_request_ref?' do
expect(MergeRequest).to receive(:merge_request_ref?).with(pipeline.ref)
@@ -606,7 +616,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#source' do
context 'when creating new pipeline' do
let(:pipeline) do
- build(:ci_empty_pipeline, status: :created, project: project, source: nil)
+ build(:ci_empty_pipeline, :created, project: project, source: nil)
end
it "prevents from creating an object" do
@@ -615,17 +625,21 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
context 'when updating existing pipeline' do
+ let(:pipeline) { create(:ci_empty_pipeline, :created) }
+
before do
pipeline.update_attribute(:source, nil)
end
- it "object is valid" do
+ it 'object is valid' do
expect(pipeline).to be_valid
end
end
end
describe '#block' do
+ let(:pipeline) { create(:ci_empty_pipeline, :created) }
+
it 'changes pipeline status to manual' do
expect(pipeline.block).to be true
expect(pipeline.reload).to be_manual
@@ -636,7 +650,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#delay' do
subject { pipeline.delay }
- let(:pipeline) { build(:ci_pipeline, status: :created) }
+ let(:pipeline) { build(:ci_pipeline, :created) }
it 'changes pipeline status to schedule' do
subject
@@ -646,6 +660,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#valid_commit_sha' do
+ let(:pipeline) { build_stubbed(:ci_empty_pipeline, :created, project: project) }
+
context 'commit.sha can not start with 00000000' do
before do
pipeline.sha = '0' * 40
@@ -659,6 +675,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#short_sha' do
subject { pipeline.short_sha }
+ let(:pipeline) { build_stubbed(:ci_empty_pipeline, :created) }
+
it 'has 8 items' do
expect(subject.size).to eq(8)
end
@@ -668,49 +686,58 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#retried' do
subject { pipeline.retried }
+ let(:pipeline) { create(:ci_empty_pipeline, :created, project: project) }
+ let!(:build1) { create(:ci_build, pipeline: pipeline, name: 'deploy', retried: true) }
+
before do
- @build1 = create(:ci_build, pipeline: pipeline, name: 'deploy', retried: true)
- @build2 = create(:ci_build, pipeline: pipeline, name: 'deploy')
+ create(:ci_build, pipeline: pipeline, name: 'deploy')
end
it 'returns old builds' do
- is_expected.to contain_exactly(@build1)
+ is_expected.to contain_exactly(build1)
end
end
describe '#coverage' do
- let(:project) { create(:project, build_coverage_regex: "/.*/") }
- let(:pipeline) { create(:ci_empty_pipeline, project: project) }
+ let_it_be_with_reload(:pipeline) { create(:ci_empty_pipeline) }
- it "calculates average when there are two builds with coverage" do
- create(:ci_build, name: "rspec", coverage: 30, pipeline: pipeline)
- create(:ci_build, name: "rubocop", coverage: 40, pipeline: pipeline)
- expect(pipeline.coverage).to eq("35.00")
- end
+ context 'with multiple pipelines' do
+ before_all do
+ create(:ci_build, name: "rspec", coverage: 30, pipeline: pipeline)
+ create(:ci_build, name: "rubocop", coverage: 40, pipeline: pipeline)
+ end
- it "calculates average when there are two builds with coverage and one with nil" do
- create(:ci_build, name: "rspec", coverage: 30, pipeline: pipeline)
- create(:ci_build, name: "rubocop", coverage: 40, pipeline: pipeline)
- create(:ci_build, pipeline: pipeline)
- expect(pipeline.coverage).to eq("35.00")
- end
+ it "calculates average when there are two builds with coverage" do
+ expect(pipeline.coverage).to eq("35.00")
+ end
+
+ it "calculates average when there are two builds with coverage and one with nil" do
+ create(:ci_build, pipeline: pipeline)
+
+ expect(pipeline.coverage).to eq("35.00")
+ end
- it "calculates average when there are two builds with coverage and one is retried" do
- create(:ci_build, name: "rspec", coverage: 30, pipeline: pipeline)
- create(:ci_build, name: "rubocop", coverage: 30, pipeline: pipeline, retried: true)
- create(:ci_build, name: "rubocop", coverage: 40, pipeline: pipeline)
- expect(pipeline.coverage).to eq("35.00")
+ it "calculates average when there are two builds with coverage and one is retried" do
+ create(:ci_build, name: "rubocop", coverage: 30, pipeline: pipeline, retried: true)
+
+ expect(pipeline.coverage).to eq("35.00")
+ end
end
- it "calculates average when there is one build without coverage" do
- FactoryBot.create(:ci_build, pipeline: pipeline)
- expect(pipeline.coverage).to be_nil
+ context 'when there is one build without coverage' do
+ it "calculates average to nil" do
+ create(:ci_build, pipeline: pipeline)
+
+ expect(pipeline.coverage).to be_nil
+ end
end
end
describe '#retryable?' do
subject { pipeline.retryable? }
+ let_it_be(:pipeline) { create(:ci_empty_pipeline, :created, project: project) }
+
context 'no failed builds' do
before do
create_build('rspec', 'success')
@@ -772,13 +799,15 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#predefined_variables' do
subject { pipeline.predefined_variables }
+ let(:pipeline) { build(:ci_empty_pipeline, :created) }
+
it 'includes all predefined variables in a valid order' do
keys = subject.map { |variable| variable[:key] }
expect(keys).to eq %w[
CI_PIPELINE_IID
CI_PIPELINE_SOURCE
- CI_CONFIG_PATH
+ CI_PIPELINE_CREATED_AT
CI_COMMIT_SHA
CI_COMMIT_SHORT_SHA
CI_COMMIT_BEFORE_SHA
@@ -798,21 +827,18 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
context 'when merge request is present' do
+ let_it_be(:assignees) { create_list(:user, 2) }
+ let_it_be(:milestone) { create(:milestone, project: project) }
+ let_it_be(:labels) { create_list(:label, 2) }
let(:merge_request) do
- create(:merge_request,
+ create(:merge_request, :simple,
source_project: project,
- source_branch: 'feature',
target_project: project,
- target_branch: 'master',
assignees: assignees,
milestone: milestone,
labels: labels)
end
- let(:assignees) { create_list(:user, 2) }
- let(:milestone) { create(:milestone, project: project) }
- let(:labels) { create_list(:label, 2) }
-
context 'when pipeline for merge request is created' do
let(:pipeline) do
create(:ci_pipeline, :detached_merge_request_pipeline,
@@ -998,9 +1024,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#protected_ref?' do
- before do
- pipeline.project = create(:project, :repository)
- end
+ let(:pipeline) { build(:ci_empty_pipeline, :created) }
it 'delegates method to project' do
expect(pipeline).not_to be_protected_ref
@@ -1008,11 +1032,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#legacy_trigger' do
- let(:trigger_request) { create(:ci_trigger_request) }
-
- before do
- pipeline.trigger_requests << trigger_request
- end
+ let(:trigger_request) { build(:ci_trigger_request) }
+ let(:pipeline) { build(:ci_empty_pipeline, :created, trigger_requests: [trigger_request]) }
it 'returns first trigger request' do
expect(pipeline.legacy_trigger).to eq trigger_request
@@ -1022,6 +1043,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#auto_canceled?' do
subject { pipeline.auto_canceled? }
+ let(:pipeline) { build(:ci_empty_pipeline, :created) }
+
context 'when it is canceled' do
before do
pipeline.cancel
@@ -1029,7 +1052,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context 'when there is auto_canceled_by' do
before do
- pipeline.update!(auto_canceled_by: create(:ci_empty_pipeline))
+ pipeline.auto_canceled_by = create(:ci_empty_pipeline)
end
it 'is auto canceled' do
@@ -1057,6 +1080,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe 'pipeline stages' do
+ let(:pipeline) { build(:ci_empty_pipeline, :created) }
+
describe 'legacy stages' do
before do
create(:commit_status, pipeline: pipeline,
@@ -1107,22 +1132,28 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
context 'when commit status is retried' do
- before do
+ let!(:old_commit_status) do
create(:commit_status, pipeline: pipeline,
- stage: 'build',
- name: 'mac',
- stage_idx: 0,
- status: 'success')
-
- Ci::ProcessPipelineService
- .new(pipeline)
- .execute
+ stage: 'build',
+ name: 'mac',
+ stage_idx: 0,
+ status: 'success')
end
- it 'ignores the previous state' do
- expect(statuses).to eq([%w(build success),
- %w(test success),
- %w(deploy running)])
+ context 'when FF ci_remove_update_retried_from_process_pipeline is disabled' do
+ before do
+ stub_feature_flags(ci_remove_update_retried_from_process_pipeline: false)
+
+ Ci::ProcessPipelineService
+ .new(pipeline)
+ .execute
+ end
+
+ it 'ignores the previous state' do
+ expect(statuses).to eq([%w(build success),
+ %w(test success),
+ %w(deploy running)])
+ end
end
end
end
@@ -1162,6 +1193,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#legacy_stage' do
subject { pipeline.legacy_stage('test') }
+ let(:pipeline) { build(:ci_empty_pipeline, :created) }
+
context 'with status in stage' do
before do
create(:commit_status, pipeline: pipeline, stage: 'test')
@@ -1184,6 +1217,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#stages' do
+ let(:pipeline) { build(:ci_empty_pipeline, :created) }
+
before do
create(:ci_stage_entity, project: project,
pipeline: pipeline,
@@ -1238,6 +1273,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe 'state machine' do
+ let_it_be_with_reload(:pipeline) { create(:ci_empty_pipeline, :created) }
let(:current) { Time.current.change(usec: 0) }
let(:build) { create_build('build1', queued_at: 0) }
let(:build_b) { create_build('build2', queued_at: 0) }
@@ -1401,28 +1437,10 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe 'pipeline caching' do
- context 'if pipeline is cacheable' do
- before do
- pipeline.source = 'push'
- end
-
- it 'performs ExpirePipelinesCacheWorker' do
- expect(ExpirePipelineCacheWorker).to receive(:perform_async).with(pipeline.id)
+ it 'performs ExpirePipelinesCacheWorker' do
+ expect(ExpirePipelineCacheWorker).to receive(:perform_async).with(pipeline.id)
- pipeline.cancel
- end
- end
-
- context 'if pipeline is not cacheable' do
- before do
- pipeline.source = 'webide'
- end
-
- it 'deos not perform ExpirePipelinesCacheWorker' do
- expect(ExpirePipelineCacheWorker).not_to receive(:perform_async)
-
- pipeline.cancel
- end
+ pipeline.cancel
end
end
@@ -1441,24 +1459,25 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe 'auto merge' do
- let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
-
- let(:pipeline) do
- create(:ci_pipeline, :running, project: merge_request.source_project,
- ref: merge_request.source_branch,
- sha: merge_request.diff_head_sha)
- end
+ context 'when auto merge is enabled' do
+ let_it_be_with_reload(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
+ let_it_be_with_reload(:pipeline) do
+ create(:ci_pipeline, :running, project: merge_request.source_project,
+ ref: merge_request.source_branch,
+ sha: merge_request.diff_head_sha)
+ end
- before do
- merge_request.update_head_pipeline
- end
+ before_all do
+ merge_request.update_head_pipeline
+ end
- %w[succeed! drop! cancel! skip!].each do |action|
- context "when the pipeline recieved #{action} event" do
- it 'performs AutoMergeProcessWorker' do
- expect(AutoMergeProcessWorker).to receive(:perform_async).with(merge_request.id)
+ %w[succeed! drop! cancel! skip!].each do |action|
+ context "when the pipeline recieved #{action} event" do
+ it 'performs AutoMergeProcessWorker' do
+ expect(AutoMergeProcessWorker).to receive(:perform_async).with(merge_request.id)
- pipeline.public_send(action)
+ pipeline.public_send(action)
+ end
end
end
end
@@ -1610,15 +1629,15 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context 'multi-project pipelines' do
let!(:downstream_project) { create(:project, :repository) }
- let!(:upstream_pipeline) { create(:ci_pipeline, project: project) }
+ let!(:upstream_pipeline) { create(:ci_pipeline) }
let!(:downstream_pipeline) { create(:ci_pipeline, :with_job, project: downstream_project) }
it_behaves_like 'upstream downstream pipeline'
end
context 'parent-child pipelines' do
- let!(:upstream_pipeline) { create(:ci_pipeline, project: project) }
- let!(:downstream_pipeline) { create(:ci_pipeline, :with_job, project: project) }
+ let!(:upstream_pipeline) { create(:ci_pipeline) }
+ let!(:downstream_pipeline) { create(:ci_pipeline, :with_job) }
it_behaves_like 'upstream downstream pipeline'
end
@@ -1637,6 +1656,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#branch?' do
subject { pipeline.branch? }
+ let(:pipeline) { build(:ci_empty_pipeline, :created) }
+
context 'when ref is not a tag' do
before do
pipeline.tag = false
@@ -1647,16 +1668,12 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
context 'when pipeline is merge request' do
- let(:pipeline) do
- create(:ci_pipeline, merge_request: merge_request)
- end
+ let(:pipeline) { build(:ci_pipeline, merge_request: merge_request) }
let(:merge_request) do
- create(:merge_request,
+ create(:merge_request, :simple,
source_project: project,
- source_branch: 'feature',
- target_project: project,
- target_branch: 'master')
+ target_project: project)
end
it 'returns false' do
@@ -1720,6 +1737,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context 'when repository exists' do
using RSpec::Parameterized::TableSyntax
+ let_it_be(:pipeline, refind: true) { create(:ci_empty_pipeline) }
+
where(:tag, :ref, :result) do
false | 'master' | true
false | 'non-existent-branch' | false
@@ -1728,8 +1747,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
with_them do
- let(:pipeline) do
- create(:ci_empty_pipeline, project: project, tag: tag, ref: ref)
+ before do
+ pipeline.update!(tag: tag, ref: ref)
end
it "correctly detects ref" do
@@ -1739,10 +1758,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
context 'when repository does not exist' do
- let(:project) { create(:project) }
- let(:pipeline) do
- create(:ci_empty_pipeline, project: project, ref: 'master')
- end
+ let(:pipeline) { build(:ci_empty_pipeline, ref: 'master', project: build(:project)) }
it 'always returns false' do
expect(pipeline.ref_exists?).to eq false
@@ -1753,7 +1769,6 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context 'with non-empty project' do
let(:pipeline) do
create(:ci_pipeline,
- project: project,
ref: project.default_branch,
sha: project.commit.sha)
end
@@ -1761,14 +1776,12 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#lazy_ref_commit' do
let(:another) do
create(:ci_pipeline,
- project: project,
ref: 'feature',
sha: project.commit('feature').sha)
end
let(:unicode) do
create(:ci_pipeline,
- project: project,
ref: 'ü/unicode/multi-byte')
end
@@ -1827,6 +1840,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#manual_actions' do
subject { pipeline.manual_actions }
+ let(:pipeline) { create(:ci_empty_pipeline, :created) }
+
it 'when none defined' do
is_expected.to be_empty
end
@@ -1853,9 +1868,11 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#branch_updated?' do
+ let(:pipeline) { create(:ci_empty_pipeline, :created) }
+
context 'when pipeline has before SHA' do
before do
- pipeline.update_column(:before_sha, 'a1b2c3d4')
+ pipeline.update!(before_sha: 'a1b2c3d4')
end
it 'runs on a branch update push' do
@@ -1866,7 +1883,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context 'when pipeline does not have before SHA' do
before do
- pipeline.update_column(:before_sha, Gitlab::Git::BLANK_SHA)
+ pipeline.update!(before_sha: Gitlab::Git::BLANK_SHA)
end
it 'does not run on a branch updating push' do
@@ -1876,6 +1893,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#modified_paths' do
+ let(:pipeline) { create(:ci_empty_pipeline, :created) }
+
context 'when old and new revisions are set' do
before do
pipeline.update!(before_sha: '1234abcd', sha: '2345bcde')
@@ -1892,7 +1911,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context 'when either old or new revision is missing' do
before do
- pipeline.update_column(:before_sha, Gitlab::Git::BLANK_SHA)
+ pipeline.update!(before_sha: Gitlab::Git::BLANK_SHA)
end
it 'returns nil' do
@@ -1906,11 +1925,9 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
let(:merge_request) do
- create(:merge_request,
+ create(:merge_request, :simple,
source_project: project,
- source_branch: 'feature',
- target_project: project,
- target_branch: 'master')
+ target_project: project)
end
it 'returns merge request modified paths' do
@@ -1944,6 +1961,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#has_kubernetes_active?' do
+ let(:pipeline) { create(:ci_empty_pipeline, :created, project: project) }
+
context 'when kubernetes is active' do
context 'when user configured kubernetes from CI/CD > Clusters' do
let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
@@ -1965,6 +1984,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#has_warnings?' do
subject { pipeline.has_warnings? }
+ let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) }
+
context 'build which is allowed to fail fails' do
before do
create :ci_build, :success, pipeline: pipeline, name: 'rspec'
@@ -2021,6 +2042,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#number_of_warnings' do
+ let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) }
+
it 'returns the number of warnings' do
create(:ci_build, :allowed_to_fail, :failed, pipeline: pipeline, name: 'rubocop')
create(:ci_bridge, :allowed_to_fail, :failed, pipeline: pipeline, name: 'rubocop')
@@ -2029,7 +2052,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
it 'supports eager loading of the number of warnings' do
- pipeline2 = create(:ci_empty_pipeline, status: :created, project: project)
+ pipeline2 = create(:ci_empty_pipeline, :created)
create(:ci_build, :allowed_to_fail, :failed, pipeline: pipeline, name: 'rubocop')
create(:ci_build, :allowed_to_fail, :failed, pipeline: pipeline2, name: 'rubocop')
@@ -2053,6 +2076,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
subject { pipeline.needs_processing? }
+ let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) }
+
where(:processed, :result) do
nil | true
false | true
@@ -2072,122 +2097,107 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
end
- shared_context 'with some outdated pipelines' do
- before do
- create_pipeline(:canceled, 'ref', 'A', project)
- create_pipeline(:success, 'ref', 'A', project)
- create_pipeline(:failed, 'ref', 'B', project)
- create_pipeline(:skipped, 'feature', 'C', project)
+ context 'with outdated pipelines' do
+ before_all do
+ create_pipeline(:canceled, 'ref', 'A')
+ create_pipeline(:success, 'ref', 'A')
+ create_pipeline(:failed, 'ref', 'B')
+ create_pipeline(:skipped, 'feature', 'C')
end
- def create_pipeline(status, ref, sha, project)
+ def create_pipeline(status, ref, sha)
create(
:ci_empty_pipeline,
status: status,
ref: ref,
- sha: sha,
- project: project
+ sha: sha
)
end
- end
- describe '.newest_first' do
- include_context 'with some outdated pipelines'
-
- it 'returns the pipelines from new to old' do
- expect(described_class.newest_first.pluck(:status))
- .to eq(%w[skipped failed success canceled])
- end
+ describe '.newest_first' do
+ it 'returns the pipelines from new to old' do
+ expect(described_class.newest_first.pluck(:status))
+ .to eq(%w[skipped failed success canceled])
+ end
- it 'searches limited backlog' do
- expect(described_class.newest_first(limit: 1).pluck(:status))
- .to eq(%w[skipped])
+ it 'searches limited backlog' do
+ expect(described_class.newest_first(limit: 1).pluck(:status))
+ .to eq(%w[skipped])
+ end
end
- end
- describe '.latest_status' do
- include_context 'with some outdated pipelines'
-
- context 'when no ref is specified' do
- it 'returns the status of the latest pipeline' do
- expect(described_class.latest_status).to eq('skipped')
+ describe '.latest_status' do
+ context 'when no ref is specified' do
+ it 'returns the status of the latest pipeline' do
+ expect(described_class.latest_status).to eq('skipped')
+ end
end
- end
- context 'when ref is specified' do
- it 'returns the status of the latest pipeline for the given ref' do
- expect(described_class.latest_status('ref')).to eq('failed')
+ context 'when ref is specified' do
+ it 'returns the status of the latest pipeline for the given ref' do
+ expect(described_class.latest_status('ref')).to eq('failed')
+ end
end
end
- end
- describe '.latest_successful_for_ref' do
- include_context 'with some outdated pipelines'
-
- let!(:latest_successful_pipeline) do
- create_pipeline(:success, 'ref', 'D', project)
- end
+ describe '.latest_successful_for_ref' do
+ let!(:latest_successful_pipeline) do
+ create_pipeline(:success, 'ref', 'D')
+ end
- it 'returns the latest successful pipeline' do
- expect(described_class.latest_successful_for_ref('ref'))
- .to eq(latest_successful_pipeline)
+ it 'returns the latest successful pipeline' do
+ expect(described_class.latest_successful_for_ref('ref'))
+ .to eq(latest_successful_pipeline)
+ end
end
- end
- describe '.latest_running_for_ref' do
- include_context 'with some outdated pipelines'
-
- let!(:latest_running_pipeline) do
- create_pipeline(:running, 'ref', 'D', project)
- end
+ describe '.latest_running_for_ref' do
+ let!(:latest_running_pipeline) do
+ create_pipeline(:running, 'ref', 'D')
+ end
- it 'returns the latest running pipeline' do
- expect(described_class.latest_running_for_ref('ref'))
- .to eq(latest_running_pipeline)
+ it 'returns the latest running pipeline' do
+ expect(described_class.latest_running_for_ref('ref'))
+ .to eq(latest_running_pipeline)
+ end
end
- end
-
- describe '.latest_failed_for_ref' do
- include_context 'with some outdated pipelines'
- let!(:latest_failed_pipeline) do
- create_pipeline(:failed, 'ref', 'D', project)
- end
+ describe '.latest_failed_for_ref' do
+ let!(:latest_failed_pipeline) do
+ create_pipeline(:failed, 'ref', 'D')
+ end
- it 'returns the latest failed pipeline' do
- expect(described_class.latest_failed_for_ref('ref'))
- .to eq(latest_failed_pipeline)
+ it 'returns the latest failed pipeline' do
+ expect(described_class.latest_failed_for_ref('ref'))
+ .to eq(latest_failed_pipeline)
+ end
end
- end
-
- describe '.latest_successful_for_sha' do
- include_context 'with some outdated pipelines'
- let!(:latest_successful_pipeline) do
- create_pipeline(:success, 'ref', 'awesomesha', project)
- end
+ describe '.latest_successful_for_sha' do
+ let!(:latest_successful_pipeline) do
+ create_pipeline(:success, 'ref', 'awesomesha')
+ end
- it 'returns the latest successful pipeline' do
- expect(described_class.latest_successful_for_sha('awesomesha'))
- .to eq(latest_successful_pipeline)
+ it 'returns the latest successful pipeline' do
+ expect(described_class.latest_successful_for_sha('awesomesha'))
+ .to eq(latest_successful_pipeline)
+ end
end
- end
-
- describe '.latest_successful_for_refs' do
- include_context 'with some outdated pipelines'
- let!(:latest_successful_pipeline1) do
- create_pipeline(:success, 'ref1', 'D', project)
- end
+ describe '.latest_successful_for_refs' do
+ let!(:latest_successful_pipeline1) do
+ create_pipeline(:success, 'ref1', 'D')
+ end
- let!(:latest_successful_pipeline2) do
- create_pipeline(:success, 'ref2', 'D', project)
- end
+ let!(:latest_successful_pipeline2) do
+ create_pipeline(:success, 'ref2', 'D')
+ end
- it 'returns the latest successful pipeline for both refs' do
- refs = %w(ref1 ref2 ref3)
+ it 'returns the latest successful pipeline for both refs' do
+ refs = %w(ref1 ref2 ref3)
- expect(described_class.latest_successful_for_refs(refs)).to eq({ 'ref1' => latest_successful_pipeline1, 'ref2' => latest_successful_pipeline2 })
+ expect(described_class.latest_successful_for_refs(refs)).to eq({ 'ref1' => latest_successful_pipeline1, 'ref2' => latest_successful_pipeline2 })
+ end
end
end
@@ -2197,8 +2207,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
:ci_empty_pipeline,
status: 'success',
ref: 'master',
- sha: '123',
- project: project
+ sha: '123'
)
end
@@ -2207,8 +2216,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
:ci_empty_pipeline,
status: 'success',
ref: 'develop',
- sha: '123',
- project: project
+ sha: '123'
)
end
@@ -2217,8 +2225,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
:ci_empty_pipeline,
status: 'success',
ref: 'test',
- sha: '456',
- project: project
+ sha: '456'
)
end
@@ -2315,12 +2322,11 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#status', :sidekiq_inline do
- let(:build) do
- create(:ci_build, :created, pipeline: pipeline, name: 'test')
- end
-
subject { pipeline.reload.status }
+ let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) }
+ let(:build) { create(:ci_build, :created, pipeline: pipeline, name: 'test') }
+
context 'on waiting for resource' do
before do
allow(build).to receive(:with_resource_group?) { true }
@@ -2412,8 +2418,10 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#detailed_status' do
subject { pipeline.detailed_status(user) }
+ let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) }
+
context 'when pipeline is created' do
- let(:pipeline) { create(:ci_pipeline, status: :created) }
+ let(:pipeline) { create(:ci_pipeline, :created) }
it 'returns detailed status for created pipeline' do
expect(subject.text).to eq s_('CiStatusText|created')
@@ -2490,6 +2498,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#cancelable?' do
+ let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) }
+
%i[created running pending].each do |status0|
context "when there is a build #{status0}" do
before do
@@ -2581,7 +2591,9 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#cancel_running' do
- let(:latest_status) { pipeline.statuses.pluck(:status) }
+ subject(:latest_status) { pipeline.statuses.pluck(:status) }
+
+ let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) }
context 'when there is a running external job and a regular job' do
before do
@@ -2624,7 +2636,9 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#retry_failed' do
- let(:latest_status) { pipeline.latest_statuses.pluck(:status) }
+ subject(:latest_status) { pipeline.latest_statuses.pluck(:status) }
+
+ let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) }
before do
stub_not_protect_default_branch
@@ -2673,11 +2687,12 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#execute_hooks' do
+ let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) }
let!(:build_a) { create_build('a', 0) }
let!(:build_b) { create_build('b', 0) }
let!(:hook) do
- create(:project_hook, project: project, pipeline_events: enabled)
+ create(:project_hook, pipeline_events: enabled)
end
before do
@@ -2703,7 +2718,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
it 'builds hook data once' do
- create(:pipelines_email_service, project: project)
+ create(:pipelines_email_service)
expect(Gitlab::DataBuilder::Pipeline).to receive(:build).once.and_call_original
@@ -2789,7 +2804,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe "#merge_requests_as_head_pipeline" do
- let(:pipeline) { create(:ci_empty_pipeline, status: 'created', project: project, ref: 'master', sha: 'a288a022a53a5a944fae87bcec6efc87b7061808') }
+ let_it_be_with_reload(:pipeline) { create(:ci_empty_pipeline, status: 'created', ref: 'master', sha: 'a288a022a53a5a944fae87bcec6efc87b7061808') }
it "returns merge requests whose `diff_head_sha` matches the pipeline's SHA" do
allow_next_instance_of(MergeRequest) do |instance|
@@ -2801,7 +2816,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
it "doesn't return merge requests whose source branch doesn't match the pipeline's ref" do
- create(:merge_request, source_project: project, source_branch: 'feature', target_branch: 'master')
+ create(:merge_request, :simple, source_project: project)
expect(pipeline.merge_requests_as_head_pipeline).to be_empty
end
@@ -2817,7 +2832,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#all_merge_requests' do
- let(:project) { create(:project) }
+ let_it_be_with_reload(:project) { create(:project) }
+ let_it_be(:pipeline) { create(:ci_empty_pipeline, :created, project: project) }
shared_examples 'a method that returns all merge requests for a given pipeline' do
let(:pipeline) { create(:ci_empty_pipeline, status: 'created', project: pipeline_project, ref: 'master') }
@@ -2911,10 +2927,9 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#related_merge_requests' do
- let(:project) { create(:project, :repository) }
let(:merge_request) { create(:merge_request, source_project: project, source_branch: 'feature', target_branch: 'master') }
let(:other_merge_request) { create(:merge_request, source_project: project, source_branch: 'feature', target_branch: 'stable') }
- let(:branch_pipeline) { create(:ci_pipeline, project: project, ref: 'feature') }
+ let(:branch_pipeline) { create(:ci_pipeline, ref: 'feature') }
let(:merge_pipeline) { create(:ci_pipeline, :detached_merge_request_pipeline, merge_request: merge_request) }
context 'for a branch pipeline' do
@@ -2951,9 +2966,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#open_merge_requests_refs' do
- let(:project) { create(:project) }
- let(:user) { create(:user) }
- let!(:pipeline) { create(:ci_pipeline, user: user, project: project, ref: 'feature') }
+ let!(:pipeline) { create(:ci_pipeline, user: user, ref: 'feature') }
let!(:merge_request) { create(:merge_request, source_project: project, source_branch: 'feature', target_branch: 'master') }
subject { pipeline.open_merge_requests_refs }
@@ -3000,6 +3013,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#same_family_pipeline_ids' do
subject { pipeline.same_family_pipeline_ids.map(&:id) }
+ let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) }
+
context 'when pipeline is not child nor parent' do
it 'returns just the pipeline id' do
expect(subject).to contain_exactly(pipeline.id)
@@ -3007,7 +3022,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
context 'when pipeline is child' do
- let(:parent) { create(:ci_pipeline, project: project) }
+ let(:parent) { create(:ci_pipeline) }
let!(:pipeline) { create(:ci_pipeline, child_of: parent) }
let!(:sibling) { create(:ci_pipeline, child_of: parent) }
@@ -3025,7 +3040,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
context 'when pipeline is a child of a child pipeline' do
- let(:ancestor) { create(:ci_pipeline, project: project) }
+ let(:ancestor) { create(:ci_pipeline) }
let!(:parent) { create(:ci_pipeline, child_of: ancestor) }
let!(:pipeline) { create(:ci_pipeline, child_of: parent) }
let!(:cousin_parent) { create(:ci_pipeline, child_of: ancestor) }
@@ -3050,10 +3065,10 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#root_ancestor' do
subject { pipeline.root_ancestor }
- let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+ let_it_be(:pipeline) { create(:ci_pipeline) }
context 'when pipeline is child of child pipeline' do
- let!(:root_ancestor) { create(:ci_pipeline, project: project) }
+ let!(:root_ancestor) { create(:ci_pipeline) }
let!(:parent_pipeline) { create(:ci_pipeline, child_of: root_ancestor) }
let!(:pipeline) { create(:ci_pipeline, child_of: parent_pipeline) }
@@ -3088,6 +3103,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#stuck?' do
+ let(:pipeline) { create(:ci_empty_pipeline, :created) }
+
before do
create(:ci_build, :pending, pipeline: pipeline)
end
@@ -3132,6 +3149,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#has_yaml_errors?' do
+ let(:pipeline) { build_stubbed(:ci_pipeline) }
+
context 'when yaml_errors is set' do
before do
pipeline.yaml_errors = 'File not found'
@@ -3201,7 +3220,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context 'when pipeline is not the latest' do
before do
- create(:ci_pipeline, :success, project: project, ci_ref: pipeline.ci_ref)
+ create(:ci_pipeline, :success, ci_ref: pipeline.ci_ref)
end
it 'does not pass ref_status' do
@@ -3302,7 +3321,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#builds_in_self_and_descendants' do
subject(:builds) { pipeline.builds_in_self_and_descendants }
- let(:pipeline) { create(:ci_pipeline, project: project) }
+ let(:pipeline) { create(:ci_pipeline) }
let!(:build) { create(:ci_build, pipeline: pipeline) }
context 'when pipeline is standalone' do
@@ -3333,6 +3352,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#build_with_artifacts_in_self_and_descendants' do
+ let_it_be(:pipeline) { create(:ci_pipeline) }
let!(:build) { create(:ci_build, name: 'test', pipeline: pipeline) }
let(:child_pipeline) { create(:ci_pipeline, child_of: pipeline) }
let!(:child_build) { create(:ci_build, :artifacts, name: 'test', pipeline: child_pipeline) }
@@ -3351,6 +3371,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#find_job_with_archive_artifacts' do
+ let(:pipeline) { create(:ci_pipeline) }
let!(:old_job) { create(:ci_build, name: 'rspec', retried: true, pipeline: pipeline) }
let!(:job_without_artifacts) { create(:ci_build, name: 'rspec', pipeline: pipeline) }
let!(:expected_job) { create(:ci_build, :artifacts, name: 'rspec', pipeline: pipeline ) }
@@ -3364,6 +3385,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#latest_builds_with_artifacts' do
+ let(:pipeline) { create(:ci_pipeline) }
let!(:fresh_build) { create(:ci_build, :success, :artifacts, pipeline: pipeline) }
let!(:stale_build) { create(:ci_build, :success, :expired, :artifacts, pipeline: pipeline) }
@@ -3390,7 +3412,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#batch_lookup_report_artifact_for_file_type' do
context 'with code quality report artifact' do
- let(:pipeline) { create(:ci_pipeline, :with_codequality_reports, project: project) }
+ let(:pipeline) { create(:ci_pipeline, :with_codequality_reports) }
it "returns the code quality artifact" do
expect(pipeline.batch_lookup_report_artifact_for_file_type(:codequality)).to eq(pipeline.job_artifacts.sample)
@@ -3399,24 +3421,26 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#latest_report_builds' do
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+
it 'returns build with test artifacts' do
- test_build = create(:ci_build, :test_reports, pipeline: pipeline, project: project)
- coverage_build = create(:ci_build, :coverage_reports, pipeline: pipeline, project: project)
+ test_build = create(:ci_build, :test_reports, pipeline: pipeline)
+ coverage_build = create(:ci_build, :coverage_reports, pipeline: pipeline)
create(:ci_build, :artifacts, pipeline: pipeline, project: project)
expect(pipeline.latest_report_builds).to contain_exactly(test_build, coverage_build)
end
it 'filters builds by scope' do
- test_build = create(:ci_build, :test_reports, pipeline: pipeline, project: project)
- create(:ci_build, :coverage_reports, pipeline: pipeline, project: project)
+ test_build = create(:ci_build, :test_reports, pipeline: pipeline)
+ create(:ci_build, :coverage_reports, pipeline: pipeline)
expect(pipeline.latest_report_builds(Ci::JobArtifact.test_reports)).to contain_exactly(test_build)
end
it 'only returns not retried builds' do
- test_build = create(:ci_build, :test_reports, pipeline: pipeline, project: project)
- create(:ci_build, :test_reports, :retried, pipeline: pipeline, project: project)
+ test_build = create(:ci_build, :test_reports, pipeline: pipeline)
+ create(:ci_build, :test_reports, :retried, pipeline: pipeline)
expect(pipeline.latest_report_builds).to contain_exactly(test_build)
end
@@ -3427,17 +3451,17 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context 'when pipeline has builds with test reports' do
before do
- create(:ci_build, :test_reports, pipeline: pipeline, project: project)
+ create(:ci_build, :test_reports, pipeline: pipeline)
end
context 'when pipeline status is running' do
- let(:pipeline) { create(:ci_pipeline, :running, project: project) }
+ let(:pipeline) { create(:ci_pipeline, :running) }
it { is_expected.to be_falsey }
end
context 'when pipeline status is success' do
- let(:pipeline) { create(:ci_pipeline, :success, project: project) }
+ let(:pipeline) { create(:ci_pipeline, :success) }
it { is_expected.to be_truthy }
end
@@ -3445,20 +3469,20 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context 'when pipeline does not have builds with test reports' do
before do
- create(:ci_build, :artifacts, pipeline: pipeline, project: project)
+ create(:ci_build, :artifacts, pipeline: pipeline)
end
- let(:pipeline) { create(:ci_pipeline, :success, project: project) }
+ let(:pipeline) { create(:ci_pipeline, :success) }
it { is_expected.to be_falsey }
end
context 'when retried build has test reports' do
before do
- create(:ci_build, :retried, :test_reports, pipeline: pipeline, project: project)
+ create(:ci_build, :retried, :test_reports, pipeline: pipeline)
end
- let(:pipeline) { create(:ci_pipeline, :success, project: project) }
+ let(:pipeline) { create(:ci_pipeline, :success) }
it { is_expected.to be_falsey }
end
@@ -3468,13 +3492,13 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
subject { pipeline.has_coverage_reports? }
context 'when pipeline has a code coverage artifact' do
- let(:pipeline) { create(:ci_pipeline, :with_coverage_report_artifact, :running, project: project) }
+ let(:pipeline) { create(:ci_pipeline, :with_coverage_report_artifact, :running) }
it { expect(subject).to be_truthy }
end
context 'when pipeline does not have a code coverage artifact' do
- let(:pipeline) { create(:ci_pipeline, :success, project: project) }
+ let(:pipeline) { create(:ci_pipeline, :success) }
it { expect(subject).to be_falsey }
end
@@ -3485,17 +3509,17 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context 'when pipeline has builds with coverage reports' do
before do
- create(:ci_build, :coverage_reports, pipeline: pipeline, project: project)
+ create(:ci_build, :coverage_reports, pipeline: pipeline)
end
context 'when pipeline status is running' do
- let(:pipeline) { create(:ci_pipeline, :running, project: project) }
+ let(:pipeline) { create(:ci_pipeline, :running) }
it { expect(subject).to be_falsey }
end
context 'when pipeline status is success' do
- let(:pipeline) { create(:ci_pipeline, :success, project: project) }
+ let(:pipeline) { create(:ci_pipeline, :success) }
it { expect(subject).to be_truthy }
end
@@ -3503,10 +3527,10 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context 'when pipeline does not have builds with coverage reports' do
before do
- create(:ci_build, :artifacts, pipeline: pipeline, project: project)
+ create(:ci_build, :artifacts, pipeline: pipeline)
end
- let(:pipeline) { create(:ci_pipeline, :success, project: project) }
+ let(:pipeline) { create(:ci_pipeline, :success) }
it { expect(subject).to be_falsey }
end
@@ -3516,13 +3540,13 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
subject { pipeline.has_codequality_mr_diff_report? }
context 'when pipeline has a codequality mr diff report' do
- let(:pipeline) { create(:ci_pipeline, :with_codequality_mr_diff_report, :running, project: project) }
+ let(:pipeline) { create(:ci_pipeline, :with_codequality_mr_diff_report, :running) }
it { expect(subject).to be_truthy }
end
context 'when pipeline does not have a codequality mr diff report' do
- let(:pipeline) { create(:ci_pipeline, :success, project: project) }
+ let(:pipeline) { create(:ci_pipeline, :success) }
it { expect(subject).to be_falsey }
end
@@ -3533,17 +3557,17 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context 'when pipeline has builds with codequality reports' do
before do
- create(:ci_build, :codequality_reports, pipeline: pipeline, project: project)
+ create(:ci_build, :codequality_reports, pipeline: pipeline)
end
context 'when pipeline status is running' do
- let(:pipeline) { create(:ci_pipeline, :running, project: project) }
+ let(:pipeline) { create(:ci_pipeline, :running) }
it { expect(subject).to be_falsey }
end
context 'when pipeline status is success' do
- let(:pipeline) { create(:ci_pipeline, :success, project: project) }
+ let(:pipeline) { create(:ci_pipeline, :success) }
it 'can generate a codequality report' do
expect(subject).to be_truthy
@@ -3563,10 +3587,10 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context 'when pipeline does not have builds with codequality reports' do
before do
- create(:ci_build, :artifacts, pipeline: pipeline, project: project)
+ create(:ci_build, :artifacts, pipeline: pipeline)
end
- let(:pipeline) { create(:ci_pipeline, :success, project: project) }
+ let(:pipeline) { create(:ci_pipeline, :success) }
it { expect(subject).to be_falsey }
end
@@ -3575,12 +3599,12 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#test_report_summary' do
subject { pipeline.test_report_summary }
- context 'when pipeline has multiple builds with report results' do
- let(:pipeline) { create(:ci_pipeline, :success, project: project) }
+ let(:pipeline) { create(:ci_pipeline, :success) }
+ context 'when pipeline has multiple builds with report results' do
before do
- create(:ci_build, :success, :report_results, name: 'rspec', pipeline: pipeline, project: project)
- create(:ci_build, :success, :report_results, name: 'java', pipeline: pipeline, project: project)
+ create(:ci_build, :success, :report_results, name: 'rspec', pipeline: pipeline)
+ create(:ci_build, :success, :report_results, name: 'java', pipeline: pipeline)
end
it 'returns test report summary with collected data' do
@@ -3598,13 +3622,15 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#test_reports' do
subject { pipeline.test_reports }
+ let_it_be(:pipeline) { create(:ci_pipeline) }
+
context 'when pipeline has multiple builds with test reports' do
- let!(:build_rspec) { create(:ci_build, :success, name: 'rspec', pipeline: pipeline, project: project) }
- let!(:build_java) { create(:ci_build, :success, name: 'java', pipeline: pipeline, project: project) }
+ let!(:build_rspec) { create(:ci_build, :success, name: 'rspec', pipeline: pipeline) }
+ let!(:build_java) { create(:ci_build, :success, name: 'java', pipeline: pipeline) }
before do
- create(:ci_job_artifact, :junit, job: build_rspec, project: project)
- create(:ci_job_artifact, :junit_with_ant, job: build_java, project: project)
+ create(:ci_job_artifact, :junit, job: build_rspec)
+ create(:ci_job_artifact, :junit_with_ant, job: build_java)
end
it 'returns test reports with collected data' do
@@ -3614,8 +3640,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
context 'when builds are retried' do
- let!(:build_rspec) { create(:ci_build, :retried, :success, name: 'rspec', pipeline: pipeline, project: project) }
- let!(:build_java) { create(:ci_build, :retried, :success, name: 'java', pipeline: pipeline, project: project) }
+ let!(:build_rspec) { create(:ci_build, :retried, :success, name: 'rspec', pipeline: pipeline) }
+ let!(:build_java) { create(:ci_build, :retried, :success, name: 'java', pipeline: pipeline) }
it 'does not take retried builds into account' do
expect(subject.total_count).to be(0)
@@ -3635,13 +3661,15 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#accessibility_reports' do
subject { pipeline.accessibility_reports }
+ let_it_be(:pipeline) { create(:ci_pipeline) }
+
context 'when pipeline has multiple builds with accessibility reports' do
- let(:build_rspec) { create(:ci_build, :success, name: 'rspec', pipeline: pipeline, project: project) }
- let(:build_golang) { create(:ci_build, :success, name: 'golang', pipeline: pipeline, project: project) }
+ let(:build_rspec) { create(:ci_build, :success, name: 'rspec', pipeline: pipeline) }
+ let(:build_golang) { create(:ci_build, :success, name: 'golang', pipeline: pipeline) }
before do
- create(:ci_job_artifact, :accessibility, job: build_rspec, project: project)
- create(:ci_job_artifact, :accessibility_without_errors, job: build_golang, project: project)
+ create(:ci_job_artifact, :accessibility, job: build_rspec)
+ create(:ci_job_artifact, :accessibility_without_errors, job: build_golang)
end
it 'returns accessibility report with collected data' do
@@ -3652,8 +3680,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
context 'when builds are retried' do
- let(:build_rspec) { create(:ci_build, :retried, :success, name: 'rspec', pipeline: pipeline, project: project) }
- let(:build_golang) { create(:ci_build, :retried, :success, name: 'golang', pipeline: pipeline, project: project) }
+ let(:build_rspec) { create(:ci_build, :retried, :success, name: 'rspec', pipeline: pipeline) }
+ let(:build_golang) { create(:ci_build, :retried, :success, name: 'golang', pipeline: pipeline) }
it 'returns empty urls for accessibility reports' do
expect(subject.urls).to be_empty
@@ -3671,13 +3699,15 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#coverage_reports' do
subject { pipeline.coverage_reports }
+ let_it_be(:pipeline) { create(:ci_pipeline) }
+
context 'when pipeline has multiple builds with coverage reports' do
- let!(:build_rspec) { create(:ci_build, :success, name: 'rspec', pipeline: pipeline, project: project) }
- let!(:build_golang) { create(:ci_build, :success, name: 'golang', pipeline: pipeline, project: project) }
+ let!(:build_rspec) { create(:ci_build, :success, name: 'rspec', pipeline: pipeline) }
+ let!(:build_golang) { create(:ci_build, :success, name: 'golang', pipeline: pipeline) }
before do
- create(:ci_job_artifact, :cobertura, job: build_rspec, project: project)
- create(:ci_job_artifact, :coverage_gocov_xml, job: build_golang, project: project)
+ create(:ci_job_artifact, :cobertura, job: build_rspec)
+ create(:ci_job_artifact, :coverage_gocov_xml, job: build_golang)
end
it 'returns coverage reports with collected data' do
@@ -3689,8 +3719,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
it 'does not execute N+1 queries' do
- single_build_pipeline = create(:ci_empty_pipeline, status: :created, project: project)
- single_rspec = create(:ci_build, :success, name: 'rspec', pipeline: single_build_pipeline, project: project)
+ single_build_pipeline = create(:ci_empty_pipeline, :created)
+ single_rspec = create(:ci_build, :success, name: 'rspec', pipeline: single_build_pipeline)
create(:ci_job_artifact, :cobertura, job: single_rspec, project: project)
control = ActiveRecord::QueryRecorder.new { single_build_pipeline.coverage_reports }
@@ -3699,8 +3729,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
context 'when builds are retried' do
- let!(:build_rspec) { create(:ci_build, :retried, :success, name: 'rspec', pipeline: pipeline, project: project) }
- let!(:build_golang) { create(:ci_build, :retried, :success, name: 'golang', pipeline: pipeline, project: project) }
+ let!(:build_rspec) { create(:ci_build, :retried, :success, name: 'rspec', pipeline: pipeline) }
+ let!(:build_golang) { create(:ci_build, :retried, :success, name: 'golang', pipeline: pipeline) }
it 'does not take retried builds into account' do
expect(subject.files).to eql({})
@@ -3718,13 +3748,15 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#codequality_reports' do
subject(:codequality_reports) { pipeline.codequality_reports }
+ let_it_be(:pipeline) { create(:ci_pipeline) }
+
context 'when pipeline has multiple builds with codequality reports' do
- let(:build_rspec) { create(:ci_build, :success, name: 'rspec', pipeline: pipeline, project: project) }
- let(:build_golang) { create(:ci_build, :success, name: 'golang', pipeline: pipeline, project: project) }
+ let(:build_rspec) { create(:ci_build, :success, name: 'rspec', pipeline: pipeline) }
+ let(:build_golang) { create(:ci_build, :success, name: 'golang', pipeline: pipeline) }
before do
- create(:ci_job_artifact, :codequality, job: build_rspec, project: project)
- create(:ci_job_artifact, :codequality_without_errors, job: build_golang, project: project)
+ create(:ci_job_artifact, :codequality, job: build_rspec)
+ create(:ci_job_artifact, :codequality_without_errors, job: build_golang)
end
it 'returns codequality report with collected data' do
@@ -3732,8 +3764,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
context 'when builds are retried' do
- let(:build_rspec) { create(:ci_build, :retried, :success, name: 'rspec', pipeline: pipeline, project: project) }
- let(:build_golang) { create(:ci_build, :retried, :success, name: 'golang', pipeline: pipeline, project: project) }
+ let(:build_rspec) { create(:ci_build, :retried, :success, name: 'rspec', pipeline: pipeline) }
+ let(:build_golang) { create(:ci_build, :retried, :success, name: 'golang', pipeline: pipeline) }
it 'returns a codequality reports without degradations' do
expect(codequality_reports.degradations).to be_empty
@@ -3749,6 +3781,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#total_size' do
+ let(:pipeline) { create(:ci_pipeline) }
let!(:build_job1) { create(:ci_build, pipeline: pipeline, stage_idx: 0) }
let!(:build_job2) { create(:ci_build, pipeline: pipeline, stage_idx: 0) }
let!(:test_job_failed_and_retried) { create(:ci_build, :failed, :retried, pipeline: pipeline, stage_idx: 1) }
@@ -3785,17 +3818,11 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#default_branch?' do
- let(:default_branch) { 'master'}
-
subject { pipeline.default_branch? }
- before do
- allow(project).to receive(:default_branch).and_return(default_branch)
- end
-
context 'when pipeline ref is the default branch of the project' do
let(:pipeline) do
- build(:ci_empty_pipeline, status: :created, project: project, ref: default_branch)
+ build(:ci_empty_pipeline, :created, project: project, ref: project.default_branch)
end
it "returns true" do
@@ -3805,7 +3832,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context 'when pipeline ref is not the default branch of the project' do
let(:pipeline) do
- build(:ci_empty_pipeline, status: :created, project: project, ref: 'another_branch')
+ build(:ci_empty_pipeline, :created, project: project, ref: 'another_branch')
end
it "returns false" do
@@ -3815,7 +3842,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#find_stage_by_name' do
- let(:pipeline) { create(:ci_pipeline) }
+ let_it_be(:pipeline) { create(:ci_pipeline) }
let(:stage_name) { 'test' }
let(:stage) do
@@ -3895,10 +3922,10 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#parent_pipeline' do
- let_it_be(:project) { create(:project) }
+ let_it_be_with_reload(:pipeline) { create(:ci_pipeline) }
context 'when pipeline is triggered by a pipeline from the same project' do
- let_it_be(:upstream_pipeline) { create(:ci_pipeline, project: project) }
+ let_it_be(:upstream_pipeline) { create(:ci_pipeline) }
let_it_be(:pipeline) { create(:ci_pipeline, child_of: upstream_pipeline) }
it 'returns the parent pipeline' do
@@ -3911,7 +3938,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
context 'when pipeline is triggered by a pipeline from another project' do
- let(:pipeline) { create(:ci_pipeline, project: project) }
+ let(:pipeline) { create(:ci_pipeline) }
let!(:upstream_pipeline) { create(:ci_pipeline, project: create(:project), upstream_of: pipeline) }
it 'returns nil' do
@@ -3938,7 +3965,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#child_pipelines' do
let_it_be(:project) { create(:project) }
- let(:pipeline) { create(:ci_pipeline, project: project) }
+ let_it_be_with_reload(:pipeline) { create(:ci_pipeline, project: project) }
context 'when pipeline triggered other pipelines on same project' do
let(:downstream_pipeline) { create(:ci_pipeline, project: pipeline.project) }
@@ -3992,6 +4019,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe 'upstream status interactions' do
+ let_it_be_with_reload(:pipeline) { create(:ci_pipeline, :created) }
+
context 'when a pipeline has an upstream status' do
context 'when an upstream status is a bridge' do
let(:bridge) { create(:ci_bridge, status: :pending) }
@@ -4050,6 +4079,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#source_ref_path' do
subject { pipeline.source_ref_path }
+ let(:pipeline) { create(:ci_pipeline, :created) }
+
context 'when pipeline is for a branch' do
it { is_expected.to eq(Gitlab::Git::BRANCH_REF_PREFIX + pipeline.source_ref.to_s) }
end
@@ -4062,13 +4093,15 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
context 'when pipeline is for a tag' do
- let(:pipeline) { create(:ci_pipeline, project: project, tag: true) }
+ let(:pipeline) { create(:ci_pipeline, tag: true) }
it { is_expected.to eq(Gitlab::Git::TAG_REF_PREFIX + pipeline.source_ref.to_s) }
end
end
- describe "#builds_with_coverage" do
+ describe '#builds_with_coverage' do
+ let_it_be(:pipeline) { create(:ci_pipeline, :created) }
+
it 'returns builds with coverage only' do
rspec = create(:ci_build, name: 'rspec', coverage: 97.1, pipeline: pipeline)
jest = create(:ci_build, name: 'jest', coverage: 94.1, pipeline: pipeline)
@@ -4092,10 +4125,11 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#base_and_ancestors' do
- let(:same_project) { false }
-
subject { pipeline.base_and_ancestors(same_project: same_project) }
+ let_it_be(:pipeline) { create(:ci_pipeline, :created) }
+ let(:same_project) { false }
+
context 'when pipeline is not child nor parent' do
it 'returns just the pipeline itself' do
expect(subject).to contain_exactly(pipeline)
@@ -4103,8 +4137,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
context 'when pipeline is child' do
- let(:parent) { create(:ci_pipeline, project: pipeline.project) }
- let(:sibling) { create(:ci_pipeline, project: pipeline.project) }
+ let(:parent) { create(:ci_pipeline) }
+ let(:sibling) { create(:ci_pipeline) }
before do
create_source_pipeline(parent, pipeline)
@@ -4117,7 +4151,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
context 'when pipeline is parent' do
- let(:child) { create(:ci_pipeline, project: pipeline.project) }
+ let(:child) { create(:ci_pipeline) }
before do
create_source_pipeline(pipeline, child)
@@ -4129,8 +4163,9 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
context 'when pipeline is a child of a child pipeline' do
- let(:ancestor) { create(:ci_pipeline, project: pipeline.project) }
- let(:parent) { create(:ci_pipeline, project: pipeline.project) }
+ let_it_be(:pipeline) { create(:ci_pipeline, :created) }
+ let(:ancestor) { create(:ci_pipeline) }
+ let(:parent) { create(:ci_pipeline) }
before do
create_source_pipeline(ancestor, parent)
@@ -4143,6 +4178,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
context 'when pipeline is a triggered pipeline' do
+ let_it_be(:pipeline) { create(:ci_pipeline, :created) }
let(:upstream) { create(:ci_pipeline, project: create(:project)) }
before do
@@ -4166,8 +4202,10 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe 'reset_ancestor_bridges!' do
+ let_it_be(:pipeline) { create(:ci_pipeline, :created) }
+
context 'when the pipeline is a child pipeline and the bridge is depended' do
- let!(:parent_pipeline) { create(:ci_pipeline, project: project) }
+ let!(:parent_pipeline) { create(:ci_pipeline) }
let!(:bridge) { create_bridge(parent_pipeline, pipeline, true) }
it 'marks source bridge as pending' do
@@ -4191,7 +4229,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
context 'when the pipeline is a child pipeline and the bridge is not depended' do
- let!(:parent_pipeline) { create(:ci_pipeline, project: project) }
+ let!(:parent_pipeline) { create(:ci_pipeline) }
let!(:bridge) { create_bridge(parent_pipeline, pipeline, false) }
it 'does not touch source bridge' do
@@ -4227,6 +4265,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe 'test failure history processing' do
+ let(:pipeline) { build(:ci_pipeline, :created) }
+
it 'performs the service asynchronously when the pipeline is completed' do
service = double
@@ -4238,21 +4278,23 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#latest_test_report_builds' do
+ let_it_be(:pipeline) { create(:ci_pipeline, :created) }
+
it 'returns pipeline builds with test report artifacts' do
- test_build = create(:ci_build, :test_reports, pipeline: pipeline, project: project)
+ test_build = create(:ci_build, :test_reports, pipeline: pipeline)
create(:ci_build, :artifacts, pipeline: pipeline, project: project)
expect(pipeline.latest_test_report_builds).to contain_exactly(test_build)
end
it 'preloads project on each build to avoid N+1 queries' do
- create(:ci_build, :test_reports, pipeline: pipeline, project: project)
+ create(:ci_build, :test_reports, pipeline: pipeline)
control_count = ActiveRecord::QueryRecorder.new do
pipeline.latest_test_report_builds.map(&:project).map(&:full_path)
end
- multi_build_pipeline = create(:ci_empty_pipeline, status: :created, project: project)
+ multi_build_pipeline = create(:ci_empty_pipeline, :created)
create(:ci_build, :test_reports, pipeline: multi_build_pipeline, project: project)
create(:ci_build, :test_reports, pipeline: multi_build_pipeline, project: project)
@@ -4262,30 +4304,32 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#builds_with_failed_tests' do
+ let_it_be(:pipeline) { create(:ci_pipeline, :created) }
+
it 'returns pipeline builds with test report artifacts' do
- failed_build = create(:ci_build, :failed, :test_reports, pipeline: pipeline, project: project)
- create(:ci_build, :success, :test_reports, pipeline: pipeline, project: project)
+ failed_build = create(:ci_build, :failed, :test_reports, pipeline: pipeline)
+ create(:ci_build, :success, :test_reports, pipeline: pipeline)
expect(pipeline.builds_with_failed_tests).to contain_exactly(failed_build)
end
it 'supports limiting the number of builds to fetch' do
- create(:ci_build, :failed, :test_reports, pipeline: pipeline, project: project)
- create(:ci_build, :failed, :test_reports, pipeline: pipeline, project: project)
+ create(:ci_build, :failed, :test_reports, pipeline: pipeline)
+ create(:ci_build, :failed, :test_reports, pipeline: pipeline)
expect(pipeline.builds_with_failed_tests(limit: 1).count).to eq(1)
end
it 'preloads project on each build to avoid N+1 queries' do
- create(:ci_build, :failed, :test_reports, pipeline: pipeline, project: project)
+ create(:ci_build, :failed, :test_reports, pipeline: pipeline)
control_count = ActiveRecord::QueryRecorder.new do
pipeline.builds_with_failed_tests.map(&:project).map(&:full_path)
end
- multi_build_pipeline = create(:ci_empty_pipeline, status: :created, project: project)
- create(:ci_build, :failed, :test_reports, pipeline: multi_build_pipeline, project: project)
- create(:ci_build, :failed, :test_reports, pipeline: multi_build_pipeline, project: project)
+ multi_build_pipeline = create(:ci_empty_pipeline, :created)
+ create(:ci_build, :failed, :test_reports, pipeline: multi_build_pipeline)
+ create(:ci_build, :failed, :test_reports, pipeline: multi_build_pipeline)
expect { multi_build_pipeline.builds_with_failed_tests.map(&:project).map(&:full_path) }
.not_to exceed_query_limit(control_count)
diff --git a/spec/models/ci/processable_spec.rb b/spec/models/ci/processable_spec.rb
index 6290f4aef16..0a43f785598 100644
--- a/spec/models/ci/processable_spec.rb
+++ b/spec/models/ci/processable_spec.rb
@@ -112,8 +112,8 @@ RSpec.describe Ci::Processable do
it 'returns all needs attributes' do
is_expected.to contain_exactly(
- { 'artifacts' => true, 'name' => 'test1' },
- { 'artifacts' => true, 'name' => 'test2' }
+ { 'artifacts' => true, 'name' => 'test1', 'optional' => false },
+ { 'artifacts' => true, 'name' => 'test2', 'optional' => false }
)
end
end
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb
index 3e5d068d780..ff3551d2a18 100644
--- a/spec/models/ci/runner_spec.rb
+++ b/spec/models/ci/runner_spec.rb
@@ -40,41 +40,39 @@ RSpec.describe Ci::Runner do
context 'runner_type validations' do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project) }
- let(:group_runner) { create(:ci_runner, :group, groups: [group]) }
- let(:project_runner) { create(:ci_runner, :project, projects: [project]) }
- let(:instance_runner) { create(:ci_runner, :instance) }
it 'disallows assigning group to project_type runner' do
- project_runner.groups << build(:group)
+ project_runner = build(:ci_runner, :project, groups: [group])
expect(project_runner).not_to be_valid
expect(project_runner.errors.full_messages).to include('Runner cannot have groups assigned')
end
it 'disallows assigning group to instance_type runner' do
- instance_runner.groups << build(:group)
+ instance_runner = build(:ci_runner, :instance, groups: [group])
expect(instance_runner).not_to be_valid
expect(instance_runner.errors.full_messages).to include('Runner cannot have groups assigned')
end
it 'disallows assigning project to group_type runner' do
- group_runner.projects << build(:project)
+ group_runner = build(:ci_runner, :instance, projects: [project])
expect(group_runner).not_to be_valid
expect(group_runner.errors.full_messages).to include('Runner cannot have projects assigned')
end
it 'disallows assigning project to instance_type runner' do
- instance_runner.projects << build(:project)
+ instance_runner = build(:ci_runner, :instance, projects: [project])
expect(instance_runner).not_to be_valid
expect(instance_runner.errors.full_messages).to include('Runner cannot have projects assigned')
end
it 'fails to save a group assigned to a project runner even if the runner is already saved' do
- group.runners << project_runner
- expect { group.save! }
+ project_runner = create(:ci_runner, :project, projects: [project])
+
+ expect { create(:group, runners: [project_runner]) }
.to raise_error(ActiveRecord::RecordInvalid)
end
end
@@ -352,6 +350,8 @@ RSpec.describe Ci::Runner do
end
describe '#can_pick?' do
+ using RSpec::Parameterized::TableSyntax
+
let_it_be(:pipeline) { create(:ci_pipeline) }
let(:build) { create(:ci_build, pipeline: pipeline) }
let(:runner_project) { build.project }
@@ -365,6 +365,11 @@ RSpec.describe Ci::Runner do
let(:other_project) { create(:project) }
let(:other_runner) { create(:ci_runner, :project, projects: [other_project], tag_list: tag_list, run_untagged: run_untagged) }
+ before do
+ # `can_pick?` is not used outside the runners available for the project
+ stub_feature_flags(ci_runners_short_circuit_assignable_for: false)
+ end
+
it 'cannot handle builds' do
expect(other_runner.can_pick?(build)).to be_falsey
end
@@ -432,9 +437,32 @@ RSpec.describe Ci::Runner do
expect(runner.can_pick?(build)).to be_truthy
end
end
+
+ it 'does not query for owned or instance runners' do
+ expect(described_class).not_to receive(:owned_or_instance_wide)
+
+ runner.can_pick?(build)
+ end
+
+ context 'when feature flag ci_runners_short_circuit_assignable_for is disabled' do
+ before do
+ stub_feature_flags(ci_runners_short_circuit_assignable_for: false)
+ end
+
+ it 'does not query for owned or instance runners' do
+ expect(described_class).to receive(:owned_or_instance_wide).and_call_original
+
+ runner.can_pick?(build)
+ end
+ end
end
context 'when runner is not shared' do
+ before do
+ # `can_pick?` is not used outside the runners available for the project
+ stub_feature_flags(ci_runners_short_circuit_assignable_for: false)
+ end
+
context 'when runner is assigned to a project' do
it 'can handle builds' do
expect(runner.can_pick?(build)).to be_truthy
@@ -502,6 +530,29 @@ RSpec.describe Ci::Runner do
it { is_expected.to be_falsey }
end
end
+
+ context 'matches tags' do
+ where(:run_untagged, :runner_tags, :build_tags, :result) do
+ true | [] | [] | true
+ true | [] | ['a'] | false
+ true | %w[a b] | ['a'] | true
+ true | ['a'] | %w[a b] | false
+ true | ['a'] | ['a'] | true
+ false | ['a'] | ['a'] | true
+ false | ['b'] | ['a'] | false
+ false | %w[a b] | ['a'] | true
+ end
+
+ with_them do
+ let(:tag_list) { runner_tags }
+
+ before do
+ build.tag_list = build_tags
+ end
+
+ it { is_expected.to eq(result) }
+ end
+ end
end
describe '#status' do
@@ -844,27 +895,50 @@ RSpec.describe Ci::Runner do
end
describe '#pick_build!' do
+ let(:build) { create(:ci_build) }
+ let(:runner) { create(:ci_runner) }
+
context 'runner can pick the build' do
it 'calls #tick_runner_queue' do
- ci_build = build(:ci_build)
- runner = build(:ci_runner)
- allow(runner).to receive(:can_pick?).with(ci_build).and_return(true)
-
expect(runner).to receive(:tick_runner_queue)
- runner.pick_build!(ci_build)
+ runner.pick_build!(build)
end
end
context 'runner cannot pick the build' do
- it 'does not call #tick_runner_queue' do
- ci_build = build(:ci_build)
- runner = build(:ci_runner)
- allow(runner).to receive(:can_pick?).with(ci_build).and_return(false)
+ before do
+ build.tag_list = [:docker]
+ end
+ it 'does not call #tick_runner_queue' do
expect(runner).not_to receive(:tick_runner_queue)
- runner.pick_build!(ci_build)
+ runner.pick_build!(build)
+ end
+ end
+
+ context 'build picking improvement enabled' do
+ before do
+ stub_feature_flags(ci_reduce_queries_when_ticking_runner_queue: true)
+ end
+
+ it 'does not check if the build is assignable to a runner' do
+ expect(runner).not_to receive(:can_pick?)
+
+ runner.pick_build!(build)
+ end
+ end
+
+ context 'build picking improvement disabled' do
+ before do
+ stub_feature_flags(ci_reduce_queries_when_ticking_runner_queue: false)
+ end
+
+ it 'checks if the build is assignable to a runner' do
+ expect(runner).to receive(:can_pick?).and_call_original
+
+ runner.pick_build!(build)
end
end
end
diff --git a/spec/models/ci/variable_spec.rb b/spec/models/ci/variable_spec.rb
index 26a7a2596af..93a24ba9157 100644
--- a/spec/models/ci/variable_spec.rb
+++ b/spec/models/ci/variable_spec.rb
@@ -14,6 +14,15 @@ RSpec.describe Ci::Variable do
it { is_expected.to validate_uniqueness_of(:key).scoped_to(:project_id, :environment_scope).with_message(/\(\w+\) has already been taken/) }
end
+ describe '.by_environment_scope' do
+ let!(:matching_variable) { create(:ci_variable, environment_scope: 'production ') }
+ let!(:non_matching_variable) { create(:ci_variable, environment_scope: 'staging') }
+
+ subject { Ci::Variable.by_environment_scope('production') }
+
+ it { is_expected.to contain_exactly(matching_variable) }
+ end
+
describe '.unprotected' do
subject { described_class.unprotected }