diff options
Diffstat (limited to 'spec/models/ci/pipeline_spec.rb')
-rw-r--r-- | spec/models/ci/pipeline_spec.rb | 281 |
1 files changed, 272 insertions, 9 deletions
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index ea022e03608..8158e71dd55 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe Ci::Pipeline, models: true do + include EmailHelpers + let(:project) { FactoryGirl.create :empty_project } let(:pipeline) { FactoryGirl.create :ci_empty_pipeline, status: 'created', project: project } @@ -18,8 +20,6 @@ describe Ci::Pipeline, models: true do it { is_expected.to respond_to :git_author_email } it { is_expected.to respond_to :short_sha } - it { is_expected.to delegate_method(:stages).to(:statuses) } - describe '#valid_commit_sha' do context 'commit.sha can not start with 00000000' do before do @@ -123,16 +123,55 @@ describe Ci::Pipeline, models: true do end describe '#stages' do - let(:pipeline2) { FactoryGirl.create :ci_pipeline, project: project } - subject { CommitStatus.where(pipeline: [pipeline, pipeline2]).stages } - before do - FactoryGirl.create :ci_build, pipeline: pipeline2, stage: 'test', stage_idx: 1 - FactoryGirl.create :ci_build, pipeline: pipeline, stage: 'build', stage_idx: 0 + create(:commit_status, pipeline: pipeline, stage: 'build', name: 'linux', stage_idx: 0, status: 'success') + create(:commit_status, pipeline: pipeline, stage: 'build', name: 'mac', stage_idx: 0, status: 'failed') + create(:commit_status, pipeline: pipeline, stage: 'deploy', name: 'staging', stage_idx: 2, status: 'running') + create(:commit_status, pipeline: pipeline, stage: 'test', name: 'rspec', stage_idx: 1, status: 'success') + end + + subject { pipeline.stages } + + context 'stages list' do + it 'returns ordered list of stages' do + expect(subject.map(&:name)).to eq(%w[build test deploy]) + end + end + + it 'returns a valid number of stages' do + expect(pipeline.stages_count).to eq(3) end - it 'return all stages' do - is_expected.to eq(%w(build test)) + it 'returns a valid names of stages' do + expect(pipeline.stages_name).to eq(['build', 'test', 'deploy']) + end + + context 'stages with statuses' do + let(:statuses) do + subject.map do |stage| + [stage.name, stage.status] + end + end + + it 'returns list of stages with statuses' do + expect(statuses).to eq([['build', 'failed'], + ['test', 'success'], + ['deploy', 'running'] + ]) + end + + context 'when build is retried' do + before do + create(:commit_status, pipeline: pipeline, stage: 'build', name: 'mac', stage_idx: 0, status: 'success') + end + + it 'ignores the previous state' do + expect(statuses).to eq([['build', 'success'], + ['test', 'success'], + ['deploy', 'running'] + ]) + end + end end end @@ -402,6 +441,230 @@ describe Ci::Pipeline, models: true do end end + describe '#detailed_status' do + context 'when pipeline is created' do + let(:pipeline) { create(:ci_pipeline, status: :created) } + + it 'returns detailed status for created pipeline' do + expect(pipeline.detailed_status.text).to eq 'created' + end + end + + context 'when pipeline is pending' do + let(:pipeline) { create(:ci_pipeline, status: :pending) } + + it 'returns detailed status for pending pipeline' do + expect(pipeline.detailed_status.text).to eq 'pending' + end + end + + context 'when pipeline is running' do + let(:pipeline) { create(:ci_pipeline, status: :running) } + + it 'returns detailed status for running pipeline' do + expect(pipeline.detailed_status.text).to eq 'running' + end + end + + context 'when pipeline is successful' do + let(:pipeline) { create(:ci_pipeline, status: :success) } + + it 'returns detailed status for successful pipeline' do + expect(pipeline.detailed_status.text).to eq 'passed' + end + end + + context 'when pipeline is failed' do + let(:pipeline) { create(:ci_pipeline, status: :failed) } + + it 'returns detailed status for failed pipeline' do + expect(pipeline.detailed_status.text).to eq 'failed' + end + end + + context 'when pipeline is canceled' do + let(:pipeline) { create(:ci_pipeline, status: :canceled) } + + it 'returns detailed status for canceled pipeline' do + expect(pipeline.detailed_status.text).to eq 'canceled' + end + end + + context 'when pipeline is skipped' do + let(:pipeline) { create(:ci_pipeline, status: :skipped) } + + it 'returns detailed status for skipped pipeline' do + expect(pipeline.detailed_status.text).to eq 'skipped' + end + end + + context 'when pipeline is successful but with warnings' do + let(:pipeline) { create(:ci_pipeline, status: :success) } + + before do + create(:ci_build, :allowed_to_fail, :failed, pipeline: pipeline) + end + + it 'retruns detailed status for successful pipeline with warnings' do + expect(pipeline.detailed_status.label).to eq 'passed with warnings' + end + end + end + + describe '#cancelable?' do + %i[created running pending].each do |status0| + context "when there is a build #{status0}" do + before do + create(:ci_build, status0, pipeline: pipeline) + end + + it 'is cancelable' do + expect(pipeline.cancelable?).to be_truthy + end + end + + context "when there is an external job #{status0}" do + before do + create(:generic_commit_status, status0, pipeline: pipeline) + end + + it 'is cancelable' do + expect(pipeline.cancelable?).to be_truthy + end + end + + %i[success failed canceled].each do |status1| + context "when there are generic_commit_status jobs for #{status0} and #{status1}" do + before do + create(:generic_commit_status, status0, pipeline: pipeline) + create(:generic_commit_status, status1, pipeline: pipeline) + end + + it 'is cancelable' do + expect(pipeline.cancelable?).to be_truthy + end + end + + context "when there are generic_commit_status and ci_build jobs for #{status0} and #{status1}" do + before do + create(:generic_commit_status, status0, pipeline: pipeline) + create(:ci_build, status1, pipeline: pipeline) + end + + it 'is cancelable' do + expect(pipeline.cancelable?).to be_truthy + end + end + + context "when there are ci_build jobs for #{status0} and #{status1}" do + before do + create(:ci_build, status0, pipeline: pipeline) + create(:ci_build, status1, pipeline: pipeline) + end + + it 'is cancelable' do + expect(pipeline.cancelable?).to be_truthy + end + end + end + end + + %i[success failed canceled].each do |status| + context "when there is a build #{status}" do + before do + create(:ci_build, status, pipeline: pipeline) + end + + it 'is not cancelable' do + expect(pipeline.cancelable?).to be_falsey + end + end + + context "when there is an external job #{status}" do + before do + create(:generic_commit_status, status, pipeline: pipeline) + end + + it 'is not cancelable' do + expect(pipeline.cancelable?).to be_falsey + end + end + end + end + + describe '#cancel_running' do + let(:latest_status) { pipeline.statuses.pluck(:status) } + + context 'when there is a running external job and created build' do + before do + create(:ci_build, :running, pipeline: pipeline) + create(:generic_commit_status, :running, pipeline: pipeline) + + pipeline.cancel_running + end + + it 'cancels both jobs' do + expect(latest_status).to contain_exactly('canceled', 'canceled') + end + end + + context 'when builds are in different stages' do + before do + create(:ci_build, :running, stage_idx: 0, pipeline: pipeline) + create(:ci_build, :running, stage_idx: 1, pipeline: pipeline) + + pipeline.cancel_running + end + + it 'cancels both jobs' do + expect(latest_status).to contain_exactly('canceled', 'canceled') + end + end + end + + describe '#retry_failed' do + let(:latest_status) { pipeline.statuses.latest.pluck(:status) } + + context 'when there is a failed build and failed external status' do + before do + create(:ci_build, :failed, name: 'build', pipeline: pipeline) + create(:generic_commit_status, :failed, name: 'jenkins', pipeline: pipeline) + + pipeline.retry_failed(create(:user)) + end + + it 'retries only build' do + expect(latest_status).to contain_exactly('pending', 'failed') + end + end + + context 'when builds are in different stages' do + before do + create(:ci_build, :failed, name: 'build', stage_idx: 0, pipeline: pipeline) + create(:ci_build, :failed, name: 'jenkins', stage_idx: 1, pipeline: pipeline) + + pipeline.retry_failed(create(:user)) + end + + it 'retries both builds' do + expect(latest_status).to contain_exactly('pending', 'pending') + end + end + + context 'when there are canceled and failed' do + before do + create(:ci_build, :failed, name: 'build', stage_idx: 0, pipeline: pipeline) + create(:ci_build, :canceled, name: 'jenkins', stage_idx: 1, pipeline: pipeline) + + pipeline.retry_failed(create(:user)) + end + + it 'retries both builds' do + expect(latest_status).to contain_exactly('pending', 'pending') + end + end + end + describe '#execute_hooks' do let!(:build_a) { create_build('a', 0) } let!(:build_b) { create_build('b', 1) } |