summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKamil Trzciński <ayufan@ayufan.eu>2016-02-18 14:28:25 +0000
committerRémy Coutable <remy@rymai.me>2016-02-18 16:18:45 +0100
commitbdbe892ea229e8916f922b168c239db393f3d677 (patch)
treebec7efd4019569ffebf8e3328f9c803e18975c36
parentfcedf80f467a856f109f6666cf9a72ae3c5295eb (diff)
downloadgitlab-ce-bdbe892ea229e8916f922b168c239db393f3d677.tar.gz
Merge branch 'fix/ci-first-job-allow-failure' into 'master'
Fix CI builds scheduler when first build in stage is allowed to fail This fixes an edge case in CI builds scheduler when first build in stage was marked as allowed to fail. Closes #3192 See merge request !2869
-rw-r--r--CHANGELOG1
-rw-r--r--app/services/ci/create_builds_service.rb1
-rw-r--r--lib/ci/status.rb4
-rw-r--r--spec/factories/ci/builds.rb20
-rw-r--r--spec/lib/ci/status_spec.rb37
-rw-r--r--spec/models/ci/commit_spec.rb29
-rw-r--r--spec/services/ci/create_builds_service_spec.rb28
7 files changed, 117 insertions, 3 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 08a9b8df4a0..b0d08d97226 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -63,6 +63,7 @@ v 8.5.0 (unreleased)
- Fix CI builds badge, add a new link to builds badge, deprecate the old one
- Fix broken link to project in build notification emails
- Ability to see and sort on vote count from Issues and MR lists
+ - Fix builds scheduler when first build in stage was allowed to fail
v 8.4.4
- Update omniauth-saml gem to 1.4.2
diff --git a/app/services/ci/create_builds_service.rb b/app/services/ci/create_builds_service.rb
index ad901f2da5d..002f7ba1278 100644
--- a/app/services/ci/create_builds_service.rb
+++ b/app/services/ci/create_builds_service.rb
@@ -34,6 +34,7 @@ module Ci
build = commit.builds.create!(build_attrs)
build.execute_hooks
+ build
end
end
end
diff --git a/lib/ci/status.rb b/lib/ci/status.rb
index c02b3b8f3e4..3fb1fe29494 100644
--- a/lib/ci/status.rb
+++ b/lib/ci/status.rb
@@ -1,11 +1,9 @@
module Ci
class Status
def self.get_status(statuses)
- statuses.reject! { |status| status.try(&:allow_failure?) }
-
if statuses.none?
'skipped'
- elsif statuses.all?(&:success?)
+ elsif statuses.all? { |status| status.success? || status.ignored? }
'success'
elsif statuses.all?(&:pending?)
'pending'
diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb
index c1b6ecd329a..1243647a78d 100644
--- a/spec/factories/ci/builds.rb
+++ b/spec/factories/ci/builds.rb
@@ -16,10 +16,30 @@ FactoryGirl.define do
commit factory: :ci_commit
+ trait :success do
+ status 'success'
+ end
+
+ trait :failed do
+ status 'failed'
+ end
+
trait :canceled do
status 'canceled'
end
+ trait :running do
+ status 'running'
+ end
+
+ trait :pending do
+ status 'pending'
+ end
+
+ trait :allowed_to_fail do
+ allow_failure true
+ end
+
after(:build) do |build, evaluator|
build.project = build.commit.project
end
diff --git a/spec/lib/ci/status_spec.rb b/spec/lib/ci/status_spec.rb
new file mode 100644
index 00000000000..cc4199dc7b6
--- /dev/null
+++ b/spec/lib/ci/status_spec.rb
@@ -0,0 +1,37 @@
+require 'spec_helper'
+
+describe Ci::Status do
+ describe '.get_status' do
+ subject { described_class.get_status(builds) }
+
+ context 'all builds successful' do
+ let(:builds) { Array.new(2) { create(:ci_build, :success) } }
+ it { is_expected.to eq 'success' }
+ end
+
+ context 'at least one build failed' do
+ let(:builds) { [create(:ci_build, :success), create(:ci_build, :failed)] }
+ it { is_expected.to eq 'failed' }
+ end
+
+ context 'at least one running' do
+ let(:builds) { [create(:ci_build, :success), create(:ci_build, :running)] }
+ it { is_expected.to eq 'running' }
+ end
+
+ context 'at least one pending' do
+ let(:builds) { [create(:ci_build, :success), create(:ci_build, :pending)] }
+ it { is_expected.to eq 'running' }
+ end
+
+ context 'build success and failed but allowed to fail' do
+ let(:builds) { [create(:ci_build, :success), create(:ci_build, :failed, :allowed_to_fail)] }
+ it { is_expected.to eq 'success' }
+ end
+
+ context 'one build failed but allowed to fail' do
+ let(:builds) { [create(:ci_build, :failed, :allowed_to_fail)] }
+ it { is_expected.to eq 'success' }
+ end
+ end
+end
diff --git a/spec/models/ci/commit_spec.rb b/spec/models/ci/commit_spec.rb
index dfc0cc3be1c..4dc309a4255 100644
--- a/spec/models/ci/commit_spec.rb
+++ b/spec/models/ci/commit_spec.rb
@@ -247,6 +247,35 @@ describe Ci::Commit, models: true do
end
end
+
+ context 'custom stage with first job allowed to fail' do
+ let(:yaml) do
+ {
+ stages: ['clean', 'test'],
+ clean_job: {
+ stage: 'clean',
+ allow_failure: true,
+ script: 'BUILD',
+ },
+ test_job: {
+ stage: 'test',
+ script: 'TEST',
+ },
+ }
+ end
+
+ before do
+ stub_ci_commit_yaml_file(YAML.dump(yaml))
+ create_builds
+ end
+
+ it 'properly schedules builds' do
+ expect(commit.builds.pluck(:status)).to contain_exactly('pending')
+ commit.builds.running_or_pending.each(&:drop)
+ expect(commit.builds.pluck(:status)).to contain_exactly('pending', 'failed')
+ end
+ end
+
context 'properly creates builds when "when" is defined' do
let(:yaml) do
{
diff --git a/spec/services/ci/create_builds_service_spec.rb b/spec/services/ci/create_builds_service_spec.rb
new file mode 100644
index 00000000000..1fca3628686
--- /dev/null
+++ b/spec/services/ci/create_builds_service_spec.rb
@@ -0,0 +1,28 @@
+require 'spec_helper'
+
+describe Ci::CreateBuildsService, services: true do
+ let(:commit) { create(:ci_commit) }
+ let(:user) { create(:user) }
+
+ describe '#execute' do
+ # Using stubbed .gitlab-ci.yml created in commit factory
+ #
+
+ subject do
+ described_class.new.execute(commit, 'test', 'master', nil, user, nil, status)
+ end
+
+ context 'next builds available' do
+ let(:status) { 'success' }
+
+ it { is_expected.to be_an_instance_of Array }
+ it { is_expected.to all(be_an_instance_of Ci::Build) }
+ end
+
+ context 'builds skipped' do
+ let(:status) { 'skipped' }
+
+ it { is_expected.to be_empty }
+ end
+ end
+end