pipeline_spec.rb 8.9 KB
Newer Older
D
Douwe Maan 已提交
1 2
require 'spec_helper'

3
describe Ci::Pipeline, models: true do
K
Kamil Trzcinski 已提交
4
  let(:project) { FactoryGirl.create :empty_project }
5
  let(:pipeline) { FactoryGirl.create :ci_pipeline, project: project }
D
Douwe Maan 已提交
6

K
Kamil Trzcinski 已提交
7
  it { is_expected.to belong_to(:project) }
8 9
  it { is_expected.to belong_to(:user) }

10
  it { is_expected.to have_many(:statuses) }
K
Kamil Trzcinski 已提交
11
  it { is_expected.to have_many(:trigger_requests) }
D
Dmitriy Zaporozhets 已提交
12
  it { is_expected.to have_many(:builds) }
13

D
Dmitriy Zaporozhets 已提交
14
  it { is_expected.to validate_presence_of :sha }
K
Kamil Trzcinski 已提交
15
  it { is_expected.to validate_presence_of :status }
D
Douwe Maan 已提交
16

D
Dmitriy Zaporozhets 已提交
17 18 19
  it { is_expected.to respond_to :git_author_name }
  it { is_expected.to respond_to :git_author_email }
  it { is_expected.to respond_to :short_sha }
D
Douwe Maan 已提交
20

21
  describe '#valid_commit_sha' do
D
Douwe Maan 已提交
22 23
    context 'commit.sha can not start with 00000000' do
      before do
24 25
        pipeline.sha = '0' * 40
        pipeline.valid_commit_sha
D
Douwe Maan 已提交
26 27
      end

28
      it('commit errors should not be empty') { expect(pipeline.errors).not_to be_empty }
D
Douwe Maan 已提交
29 30 31
    end
  end

32
  describe '#short_sha' do
33
    subject { pipeline.short_sha }
D
Douwe Maan 已提交
34

D
Dmitriy Zaporozhets 已提交
35 36 37
    it 'has 8 items' do
      expect(subject.size).to eq(8)
    end
38
    it { expect(pipeline.sha).to start_with(subject) }
D
Douwe Maan 已提交
39 40
  end

41
  describe '#retried' do
42
    subject { pipeline.retried }
K
Kamil Trzcinski 已提交
43 44

    before do
45 46
      @build1 = FactoryGirl.create :ci_build, pipeline: pipeline, name: 'deploy'
      @build2 = FactoryGirl.create :ci_build, pipeline: pipeline, name: 'deploy'
K
Kamil Trzcinski 已提交
47 48 49
    end

    it 'returns old builds' do
50
      is_expected.to contain_exactly(@build1)
K
Kamil Trzcinski 已提交
51 52 53
    end
  end

D
Douwe Maan 已提交
54
  describe "#finished_at" do
55
    let(:pipeline) { FactoryGirl.create :ci_pipeline }
D
Douwe Maan 已提交
56 57

    it "returns finished_at of latest build" do
58 59
      build = FactoryGirl.create :ci_build, pipeline: pipeline, finished_at: Time.now - 60
      FactoryGirl.create :ci_build, pipeline: pipeline, finished_at: Time.now - 120
60
      pipeline.reload_status!
D
Douwe Maan 已提交
61

62
      expect(pipeline.finished_at.to_i).to eq(build.finished_at.to_i)
D
Douwe Maan 已提交
63 64 65
    end

    it "returns nil if there is no finished build" do
66
      FactoryGirl.create :ci_not_started_build, pipeline: pipeline
67
      pipeline.reload_status!
D
Douwe Maan 已提交
68

69
      expect(pipeline.finished_at).to be_nil
D
Douwe Maan 已提交
70 71 72 73
    end
  end

  describe "coverage" do
K
Kamil Trzcinski 已提交
74
    let(:project) { FactoryGirl.create :empty_project, build_coverage_regex: "/.*/" }
75
    let(:pipeline) { FactoryGirl.create :ci_empty_pipeline, project: project }
D
Douwe Maan 已提交
76 77

    it "calculates average when there are two builds with coverage" do
