builds_spec.rb 15.4 KB
Newer Older
1 2
require 'spec_helper'

3
describe API::V3::Builds do
R
Rémy Coutable 已提交
4
  set(:user) { create(:user) }
K
Kamil Trzcinski 已提交
5
  let(:api_user) { user }
R
Rémy Coutable 已提交
6 7 8 9 10
  set(:project) { create(:project, :repository, creator: user, public_builds: false) }
  set(:developer) { create(:project_member, :developer, user: user, project: project) }
  set(:reporter) { create(:project_member, :reporter, project: project) }
  set(:guest) { create(:project_member, :guest, project: project) }
  set(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.id, ref: project.default_branch) }
K
Kamil Trzcinski 已提交
11
  let!(:build) { create(:ci_build, pipeline: pipeline) }
12 13

  describe 'GET /projects/:id/builds ' do
K
Kamil Trzcinski 已提交
14 15
    let(:query) { '' }

16
    before do |example|
17 18
      create(:ci_build, :skipped, pipeline: pipeline)

19 20 21
      unless example.metadata[:skip_before_request]
        get v3_api("/projects/#{project.id}/builds?#{query}", api_user)
      end
L
Lin Jen-Shin 已提交
22
    end
K
Kamil Trzcinski 已提交
23

24
    context 'authorized user' do
25
      it 'returns project builds' do
26
        expect(response).to have_gitlab_http_status(200)
27
        expect(response).to include_pagination_headers
28 29 30
        expect(json_response).to be_an Array
      end

31 32 33 34 35
      it 'returns correct values' do
        expect(json_response).not_to be_empty
        expect(json_response.first['commit']['id']).to eq project.commit.id
      end

36 37 38 39 40 41 42 43 44
      it 'returns pipeline data' do
        json_build = json_response.first
        expect(json_build['pipeline']).not_to be_empty
        expect(json_build['pipeline']['id']).to eq build.pipeline.id
        expect(json_build['pipeline']['ref']).to eq build.pipeline.ref
        expect(json_build['pipeline']['sha']).to eq build.pipeline.sha
        expect(json_build['pipeline']['status']).to eq build.pipeline.status
      end

45
      it 'avoids N+1 queries', skip_before_request: true do
46 47 48 49 50
        first_build = create(:ci_build, :artifacts, pipeline: pipeline)
        first_build.runner = create(:ci_runner)
        first_build.user = create(:user)
        first_build.save

51
        control_count = ActiveRecord::QueryRecorder.new { go }.count
52 53 54 55 56 57 58

        second_pipeline = create(:ci_empty_pipeline, project: project, sha: project.commit.id, ref: project.default_branch)
        second_build = create(:ci_build, :artifacts, pipeline: second_pipeline)
        second_build.runner = create(:ci_runner)
        second_build.user = create(:user)
        second_build.save

59 60 61
        expect { go }.not_to exceed_query_limit(control_count)
      end

K
Kamil Trzcinski 已提交
62 63
      context 'filter project with one scope element' do
        let(:query) { 'scope=pending' }
64

K
Kamil Trzcinski 已提交
65
        it do
66
          expect(response).to have_gitlab_http_status(200)
K
Kamil Trzcinski 已提交
67 68
          expect(json_response).to be_an Array
        end
69 70
      end

71 72 73 74 75
      context 'filter project with scope skipped' do
        let(:query) { 'scope=skipped' }
        let(:json_build) { json_response.first }

        it 'return builds with status skipped' do
76
          expect(response).to have_gitlab_http_status 200
77 78 79 80 81 82
          expect(json_response).to be_an Array
          expect(json_response.length).to eq 1
          expect(json_build['status']).to eq 'skipped'
        end
      end

K
Kamil Trzcinski 已提交
83 84
      context 'filter project with array of scope elements' do
        let(:query) { 'scope[0]=pending&scope[1]=running' }
85

K
Kamil Trzcinski 已提交
86
        it do
87
          expect(response).to have_gitlab_http_status(200)
K
Kamil Trzcinski 已提交
88 89
          expect(json_response).to be_an Array
        end
90
      end
T
Tomasz Maczukin 已提交
91

K
Kamil Trzcinski 已提交
92 93
      context 'respond 400 when scope contains invalid state' do
        let(:query) { 'scope[0]=pending&scope[1]=unknown_status' }
T
Tomasz Maczukin 已提交
94

