builds_spec.rb 11.6 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 }
K
Kamil Trzcinski 已提交
8 9
  let!(:project) { create(:project, creator_id: user.id) }
  let!(:developer) { create(:project_member, :developer, user: user, project: project) }
L
Lin Jen-Shin 已提交
10 11
  let(:reporter) { create(:project_member, :reporter, project: project) }
  let(:guest) { create(:project_member, :guest, project: project) }
12
  let!(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.id, ref: project.default_branch) }
K
Kamil Trzcinski 已提交
13
  let!(:build) { create(:ci_build, pipeline: pipeline) }
14 15

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

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

20
    context 'authorized user' do
21
      it 'returns project builds' do
Z
Z.J. van de Weg 已提交
22
        expect(response).to have_http_status(200)
23 24 25
        expect(json_response).to be_an Array
      end

26 27 28 29 30
      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 已提交
31 32
      context 'filter project with one scope element' do
        let(:query) { 'scope=pending' }
33

K
Kamil Trzcinski 已提交
34
        it do
Z
Z.J. van de Weg 已提交
35
          expect(response).to have_http_status(200)
K
Kamil Trzcinski 已提交
36 37
          expect(json_response).to be_an Array
        end
38 39
      end

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

K
Kamil Trzcinski 已提交
43
        it do
Z
Z.J. van de Weg 已提交
44
          expect(response).to have_http_status(200)
K
Kamil Trzcinski 已提交
45 46
          expect(json_response).to be_an Array
        end
47
      end
T
Tomasz Maczukin 已提交
48

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

Z
Z.J. van de Weg 已提交
52
        it { expect(response).to have_http_status(400) }
T
Tomasz Maczukin 已提交
53
      end
54 55 56
    end

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

K
Kamil Trzcinski 已提交
59
      it 'should not return project builds' do
Z
Z.J. van de Weg 已提交
60
        expect(response).to have_http_status(401)
61 62 63 64
      end
    end
  end

65
  describe 'GET /projects/:id/repository/commits/:sha/builds' do
66 67 68 69
    context 'when commit does not exist in repository' do
      before do
        get api("/projects/#{project.id}/repository/commits/1a271fd1/builds", api_user)
      end
70

71 72 73
      it 'responds with 404' do
        expect(response).to have_http_status(404)
      end
K
Kamil Trzcinski 已提交
74 75
    end

76 77 78 79
    context 'when commit exists in repository' do
      context 'when user is authorized' do
        context 'when pipeline has builds' do
          before do
K
Kamil Trzcinski 已提交
80
            create(:ci_pipeline, project: project, sha: project.commit.id)
81
            create(:ci_build, pipeline: pipeline)
K
Kamil Trzcinski 已提交
82
            create(:ci_build)
83 84 85 86

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

87
          it 'returns project builds for specific commit' do
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
            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
            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
106 107
      end

108 109
      context 'when user is not authorized' do
        before do
K
Kamil Trzcinski 已提交
110 111
          create(:ci_pipeline, project: project, sha: project.commit.id)
          create(:ci_build, pipeline: pipeline)
112

113 114 115
          get api("/projects/#{project.id}/repository/commits/#{project.commit.id}/builds", nil)
        end

116
        it 'does not return project builds' do
117 118 119
          expect(response).to have_http_status(401)
          expect(json_response.except('message')).to be_empty
        end
120 121 122
      end
    end
  end
123

124
  describe 'GET /projects/:id/builds/:build_id' do
K
Kamil Trzcinski 已提交
125
    before { get api("/projects/#{project.id}/builds/#{build.id}", api_user) }
K
Kamil Trzcinski 已提交
126

127
    context 'authorized user' do
128
      it 'returns specific build data' do
Z
Z.J. van de Weg 已提交
129
        expect(response).to have_http_status(200)
130 131
        expect(json_response['name']).to eq('test')
      end
132 133 134
    end

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

137
      it 'does not return specific build data' do
Z
Z.J. van de Weg 已提交
138
        expect(response).to have_http_status(401)
139 140 141 142
      end
    end
  end

143
  describe 'GET /projects/:id/builds/:build_id/artifacts' do
