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

3
describe API::API, api: true do
4 5 6
  include ApiHelpers

  let(:user) { create(:user) }
K
Kamil Trzcinski 已提交
7
  let(:api_user) { user }
8
  let(:user2) { create(:user) }
9 10 11 12 13
  let(:project) { create(:project, creator_id: user.id) }
  let(:developer) { create(:project_member, :developer, user: user, project: project) }
  let(:reporter) { create(:project_member, :reporter, user: user2, project: project) }
  let(:pipeline) { create(:ci_pipeline, project: project, sha: project.commit.id) }
  let(:build) { create(:ci_build, pipeline: pipeline) }
14 15

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

18 19 20 21 22 23
    before do
      developer
      build

      get api("/projects/#{project.id}/builds?#{query}", api_user)
    end
K
Kamil Trzcinski 已提交
24

25 26
    context 'authorized user' do
      it 'should return project builds' do
Z
Z.J. van de Weg 已提交
27
        expect(response).to have_http_status(200)
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

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

K
Kamil Trzcinski 已提交
39
        it do
Z
Z.J. van de Weg 已提交
40
          expect(response).to have_http_status(200)
K
Kamil Trzcinski 已提交
41 42
          expect(json_response).to be_an Array
        end
43 44
      end

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

K
Kamil Trzcinski 已提交
48
        it do
Z
Z.J. van de Weg 已提交
49
          expect(response).to have_http_status(200)
K
Kamil Trzcinski 已提交
50 51
          expect(json_response).to be_an Array
        end
52
      end
T
Tomasz Maczukin 已提交
53

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

Z
Z.J. van de Weg 已提交
57
        it { expect(response).to have_http_status(400) }
T
Tomasz Maczukin 已提交
58
      end
59 60 61
    end

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

K
Kamil Trzcinski 已提交
64
      it 'should not return project builds' do
Z
Z.J. van de Weg 已提交
65
        expect(response).to have_http_status(401)
66 67 68 69
      end
    end
  end

70
  describe 'GET /projects/:id/repository/commits/:sha/builds' do
71 72 73 74
    context 'when commit does not exist in repository' do
      before do
        get api("/projects/#{project.id}/repository/commits/1a271fd1/builds", api_user)
      end
75

76 77 78
      it 'responds with 404' do
        expect(response).to have_http_status(404)
      end
K
Kamil Trzcinski 已提交
79 80
    end

81 82 83 84
    context 'when commit exists in repository' do
      context 'when user is authorized' do
        context 'when pipeline has builds' do
          before do
85 86
            developer
            build
87 88 89 90 91 92 93 94 95 96 97 98 99 100
            create(:ci_build, pipeline: pipeline)

            get api("/projects/#{project.id}/repository/commits/#{project.commit.id}/builds", api_user)
          end

          it 'should return project builds for specific commit' do
            expect(response).to have_http_status(200)
            expect(json_response).to be_an Array
            expect(json_response.size).to eq 2
          end
        end

        context 'when pipeline has no builds' do
          before do
101 102
            developer

103 104 105 106 107 108 109 110 111 112
            branch_head = project.commit('feature').id
            get api("/projects/#{project.id}/repository/commits/#{branch_head}/builds", api_user)
          end

          it 'returns an empty array' do
            expect(response).to have_http_status(200)
            expect(json_response).to be_an Array
            expect(json_response).to be_empty
          end
        end
113 114
      end

115 116
      context 'when user is not authorized' do
        before do
117
          build
118

119 120 121 122 123 124 125
          get api("/projects/#{project.id}/repository/commits/#{project.commit.id}/builds", nil)
        end

        it 'should not return project builds' do
          expect(response).to have_http_status(401)
          expect(json_response.except('message')).to be_empty
        end
126 127 128
      end
    end
  end
129

130
  describe 'GET /projects/:id/builds/:build_id' do
131 132 133 134 135
    before do
      developer

      get api("/projects/#{project.id}/builds/#{build.id}", api_user)
    end
K
Kamil Trzcinski 已提交
136

137 138
    context 'authorized user' do
      it 'should return specific build data' do
Z
Z.J. van de Weg 已提交
139
        expect(response).to have_http_status(200)
140 141
        expect(json_response['name']).to eq('test')
      end
142 143 144
    end

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

K
Kamil Trzcinski 已提交
147
      it 'should not return specific build data' do
Z
Z.J. van de Weg 已提交
148
        expect(response).to have_http_status(401)
149 150 151 152
      end
    end
  end

153
  describe 'GET /projects/:id/builds/:build_id/artifacts' do
154 155 156 157 158
    before do
      developer

      get api("/projects/#{project.id}/builds/#{build.id}/artifacts", api_user)
    end
159

