summaryrefslogtreecommitdiff
path: root/spec/models/ci
diff options
context:
space:
mode:
Diffstat (limited to 'spec/models/ci')
-rw-r--r--spec/models/ci/build_spec.rb428
-rw-r--r--spec/models/ci/job_artifact_spec.rb74
-rw-r--r--spec/models/ci/pipeline_spec.rb228
-rw-r--r--spec/models/ci/runner_spec.rb2
4 files changed, 577 insertions, 155 deletions
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 99a669464e0..1a20c2dda00 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -23,6 +23,8 @@ describe Ci::Build do
it { is_expected.to respond_to(:has_trace?) }
it { is_expected.to respond_to(:trace) }
+ it { is_expected.to be_a(ArtifactMigratable) }
+
describe 'callbacks' do
context 'when running after_create callback' do
it 'triggers asynchronous build hooks worker' do
@@ -130,34 +132,55 @@ describe Ci::Build do
end
describe '#artifacts?' do
- subject { build.artifacts? }
+ context 'when new artifacts are used' do
+ let(:build) { create(:ci_build, :artifacts) }
- context 'artifacts archive does not exist' do
- before do
- build.update_attributes(artifacts_file: nil)
+ subject { build.artifacts? }
+
+ context 'artifacts archive does not exist' do
+ let(:build) { create(:ci_build) }
+
+ it { is_expected.to be_falsy }
end
- it { is_expected.to be_falsy }
- end
+ context 'artifacts archive exists' do
+ it { is_expected.to be_truthy }
- context 'artifacts archive exists' do
- let(:build) { create(:ci_build, :artifacts) }
- it { is_expected.to be_truthy }
+ context 'is expired' do
+ let!(:build) { create(:ci_build, :artifacts, :expired) }
- context 'is expired' do
- before do
- build.update(artifacts_expire_at: Time.now - 7.days)
+ it { is_expected.to be_falsy }
end
+ context 'is not expired' do
+ it { is_expected.to be_truthy }
+ end
+ end
+ end
+
+ context 'when legacy artifacts are used' do
+ let(:build) { create(:ci_build, :legacy_artifacts) }
+
+ subject { build.artifacts? }
+
+ context 'artifacts archive does not exist' do
+ let(:build) { create(:ci_build) }
+
it { is_expected.to be_falsy }
end
- context 'is not expired' do
- before do
- build.update(artifacts_expire_at: Time.now + 7.days)
+ context 'artifacts archive exists' do
+ it { is_expected.to be_truthy }
+
+ context 'is expired' do
+ let!(:build) { create(:ci_build, :legacy_artifacts, :expired) }
+
+ it { is_expected.to be_falsy }
end
- it { is_expected.to be_truthy }
+ context 'is not expired' do
+ it { is_expected.to be_truthy }
+ end
end
end
end
@@ -314,6 +337,23 @@ describe Ci::Build do
end
end
+ describe '#triggered_by?' do
+ subject { build.triggered_by?(user) }
+
+ context 'when user is owner' do
+ let(:build) { create(:ci_build, pipeline: pipeline, user: user) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when user is not owner' do
+ let(:another_user) { create(:user) }
+ let(:build) { create(:ci_build, pipeline: pipeline, user: another_user) }
+
+ it { is_expected.to be_falsy }
+ end
+ end
+
describe '#detailed_status' do
it 'returns a detailed status' do
expect(build.detailed_status(user))
@@ -639,71 +679,144 @@ describe Ci::Build do
describe '#erasable?' do
subject { build.erasable? }
+
it { is_expected.to eq false }
end
end
context 'build is erasable' do
- let!(:build) { create(:ci_build, :trace, :success, :artifacts) }
+ context 'new artifacts' do
+ let!(:build) { create(:ci_build, :trace, :success, :artifacts) }
- describe '#erase' do
- before do
- build.erase(erased_by: user)
- end
+ describe '#erase' do
+ before do
+ build.erase(erased_by: user)
+ end
- context 'erased by user' do
- let!(:user) { create(:user, username: 'eraser') }
+ context 'erased by user' do
+ let!(:user) { create(:user, username: 'eraser') }
- include_examples 'erasable'
+ include_examples 'erasable'
- it 'records user who erased a build' do
- expect(build.erased_by).to eq user
+ it 'records user who erased a build' do
+ expect(build.erased_by).to eq user
+ end
end
- end
- context 'erased by system' do
- let(:user) { nil }
+ context 'erased by system' do
+ let(:user) { nil }
- include_examples 'erasable'
+ include_examples 'erasable'
- it 'does not set user who erased a build' do
- expect(build.erased_by).to be_nil
+ it 'does not set user who erased a build' do
+ expect(build.erased_by).to be_nil
+ end
end
end
- end
- describe '#erasable?' do
- subject { build.erasable? }
- it { is_expected.to be_truthy }
- end
+ describe '#erasable?' do
+ subject { build.erasable? }
+ it { is_expected.to be_truthy }
+ end
- describe '#erased?' do
- let!(:build) { create(:ci_build, :trace, :success, :artifacts) }
- subject { build.erased? }
+ describe '#erased?' do
+ let!(:build) { create(:ci_build, :trace, :success, :artifacts) }
+ subject { build.erased? }
- context 'job has not been erased' do
- it { is_expected.to be_falsey }
+ context 'job has not been erased' do
+ it { is_expected.to be_falsey }
+ end
+
+ context 'job has been erased' do
+ before do
+ build.erase
+ end
+
+ it { is_expected.to be_truthy }
+ end
end
- context 'job has been erased' do
+ context 'metadata and build trace are not available' do
+ let!(:build) { create(:ci_build, :success, :artifacts) }
+
before do
- build.erase
+ build.remove_artifacts_metadata!
end
- it { is_expected.to be_truthy }
+ describe '#erase' do
+ it 'does not raise error' do
+ expect { build.erase }.not_to raise_error
+ end
+ end
end
end
+ end
- context 'metadata and build trace are not available' do
- let!(:build) { create(:ci_build, :success, :artifacts) }
+ context 'old artifacts' do
+ context 'build is erasable' do
+ context 'new artifacts' do
+ let!(:build) { create(:ci_build, :trace, :success, :legacy_artifacts) }
- before do
- build.remove_artifacts_metadata!
- end
+ describe '#erase' do
+ before do
+ build.erase(erased_by: user)
+ end
- describe '#erase' do
- it 'does not raise error' do
- expect { build.erase }.not_to raise_error
+ context 'erased by user' do
+ let!(:user) { create(:user, username: 'eraser') }
+
+ include_examples 'erasable'
+
+ it 'records user who erased a build' do
+ expect(build.erased_by).to eq user
+ end
+ end
+
+ context 'erased by system' do
+ let(:user) { nil }
+
+ include_examples 'erasable'
+
+ it 'does not set user who erased a build' do
+ expect(build.erased_by).to be_nil
+ end
+ end
+ end
+
+ describe '#erasable?' do
+ subject { build.erasable? }
+ it { is_expected.to be_truthy }
+ end
+
+ describe '#erased?' do
+ let!(:build) { create(:ci_build, :trace, :success, :legacy_artifacts) }
+ subject { build.erased? }
+
+ context 'job has not been erased' do
+ it { is_expected.to be_falsey }
+ end
+
+ context 'job has been erased' do
+ before do
+ build.erase
+ end
+
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ context 'metadata and build trace are not available' do
+ let!(:build) { create(:ci_build, :success, :legacy_artifacts) }
+
+ before do
+ build.remove_artifacts_metadata!
+ end
+
+ describe '#erase' do
+ it 'does not raise error' do
+ expect { build.erase }.not_to raise_error
+ end
+ end
end
end
end
@@ -939,11 +1052,23 @@ describe Ci::Build do
describe '#keep_artifacts!' do
let(:build) { create(:ci_build, artifacts_expire_at: Time.now + 7.days) }
+ subject { build.keep_artifacts! }
+
it 'to reset expire_at' do
- build.keep_artifacts!
+ subject
expect(build.artifacts_expire_at).to be_nil
end
+
+ context 'when having artifacts files' do
+ let!(:artifact) { create(:ci_job_artifact, job: build, expire_in: '7 days') }
+
+ it 'to reset dependent objects' do
+ subject
+
+ expect(artifact.reload.expire_at).to be_nil
+ end
+ end
end
describe '#merge_request' do
@@ -1268,10 +1393,10 @@ describe Ci::Build do
context 'when config does not have a questioned job' do
let(:config) do
YAML.dump({
- test_other: {
- script: 'Hello World'
- }
- })
+ test_other: {
+ script: 'Hello World'
+ }
+ })
end
it { is_expected.to eq('on_success') }
@@ -1280,11 +1405,11 @@ describe Ci::Build do
context 'when config has `when`' do
let(:config) do
YAML.dump({
- test: {
- script: 'Hello World',
- when: 'always'
- }
- })
+ test: {
+ script: 'Hello World',
+ when: 'always'
+ }
+ })
end
it { is_expected.to eq('always') }
@@ -1365,10 +1490,10 @@ describe Ci::Build do
let!(:environment) do
create(:environment,
- project: build.project,
- name: 'production',
- slug: 'prod-slug',
- external_url: '')
+ project: build.project,
+ name: 'production',
+ slug: 'prod-slug',
+ external_url: '')
end
before do
@@ -1592,8 +1717,8 @@ describe Ci::Build do
let!(:pipeline_schedule_variable) do
create(:ci_pipeline_schedule_variable,
- key: 'SCHEDULE_VARIABLE_KEY',
- pipeline_schedule: pipeline_schedule)
+ key: 'SCHEDULE_VARIABLE_KEY',
+ pipeline_schedule: pipeline_schedule)
end
before do
@@ -1735,8 +1860,8 @@ describe Ci::Build do
allow_any_instance_of(Project)
.to receive(:secret_variables_for)
.with(ref: 'master', environment: nil) do
- [create(:ci_variable, key: 'secret', value: 'value')]
- end
+ [create(:ci_variable, key: 'secret', value: 'value')]
+ end
allow_any_instance_of(Ci::Pipeline)
.to receive(:predefined_variables) { [pipeline_pre_var] }
@@ -1787,6 +1912,94 @@ describe Ci::Build do
end
end
+ describe 'state transition: any => [:running]' do
+ shared_examples 'validation is active' do
+ context 'when depended job has not been completed yet' do
+ let!(:pre_stage_job) { create(:ci_build, :running, pipeline: pipeline, name: 'test', stage_idx: 0) }
+
+ it { expect { job.run! }.to raise_error(Ci::Build::MissingDependenciesError) }
+ end
+
+ context 'when artifacts of depended job has been expired' do
+ let!(:pre_stage_job) { create(:ci_build, :success, :expired, pipeline: pipeline, name: 'test', stage_idx: 0) }
+
+ it { expect { job.run! }.to raise_error(Ci::Build::MissingDependenciesError) }
+ end
+
+ context 'when artifacts of depended job has been erased' do
+ let!(:pre_stage_job) { create(:ci_build, :success, pipeline: pipeline, name: 'test', stage_idx: 0, erased_at: 1.minute.ago) }
+
+ before do
+ pre_stage_job.erase
+ end
+
+ it { expect { job.run! }.to raise_error(Ci::Build::MissingDependenciesError) }
+ end
+ end
+
+ shared_examples 'validation is not active' do
+ context 'when depended job has not been completed yet' do
+ let!(:pre_stage_job) { create(:ci_build, :running, pipeline: pipeline, name: 'test', stage_idx: 0) }
+
+ it { expect { job.run! }.not_to raise_error }
+ end
+
+ context 'when artifacts of depended job has been expired' do
+ let!(:pre_stage_job) { create(:ci_build, :success, :expired, pipeline: pipeline, name: 'test', stage_idx: 0) }
+
+ it { expect { job.run! }.not_to raise_error }
+ end
+
+ context 'when artifacts of depended job has been erased' do
+ let!(:pre_stage_job) { create(:ci_build, :success, pipeline: pipeline, name: 'test', stage_idx: 0, erased_at: 1.minute.ago) }
+
+ before do
+ pre_stage_job.erase
+ end
+
+ it { expect { job.run! }.not_to raise_error }
+ end
+ end
+
+ let!(:job) { create(:ci_build, :pending, pipeline: pipeline, stage_idx: 1, options: options) }
+
+ context 'when validates for dependencies is enabled' do
+ before do
+ stub_feature_flags(ci_disable_validates_dependencies: false)
+ end
+
+ let!(:pre_stage_job) { create(:ci_build, :success, pipeline: pipeline, name: 'test', stage_idx: 0) }
+
+ context 'when "dependencies" keyword is not defined' do
+ let(:options) { {} }
+
+ it { expect { job.run! }.not_to raise_error }
+ end
+
+ context 'when "dependencies" keyword is empty' do
+ let(:options) { { dependencies: [] } }
+
+ it { expect { job.run! }.not_to raise_error }
+ end
+
+ context 'when "dependencies" keyword is specified' do
+ let(:options) { { dependencies: ['test'] } }
+
+ it_behaves_like 'validation is active'
+ end
+ end
+
+ context 'when validates for dependencies is disabled' do
+ let(:options) { { dependencies: ['test'] } }
+
+ before do
+ stub_feature_flags(ci_disable_validates_dependencies: true)
+ end
+
+ it_behaves_like 'validation is not active'
+ end
+ end
+
describe 'state transition when build fails' do
let(:service) { MergeRequests::AddTodoWhenBuildFailsService.new(project, user) }
@@ -1840,4 +2053,77 @@ describe Ci::Build do
end
end
end
+
+ describe '.matches_tag_ids' do
+ set(:build) { create(:ci_build, project: project, user: user) }
+ let(:tag_ids) { ::ActsAsTaggableOn::Tag.named_any(tag_list).ids }
+
+ subject { described_class.where(id: build).matches_tag_ids(tag_ids) }
+
+ before do
+ build.update(tag_list: build_tag_list)
+ end
+
+ context 'when have different tags' do
+ let(:build_tag_list) { %w(A B) }
+ let(:tag_list) { %w(C D) }
+
+ it "does not match a build" do
+ is_expected.not_to contain_exactly(build)
+ end
+ end
+
+ context 'when have a subset of tags' do
+ let(:build_tag_list) { %w(A B) }
+ let(:tag_list) { %w(A B C D) }
+
+ it "does match a build" do
+ is_expected.to contain_exactly(build)
+ end
+ end
+
+ context 'when build does not have tags' do
+ let(:build_tag_list) { [] }
+ let(:tag_list) { %w(C D) }
+
+ it "does match a build" do
+ is_expected.to contain_exactly(build)
+ end
+ end
+
+ context 'when does not have a subset of tags' do
+ let(:build_tag_list) { %w(A B C) }
+ let(:tag_list) { %w(C D) }
+
+ it "does not match a build" do
+ is_expected.not_to contain_exactly(build)
+ end
+ end
+ end
+
+ describe '.matches_tags' do
+ set(:build) { create(:ci_build, project: project, user: user) }
+
+ subject { described_class.where(id: build).with_any_tags }
+
+ before do
+ build.update(tag_list: tag_list)
+ end
+
+ context 'when does have tags' do
+ let(:tag_list) { %w(A B) }
+
+ it "does match a build" do
+ is_expected.to contain_exactly(build)
+ end
+ end
+
+ context 'when does not have tags' do
+ let(:tag_list) { [] }
+
+ it "does not match a build" do
+ is_expected.not_to contain_exactly(build)
+ end
+ end
+ end
end
diff --git a/spec/models/ci/job_artifact_spec.rb b/spec/models/ci/job_artifact_spec.rb
new file mode 100644
index 00000000000..0e18a326c68
--- /dev/null
+++ b/spec/models/ci/job_artifact_spec.rb
@@ -0,0 +1,74 @@
+require 'spec_helper'
+
+describe Ci::JobArtifact do
+ set(:artifact) { create(:ci_job_artifact, :archive) }
+
+ describe "Associations" do
+ it { is_expected.to belong_to(:project) }
+ it { is_expected.to belong_to(:job) }
+ end
+
+ it { is_expected.to respond_to(:file) }
+ it { is_expected.to respond_to(:created_at) }
+ it { is_expected.to respond_to(:updated_at) }
+
+ describe '#set_size' do
+ it 'sets the size' do
+ expect(artifact.size).to eq(106365)
+ end
+ end
+
+ describe '#file' do
+ subject { artifact.file }
+
+ context 'the uploader api' do
+ it { is_expected.to respond_to(:store_dir) }
+ it { is_expected.to respond_to(:cache_dir) }
+ it { is_expected.to respond_to(:work_dir) }
+ end
+ end
+
+ describe '#expire_in' do
+ subject { artifact.expire_in }
+
+ it { is_expected.to be_nil }
+
+ context 'when expire_at is specified' do
+ let(:expire_at) { Time.now + 7.days }
+
+ before do
+ artifact.expire_at = expire_at
+ end
+
+ it { is_expected.to be_within(5).of(expire_at - Time.now) }
+ end
+ end
+
+ describe '#expire_in=' do
+ subject { artifact.expire_in }
+
+ it 'when assigning valid duration' do
+ artifact.expire_in = '7 days'
+
+ is_expected.to be_within(10).of(7.days.to_i)
+ end
+
+ it 'when assigning invalid duration' do
+ expect { artifact.expire_in = '7 elephants' }.to raise_error(ChronicDuration::DurationParseError)
+
+ is_expected.to be_nil
+ end
+
+ it 'when resetting value' do
+ artifact.expire_in = nil
+
+ is_expected.to be_nil
+ end
+
+ it 'when setting to 0' do
+ artifact.expire_in = '0'
+
+ is_expected.to be_nil
+ end
+ end
+end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 2c9e7013b77..bb89e093890 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -557,10 +557,23 @@ describe Ci::Pipeline, :mailer do
describe '#has_kubernetes_active?' do
context 'when kubernetes is active' do
- let(:project) { create(:kubernetes_project) }
+ shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
+ it 'returns true' do
+ expect(pipeline).to have_kubernetes_active
+ end
+ end
- it 'returns true' do
- expect(pipeline).to have_kubernetes_active
+ 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'
end
end
@@ -625,38 +638,29 @@ describe Ci::Pipeline, :mailer do
shared_context 'with some outdated pipelines' do
before do
- create_pipeline(:canceled, 'ref', 'A')
- create_pipeline(:success, 'ref', 'A')
- create_pipeline(:failed, 'ref', 'B')
- create_pipeline(:skipped, 'feature', 'C')
+ create_pipeline(:canceled, 'ref', 'A', project)
+ create_pipeline(:success, 'ref', 'A', project)
+ create_pipeline(:failed, 'ref', 'B', project)
+ create_pipeline(:skipped, 'feature', 'C', project)
end
- def create_pipeline(status, ref, sha)
- create(:ci_empty_pipeline, status: status, ref: ref, sha: sha)
+ def create_pipeline(status, ref, sha, project)
+ create(
+ :ci_empty_pipeline,
+ status: status,
+ ref: ref,
+ sha: sha,
+ project: project
+ )
end
end
- describe '.latest' do
+ describe '.newest_first' do
include_context 'with some outdated pipelines'
- context 'when no ref is specified' do
- let(:pipelines) { described_class.latest.all }
-
- it 'returns the latest pipeline for the same ref and different sha' do
- expect(pipelines.map(&:sha)).to contain_exactly('A', 'B', 'C')
- expect(pipelines.map(&:status))
- .to contain_exactly('success', 'failed', 'skipped')
- end
- end
-
- context 'when ref is specified' do
- let(:pipelines) { described_class.latest('ref').all }
-
- it 'returns the latest pipeline for ref and different sha' do
- expect(pipelines.map(&:sha)).to contain_exactly('A', 'B')
- expect(pipelines.map(&:status))
- .to contain_exactly('success', 'failed')
- end
+ it 'returns the pipelines from new to old' do
+ expect(described_class.newest_first.pluck(:status))
+ .to eq(%w[skipped failed success canceled])
end
end
@@ -664,20 +668,14 @@ describe Ci::Pipeline, :mailer do
include_context 'with some outdated pipelines'
context 'when no ref is specified' do
- let(:latest_status) { described_class.latest_status }
-
- it 'returns the latest status for the same ref and different sha' do
- expect(latest_status).to eq(described_class.latest.status)
- expect(latest_status).to eq('failed')
+ it 'returns the status of the latest pipeline' do
+ expect(described_class.latest_status).to eq('skipped')
end
end
context 'when ref is specified' do
- let(:latest_status) { described_class.latest_status('ref') }
-
- it 'returns the latest status for ref and different sha' do
- expect(latest_status).to eq(described_class.latest_status('ref'))
- expect(latest_status).to eq('failed')
+ 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
@@ -686,7 +684,7 @@ describe Ci::Pipeline, :mailer do
include_context 'with some outdated pipelines'
let!(:latest_successful_pipeline) do
- create_pipeline(:success, 'ref', 'D')
+ create_pipeline(:success, 'ref', 'D', project)
end
it 'returns the latest successful pipeline' do
@@ -698,8 +696,13 @@ describe Ci::Pipeline, :mailer do
describe '.latest_successful_for_refs' do
include_context 'with some outdated pipelines'
- let!(:latest_successful_pipeline1) { create_pipeline(:success, 'ref1', 'D') }
- let!(:latest_successful_pipeline2) { create_pipeline(:success, 'ref2', 'D') }
+ let!(:latest_successful_pipeline1) do
+ create_pipeline(:success, 'ref1', 'D', project)
+ end
+
+ let!(:latest_successful_pipeline2) do
+ create_pipeline(:success, 'ref2', 'D', project)
+ end
it 'returns the latest successful pipeline for both refs' do
refs = %w(ref1 ref2 ref3)
@@ -708,6 +711,62 @@ describe Ci::Pipeline, :mailer do
end
end
+ describe '.latest_status_per_commit' do
+ let(:project) { create(:project) }
+
+ before do
+ pairs = [
+ %w[success ref1 123],
+ %w[manual master 123],
+ %w[failed ref 456]
+ ]
+
+ pairs.each do |(status, ref, sha)|
+ create(
+ :ci_empty_pipeline,
+ status: status,
+ ref: ref,
+ sha: sha,
+ project: project
+ )
+ end
+ end
+
+ context 'without a ref' do
+ it 'returns a Hash containing the latest status per commit for all refs' do
+ expect(described_class.latest_status_per_commit(%w[123 456]))
+ .to eq({ '123' => 'manual', '456' => 'failed' })
+ end
+
+ it 'only includes the status of the given commit SHAs' do
+ expect(described_class.latest_status_per_commit(%w[123]))
+ .to eq({ '123' => 'manual' })
+ end
+
+ context 'when there are two pipelines for a ref and SHA' do
+ it 'returns the status of the latest pipeline' do
+ create(
+ :ci_empty_pipeline,
+ status: 'failed',
+ ref: 'master',
+ sha: '123',
+ project: project
+ )
+
+ expect(described_class.latest_status_per_commit(%w[123]))
+ .to eq({ '123' => 'failed' })
+ end
+ end
+ end
+
+ context 'with a ref' do
+ it 'only includes the pipelines for the given ref' do
+ expect(described_class.latest_status_per_commit(%w[123 456], 'master'))
+ .to eq({ '123' => 'manual' })
+ end
+ end
+ end
+
describe '.internal_sources' do
subject { described_class.internal_sources }
@@ -809,62 +868,59 @@ describe Ci::Pipeline, :mailer do
end
describe '#set_config_source' do
- context 'on object initialisation' do
- context 'when pipelines does not contain needed data' do
- let(:pipeline) do
- Ci::Pipeline.new
- end
+ context 'when pipelines does not contain needed data' do
+ it 'defines source to be unknown' do
+ pipeline.set_config_source
- it 'defines source to be unknown' do
- expect(pipeline).to be_unknown_source
- end
+ expect(pipeline).to be_unknown_source
+ end
+ end
+
+ context 'when pipeline contains all needed data' do
+ let(:pipeline) do
+ create(:ci_pipeline, project: project,
+ sha: '1234',
+ ref: 'master',
+ source: :push)
end
- context 'when pipeline contains all needed data' do
- let(:pipeline) do
- Ci::Pipeline.new(
- project: project,
- sha: '1234',
- ref: 'master',
- source: :push)
+ context 'when the repository has a config file' do
+ before do
+ allow(project.repository).to receive(:gitlab_ci_yml_for)
+ .and_return('config')
end
- context 'when the repository has a config file' do
- before do
- allow(project.repository).to receive(:gitlab_ci_yml_for)
- .and_return('config')
- end
+ it 'defines source to be from repository' do
+ pipeline.set_config_source
- it 'defines source to be from repository' do
- expect(pipeline).to be_repository_source
- end
+ expect(pipeline).to be_repository_source
+ end
- context 'when loading an object' do
- let(:new_pipeline) { Ci::Pipeline.find(pipeline.id) }
+ context 'when loading an object' do
+ let(:new_pipeline) { Ci::Pipeline.find(pipeline.id) }
- it 'does not redefine the source' do
- # force to overwrite the source
- pipeline.unknown_source!
+ it 'does not redefine the source' do
+ # force to overwrite the source
+ pipeline.unknown_source!
- expect(new_pipeline).to be_unknown_source
- end
+ expect(new_pipeline).to be_unknown_source
end
end
+ end
- context 'when the repository does not have a config file' do
- let(:implied_yml) { Gitlab::Template::GitlabCiYmlTemplate.find('Auto-DevOps').content }
+ context 'when the repository does not have a config file' do
+ let(:implied_yml) { Gitlab::Template::GitlabCiYmlTemplate.find('Auto-DevOps').content }
- context 'auto devops enabled' do
- before do
- stub_application_setting(auto_devops_enabled: true)
- allow(project).to receive(:ci_config_path) { 'custom' }
- end
+ context 'auto devops enabled' do
+ before do
+ stub_application_setting(auto_devops_enabled: true)
+ allow(project).to receive(:ci_config_path) { 'custom' }
+ end
- it 'defines source to be auto devops' do
- subject
+ it 'defines source to be auto devops' do
+ pipeline.set_config_source
- expect(pipeline).to be_auto_devops_source
- end
+ expect(pipeline).to be_auto_devops_source
end
end
end
@@ -1188,7 +1244,7 @@ describe Ci::Pipeline, :mailer do
describe '#execute_hooks' do
let!(:build_a) { create_build('a', 0) }
- let!(:build_b) { create_build('b', 1) }
+ let!(:build_b) { create_build('b', 0) }
let!(:hook) do
create(:project_hook, project: project, pipeline_events: enabled)
@@ -1244,6 +1300,8 @@ describe Ci::Pipeline, :mailer do
end
context 'when stage one failed' do
+ let!(:build_b) { create_build('b', 1) }
+
before do
build_a.drop
end
@@ -1456,6 +1514,10 @@ describe Ci::Pipeline, :mailer do
create(:ci_build, :success, :artifacts, pipeline: pipeline)
end
+ it 'returns an Array' do
+ expect(pipeline.latest_builds_with_artifacts).to be_an_instance_of(Array)
+ end
+
it 'returns the latest builds' do
expect(pipeline.latest_builds_with_artifacts).to eq([build])
end
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb
index 584dfe9a5c1..a93e7e233a8 100644
--- a/spec/models/ci/runner_spec.rb
+++ b/spec/models/ci/runner_spec.rb
@@ -473,7 +473,7 @@ describe Ci::Runner do
end
describe '.search' do
- let(:runner) { create(:ci_runner, token: '123abc') }
+ let(:runner) { create(:ci_runner, token: '123abc', description: 'test runner') }
it 'returns runners with a matching token' do
expect(described_class.search(runner.token)).to eq([runner])