K
Kamil Trzcinski 已提交
144
    before { get api("/projects/#{project.id}/builds/#{build.id}/artifacts", api_user) }
145

K
Kamil Trzcinski 已提交
146
    context 'build with artifacts' do
147
      let(:build) { create(:ci_build, :artifacts, pipeline: pipeline) }
148

K
Kamil Trzcinski 已提交
149 150
      context 'authorized user' do
        let(:download_headers) do
151 152
          { 'Content-Transfer-Encoding' => 'binary',
            'Content-Disposition' => 'attachment; filename=ci_build_artifacts.zip' }
K
Kamil Trzcinski 已提交
153
        end
154

155
        it 'returns specific build artifacts' do
Z
Z.J. van de Weg 已提交
156
          expect(response).to have_http_status(200)
K
Kamil Trzcinski 已提交
157 158
          expect(response.headers).to include(download_headers)
        end
159 160
      end

K
Kamil Trzcinski 已提交
161 162
      context 'unauthorized user' do
        let(:api_user) { nil }
163

164
        it 'does not return specific build artifacts' do
Z
Z.J. van de Weg 已提交
165
          expect(response).to have_http_status(401)
K
Kamil Trzcinski 已提交
166
        end
167 168
      end
    end
K
Kamil Trzcinski 已提交
169

170
    it 'does not return build artifacts if not uploaded' do
Z
Z.J. van de Weg 已提交
171
      expect(response).to have_http_status(404)
K
Kamil Trzcinski 已提交
172
    end
173 174
  end

175
  describe 'GET /projects/:id/artifacts/:ref_name/download?job=name' do
L
Lin Jen-Shin 已提交
176
    let(:api_user) { reporter.user }
177 178 179 180 181
    let(:build) { create(:ci_build, :artifacts, pipeline: pipeline) }

    before do
      build.success
    end
182

183
    def path_for_ref(ref = pipeline.ref, job = build.name)
K
Kamil Trzcinski 已提交
184
      api("/projects/#{project.id}/builds/artifacts/#{ref}/download?job=#{job}", api_user)
185 186
    end

187
    context 'when not logged in' do
K
Kamil Trzcinski 已提交
188
      let(:api_user) { nil }
189 190

      before do
191
        get path_for_ref
192 193
      end

194 195 196
      it 'gives 401' do
        expect(response).to have_http_status(401)
      end
197 198
    end

199
    context 'when logging as guest' do
L
Lin Jen-Shin 已提交
200
      let(:api_user) { guest.user }
201 202 203 204 205 206 207 208 209 210

      before do
        get path_for_ref
      end

      it 'gives 403' do
        expect(response).to have_http_status(403)
      end
    end

211
    context 'non-existing build' do
L
Lin Jen-Shin 已提交
212 213
      shared_examples 'not found' do
        it { expect(response).to have_http_status(:not_found) }
214 215 216 217
      end

      context 'has no such ref' do
        before do
218
          get path_for_ref('TAIL', build.name)
219 220
        end

L
Lin Jen-Shin 已提交
221
        it_behaves_like 'not found'
222 223 224 225
      end

      context 'has no such build' do
        before do
226
          get path_for_ref(pipeline.ref, 'NOBUILD')
227 228
        end

L
Lin Jen-Shin 已提交
229
        it_behaves_like 'not found'
230 231 232 233
      end
    end

    context 'find proper build' do
234
      shared_examples 'a valid file' do
L
Lin Jen-Shin 已提交
235 236 237 238 239 240
        let(:download_headers) do
          { 'Content-Transfer-Encoding' => 'binary',
            'Content-Disposition' =>
              "attachment; filename=#{build.artifacts_file.filename}" }
        end

241 242
        it { expect(response).to have_http_status(200) }
        it { expect(response.headers).to include(download_headers) }
243 244 245 246 247 248 249
      end

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

250
          get path_for_ref('master')
251 252
        end

253
        it_behaves_like 'a valid file'
254 255 256 257 258 259 260 261 262
      end

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

        before do
263
          get path_for_ref('improve/awesome')
264 265
        end

266
        it_behaves_like 'a valid file'
