2019-07-07 11:18:12 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2016-06-02 11:05:42 +05:30
|
|
|
require 'spec_helper'
|
|
|
|
|
2016-09-29 09:46:39 +05:30
|
|
|
describe HasStatus do
|
2019-12-21 20:55:43 +05:30
|
|
|
describe '.slow_composite_status' do
|
|
|
|
using RSpec::Parameterized::TableSyntax
|
|
|
|
|
2020-04-22 19:07:51 +05:30
|
|
|
subject { CommitStatus.slow_composite_status(project: nil) }
|
2016-09-29 09:46:39 +05:30
|
|
|
|
2016-06-02 11:05:42 +05:30
|
|
|
shared_examples 'build status summary' do
|
|
|
|
context 'all successful' do
|
2016-11-03 12:29:30 +05:30
|
|
|
let!(:statuses) { Array.new(2) { create(type, status: :success) } }
|
2019-12-21 20:55:43 +05:30
|
|
|
|
2016-06-02 11:05:42 +05:30
|
|
|
it { is_expected.to eq 'success' }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'at least one failed' do
|
2016-11-03 12:29:30 +05:30
|
|
|
let!(:statuses) do
|
2016-06-02 11:05:42 +05:30
|
|
|
[create(type, status: :success), create(type, status: :failed)]
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to eq 'failed' }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'at least one running' do
|
2016-11-03 12:29:30 +05:30
|
|
|
let!(:statuses) do
|
2016-06-02 11:05:42 +05:30
|
|
|
[create(type, status: :success), create(type, status: :running)]
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to eq 'running' }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'at least one pending' do
|
2016-11-03 12:29:30 +05:30
|
|
|
let!(:statuses) do
|
2016-06-02 11:05:42 +05:30
|
|
|
[create(type, status: :success), create(type, status: :pending)]
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to eq 'running' }
|
|
|
|
end
|
|
|
|
|
2020-03-13 15:44:24 +05:30
|
|
|
context 'all waiting for resource' do
|
|
|
|
let!(:statuses) do
|
|
|
|
[create(type, status: :waiting_for_resource), create(type, status: :waiting_for_resource)]
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to eq 'waiting_for_resource' }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'at least one waiting for resource' do
|
|
|
|
let!(:statuses) do
|
|
|
|
[create(type, status: :success), create(type, status: :waiting_for_resource)]
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to eq 'waiting_for_resource' }
|
|
|
|
end
|
|
|
|
|
2019-07-07 11:18:12 +05:30
|
|
|
context 'all preparing' do
|
|
|
|
let!(:statuses) do
|
|
|
|
[create(type, status: :preparing), create(type, status: :preparing)]
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to eq 'preparing' }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'at least one preparing' do
|
|
|
|
let!(:statuses) do
|
|
|
|
[create(type, status: :success), create(type, status: :preparing)]
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to eq 'preparing' }
|
|
|
|
end
|
|
|
|
|
2016-06-02 11:05:42 +05:30
|
|
|
context 'success and failed but allowed to fail' do
|
2016-11-03 12:29:30 +05:30
|
|
|
let!(:statuses) do
|
2016-06-02 11:05:42 +05:30
|
|
|
[create(type, status: :success),
|
|
|
|
create(type, status: :failed, allow_failure: true)]
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to eq 'success' }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'one failed but allowed to fail' do
|
2016-11-03 12:29:30 +05:30
|
|
|
let!(:statuses) do
|
|
|
|
[create(type, status: :failed, allow_failure: true)]
|
|
|
|
end
|
|
|
|
|
2017-09-10 17:25:29 +05:30
|
|
|
it { is_expected.to eq 'success' }
|
2016-06-02 11:05:42 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
context 'success and canceled' do
|
2016-11-03 12:29:30 +05:30
|
|
|
let!(:statuses) do
|
2016-06-02 11:05:42 +05:30
|
|
|
[create(type, status: :success), create(type, status: :canceled)]
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to eq 'canceled' }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'one failed and one canceled' do
|
2016-11-03 12:29:30 +05:30
|
|
|
let!(:statuses) do
|
2016-06-02 11:05:42 +05:30
|
|
|
[create(type, status: :failed), create(type, status: :canceled)]
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to eq 'failed' }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'one failed but allowed to fail and one canceled' do
|
2016-11-03 12:29:30 +05:30
|
|
|
let!(:statuses) do
|
2016-06-02 11:05:42 +05:30
|
|
|
[create(type, status: :failed, allow_failure: true),
|
|
|
|
create(type, status: :canceled)]
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to eq 'canceled' }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'one running one canceled' do
|
2016-11-03 12:29:30 +05:30
|
|
|
let!(:statuses) do
|
2016-06-02 11:05:42 +05:30
|
|
|
[create(type, status: :running), create(type, status: :canceled)]
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to eq 'running' }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'all canceled' do
|
2016-11-03 12:29:30 +05:30
|
|
|
let!(:statuses) do
|
2016-06-02 11:05:42 +05:30
|
|
|
[create(type, status: :canceled), create(type, status: :canceled)]
|
|
|
|
end
|
2016-11-03 12:29:30 +05:30
|
|
|
|
2016-06-02 11:05:42 +05:30
|
|
|
it { is_expected.to eq 'canceled' }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'success and canceled but allowed to fail' do
|
2016-11-03 12:29:30 +05:30
|
|
|
let!(:statuses) do
|
2016-06-02 11:05:42 +05:30
|
|
|
[create(type, status: :success),
|
|
|
|
create(type, status: :canceled, allow_failure: true)]
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to eq 'success' }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'one finished and second running but allowed to fail' do
|
2016-11-03 12:29:30 +05:30
|
|
|
let!(:statuses) do
|
2016-06-02 11:05:42 +05:30
|
|
|
[create(type, status: :success),
|
|
|
|
create(type, status: :running, allow_failure: true)]
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to eq 'running' }
|
|
|
|
end
|
2017-08-17 22:00:37 +05:30
|
|
|
|
|
|
|
context 'when one status finished and second is still created' do
|
|
|
|
let!(:statuses) do
|
|
|
|
[create(type, status: :success), create(type, status: :created)]
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to eq 'running' }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when there is a manual status before created status' do
|
|
|
|
let!(:statuses) do
|
|
|
|
[create(type, status: :success),
|
|
|
|
create(type, status: :manual, allow_failure: false),
|
|
|
|
create(type, status: :created)]
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to eq 'manual' }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when one status is a blocking manual action' do
|
|
|
|
let!(:statuses) do
|
|
|
|
[create(type, status: :failed),
|
|
|
|
create(type, status: :manual, allow_failure: false)]
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to eq 'manual' }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when one status is a non-blocking manual action' do
|
|
|
|
let!(:statuses) do
|
|
|
|
[create(type, status: :failed),
|
|
|
|
create(type, status: :manual, allow_failure: true)]
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to eq 'failed' }
|
|
|
|
end
|
2016-06-02 11:05:42 +05:30
|
|
|
end
|
|
|
|
|
2019-12-21 20:55:43 +05:30
|
|
|
where(:ci_composite_status) do
|
|
|
|
[false, true]
|
2016-06-02 11:05:42 +05:30
|
|
|
end
|
|
|
|
|
2019-12-21 20:55:43 +05:30
|
|
|
with_them do
|
|
|
|
before do
|
|
|
|
stub_feature_flags(ci_composite_status: ci_composite_status)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'ci build statuses' do
|
|
|
|
let(:type) { :ci_build }
|
2016-11-03 12:29:30 +05:30
|
|
|
|
2019-12-21 20:55:43 +05:30
|
|
|
it_behaves_like 'build status summary'
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'generic commit statuses' do
|
|
|
|
let(:type) { :generic_commit_status }
|
|
|
|
|
|
|
|
it_behaves_like 'build status summary'
|
|
|
|
end
|
2016-06-02 11:05:42 +05:30
|
|
|
end
|
|
|
|
end
|
2017-08-17 22:00:37 +05:30
|
|
|
|
|
|
|
context 'for scope with one status' do
|
|
|
|
shared_examples 'having a job' do |status|
|
|
|
|
%i[ci_build generic_commit_status].each do |type|
|
|
|
|
context "when it's #{status} #{type} job" do
|
|
|
|
let!(:job) { create(type, status) }
|
|
|
|
|
|
|
|
describe ".#{status}" do
|
|
|
|
it 'contains the job' do
|
2017-09-10 17:25:29 +05:30
|
|
|
expect(CommitStatus.public_send(status).all)
|
|
|
|
.to contain_exactly(job)
|
2017-08-17 22:00:37 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '.relevant' do
|
|
|
|
if status == :created
|
|
|
|
it 'contains nothing' do
|
|
|
|
expect(CommitStatus.relevant.all).to be_empty
|
|
|
|
end
|
|
|
|
else
|
|
|
|
it 'contains the job' do
|
|
|
|
expect(CommitStatus.relevant.all).to contain_exactly(job)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-03-13 15:44:24 +05:30
|
|
|
%i[created waiting_for_resource preparing running pending success
|
2017-08-17 22:00:37 +05:30
|
|
|
failed canceled skipped].each do |status|
|
|
|
|
it_behaves_like 'having a job', status
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'for scope with more statuses' do
|
|
|
|
shared_examples 'containing the job' do |status|
|
|
|
|
%i[ci_build generic_commit_status].each do |type|
|
|
|
|
context "when it's #{status} #{type} job" do
|
|
|
|
let!(:job) { create(type, status) }
|
|
|
|
|
|
|
|
it 'contains the job' do
|
|
|
|
is_expected.to contain_exactly(job)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
shared_examples 'not containing the job' do |status|
|
|
|
|
%i[ci_build generic_commit_status].each do |type|
|
|
|
|
context "when it's #{status} #{type} job" do
|
|
|
|
let!(:job) { create(type, status) }
|
|
|
|
|
|
|
|
it 'contains nothing' do
|
|
|
|
is_expected.to be_empty
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '.running_or_pending' do
|
|
|
|
subject { CommitStatus.running_or_pending }
|
|
|
|
|
|
|
|
%i[running pending].each do |status|
|
|
|
|
it_behaves_like 'containing the job', status
|
|
|
|
end
|
|
|
|
|
|
|
|
%i[created failed success].each do |status|
|
|
|
|
it_behaves_like 'not containing the job', status
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-03-17 18:26:18 +05:30
|
|
|
describe '.alive' do
|
|
|
|
subject { CommitStatus.alive }
|
|
|
|
|
2020-03-13 15:44:24 +05:30
|
|
|
%i[running pending waiting_for_resource preparing created].each do |status|
|
2018-03-17 18:26:18 +05:30
|
|
|
it_behaves_like 'containing the job', status
|
|
|
|
end
|
|
|
|
|
|
|
|
%i[failed success].each do |status|
|
|
|
|
it_behaves_like 'not containing the job', status
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-12-04 20:38:33 +05:30
|
|
|
describe '.alive_or_scheduled' do
|
|
|
|
subject { CommitStatus.alive_or_scheduled }
|
|
|
|
|
2020-03-13 15:44:24 +05:30
|
|
|
%i[running pending waiting_for_resource preparing created scheduled].each do |status|
|
2019-12-04 20:38:33 +05:30
|
|
|
it_behaves_like 'containing the job', status
|
|
|
|
end
|
|
|
|
|
|
|
|
%i[failed success canceled skipped].each do |status|
|
|
|
|
it_behaves_like 'not containing the job', status
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-08-17 22:00:37 +05:30
|
|
|
describe '.created_or_pending' do
|
|
|
|
subject { CommitStatus.created_or_pending }
|
|
|
|
|
|
|
|
%i[created pending].each do |status|
|
|
|
|
it_behaves_like 'containing the job', status
|
|
|
|
end
|
|
|
|
|
|
|
|
%i[running failed success].each do |status|
|
|
|
|
it_behaves_like 'not containing the job', status
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '.finished' do
|
|
|
|
subject { CommitStatus.finished }
|
|
|
|
|
|
|
|
%i[success failed canceled].each do |status|
|
|
|
|
it_behaves_like 'containing the job', status
|
|
|
|
end
|
|
|
|
|
|
|
|
%i[created running pending].each do |status|
|
|
|
|
it_behaves_like 'not containing the job', status
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '.cancelable' do
|
|
|
|
subject { CommitStatus.cancelable }
|
|
|
|
|
2020-03-13 15:44:24 +05:30
|
|
|
%i[running pending waiting_for_resource preparing created scheduled].each do |status|
|
2017-08-17 22:00:37 +05:30
|
|
|
it_behaves_like 'containing the job', status
|
|
|
|
end
|
|
|
|
|
2018-12-05 23:21:45 +05:30
|
|
|
%i[failed success skipped canceled manual].each do |status|
|
2017-08-17 22:00:37 +05:30
|
|
|
it_behaves_like 'not containing the job', status
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '.manual' do
|
|
|
|
subject { CommitStatus.manual }
|
|
|
|
|
|
|
|
%i[manual].each do |status|
|
|
|
|
it_behaves_like 'containing the job', status
|
|
|
|
end
|
|
|
|
|
|
|
|
%i[failed success skipped canceled].each do |status|
|
|
|
|
it_behaves_like 'not containing the job', status
|
|
|
|
end
|
|
|
|
end
|
2018-12-05 23:21:45 +05:30
|
|
|
|
|
|
|
describe '.scheduled' do
|
|
|
|
subject { CommitStatus.scheduled }
|
|
|
|
|
|
|
|
%i[scheduled].each do |status|
|
|
|
|
it_behaves_like 'containing the job', status
|
|
|
|
end
|
|
|
|
|
|
|
|
%i[failed success skipped canceled].each do |status|
|
|
|
|
it_behaves_like 'not containing the job', status
|
|
|
|
end
|
|
|
|
end
|
2017-08-17 22:00:37 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
describe '::DEFAULT_STATUS' do
|
|
|
|
it 'is a status created' do
|
|
|
|
expect(described_class::DEFAULT_STATUS).to eq 'created'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '::BLOCKED_STATUS' do
|
|
|
|
it 'is a status manual' do
|
2018-12-05 23:21:45 +05:30
|
|
|
expect(described_class::BLOCKED_STATUS).to eq %w[manual scheduled]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'blocked?' do
|
|
|
|
subject { object.blocked? }
|
|
|
|
|
|
|
|
%w[ci_pipeline ci_stage ci_build generic_commit_status].each do |type|
|
|
|
|
let(:object) { build(type, status: status) }
|
|
|
|
|
|
|
|
context 'when status is scheduled' do
|
|
|
|
let(:status) { :scheduled }
|
|
|
|
|
|
|
|
it { is_expected.to be_truthy }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when status is manual' do
|
|
|
|
let(:status) { :manual }
|
|
|
|
|
|
|
|
it { is_expected.to be_truthy }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when status is created' do
|
|
|
|
let(:status) { :created }
|
|
|
|
|
|
|
|
it { is_expected.to be_falsy }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-12-21 20:55:43 +05:30
|
|
|
describe '.legacy_status_sql' do
|
|
|
|
subject { Ci::Build.legacy_status_sql }
|
2018-12-05 23:21:45 +05:30
|
|
|
|
|
|
|
it 'returns SQL' do
|
|
|
|
puts subject
|
2017-08-17 22:00:37 +05:30
|
|
|
end
|
|
|
|
end
|
2016-06-02 11:05:42 +05:30
|
|
|
end
|