95
        it { expect(response).to have_gitlab_http_status(400) }
T
Tomasz Maczukin 已提交
96
      end
97 98 99
    end

    context 'unauthorized user' do
K
Kamil Trzcinski 已提交
100
      let(:api_user) { nil }
101

V
Valery Sizov 已提交
102
      it 'does not return project builds' do
103
        expect(response).to have_gitlab_http_status(401)
104 105
      end
    end
106 107 108 109

    def go
      get v3_api("/projects/#{project.id}/builds?#{query}", api_user)
    end
110 111
  end

112
  describe 'GET /projects/:id/repository/commits/:sha/builds' do
113 114
    context 'when commit does not exist in repository' do
      before do
115
        get v3_api("/projects/#{project.id}/repository/commits/1a271fd1/builds", api_user)
116
      end
117

118
      it 'responds with 404' do
119
        expect(response).to have_gitlab_http_status(404)
120
      end
K
Kamil Trzcinski 已提交
121 122
    end

123 124
    context 'when commit exists in repository' do
      context 'when user is authorized' do
F
Filipa Lacerda 已提交
125
        context 'when pipeline has jobs' do
126
          before do
L
Lin Jen-Shin 已提交
127
            create(:ci_pipeline, project: project, sha: project.commit.id)
128
            create(:ci_build, pipeline: pipeline)
L
Lin Jen-Shin 已提交
129
            create(:ci_build)
130

131
            get v3_api("/projects/#{project.id}/repository/commits/#{project.commit.id}/builds", api_user)
132 133
          end

F
Filipa Lacerda 已提交
134
          it 'returns project jobs for specific commit' do
135
            expect(response).to have_gitlab_http_status(200)
136
            expect(response).to include_pagination_headers
137 138 139
            expect(json_response).to be_an Array
            expect(json_response.size).to eq 2
          end
140 141 142 143 144 145 146 147 148

          it 'returns pipeline data' do
            json_build = json_response.first
            expect(json_build['pipeline']).not_to be_empty
            expect(json_build['pipeline']['id']).to eq build.pipeline.id
            expect(json_build['pipeline']['ref']).to eq build.pipeline.ref
            expect(json_build['pipeline']['sha']).to eq build.pipeline.sha
            expect(json_build['pipeline']['status']).to eq build.pipeline.status
          end
149 150
        end

F
Filipa Lacerda 已提交
151
        context 'when pipeline has no jobs' do
152 153
          before do
            branch_head = project.commit('feature').id
154
            get v3_api("/projects/#{project.id}/repository/commits/#{branch_head}/builds", api_user)
155 156 157
          end

          it 'returns an empty array' do
158
            expect(response).to have_gitlab_http_status(200)
159 160 161 162
            expect(json_response).to be_an Array
            expect(json_response).to be_empty
          end
        end
163 164
      end

165 166
      context 'when user is not authorized' do
        before do
L
Lin Jen-Shin 已提交
167 168
          create(:ci_pipeline, project: project, sha: project.commit.id)
          create(:ci_build, pipeline: pipeline)
169

170
          get v3_api("/projects/#{project.id}/repository/commits/#{project.commit.id}/builds", nil)
171 172
        end

F
Filipa Lacerda 已提交
173
        it 'does not return project jobs' do
174
          expect(response).to have_gitlab_http_status(401)
175 176
          expect(json_response.except('message')).to be_empty
        end
177 178 179
      end
    end
  end
180

181
  describe 'GET /projects/:id/builds/:build_id' do
L
Lin Jen-Shin 已提交
182
    before do
183
      get v3_api("/projects/#{project.id}/builds/#{build.id}", api_user)
L
Lin Jen-Shin 已提交
184
    end
K
Kamil Trzcinski 已提交
185

186
    context 'authorized user' do
F
Filipa Lacerda 已提交
187
      it 'returns specific job data' do
188
        expect(response).to have_gitlab_http_status(200)
189 190
        expect(json_response['name']).to eq('test')
      end
191 192 193 194 195 196 197 198 199

      it 'returns pipeline data' do
        json_build = json_response
        expect(json_build['pipeline']).not_to be_empty
        expect(json_build['pipeline']['id']).to eq build.pipeline.id
        expect(json_build['pipeline']['ref']).to eq build.pipeline.ref
        expect(json_build['pipeline']['sha']).to eq build.pipeline.sha
        expect(json_build['pipeline']['status']).to eq build.pipeline.status
      end