267 268 269 270
      end
    end
  end

271
  describe 'GET /projects/:id/builds/:build_id/trace' do
272
    let(:build) { create(:ci_build, :trace, pipeline: pipeline) }
273

274 275 276
    before do
      get api("/projects/#{project.id}/builds/#{build.id}/trace", api_user)
    end
K
Kamil Trzcinski 已提交
277

278
    context 'authorized user' do
279
      it 'returns specific build trace' do
Z
Z.J. van de Weg 已提交
280
        expect(response).to have_http_status(200)
K
Kamil Trzcinski 已提交
281
        expect(response.body).to eq(build.trace)
282 283 284 285
      end
    end

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

288
      it 'does not return specific build trace' do
Z
Z.J. van de Weg 已提交
289
        expect(response).to have_http_status(401)
290 291 292
      end
    end
  end
293

294
  describe 'POST /projects/:id/builds/:build_id/cancel' do
K
Kamil Trzcinski 已提交
295
    before { post api("/projects/#{project.id}/builds/#{build.id}/cancel", api_user) }
K
Kamil Trzcinski 已提交
296

297
    context 'authorized user' do
298
      context 'user with :update_build persmission' do
299
        it 'cancels running or pending build' do
Z
Z.J. van de Weg 已提交
300
          expect(response).to have_http_status(201)
301 302 303 304
          expect(project.builds.first.status).to eq('canceled')
        end
      end

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

308
        it 'does not cancel build' do
Z
Z.J. van de Weg 已提交
309
          expect(response).to have_http_status(403)
310 311 312 313 314
        end
      end
    end

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

317
      it 'does not cancel build' do
Z
Z.J. van de Weg 已提交
318
        expect(response).to have_http_status(401)
319 320 321 322
      end
    end
  end

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

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

328
    context 'authorized user' do
K
Kamil Trzcinski 已提交
329
      context 'user with :update_build permission' do
330
        it 'retries non-running build' do
Z
Z.J. van de Weg 已提交
331
          expect(response).to have_http_status(201)
332 333 334 335 336
          expect(project.builds.first.status).to eq('canceled')
          expect(json_response['status']).to eq('pending')
        end
      end

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

340
        it 'does not retry build' do
Z
Z.J. van de Weg 已提交
341
          expect(response).to have_http_status(403)
342 343 344 345 346
        end
      end
    end

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

349
      it 'does not retry build' do
Z
Z.J. van de Weg 已提交
350
        expect(response).to have_http_status(401)
351 352 353
      end
    end
  end
354

355
  describe 'POST /projects/:id/builds/:build_id/erase' do
356
    before do
357
      post api("/projects/#{project.id}/builds/#{build.id}/erase", user)
358 359
    end

360
    context 'build is erasable' do
361
      let(:build) { create(:ci_build, :trace, :artifacts, :success, project: project, pipeline: pipeline) }
362

363
      it 'erases build content' do
364
        expect(response.status).to eq 201
365 366 367 368
        expect(build.trace).to be_empty
        expect(build.artifacts_file.exists?).to be_falsy
        expect(build.artifacts_metadata.exists?).to be_falsy
      end
369

370
      it 'updates build' do
371 372 373
        expect(build.reload.erased_at).to be_truthy
        expect(build.reload.erased_by).to eq user
      end
374 375
    end

376
    context 'build is not erasable' do
377
      let(:build) { create(:ci_build, :trace, project: project, pipeline: pipeline) }
378

379
      it 'responds with forbidden' do
380 381 382 383
        expect(response.status).to eq 403
      end
    end
  end
384 385 386 387 388 389 390 391 392 393 394 395

  describe 'POST /projects/:id/builds/:build_id/artifacts/keep' do
    before do
      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 已提交
396
      it 'keeps artifacts' do
397
        expect(response.status).to eq 200
K
Kamil Trzcinski 已提交
398
        expect(build.reload.artifacts_expire_at).to be_nil
399 400 401 402 403 404
      end
    end

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

K
Kamil Trzcinski 已提交
405
      it 'responds with not found' do
406 407 408 409
        expect(response.status).to eq 404
      end
    end
  end
410
end