78 79 80
      FactoryGirl.create :ci_build, name: "rspec", coverage: 30, pipeline: pipeline
      FactoryGirl.create :ci_build, name: "rubocop", coverage: 40, pipeline: pipeline
      expect(pipeline.coverage).to eq("35.00")
D
Douwe Maan 已提交
81 82 83
    end

    it "calculates average when there are two builds with coverage and one with nil" do
84 85 86 87
      FactoryGirl.create :ci_build, name: "rspec", coverage: 30, pipeline: pipeline
      FactoryGirl.create :ci_build, name: "rubocop", coverage: 40, pipeline: pipeline
      FactoryGirl.create :ci_build, pipeline: pipeline
      expect(pipeline.coverage).to eq("35.00")
D
Douwe Maan 已提交
88 89 90
    end

    it "calculates average when there are two builds with coverage and one is retried" do
91 92 93 94
      FactoryGirl.create :ci_build, name: "rspec", coverage: 30, pipeline: pipeline
      FactoryGirl.create :ci_build, name: "rubocop", coverage: 30, pipeline: pipeline
      FactoryGirl.create :ci_build, name: "rubocop", coverage: 40, pipeline: pipeline
      expect(pipeline.coverage).to eq("35.00")
D
Douwe Maan 已提交
95 96 97
    end

    it "calculates average when there is one build without coverage" do
98 99
      FactoryGirl.create :ci_build, pipeline: pipeline
      expect(pipeline.coverage).to be_nil
D
Douwe Maan 已提交
100 101
    end
  end
K
Kamil Trzcinski 已提交
102 103

  describe '#retryable?' do
104
    subject { pipeline.retryable? }
K
Kamil Trzcinski 已提交
105 106 107

    context 'no failed builds' do
      before do
108
        FactoryGirl.create :ci_build, name: "rspec", pipeline: pipeline, status: 'success'
K
Kamil Trzcinski 已提交
109 110 111 112 113 114 115 116 117
      end

      it 'be not retryable' do
        is_expected.to be_falsey
      end
    end

    context 'with failed builds' do
      before do
118 119
        FactoryGirl.create :ci_build, name: "rspec", pipeline: pipeline, status: 'running'
        FactoryGirl.create :ci_build, name: "rubocop", pipeline: pipeline, status: 'failed'
K
Kamil Trzcinski 已提交
120 121 122 123 124 125 126 127 128
      end

      it 'be retryable' do
        is_expected.to be_truthy
      end
    end
  end

  describe '#stages' do
129 130
    let(:pipeline2) { FactoryGirl.create :ci_pipeline, project: project }
    subject { CommitStatus.where(pipeline: [pipeline, pipeline2]).stages }
K
Kamil Trzcinski 已提交
131 132

    before do
133 134
      FactoryGirl.create :ci_build, pipeline: pipeline2, stage: 'test', stage_idx: 1
      FactoryGirl.create :ci_build, pipeline: pipeline, stage: 'build', stage_idx: 0
K
Kamil Trzcinski 已提交
135 136 137 138 139 140 141
    end

    it 'return all stages' do
      is_expected.to eq(%w(build test))
    end
  end

142 143
  describe '#reload_status!' do
    let(:pipeline) { create :ci_empty_pipeline, project: project }
K
Kamil Trzcinski 已提交
144 145

    context 'dependent objects' do
146 147 148 149
      let(:commit_status) { create :commit_status, :pending, pipeline: pipeline }

      it 'executes reload_status! after succeeding dependent object' do
        expect(pipeline).to receive(:reload_status!).and_return(true)
K
Kamil Trzcinski 已提交
150

151
        commit_status.success
K
Kamil Trzcinski 已提交
152 153 154
      end
    end

155
    context 'updates' do
K
Kamil Trzcinski 已提交
156
      let(:current) { Time.now.change(usec: 0) }
157
      let(:build) { FactoryGirl.create :ci_build, pipeline: pipeline, started_at: current - 120, finished_at: current - 60 }
K
Kamil Trzcinski 已提交
158 159 160

      before do
        build
161
        pipeline.reload_status!
K
Kamil Trzcinski 已提交
162 163 164
      end

      [:status, :started_at, :finished_at, :duration].each do |param|
165
        it "#{param}" do
166
          expect(pipeline.send(param)).to eq(build.send(param))