200 201 202
    end

    context 'unauthorized user' do
K
Kamil Trzcinski 已提交
203
      let(:api_user) { nil }
204

F
Filipa Lacerda 已提交
205
      it 'does not return specific job data' do
206
        expect(response).to have_gitlab_http_status(401)
207 208 209 210
      end
    end
  end

211
  describe 'GET /projects/:id/builds/:build_id/artifacts' do
L
Lin Jen-Shin 已提交
212
    before do
213
      get v3_api("/projects/#{project.id}/builds/#{build.id}/artifacts", api_user)
L
Lin Jen-Shin 已提交
214
    end
215

F
Filipa Lacerda 已提交
216
    context 'job with artifacts' do
217
      let(:build) { create(:ci_build, :artifacts, pipeline: pipeline) }
218

K
Kamil Trzcinski 已提交
219 220
      context 'authorized user' do
        let(:download_headers) do
221 222
          { 'Content-Transfer-Encoding' => 'binary',
            'Content-Disposition' => 'attachment; filename=ci_build_artifacts.zip' }
K
Kamil Trzcinski 已提交
223
        end
224

F
Filipa Lacerda 已提交
225
        it 'returns specific job artifacts' do
226
          expect(response).to have_gitlab_http_status(200)
K
Kamil Trzcinski 已提交
227
          expect(response.headers).to include(download_headers)
228
          expect(response.body).to match_file(build.artifacts_file.file.file)
K
Kamil Trzcinski 已提交
229
        end
230 231
      end

K
Kamil Trzcinski 已提交
232 233
      context 'unauthorized user' do
        let(:api_user) { nil }
234

F
Filipa Lacerda 已提交
235
        it 'does not return specific job artifacts' do
236
          expect(response).to have_gitlab_http_status(401)
K
Kamil Trzcinski 已提交
237
        end
238 239
      end
    end
K
Kamil Trzcinski 已提交
240

F
Filipa Lacerda 已提交
241
    it 'does not return job artifacts if not uploaded' do
242
      expect(response).to have_gitlab_http_status(404)
K
Kamil Trzcinski 已提交
243
    end
244 245
  end

246
  describe 'GET /projects/:id/artifacts/:ref_name/download?job=name' do
L
Lin Jen-Shin 已提交
247
    let(:api_user) { reporter.user }
248 249 250 251 252
    let(:build) { create(:ci_build, :artifacts, pipeline: pipeline) }

    before do
      build.success
    end
L
Lin Jen-Shin 已提交
253

254
    def path_for_ref(ref = pipeline.ref, job = build.name)
255
      v3_api("/projects/#{project.id}/builds/artifacts/#{ref}/download?job=#{job}", api_user)
L
Lin Jen-Shin 已提交
256 257
    end

258
    context 'when not logged in' do
K
Kamil Trzcinski 已提交
259
      let(:api_user) { nil }
L
Lin Jen-Shin 已提交
260 261

      before do
262
        get path_for_ref
L
Lin Jen-Shin 已提交
263 264
      end

265
      it 'gives 401' do
266
        expect(response).to have_gitlab_http_status(401)
L
Lin Jen-Shin 已提交
267 268 269
      end
    end

270
    context 'when logging as guest' do
L
Lin Jen-Shin 已提交
271
      let(:api_user) { guest.user }
272 273 274 275 276 277

      before do
        get path_for_ref
      end

      it 'gives 403' do
278
        expect(response).to have_gitlab_http_status(403)
279 280 281
      end
    end

F
Filipa Lacerda 已提交
282
    context 'non-existing job' do
L
Lin Jen-Shin 已提交
283
      shared_examples 'not found' do
284
        it { expect(response).to have_gitlab_http_status(:not_found) }
L
Lin Jen-Shin 已提交
285 286
      end

287 288
      context 'has no such ref' do
        before do
289
          get path_for_ref('TAIL', build.name)
290 291
        end

L
Lin Jen-Shin 已提交
292
        it_behaves_like 'not found'
293 294
      end

F
Filipa Lacerda 已提交
295
      context 'has no such job' do
296
        before do
297
          get path_for_ref(pipeline.ref, 'NOBUILD')
298 299
        end

L
Lin Jen-Shin 已提交
300
        it_behaves_like 'not found'
301
      end
L
Lin Jen-Shin 已提交
302 303
    end