K
Kamil Trzcinski 已提交
160
    context 'build with artifacts' do
161
      let(:build) { create(:ci_build, :artifacts, pipeline: pipeline) }
162

K
Kamil Trzcinski 已提交
163 164
      context 'authorized user' do
        let(:download_headers) do
165 166
          { 'Content-Transfer-Encoding' => 'binary',
            'Content-Disposition' => 'attachment; filename=ci_build_artifacts.zip' }
K
Kamil Trzcinski 已提交
167
        end
168

K
Kamil Trzcinski 已提交
169
        it 'should return specific build artifacts' do
Z
Z.J. van de Weg 已提交
170
          expect(response).to have_http_status(200)
K
Kamil Trzcinski 已提交
171 172
          expect(response.headers).to include(download_headers)
        end
173 174
      end

K
Kamil Trzcinski 已提交
175 176
      context 'unauthorized user' do
        let(:api_user) { nil }
177

K
Kamil Trzcinski 已提交
178
        it 'should not return specific build artifacts' do
Z
Z.J. van de Weg 已提交
179
          expect(response).to have_http_status(401)
K
Kamil Trzcinski 已提交
180
        end
181 182
      end
    end
K
Kamil Trzcinski 已提交
183 184

    it 'should not return build artifacts if not uploaded' do
Z
Z.J. van de Weg 已提交
185
      expect(response).to have_http_status(404)
K
Kamil Trzcinski 已提交
186
    end
187 188
  end

189 190 191 192 193 194
  describe 'GET /projects/:id/artifacts/:ref_name/download?job=name' do
    let(:user) { create(:user) }
    let(:project) { create(:project) }
    let(:pipeline) do
      create(:ci_pipeline,
              project: project,
195 196
              sha: project.commit.sha,
              ref: project.default_branch)
197 198 199 200 201 202 203
    end
    let(:build) { create(:ci_build, :success, :artifacts, pipeline: pipeline) }

    before do
      project.team << [user, :developer]
    end

204
    def path_for_ref(ref = pipeline.ref, job = build.name)
205 206 207
      api("/projects/#{project.id}/builds/artifacts/#{ref}/download?job=#{job}", user)
    end

L
Lin Jen-Shin 已提交
208
    context 'when unauthorized' do
209 210 211
      let(:user) { nil }

      before do
212
        get path_for_ref
213 214
      end

215
      it { expect(response).to have_http_status(401) }
216 217 218 219 220 221 222 223 224
    end

    context 'non-existing build' do
      def verify
        expect(response).to have_http_status(404)
      end

      context 'has no such ref' do
        before do
225
          get path_for_ref('TAIL', build.name)
226 227 228 229 230 231 232
        end

        it('gives 404') { verify }
      end

      context 'has no such build' do
        before do
233
          get path_for_ref(pipeline.ref, 'NOBUILD')
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
        end

        it('gives 404') { verify }
      end
    end

    context 'find proper build' do
      def verify
        download_headers =
          { 'Content-Transfer-Encoding' => 'binary',
            'Content-Disposition' =>
              "attachment; filename=#{build.artifacts_file.filename}" }

        expect(response).to have_http_status(200)
        expect(response.headers).to include(download_headers)
      end

      def create_new_pipeline(status)
        new_pipeline = create(:ci_pipeline, status: 'success')
        create(:ci_build, status, :artifacts, pipeline: new_pipeline)
      end

      context 'with regular branch' do
        before do
          pipeline.update(ref: 'master',
                          sha: project.commit('master').sha)
        end

        before do
263
          get path_for_ref('master')
264 265 266 267 268 269 270 271 272 273 274 275
        end

        it('gives the file') { verify }
      end

      context 'with branch name containing slash' do
        before do
          pipeline.update(ref: 'improve/awesome',
                          sha: project.commit('improve/awesome').sha)
        end

        before do
276
          get path_for_ref('improve/awesome')
277 278 279 280 281 282 283 284 285 286 287 288 289
        end

        it('gives the file') { verify }
      end

      context 'with latest pipeline' do
        before do
          3.times do # creating some old pipelines
            create_new_pipeline(:success)
          end
        end

        before do
290
          get path_for_ref
291 292 293 294 295 296 297 298 299 300 301 302
        end

        it('gives the file') { verify }
      end

      context 'with success pipeline' do
        before do
          build # make sure pipeline was old, but still the latest success one
          create_new_pipeline(:pending)
        end

        before do
303
          get path_for_ref
304 305 306 307 308 309 310
        end

        it('gives the file') { verify }
      end
    end
  end

311
  describe 'GET /projects/:id/builds/:build_id/trace' do
312
    let(:build) { create(:ci_build, :trace, pipeline: pipeline) }
313