K
Kamil Trzcinski 已提交
167 168 169 170
        end
      end
    end
  end
K
Kamil Trzcinski 已提交
171 172

  describe '#branch?' do
173
    subject { pipeline.branch? }
K
Kamil Trzcinski 已提交
174 175 176

    context 'is not a tag' do
      before do
177
        pipeline.tag = false
K
Kamil Trzcinski 已提交
178 179 180 181 182 183 184 185 186
      end

      it 'return true when tag is set to false' do
        is_expected.to be_truthy
      end
    end

    context 'is not a tag' do
      before do
187
        pipeline.tag = true
K
Kamil Trzcinski 已提交
188 189 190 191 192 193 194
      end

      it 'return false when tag is set to true' do
        is_expected.to be_falsey
      end
    end
  end
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218

  describe '#manual_actions' do
    subject { pipeline.manual_actions }

    it 'when none defined' do
      is_expected.to be_empty
    end

    context 'when action defined' do
      let!(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy') }

      it 'returns one action' do
        is_expected.to contain_exactly(manual)
      end

      context 'there are multiple of the same name' do
        let!(:manual2) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy') }

        it 'returns latest one' do
          is_expected.to contain_exactly(manual2)
        end
      end
    end
  end
219

C
Connor Shea 已提交
220 221
  describe '#has_warnings?' do
    subject { pipeline.has_warnings? }
222 223 224

    context 'build which is allowed to fail fails' do
      before do
C
Connor Shea 已提交
225 226
        create :ci_build, :success, pipeline: pipeline, name: 'rspec'
        create :ci_build, :allowed_to_fail, :failed, pipeline: pipeline, name: 'rubocop'
227
      end
228

229 230 231 232 233 234 235
      it 'returns true' do
        is_expected.to be_truthy
      end
    end

    context 'build which is allowed to fail succeeds' do
      before do
C
Connor Shea 已提交
236 237
        create :ci_build, :success, pipeline: pipeline, name: 'rspec'
        create :ci_build, :allowed_to_fail, :success, pipeline: pipeline, name: 'rubocop'
238
      end
239

240 241 242 243
      it 'returns false' do
        is_expected.to be_falsey
      end
    end
C
Connor Shea 已提交
244 245 246 247 248 249 250 251 252 253 254 255

    context 'build is retried and succeeds' do
      before do
        create :ci_build, :success, pipeline: pipeline, name: 'rubocop'
        create :ci_build, :failed, pipeline: pipeline, name: 'rspec'
        create :ci_build, :success, pipeline: pipeline, name: 'rspec'
      end

      it 'returns false' do
        is_expected.to be_falsey
      end
    end
256
  end
257 258 259 260 261 262 263 264

  describe '#execute_hooks' do
    let!(:hook) do
      create(:project_hook, project: project, pipeline_events: enabled)
    end

    before do
      WebMock.stub_request(:post, hook.url)
265
      pipeline.touch
266 267 268 269 270 271 272 273 274
      ProjectWebHookWorker.drain
    end

    context 'with pipeline hooks enabled' do
      let(:enabled) { true }

      it 'executes pipeline_hook after touched' do
        expect(WebMock).to have_requested(:post, hook.url).once
      end
275 276 277 278 279 280 281 282 283 284 285 286 287

      context 'with multiple builds' do
        let(:build_a) { create_build('a') }
        let(:build_b) { create_build('b') }

        before do
          build_a.run
          build_b.run
          build_a.success
          build_b.success
        end

        it 'fires 3 hooks' do
288 289 290
          %w(pending running success).each do |status|
            expect(WebMock).to requested(status)
          end
291
        end
292 293 294 295 296 297 298 299 300 301

        def create_build(name)
          create(:ci_build, :pending, pipeline: pipeline, name: name)
        end

        def requested(status)
          have_requested(:post, hook.url).with do |req|
            JSON.parse(req.body)['object_attributes']['status'] == status
          end.once
        end
302
      end
303 304 305 306 307 308 309 310 311 312
    end

    context 'with pipeline hooks disabled' do
      let(:enabled) { false }

      it 'did not execute pipeline_hook after touched' do
        expect(WebMock).not_to have_requested(:post, hook.url)
      end
    end
  end
D
Douwe Maan 已提交
313
end