F
Filipa Lacerda 已提交
304
    context 'find proper job' do
305
      shared_examples 'a valid file' do
L
Lin Jen-Shin 已提交
306
        let(:download_headers) do
L
Lin Jen-Shin 已提交
307 308 309
          { 'Content-Transfer-Encoding' => 'binary',
            'Content-Disposition' =>
              "attachment; filename=#{build.artifacts_file.filename}" }
L
Lin Jen-Shin 已提交
310
        end
L
Lin Jen-Shin 已提交
311

312
        it { expect(response).to have_gitlab_http_status(200) }
313
        it { expect(response.headers).to include(download_headers) }
314 315 316 317
      end

      context 'with regular branch' do
        before do
K
Kamil Trzcinski 已提交
318
          pipeline.reload
319 320 321
          pipeline.update(ref: 'master',
                          sha: project.commit('master').sha)

322
          get path_for_ref('master')
323 324
        end

325
        it_behaves_like 'a valid file'
L
Lin Jen-Shin 已提交
326 327
      end

328 329
      context 'with branch name containing slash' do
        before do
K
Kamil Trzcinski 已提交
330
          pipeline.reload
331 332 333 334 335
          pipeline.update(ref: 'improve/awesome',
                          sha: project.commit('improve/awesome').sha)
        end

        before do
336
          get path_for_ref('improve/awesome')
337 338
        end

339
        it_behaves_like 'a valid file'
340
      end
L
Lin Jen-Shin 已提交
341 342 343
    end
  end

344
  describe 'GET /projects/:id/builds/:build_id/trace' do
345
    let(:build) { create(:ci_build, :trace, pipeline: pipeline) }
346

L
Lin Jen-Shin 已提交
347
    before do
348
      get v3_api("/projects/#{project.id}/builds/#{build.id}/trace", api_user)
L
Lin Jen-Shin 已提交
349
    end
K
Kamil Trzcinski 已提交
350

351
    context 'authorized user' do
F
Filipa Lacerda 已提交
352
      it 'returns specific job trace' do
353
        expect(response).to have_gitlab_http_status(200)
354
        expect(response.body).to eq(build.trace.raw)
355 356 357 358
      end
    end

    context 'unauthorized user' do
K
Kamil Trzcinski 已提交
359
      let(:api_user) { nil }
360

F
Filipa Lacerda 已提交
361
      it 'does not return specific job trace' do
362
        expect(response).to have_gitlab_http_status(401)
363 364 365
      end
    end
  end
366

367
  describe 'POST /projects/:id/builds/:build_id/cancel' do
L
Lin Jen-Shin 已提交
368
    before do
369
      post v3_api("/projects/#{project.id}/builds/#{build.id}/cancel", api_user)
L
Lin Jen-Shin 已提交
370
    end
K
Kamil Trzcinski 已提交
371

372
    context 'authorized user' do
373
      context 'user with :update_build persmission' do
F
Filipa Lacerda 已提交
374
        it 'cancels running or pending job' do
375
          expect(response).to have_gitlab_http_status(201)
376 377 378 379
          expect(project.builds.first.status).to eq('canceled')
        end
      end

380
      context 'user without :update_build permission' do
L
Lin Jen-Shin 已提交
381
        let(:api_user) { reporter.user }
382

F
Filipa Lacerda 已提交
383
        it 'does not cancel job' do
384
          expect(response).to have_gitlab_http_status(403)
385 386 387 388 389
        end
      end
    end

    context 'unauthorized user' do
K
Kamil Trzcinski 已提交
390
      let(:api_user) { nil }
391

F
Filipa Lacerda 已提交
392
      it 'does not cancel job' do
393
        expect(response).to have_gitlab_http_status(401)
394 395 396 397
      end
    end
  end

398
  describe 'POST /projects/:id/builds/:build_id/retry' do
399
    let(:build) { create(:ci_build, :canceled, pipeline: pipeline) }
K
Kamil Trzcinski 已提交
400

L
Lin Jen-Shin 已提交
401
    before do
402
      post v3_api("/projects/#{project.id}/builds/#{build.id}/retry", api_user)
L
Lin Jen-Shin 已提交
403
    end
K
Kamil Trzcinski 已提交
404

405
    context 'authorized user' do
K
Kamil Trzcinski 已提交
406
      context 'user with :update_build permission' do
F
Filipa Lacerda 已提交
407
        it 'retries non-running job' do