314 315 316 317 318
    before do
      developer

      get api("/projects/#{project.id}/builds/#{build.id}/trace", api_user)
    end
K
Kamil Trzcinski 已提交
319

320
    context 'authorized user' do
321
      it 'should return specific build trace' do
Z
Z.J. van de Weg 已提交
322
        expect(response).to have_http_status(200)
K
Kamil Trzcinski 已提交
323
        expect(response.body).to eq(build.trace)
324 325 326 327
      end
    end

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

K
Kamil Trzcinski 已提交
330
      it 'should not return specific build trace' do
Z
Z.J. van de Weg 已提交
331
        expect(response).to have_http_status(401)
332 333 334
      end
    end
  end
335

336
  describe 'POST /projects/:id/builds/:build_id/cancel' do
337 338 339 340 341 342
    before do
      developer
      reporter

      post api("/projects/#{project.id}/builds/#{build.id}/cancel", api_user)
    end
K
Kamil Trzcinski 已提交
343

344
    context 'authorized user' do
345
      context 'user with :update_build persmission' do
346
        it 'should cancel running or pending build' do
Z
Z.J. van de Weg 已提交
347
          expect(response).to have_http_status(201)
348 349 350 351
          expect(project.builds.first.status).to eq('canceled')
        end
      end

352
      context 'user without :update_build permission' do
K
Kamil Trzcinski 已提交
353
        let(:api_user) { user2 }
354

K
Kamil Trzcinski 已提交
355
        it 'should not cancel build' do
Z
Z.J. van de Weg 已提交
356
          expect(response).to have_http_status(403)
357 358 359 360 361
        end
      end
    end

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

K
Kamil Trzcinski 已提交
364
      it 'should not cancel build' do
Z
Z.J. van de Weg 已提交
365
        expect(response).to have_http_status(401)
366 367 368 369
      end
    end
  end

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

373 374 375 376 377 378
    before do
      developer
      reporter

      post api("/projects/#{project.id}/builds/#{build.id}/retry", api_user)
    end
K
Kamil Trzcinski 已提交
379

380
    context 'authorized user' do
K
Kamil Trzcinski 已提交
381
      context 'user with :update_build permission' do
382
        it 'should retry non-running build' do
Z
Z.J. van de Weg 已提交
383
          expect(response).to have_http_status(201)
384 385 386 387 388
          expect(project.builds.first.status).to eq('canceled')
          expect(json_response['status']).to eq('pending')
        end
      end

389
      context 'user without :update_build permission' do
K
Kamil Trzcinski 已提交
390
        let(:api_user) { user2 }
391

K
Kamil Trzcinski 已提交
392
        it 'should not retry build' do
Z
Z.J. van de Weg 已提交
393
          expect(response).to have_http_status(403)
394 395 396 397 398
        end
      end
    end

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

K
Kamil Trzcinski 已提交
401
      it 'should not retry build' do
Z
Z.J. van de Weg 已提交
402
        expect(response).to have_http_status(401)
403 404 405
      end
    end
  end
406

407
  describe 'POST /projects/:id/builds/:build_id/erase' do
408
    before do
409 410
      developer

411
      post api("/projects/#{project.id}/builds/#{build.id}/erase", user)
412 413
    end

414
    context 'build is erasable' do
415
      let(:build) { create(:ci_build, :trace, :artifacts, :success, project: project, pipeline: pipeline) }
416 417

      it 'should erase build content' do
418
        expect(response.status).to eq 201
419 420 421 422
        expect(build.trace).to be_empty
        expect(build.artifacts_file.exists?).to be_falsy
        expect(build.artifacts_metadata.exists?).to be_falsy
      end
423 424 425 426 427

      it 'should update build' do
        expect(build.reload.erased_at).to be_truthy
        expect(build.reload.erased_by).to eq user
      end
428 429
    end

430
    context 'build is not erasable' do
431
      let(:build) { create(:ci_build, :trace, project: project, pipeline: pipeline) }
432 433 434 435 436 437

      it 'should respond with forbidden' do
        expect(response.status).to eq 403
      end
    end
  end
438 439 440

  describe 'POST /projects/:id/builds/:build_id/artifacts/keep' do
    before do
441 442
      developer

443 444 445 446 447 448 449 450 451
      post api("/projects/#{project.id}/builds/#{build.id}/artifacts/keep", user)
    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 已提交
452
      it 'keeps artifacts' do
453
        expect(response.status).to eq 200
K
Kamil Trzcinski 已提交
454
        expect(build.reload.artifacts_expire_at).to be_nil
455 456 457 458 459 460
      end
    end

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

K
Kamil Trzcinski 已提交
461
      it 'responds with not found' do
462 463 464 465
        expect(response.status).to eq 404
      end
    end
  end
466
end