summaryrefslogtreecommitdiff
path: root/spec/models/ci
diff options
context:
space:
mode:
authorAchilleas Pipinellis <axil@gitlab.com>2019-08-20 20:22:43 +0200
committerAchilleas Pipinellis <axil@gitlab.com>2019-08-20 20:22:43 +0200
commite61308ce1d82e12e5087371469baea4a452875d1 (patch)
tree62551a3ae4eab75e5af7e3b35358c07a51b2132f /spec/models/ci
parent4f323bb62fbe71a4352de25cab141f361a3fe1a6 (diff)
parent2989ed078c1d45b0959dcecb1bc3c8f4740a3c0d (diff)
downloadgitlab-ce-docs-patch-71.tar.gz
Merge branch 'master' into docs-patch-71docs-patch-71
Diffstat (limited to 'spec/models/ci')
-rw-r--r--spec/models/ci/bridge_spec.rb2
-rw-r--r--spec/models/ci/build_need_spec.rb13
-rw-r--r--spec/models/ci/build_spec.rb167
-rw-r--r--spec/models/ci/job_artifact_spec.rb25
-rw-r--r--spec/models/ci/job_variable_spec.rb12
-rw-r--r--spec/models/ci/pipeline_schedule_spec.rb55
-rw-r--r--spec/models/ci/pipeline_spec.rb98
-rw-r--r--spec/models/ci/runner_spec.rb6
-rw-r--r--spec/models/ci/trigger_spec.rb20
-rw-r--r--spec/models/ci/variable_spec.rb1
10 files changed, 324 insertions, 75 deletions
diff --git a/spec/models/ci/bridge_spec.rb b/spec/models/ci/bridge_spec.rb
index eb32198265b..a871f9b3fe6 100644
--- a/spec/models/ci/bridge_spec.rb
+++ b/spec/models/ci/bridge_spec.rb
@@ -23,7 +23,7 @@ describe Ci::Bridge do
let(:status) { bridge.detailed_status(user) }
it 'returns detailed status object' do
- expect(status).to be_a Gitlab::Ci::Status::Success
+ expect(status).to be_a Gitlab::Ci::Status::Created
end
end
diff --git a/spec/models/ci/build_need_spec.rb b/spec/models/ci/build_need_spec.rb
new file mode 100644
index 00000000000..450dd550a8f
--- /dev/null
+++ b/spec/models/ci/build_need_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Ci::BuildNeed, model: true do
+ let(:build_need) { build(:ci_build_need) }
+
+ it { is_expected.to belong_to(:build) }
+
+ it { is_expected.to validate_presence_of(:build) }
+ it { is_expected.to validate_presence_of(:name) }
+ it { is_expected.to validate_length_of(:name).is_at_most(128) }
+end
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index d98db024f73..4aac4b640f4 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -19,9 +19,11 @@ describe Ci::Build do
it { is_expected.to belong_to(:runner) }
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(:trace_sections) }
+ it { is_expected.to have_many(:needs) }
it { is_expected.to have_one(:deployment) }
- it { is_expected.to have_one(:runner_session)}
+ it { is_expected.to have_one(:runner_session) }
+ it { is_expected.to have_many(:job_variables) }
it { is_expected.to validate_presence_of(:ref) }
it { is_expected.to respond_to(:has_trace?) }
it { is_expected.to respond_to(:trace) }
@@ -181,6 +183,47 @@ describe Ci::Build do
end
end
+ describe '.with_needs' do
+ let!(:build) { create(:ci_build) }
+ let!(:build_b) { create(:ci_build) }
+ let!(:build_need_a) { create(:ci_build_need, build: build) }
+ let!(:build_need_b) { create(:ci_build_need, build: build_b) }
+
+ context 'when passing build name' do
+ subject { described_class.with_needs(build_need_a.name) }
+
+ it { is_expected.to contain_exactly(build) }
+ end
+
+ context 'when not passing any build name' do
+ subject { described_class.with_needs }
+
+ it { is_expected.to contain_exactly(build, build_b) }
+ end
+
+ context 'when not matching build name' do
+ subject { described_class.with_needs('undefined') }
+
+ it { is_expected.to be_empty }
+ end
+ end
+
+ describe '.without_needs' do
+ let!(:build) { create(:ci_build) }
+
+ subject { described_class.without_needs }
+
+ context 'when no build_need is created' do
+ it { is_expected.to contain_exactly(build) }
+ end
+
+ context 'when a build_need is created' do
+ let!(:need_a) { create(:ci_build_need, build: build) }
+
+ it { is_expected.to be_empty }
+ end
+ end
+
describe '#enqueue' do
let(:build) { create(:ci_build, :created) }
@@ -594,6 +637,59 @@ describe Ci::Build do
expect(staging.depends_on_builds.map(&:id))
.to contain_exactly(build.id, retried_rspec.id, rubocop_test.id)
end
+
+ describe '#dependencies' do
+ let(:dependencies) { }
+ let(:needs) { }
+
+ let!(:final) do
+ create(:ci_build,
+ pipeline: pipeline, name: 'final',
+ stage_idx: 3, stage: 'deploy', options: {
+ dependencies: dependencies
+ }
+ )
+ end
+
+ before do
+ needs.to_a.each do |need|
+ create(:ci_build_need, build: final, name: need)
+ end
+ end
+
+ subject { final.dependencies }
+
+ context 'when depedencies are defined' do
+ let(:dependencies) { %w(rspec staging) }
+
+ it { is_expected.to contain_exactly(rspec_test, staging) }
+ end
+
+ context 'when needs are defined' do
+ let(:needs) { %w(build rspec staging) }
+
+ it { is_expected.to contain_exactly(build, rspec_test, staging) }
+
+ context 'when ci_dag_support is disabled' do
+ before do
+ stub_feature_flags(ci_dag_support: false)
+ end
+
+ it { is_expected.to contain_exactly(build, rspec_test, rubocop_test, staging) }
+ end
+ end
+
+ context 'when needs and dependencies are defined' do
+ let(:dependencies) { %w(rspec staging) }
+ let(:needs) { %w(build rspec staging) }
+
+ it { is_expected.to contain_exactly(rspec_test, staging) }
+ end
+
+ context 'when nor dependencies or needs are defined' do
+ it { is_expected.to contain_exactly(build, rspec_test, rubocop_test, staging) }
+ end
+ end
end
describe '#triggered_by?' do
@@ -692,6 +788,34 @@ describe Ci::Build do
end
end
+ describe '#has_live_trace?' do
+ subject { build.has_live_trace? }
+
+ let(:build) { create(:ci_build, :trace_live) }
+
+ it { is_expected.to be_truthy }
+
+ context 'when build does not have live trace' do
+ let(:build) { create(:ci_build) }
+
+ it { is_expected.to be_falsy }
+ end
+ end
+
+ describe '#has_archived_trace?' do
+ subject { build.has_archived_trace? }
+
+ let(:build) { create(:ci_build, :trace_artifact) }
+
+ it { is_expected.to be_truthy }
+
+ context 'when build does not have archived trace' do
+ let(:build) { create(:ci_build) }
+
+ it { is_expected.to be_falsy }
+ end
+ end
+
describe '#has_job_artifacts?' do
subject { build.has_job_artifacts? }
@@ -2013,6 +2137,7 @@ describe Ci::Build do
{ key: 'CI', value: 'true', public: true, masked: false },
{ key: 'GITLAB_CI', value: 'true', public: true, masked: false },
{ key: 'GITLAB_FEATURES', value: project.licensed_features.join(','), public: true, masked: false },
+ { key: 'CI_SERVER_HOST', value: Gitlab.config.gitlab.host, public: true, masked: false },
{ key: 'CI_SERVER_NAME', value: 'GitLab', public: true, masked: false },
{ key: 'CI_SERVER_VERSION', value: Gitlab::VERSION, public: true, masked: false },
{ key: 'CI_SERVER_VERSION_MAJOR', value: Gitlab.version_info.major.to_s, public: true, masked: false },
@@ -2215,6 +2340,32 @@ describe Ci::Build do
it_behaves_like 'containing environment variables'
end
end
+
+ context 'when project has an environment specific variable' do
+ let(:environment_specific_variable) do
+ { key: 'MY_STAGING_ONLY_VARIABLE', value: 'environment_specific_variable', public: false, masked: false }
+ end
+
+ before do
+ create(:ci_variable, environment_specific_variable.slice(:key, :value)
+ .merge(project: project, environment_scope: 'stag*'))
+ end
+
+ it_behaves_like 'containing environment variables'
+
+ context 'when environment scope does not match build environment' do
+ it { is_expected.not_to include(environment_specific_variable) }
+ end
+
+ context 'when environment scope matches build environment' do
+ before do
+ create(:environment, name: 'staging', project: project)
+ build.update!(environment: 'staging')
+ end
+
+ it { is_expected.to include(environment_specific_variable) }
+ end
+ end
end
context 'when build started manually' do
@@ -2229,6 +2380,16 @@ describe Ci::Build do
it { is_expected.to include(manual_variable) }
end
+ context 'when job variable is defined' do
+ let(:job_variable) { { key: 'first', value: 'first', public: false, masked: false } }
+
+ before do
+ create(:ci_job_variable, job_variable.slice(:key, :value).merge(job: build))
+ end
+
+ it { is_expected.to include(job_variable) }
+ end
+
context 'when build is for tag' do
let(:tag_variable) do
{ key: 'CI_COMMIT_TAG', value: 'master', public: true, masked: false }
@@ -3574,6 +3735,7 @@ describe Ci::Build do
before do
build.ensure_metadata
+ build.needs.create!(name: 'another-job')
end
it 'drops metadata' do
@@ -3581,6 +3743,7 @@ describe Ci::Build do
expect(build.reload).to be_degenerated
expect(build.metadata).to be_nil
+ expect(build.needs).to be_empty
end
end
diff --git a/spec/models/ci/job_artifact_spec.rb b/spec/models/ci/job_artifact_spec.rb
index 1ba66565e03..1413da231e0 100644
--- a/spec/models/ci/job_artifact_spec.rb
+++ b/spec/models/ci/job_artifact_spec.rb
@@ -70,6 +70,31 @@ describe Ci::JobArtifact do
end
end
+ describe '.archived_trace_exists_for?' do
+ subject { described_class.archived_trace_exists_for?(job_id) }
+
+ let!(:artifact) { create(:ci_job_artifact, :trace, job: job) }
+ let(:job) { create(:ci_build) }
+
+ context 'when the specified job_id exists' do
+ let(:job_id) { job.id }
+
+ it { is_expected.to be_truthy }
+
+ context 'when the job does have archived trace' do
+ let!(:artifact) { }
+
+ it { is_expected.to be_falsy }
+ end
+ end
+
+ context 'when the specified job_id does not exist' do
+ let(:job_id) { 10000 }
+
+ it { is_expected.to be_falsy }
+ end
+ end
+
describe 'callbacks' do
subject { create(:ci_job_artifact, :archive) }
diff --git a/spec/models/ci/job_variable_spec.rb b/spec/models/ci/job_variable_spec.rb
new file mode 100644
index 00000000000..b94a914c784
--- /dev/null
+++ b/spec/models/ci/job_variable_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Ci::JobVariable do
+ subject { build(:ci_job_variable) }
+
+ it_behaves_like "CI variable"
+
+ it { is_expected.to belong_to(:job) }
+ it { is_expected.to validate_uniqueness_of(:key).scoped_to(:job_id) }
+end
diff --git a/spec/models/ci/pipeline_schedule_spec.rb b/spec/models/ci/pipeline_schedule_spec.rb
index 227870eb27f..aee43025288 100644
--- a/spec/models/ci/pipeline_schedule_spec.rb
+++ b/spec/models/ci/pipeline_schedule_spec.rb
@@ -88,23 +88,8 @@ describe Ci::PipelineSchedule do
describe '#set_next_run_at' do
let(:pipeline_schedule) { create(:ci_pipeline_schedule, :nightly) }
- let(:ideal_next_run_at) { pipeline_schedule.send(:ideal_next_run_at) }
-
- let(:expected_next_run_at) do
- Gitlab::Ci::CronParser.new(Settings.cron_jobs['pipeline_schedule_worker']['cron'], Time.zone.name)
- .next_time_from(ideal_next_run_at)
- end
-
- let(:cron_worker_next_run_at) do
- Gitlab::Ci::CronParser.new(Settings.cron_jobs['pipeline_schedule_worker']['cron'], Time.zone.name)
- .next_time_from(Time.zone.now)
- end
-
- context 'when creates new pipeline schedule' do
- it 'updates next_run_at automatically' do
- expect(pipeline_schedule.next_run_at).to eq(expected_next_run_at)
- end
- end
+ let(:ideal_next_run_at) { pipeline_schedule.send(:ideal_next_run_from, Time.zone.now) }
+ let(:cron_worker_next_run_at) { pipeline_schedule.send(:cron_worker_next_run_from, Time.zone.now) }
context 'when PipelineScheduleWorker runs at a specific interval' do
before do
@@ -128,8 +113,10 @@ describe Ci::PipelineSchedule do
context 'when pipeline schedule runs every minute' do
let(:pipeline_schedule) { create(:ci_pipeline_schedule, :every_minute) }
- it "updates next_run_at to the sidekiq worker's execution time", :quarantine do
- expect(pipeline_schedule.next_run_at).to eq(cron_worker_next_run_at)
+ it "updates next_run_at to the sidekiq worker's execution time" do
+ Timecop.freeze(Time.parse("2019-06-01 12:18:00+0000")) do
+ expect(pipeline_schedule.next_run_at).to eq(cron_worker_next_run_at)
+ end
end
end
@@ -155,9 +142,8 @@ describe Ci::PipelineSchedule do
let(:new_cron) { '0 0 1 1 *' }
it 'updates next_run_at automatically' do
- pipeline_schedule.update!(cron: new_cron)
-
- expect(pipeline_schedule.next_run_at).to eq(expected_next_run_at)
+ expect { pipeline_schedule.update!(cron: new_cron) }
+ .to change { pipeline_schedule.next_run_at }
end
end
end
@@ -165,21 +151,24 @@ describe Ci::PipelineSchedule do
describe '#schedule_next_run!' do
let!(:pipeline_schedule) { create(:ci_pipeline_schedule, :nightly) }
- context 'when reschedules after 10 days from now' do
- let(:future_time) { 10.days.from_now }
- let(:ideal_next_run_at) { pipeline_schedule.send(:ideal_next_run_at) }
+ before do
+ pipeline_schedule.update_column(:next_run_at, nil)
+ end
+
+ it 'updates next_run_at' do
+ expect { pipeline_schedule.schedule_next_run! }
+ .to change { pipeline_schedule.next_run_at }
+ end
- let(:expected_next_run_at) do
- Gitlab::Ci::CronParser.new(Settings.cron_jobs['pipeline_schedule_worker']['cron'], Time.zone.name)
- .next_time_from(ideal_next_run_at)
+ context 'when record is invalid' do
+ before do
+ allow(pipeline_schedule).to receive(:save!) { raise ActiveRecord::RecordInvalid.new(pipeline_schedule) }
end
- it 'points to proper next_run_at' do
- Timecop.freeze(future_time) do
- pipeline_schedule.schedule_next_run!
+ it 'nullifies the next run at' do
+ pipeline_schedule.schedule_next_run!
- expect(pipeline_schedule.next_run_at).to eq(expected_next_run_at)
- end
+ expect(pipeline_schedule.next_run_at).to be_nil
end
end
end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index a8701f0efa4..78be4a8131a 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -962,7 +962,11 @@ describe Ci::Pipeline, :mailer do
end
context 'when kubernetes is active' do
- shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
+ context 'when user configured kubernetes from CI/CD > Clusters' do
+ let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:project) { cluster.project }
+ let(:pipeline) { build(:ci_pipeline, project: project, config: config) }
+
it 'returns seeds for kubernetes dependent job' do
seeds = pipeline.stage_seeds
@@ -971,21 +975,6 @@ describe Ci::Pipeline, :mailer do
expect(seeds.dig(1, 0, :name)).to eq 'production'
end
end
-
- context 'when user configured kubernetes from Integration > Kubernetes' do
- let(:project) { create(:kubernetes_project) }
- let(:pipeline) { build(:ci_pipeline, project: project, config: config) }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
- context 'when user configured kubernetes from CI/CD > Clusters' do
- let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:project) { cluster.project }
- let(:pipeline) { build(:ci_pipeline, project: project, config: config) }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
end
context 'when kubernetes is not active' do
@@ -1679,23 +1668,13 @@ describe Ci::Pipeline, :mailer do
describe '#has_kubernetes_active?' do
context 'when kubernetes is active' do
- shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
- it 'returns true' do
- expect(pipeline).to have_kubernetes_active
- end
- end
-
- context 'when user configured kubernetes from Integration > Kubernetes' do
- let(:project) { create(:kubernetes_project) }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
context 'when user configured kubernetes from CI/CD > Clusters' do
let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:project) { cluster.project }
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
+ it 'returns true' do
+ expect(pipeline).to have_kubernetes_active
+ end
end
end
@@ -1820,7 +1799,7 @@ describe Ci::Pipeline, :mailer do
end
end
- describe '.latest_successful_for' do
+ describe '.latest_successful_for_ref' do
include_context 'with some outdated pipelines'
let!(:latest_successful_pipeline) do
@@ -1828,7 +1807,20 @@ describe Ci::Pipeline, :mailer do
end
it 'returns the latest successful pipeline' do
- expect(described_class.latest_successful_for('ref'))
+ expect(described_class.latest_successful_for_ref('ref'))
+ .to eq(latest_successful_pipeline)
+ 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
+
+ it 'returns the latest successful pipeline' do
+ expect(described_class.latest_successful_for_sha('awesomesha'))
.to eq(latest_successful_pipeline)
end
end
@@ -1907,6 +1899,17 @@ describe Ci::Pipeline, :mailer do
end
end
+ describe '.latest_for_shas' do
+ let(:sha) { 'abc' }
+
+ it 'returns latest pipeline for sha' do
+ create(:ci_pipeline, sha: sha)
+ pipeline2 = create(:ci_pipeline, sha: sha)
+
+ expect(described_class.latest_for_shas(sha)).to contain_exactly(pipeline2)
+ end
+ end
+
describe '.latest_successful_ids_per_project' do
let(:projects) { create_list(:project, 2) }
let!(:pipeline1) { create(:ci_pipeline, :success, project: projects[0]) }
@@ -1926,6 +1929,13 @@ describe Ci::Pipeline, :mailer do
it { is_expected.to be_an(Array) }
end
+ describe '.bridgeable_statuses' do
+ subject { described_class.bridgeable_statuses }
+
+ it { is_expected.to be_an(Array) }
+ it { is_expected.not_to include('created', 'preparing', 'pending') }
+ end
+
describe '#status' do
let(:build) do
create(:ci_build, :created, pipeline: pipeline, name: 'test')
@@ -2736,7 +2746,7 @@ describe Ci::Pipeline, :mailer do
create(:ci_pipeline,
project: project,
sha: project.commit('master').sha,
- user: create(:user))
+ user: project.owner)
end
before do
@@ -3008,4 +3018,28 @@ describe Ci::Pipeline, :mailer do
end
end
end
+
+ describe '#error_messages' do
+ subject { pipeline.error_messages }
+
+ before do
+ pipeline.valid?
+ end
+
+ context 'when pipeline has errors' do
+ let(:pipeline) { build(:ci_pipeline, sha: nil, ref: nil) }
+
+ it 'returns the full error messages' do
+ is_expected.to eq("Sha can't be blank and Ref can't be blank")
+ end
+ end
+
+ context 'when pipeline does not have errors' do
+ let(:pipeline) { build(:ci_pipeline) }
+
+ it 'returns empty string' do
+ is_expected.to be_empty
+ end
+ end
+ end
end
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb
index f735a89f69f..78b151631c1 100644
--- a/spec/models/ci/runner_spec.rb
+++ b/spec/models/ci/runner_spec.rb
@@ -146,7 +146,7 @@ describe Ci::Runner do
expect(described_class.belonging_to_parent_group_of_project(project.id)).to contain_exactly(runner)
end
- context 'with a parent group with a runner', :nested_groups do
+ context 'with a parent group with a runner' do
let(:runner) { create(:ci_runner, :group, groups: [parent_group]) }
let(:project) { create(:project, group: group) }
let(:group) { create(:group, parent: parent_group) }
@@ -554,7 +554,7 @@ describe Ci::Runner do
end
def expect_value_in_queues
- Gitlab::Redis::Queues.with do |redis|
+ Gitlab::Redis::SharedState.with do |redis|
runner_queue_key = runner.send(:runner_queue_key)
expect(redis.get(runner_queue_key))
end
@@ -627,7 +627,7 @@ describe Ci::Runner do
end
it 'cleans up the queue' do
- Gitlab::Redis::Queues.with do |redis|
+ Gitlab::Redis::SharedState.with do |redis|
expect(redis.get(queue_key)).to be_nil
end
end
diff --git a/spec/models/ci/trigger_spec.rb b/spec/models/ci/trigger_spec.rb
index fde8375f2a5..5b5d6f51b33 100644
--- a/spec/models/ci/trigger_spec.rb
+++ b/spec/models/ci/trigger_spec.rb
@@ -54,19 +54,31 @@ describe Ci::Trigger do
end
describe '#can_access_project?' do
+ let(:owner) { create(:user) }
let(:trigger) { create(:ci_trigger, owner: owner, project: project) }
context 'when owner is blank' do
- let(:owner) { nil }
+ before do
+ stub_feature_flags(use_legacy_pipeline_triggers: false)
+ trigger.update_attribute(:owner, nil)
+ end
subject { trigger.can_access_project? }
- it { is_expected.to eq(true) }
+ it { is_expected.to eq(false) }
+
+ context 'when :use_legacy_pipeline_triggers feature flag is enabled' do
+ before do
+ stub_feature_flags(use_legacy_pipeline_triggers: true)
+ end
+
+ subject { trigger.can_access_project? }
+
+ it { is_expected.to eq(true) }
+ end
end
context 'when owner is set' do
- let(:owner) { create(:user) }
-
subject { trigger.can_access_project? }
context 'and is member of the project' do
diff --git a/spec/models/ci/variable_spec.rb b/spec/models/ci/variable_spec.rb
index a231c7eaed8..3ff547456c6 100644
--- a/spec/models/ci/variable_spec.rb
+++ b/spec/models/ci/variable_spec.rb
@@ -10,6 +10,7 @@ describe Ci::Variable do
describe 'validations' do
it { is_expected.to include_module(Presentable) }
it { is_expected.to include_module(Maskable) }
+ it { is_expected.to include_module(HasEnvironmentScope) }
it { is_expected.to validate_uniqueness_of(:key).scoped_to(:project_id, :environment_scope).with_message(/\(\w+\) has already been taken/) }
end