408
          expect(response).to have_gitlab_http_status(201)
409 410 411 412 413
          expect(project.builds.first.status).to eq('canceled')
          expect(json_response['status']).to eq('pending')
        end
      end

414
      context 'user without :update_build permission' do
L
Lin Jen-Shin 已提交
415
        let(:api_user) { reporter.user }
416

F
Filipa Lacerda 已提交
417
        it 'does not retry job' do
418
          expect(response).to have_gitlab_http_status(403)
419 420 421 422 423
        end
      end
    end

    context 'unauthorized user' do
K
Kamil Trzcinski 已提交
424
      let(:api_user) { nil }
425

F
Filipa Lacerda 已提交
426
      it 'does not retry job' do
427
        expect(response).to have_gitlab_http_status(401)
428 429 430
      end
    end
  end
431

432
  describe 'POST /projects/:id/builds/:build_id/erase' do
433
    before do
434 435
      project.add_master(user)

436
      post v3_api("/projects/#{project.id}/builds/#{build.id}/erase", user)
437 438
    end

F
Filipa Lacerda 已提交
439
    context 'job is erasable' do
440
      let(:build) { create(:ci_build, :trace, :artifacts, :success, project: project, pipeline: pipeline) }
441

F
Filipa Lacerda 已提交
442
      it 'erases job content' do
443
        expect(response.status).to eq 201
444
        expect(build).not_to have_trace
445 446 447
        expect(build.artifacts_file.exists?).to be_falsy
        expect(build.artifacts_metadata.exists?).to be_falsy
      end
448

F
Filipa Lacerda 已提交
449
      it 'updates job' do
450 451 452
        expect(build.reload.erased_at).to be_truthy
        expect(build.reload.erased_by).to eq user
      end
453 454
    end

F
Filipa Lacerda 已提交
455
    context 'job is not erasable' do
456
      let(:build) { create(:ci_build, :trace, project: project, pipeline: pipeline) }
457

458
      it 'responds with forbidden' do
459 460 461 462
        expect(response.status).to eq 403
      end
    end
  end
463 464 465

  describe 'POST /projects/:id/builds/:build_id/artifacts/keep' do
    before do
466
      post v3_api("/projects/#{project.id}/builds/#{build.id}/artifacts/keep", user)
467 468 469 470 471 472 473 474
    end

    context 'artifacts did not expire' do
      let(:build) do
        create(:ci_build, :trace, :artifacts, :success,
               project: project, pipeline: pipeline, artifacts_expire_at: Time.now + 7.days)
      end

K
Kamil Trzcinski 已提交
475
      it 'keeps artifacts' do
476
        expect(response.status).to eq 200
K
Kamil Trzcinski 已提交
477
        expect(build.reload.artifacts_expire_at).to be_nil
478 479 480 481 482 483
      end
    end

    context 'no artifacts' do
      let(:build) { create(:ci_build, project: project, pipeline: pipeline) }

K
Kamil Trzcinski 已提交
484
      it 'responds with not found' do
485 486 487 488
        expect(response.status).to eq 404
      end
    end
  end
Z
Z.J. van de Weg 已提交
489 490 491

  describe 'POST /projects/:id/builds/:build_id/play' do
    before do
492
      post v3_api("/projects/#{project.id}/builds/#{build.id}/play", user)
Z
Z.J. van de Weg 已提交
493 494
    end

F
Filipa Lacerda 已提交
495
    context 'on an playable job' do
Z
Z.J. van de Weg 已提交
496 497
      let(:build) { create(:ci_build, :manual, project: project, pipeline: pipeline) }

F
Filipa Lacerda 已提交
498
      it 'plays the job' do
499
        expect(response).to have_gitlab_http_status 200
Z
Z.J. van de Weg 已提交
500
        expect(json_response['user']['id']).to eq(user.id)
Z
Z.J. van de Weg 已提交
501
        expect(json_response['id']).to eq(build.id)
Z
Z.J. van de Weg 已提交
502 503 504
      end
    end

F
Filipa Lacerda 已提交
505
    context 'on a non-playable job' do
Z
Z.J. van de Weg 已提交
506
      it 'returns a status code 400, Bad Request' do
507
        expect(response).to have_gitlab_http_status 400
F
Filipa Lacerda 已提交
508
        expect(response.body).to match("Unplayable Job")
Z
Z.J. van de Weg 已提交
509 510 511
      end
    end
  end
512
end