builds_spec.rb 11.5 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) }
K
Kamil Trzcinski 已提交
12 13
  let!(:pipeline) { create(:ci_pipeline, project: project, sha: project.commit.id, ref: project.default_branch) }
  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
    let(:build) { create(:ci_build, :success, :artifacts, pipeline: pipeline) }

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

183
    context 'when not logged in' do
K
Kamil Trzcinski 已提交
184
      let(:api_user) { nil }
185 186

      before do
187
        get path_for_ref
188 189
      end

190 191 192
      it 'gives 401' do
        expect(response).to have_http_status(401)
      end
193 194
    end

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

      before do
        get path_for_ref
      end

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

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

      context 'has no such ref' do
        before do
214
          get path_for_ref('TAIL', build.name)
215 216
        end

L
Lin Jen-Shin 已提交
217
        it_behaves_like 'not found'
218 219 220 221
      end

      context 'has no such build' do
        before do
222
          get path_for_ref(pipeline.ref, 'NOBUILD')
223 224
        end

L
Lin Jen-Shin 已提交
225
        it_behaves_like 'not found'
226 227 228 229
      end
    end

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

237 238
        it { expect(response).to have_http_status(200) }
        it { expect(response.headers).to include(download_headers) }
239 240 241 242 243 244 245
      end

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

246
          get path_for_ref('master')
247 248
        end

249
        it_behaves_like 'a valid file'
250 251 252 253 254 255 256 257 258
      end

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

        before do
259
          get path_for_ref('improve/awesome')
260 261
        end

262
        it_behaves_like 'a valid file'
263 264 265 266
      end
    end
  end

267
  describe 'GET /projects/:id/builds/:build_id/trace' do
268
    let(:build) { create(:ci_build, :trace, pipeline: pipeline) }
269

270 271 272
    before do
      get api("/projects/#{project.id}/builds/#{build.id}/trace", api_user)
    end
K
Kamil Trzcinski 已提交
273

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

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

284
      it 'does not return specific build trace' do
Z
Z.J. van de Weg 已提交
285
        expect(response).to have_http_status(401)
286 287 288
      end
    end
  end
289

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

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

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

304
        it 'does not cancel build' do
Z
Z.J. van de Weg 已提交
305
          expect(response).to have_http_status(403)
306 307 308 309 310
        end
      end
    end

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

313
      it 'does not cancel build' do
Z
Z.J. van de Weg 已提交
314
        expect(response).to have_http_status(401)
315 316 317 318
      end
    end
  end

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

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

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

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

336
        it 'does not retry build' do
Z
Z.J. van de Weg 已提交
337
          expect(response).to have_http_status(403)
338 339 340 341 342
        end
      end
    end

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

345
      it 'does not retry build' do
Z
Z.J. van de Weg 已提交
346
        expect(response).to have_http_status(401)
347 348 349
      end
    end
  end
350

351
  describe 'POST /projects/:id/builds/:build_id/erase' do
352
    before do
353
      post api("/projects/#{project.id}/builds/#{build.id}/erase", user)
354 355
    end

356
    context 'build is erasable' do
357
      let(:build) { create(:ci_build, :trace, :artifacts, :success, project: project, pipeline: pipeline) }
358

359
      it 'erases build content' do
360
        expect(response.status).to eq 201
361 362 363 364
        expect(build.trace).to be_empty
        expect(build.artifacts_file.exists?).to be_falsy
        expect(build.artifacts_metadata.exists?).to be_falsy
      end
365

366
      it 'updates build' do
367 368 369
        expect(build.reload.erased_at).to be_truthy
        expect(build.reload.erased_by).to eq user
      end
370 371
    end

372
    context 'build is not erasable' do
373
      let(:build) { create(:ci_build, :trace, project: project, pipeline: pipeline) }
374

375
      it 'responds with forbidden' do
376 377 378 379
        expect(response.status).to eq 403
      end
    end
  end
380 381 382 383 384 385 386 387 388 389 390 391

  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 已提交
392
      it 'keeps artifacts' do
393
        expect(response.status).to eq 200
K
Kamil Trzcinski 已提交
394
        expect(build.reload.artifacts_expire_at).to be_nil
395 396 397 398 399 400
      end
    end

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

K
Kamil Trzcinski 已提交
401
      it 'responds with not found' do
402 403 404 405
        expect(response.status).to eq 404
      end
    end
  end
406
end