From f4e7a8893d71bcbc92a5ecd16c95593f17d1ddf5 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Thu, 24 Dec 2015 19:05:57 +0100 Subject: Add builds API (listing, showing trace) --- lib/api/api.rb | 2 ++ lib/api/builds.rb | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/api/entities.rb | 13 +++++++++ 3 files changed, 95 insertions(+) create mode 100644 lib/api/builds.rb diff --git a/lib/api/api.rb b/lib/api/api.rb index 7834262d612..266b5f48f8f 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -54,5 +54,7 @@ module API mount Keys mount Tags mount Triggers + + mount Builds end end diff --git a/lib/api/builds.rb b/lib/api/builds.rb new file mode 100644 index 00000000000..ce4892b5eeb --- /dev/null +++ b/lib/api/builds.rb @@ -0,0 +1,80 @@ +module API + # Projects builds API + class Builds < Grape::API + before { authenticate! } + + resource :projects do + # Get a project repository commits + # + # Parameters: + # id (required) - The ID of a project + # scope (optional) - The scope of builds to show (one of: all, finished, running) + # page (optional) - The page number for pagination (default: 1) + # per_page (ooptional) - The value of items per page to show (default 30) + # Example Request: + # GET /projects/:id/builds/all + get ':id/builds' do + all_builds = user_project.builds + builds = all_builds.order('created_at DESC') + builds = + case params[:scope] + when 'all' + builds + when 'finished' + builds.finished + when 'running' + builds.running + when 'pending' + builds.pending + when 'success' + builds.success + when 'failed' + builds.failed + else + builds.running_or_pending.reverse_order + end + + page = (params[:page] || 1).to_i + per_page = (params[:per_page] || 30).to_i + + present builds.page(page).per(per_page), with: Entities::Build + end + + # Get a specific build of a project + # + # Parameters: + # id (required) - The ID of a project + # build_id (required) - The ID of a build + # Example Request: + # GET /projects/:id/builds/:build_id + get ':id/builds/:build_id' do + present get_build(params[:build_id]), with: Entities::Build + end + + # Get a trace of a specific build of a project + # + # Parameters: + # id (required) - The ID of a project + # build_id (required) - The ID of a build + # Example Request: + # GET /projects/:id/build/:build_id/trace + get ':id/builds/:build_id/trace' do + trace = get_build(params[:build_id]).trace + trace = + unless trace.nil? + trace.split("\n") + else + [] + end + + present trace + end + end + + helpers do + def get_build(id) + user_project.builds.where(id: id).first + end + end + end +end diff --git a/lib/api/entities.rb b/lib/api/entities.rb index f8511ac5f5c..0bf50490eac 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -366,5 +366,18 @@ module API class TriggerRequest < Grape::Entity expose :id, :variables end + + class Build < Grape::Entity + expose :id + expose :status + expose :stage + expose :name + expose :ref + expose :commit + expose :runner + expose :created_at + expose :started_at + expose :finished_at + end end end -- cgit v1.2.1 From b5fef34f1e3beb60e7184cfb3420976bfa367137 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Thu, 24 Dec 2015 19:18:01 +0100 Subject: Fix example request url --- lib/api/builds.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/api/builds.rb b/lib/api/builds.rb index ce4892b5eeb..0ddb9e98de6 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -12,7 +12,7 @@ module API # page (optional) - The page number for pagination (default: 1) # per_page (ooptional) - The value of items per page to show (default 30) # Example Request: - # GET /projects/:id/builds/all + # GET /projects/:id/builds get ':id/builds' do all_builds = user_project.builds builds = all_builds.order('created_at DESC') -- cgit v1.2.1 From f39959d00a1358ba7d73ebeaccb827738c8151ba Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Mon, 28 Dec 2015 13:09:51 +0100 Subject: Add some fixes to builds API --- lib/api/builds.rb | 27 +++++++++------------------ lib/api/entities.rb | 20 ++++++++++++++++++-- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 0ddb9e98de6..863be0d5e40 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -15,23 +15,15 @@ module API # GET /projects/:id/builds get ':id/builds' do all_builds = user_project.builds - builds = all_builds.order('created_at DESC') + builds = all_builds.order('id DESC') builds = case params[:scope] - when 'all' - builds when 'finished' builds.finished when 'running' builds.running - when 'pending' - builds.pending - when 'success' - builds.success - when 'failed' - builds.failed else - builds.running_or_pending.reverse_order + builds end page = (params[:page] || 1).to_i @@ -59,15 +51,14 @@ module API # Example Request: # GET /projects/:id/build/:build_id/trace get ':id/builds/:build_id/trace' do - trace = get_build(params[:build_id]).trace - trace = - unless trace.nil? - trace.split("\n") - else - [] - end + build = get_build(params[:build_id]) + + header 'Content-Disposition', "infile; filename=\"#{build.id}.log\"" + content_type 'text/plain' + env['api.format'] = :binary - present trace + trace = build.trace + body trace end end diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 0bf50490eac..76b5d14f202 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -367,14 +367,30 @@ module API expose :id, :variables end + class CiCommit < Grape::Entity + expose :id + expose :ref + expose :sha + expose :committed_at + end + + class CiRunner < Grape::Entity + expose :id + expose :token + expose :description + expose :active + expose :is_shared + expose :name + end + class Build < Grape::Entity expose :id expose :status expose :stage expose :name expose :ref - expose :commit - expose :runner + expose :commit, with: CiCommit + expose :runner, with: CiRunner expose :created_at expose :started_at expose :finished_at -- cgit v1.2.1 From f4cff4dcd0b11d4597efe454731838fbf5803516 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Mon, 28 Dec 2015 13:33:03 +0100 Subject: Modify build pagination to use 'paginate' helper --- lib/api/builds.rb | 5 +---- lib/api/helpers.rb | 6 ++++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 863be0d5e40..f219b0f5241 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -26,10 +26,7 @@ module API builds end - page = (params[:page] || 1).to_i - per_page = (params[:per_page] || 30).to_i - - present builds.page(page).per(per_page), with: Entities::Build + present paginate(builds), with: Entities::Build end # Get a specific build of a project diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index a4df810e755..8fb5cd6ab63 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -97,8 +97,10 @@ module API end def paginate(relation) - per_page = params[:per_page].to_i - paginated = relation.page(params[:page]).per(per_page) + page = (params[:page] || 1).to_i + per_page = (params[:per_page] || 30).to_i + + paginated = relation.page(page).per(per_page) add_pagination_headers(paginated, per_page) paginated -- cgit v1.2.1 From d398e78ea09c1f88800cd4c99f92dd8e5d1d0d39 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Mon, 28 Dec 2015 15:49:13 +0100 Subject: Add endpoint for getting builds for a specific commit --- lib/api/builds.rb | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/lib/api/builds.rb b/lib/api/builds.rb index f219b0f5241..7488863cdcf 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -4,7 +4,7 @@ module API before { authenticate! } resource :projects do - # Get a project repository commits + # Get a project builds # # Parameters: # id (required) - The ID of a project @@ -14,18 +14,21 @@ module API # Example Request: # GET /projects/:id/builds get ':id/builds' do - all_builds = user_project.builds - builds = all_builds.order('id DESC') - builds = - case params[:scope] - when 'finished' - builds.finished - when 'running' - builds.running - else - builds - end + builds = user_project.builds.order('id DESC') + builds = filter_builds(builds, params[:scope]) + present paginate(builds), with: Entities::Build + end + # GET builds for a specific commit of a project + # + # Parameters: + # id (required) - The ID of a project + # sha (required) - The SHA id of a commit + # Example Request: + # GET /projects/:id/builds/commit/:sha + get ':id/builds/commit/:sha' do + builds = user_project.ci_commits.find_by_sha(params[:sha]).builds.order('id DESC') + builds = filter_builds(builds, params[:scope]) present paginate(builds), with: Entities::Build end @@ -63,6 +66,17 @@ module API def get_build(id) user_project.builds.where(id: id).first end + + def filter_builds(builds, scope) + case scope + when 'finished' + builds.finished + when 'running' + builds.running + else + builds + end + end end end end -- cgit v1.2.1 From e7d0746d9319119c459581615ae4205139bee444 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Mon, 28 Dec 2015 16:38:02 +0100 Subject: Add 'not_found' notifications in build/trace details --- lib/api/builds.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 7488863cdcf..5ac24d0367a 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -19,7 +19,7 @@ module API present paginate(builds), with: Entities::Build end - # GET builds for a specific commit of a project + # Get builds for a specific commit of a project # # Parameters: # id (required) - The ID of a project @@ -40,7 +40,10 @@ module API # Example Request: # GET /projects/:id/builds/:build_id get ':id/builds/:build_id' do - present get_build(params[:build_id]), with: Entities::Build + build = get_build(params[:build_id]) + return not_found!(build) unless build + + present build, with: Entities::Build end # Get a trace of a specific build of a project @@ -52,6 +55,7 @@ module API # GET /projects/:id/build/:build_id/trace get ':id/builds/:build_id/trace' do build = get_build(params[:build_id]) + return not_found!(build) unless build header 'Content-Disposition', "infile; filename=\"#{build.id}.log\"" content_type 'text/plain' -- cgit v1.2.1 From 8d4555037a844d21dbf56c2995cff30782af920b Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Mon, 28 Dec 2015 16:38:29 +0100 Subject: Add cancel/retry endpoints to build API --- lib/api/builds.rb | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 5ac24d0367a..16e4549d280 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -64,6 +64,42 @@ module API trace = build.trace body trace end + + # cancel a specific build of a project + # + # parameters: + # id (required) - the id of a project + # build_id (required) - the id of a build + # example request: + # post /projects/:id/build/:build_id/cancel + post ':id/builds/:build_id/cancel' do + authorize_manage_builds! + + build = get_build(params[:build_id]) + return not_found!(build) unless build + + build.cancel + + present build, with: Entities::Build + end + + # cancel a specific build of a project + # + # parameters: + # id (required) - the id of a project + # build_id (required) - the id of a build + # example request: + # post /projects/:id/build/:build_id/retry + post ':id/builds/:build_id/retry' do + authorize_manage_builds! + + build = get_build(params[:build_id]) + return not_found!(build) unless build && build.retryable? + + build = Ci::Build.retry(build) + + present build, with: Entities::Build + end end helpers do @@ -81,6 +117,10 @@ module API builds end end + + def authorize_manage_builds! + authorize! :manage_builds, user_project + end end end end -- cgit v1.2.1 From b2fbeb377d8ba17352d40817b0b444196cb97636 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Mon, 28 Dec 2015 17:01:02 +0100 Subject: Remove changes in 'paginate' helper --- lib/api/helpers.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 8fb5cd6ab63..a4df810e755 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -97,10 +97,8 @@ module API end def paginate(relation) - page = (params[:page] || 1).to_i - per_page = (params[:per_page] || 30).to_i - - paginated = relation.page(page).per(per_page) + per_page = params[:per_page].to_i + paginated = relation.page(params[:page]).per(per_page) add_pagination_headers(paginated, per_page) paginated -- cgit v1.2.1 From d2601211a0c7a44666501dea82a8488b08f8faa7 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Tue, 29 Dec 2015 23:12:36 +0100 Subject: Add specs for build listings in API --- lib/api/builds.rb | 9 ++++--- spec/requests/api/builds_spec.rb | 52 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 spec/requests/api/builds_spec.rb diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 16e4549d280..a519224d2b8 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -27,7 +27,10 @@ module API # Example Request: # GET /projects/:id/builds/commit/:sha get ':id/builds/commit/:sha' do - builds = user_project.ci_commits.find_by_sha(params[:sha]).builds.order('id DESC') + commit = user_project.ci_commits.find_by_sha(params[:sha]) + return not_found! unless commit + + builds = commit.builds.order('id DESC') builds = filter_builds(builds, params[:scope]) present paginate(builds), with: Entities::Build end @@ -65,7 +68,7 @@ module API body trace end - # cancel a specific build of a project + # Cancel a specific build of a project # # parameters: # id (required) - the id of a project @@ -83,7 +86,7 @@ module API present build, with: Entities::Build end - # cancel a specific build of a project + # Retry a specific build of a project # # parameters: # id (required) - the id of a project diff --git a/spec/requests/api/builds_spec.rb b/spec/requests/api/builds_spec.rb new file mode 100644 index 00000000000..81c176c9fb0 --- /dev/null +++ b/spec/requests/api/builds_spec.rb @@ -0,0 +1,52 @@ +require 'spec_helper' + +describe API::API, api: true do + include ApiHelpers + + let(:user) { create(:user) } + let(:user2) { create(:user) } + let!(:project) { create(:project, creator_id: user.id) } + let!(:master) { create(:project_member, user: user, project: project, access_level: ProjectMember::MASTER) } + let!(:guest) { create(:project_member, user: user2, project: project, access_level: ProjectMember::GUEST) } + + describe 'GET /projects/:id/builds ' do + context 'authorized user' do + it 'should return project builds' do + get api("/projects/#{project.id}/builds", user) + + puts json_response + expect(response.status).to eq(200) + expect(json_response).to be_an Array + end + end + + context 'unauthorized user' do + it 'should not return project builds' do + get api("/projects/#{project.id}/builds") + + expect(response.status).to eq(401) + end + end + end + + describe 'GET /projects/:id/builds/commit/:sha' do + context 'authorized user' do + it 'should return project builds for specific commit' do + project.ensure_ci_commit(project.repository.commit.sha) + get api("/projects/#{project.id}/builds/commit/#{project.ci_commits.first.sha}", user) + + expect(response.status).to eq(200) + expect(json_response).to be_an Array + end + end + + context 'unauthorized user' do + it 'should not return project builds' do + project.ensure_ci_commit(project.repository.commit.sha) + get api("/projects/#{project.id}/builds/commit/#{project.ci_commits.first.sha}") + + expect(response.status).to eq(401) + end + end + end +end -- cgit v1.2.1 From 593d87ea54eec4d60cf7eeb404af82d9e015b066 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Wed, 30 Dec 2015 15:12:07 +0100 Subject: Add specs for build details/traces features in builds API --- spec/factories/ci/builds.rb | 6 ++++++ spec/requests/api/builds_spec.rb | 40 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb index f76e826f138..4551ee57d78 100644 --- a/spec/factories/ci/builds.rb +++ b/spec/factories/ci/builds.rb @@ -30,6 +30,7 @@ FactoryGirl.define do name 'test' ref 'master' tag false + created_at 'Di 29. Okt 09:50:00 CET 2013' started_at 'Di 29. Okt 09:51:28 CET 2013' finished_at 'Di 29. Okt 09:53:28 CET 2013' commands 'ls -a' @@ -54,5 +55,10 @@ FactoryGirl.define do factory :ci_build_tag do tag true end + + factory :ci_build_with_trace do + id 999 + trace 'BUILD TRACE' + end end end diff --git a/spec/requests/api/builds_spec.rb b/spec/requests/api/builds_spec.rb index 81c176c9fb0..c68ea0898b8 100644 --- a/spec/requests/api/builds_spec.rb +++ b/spec/requests/api/builds_spec.rb @@ -8,6 +8,9 @@ describe API::API, api: true do let!(:project) { create(:project, creator_id: user.id) } let!(:master) { create(:project_member, user: user, project: project, access_level: ProjectMember::MASTER) } let!(:guest) { create(:project_member, user: user2, project: project, access_level: ProjectMember::GUEST) } + let(:commit) { create(:ci_commit, project: project)} + let(:build) { create(:ci_build, commit: commit) } + let(:build_with_trace) { create(:ci_build_with_trace, commit: commit) } describe 'GET /projects/:id/builds ' do context 'authorized user' do @@ -32,7 +35,7 @@ describe API::API, api: true do describe 'GET /projects/:id/builds/commit/:sha' do context 'authorized user' do it 'should return project builds for specific commit' do - project.ensure_ci_commit(project.repository.commit.sha) + project.ensure_ci_commit(commit.sha) get api("/projects/#{project.id}/builds/commit/#{project.ci_commits.first.sha}", user) expect(response.status).to eq(200) @@ -42,11 +45,44 @@ describe API::API, api: true do context 'unauthorized user' do it 'should not return project builds' do - project.ensure_ci_commit(project.repository.commit.sha) + project.ensure_ci_commit(commit.sha) get api("/projects/#{project.id}/builds/commit/#{project.ci_commits.first.sha}") expect(response.status).to eq(401) end end end + + describe 'GET /projects/:id/builds/:build_id(/trace)?' do + context 'authorized user' do + it 'should return specific build data' do + get api("/projects/#{project.id}/builds/#{build.id}", user) + + expect(response.status).to eq(200) + expect(json_response['name']).to eq('test') + expect(json_response['commit']['sha']).to eq(commit.sha) + end + + it 'should return specific build trace' do + get api("/projects/#{project.id}/builds/#{build_with_trace.id}/trace", user) + + expect(response.status).to eq(200) + expect(response.body).to eq(build_with_trace.trace) + end + end + + context 'unauthorized user' do + it 'should not return specific build data' do + get api("/projects/#{project.id}/builds/#{build.id}") + + expect(response.status).to eq(401) + end + + it 'should not return specific build trace' do + get api("/projects/#{project.id}/builds/#{build_with_trace.id}/trace") + + expect(response.status).to eq(401) + end + end + end end -- cgit v1.2.1 From a17bf380cb4c90696349f268ca4a8c2fedc1f545 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Wed, 30 Dec 2015 16:37:47 +0100 Subject: Add cancel/retry features to builds API --- spec/factories/ci/builds.rb | 4 +++ spec/requests/api/builds_spec.rb | 62 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb index 4551ee57d78..ce68457f86b 100644 --- a/spec/factories/ci/builds.rb +++ b/spec/factories/ci/builds.rb @@ -60,5 +60,9 @@ FactoryGirl.define do id 999 trace 'BUILD TRACE' end + + factory :ci_build_canceled do + status 'canceled' + end end end diff --git a/spec/requests/api/builds_spec.rb b/spec/requests/api/builds_spec.rb index c68ea0898b8..d4af7639d4b 100644 --- a/spec/requests/api/builds_spec.rb +++ b/spec/requests/api/builds_spec.rb @@ -7,10 +7,11 @@ describe API::API, api: true do let(:user2) { create(:user) } let!(:project) { create(:project, creator_id: user.id) } let!(:master) { create(:project_member, user: user, project: project, access_level: ProjectMember::MASTER) } - let!(:guest) { create(:project_member, user: user2, project: project, access_level: ProjectMember::GUEST) } + let!(:reporter) { create(:project_member, user: user2, project: project, access_level: ProjectMember::REPORTER) } let(:commit) { create(:ci_commit, project: project)} let(:build) { create(:ci_build, commit: commit) } let(:build_with_trace) { create(:ci_build_with_trace, commit: commit) } + let(:build_canceled) { create(:ci_build_canceled, commit: commit) } describe 'GET /projects/:id/builds ' do context 'authorized user' do @@ -85,4 +86,63 @@ describe API::API, api: true do end end end + + describe 'GET /projects/:id/builds/:build_id/cancel' do + context 'authorized user' do + context 'user with :manage_builds persmission' do + it 'should cancel running or pending build' do + post api("/projects/#{project.id}/builds/#{build.id}/cancel", user) + + expect(response.status).to eq(201) + expect(project.builds.first.status).to eq('canceled') + end + end + + context 'user without :manage_builds permission' do + it 'should not cancel build' do + post api("/projects/#{project.id}/builds/#{build.id}/cancel", user2) + + expect(response.status).to eq(403) + end + end + end + + context 'unauthorized user' do + it 'should not cancel build' do + post api("/projects/#{project.id}/builds/#{build.id}/cancel") + + expect(response.status).to eq(401) + end + end + end + + describe 'GET /projects/:id/builds/:build_id/retry' do + context 'authorized user' do + context 'user with :manage_builds persmission' do + it 'should retry non-running build' do + post api("/projects/#{project.id}/builds/#{build_canceled.id}/retry", user) + + expect(response.status).to eq(201) + expect(project.builds.first.status).to eq('canceled') + expect(json_response['status']).to eq('pending') + end + end + + context 'user without :manage_builds permission' do + it 'should not retry build' do + post api("/projects/#{project.id}/builds/#{build_canceled.id}/retry", user2) + + expect(response.status).to eq(403) + end + end + end + + context 'unauthorized user' do + it 'should not retry build' do + post api("/projects/#{project.id}/builds/#{build_canceled.id}/retry") + + expect(response.status).to eq(401) + end + end + end end -- cgit v1.2.1 From 628297fe5692fc241c93ff34cece71132bfb9aed Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Thu, 31 Dec 2015 23:01:28 +0100 Subject: Remove incorrect 'default' values from method description --- lib/api/builds.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/api/builds.rb b/lib/api/builds.rb index a519224d2b8..92bf849824c 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -9,8 +9,8 @@ module API # Parameters: # id (required) - The ID of a project # scope (optional) - The scope of builds to show (one of: all, finished, running) - # page (optional) - The page number for pagination (default: 1) - # per_page (ooptional) - The value of items per page to show (default 30) + # page (optional) - The page number for pagination + # per_page (ooptional) - The value of items per page to show # Example Request: # GET /projects/:id/builds get ':id/builds' do -- cgit v1.2.1 From a862ade55bf68f56734538b40e02e56036f8a1bd Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Tue, 5 Jan 2016 16:36:14 +0100 Subject: Update ./doc/api/ --- doc/api/README.md | 1 + doc/api/builds.md | 206 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/api/builds.rb | 3 +- 3 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 doc/api/builds.md diff --git a/doc/api/README.md b/doc/api/README.md index 25a31b235cc..43ee24ddb63 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -23,6 +23,7 @@ - [Namespaces](namespaces.md) - [Settings](settings.md) - [Keys](keys.md) +- [Builds](builds.md) ## Clients diff --git a/doc/api/builds.md b/doc/api/builds.md new file mode 100644 index 00000000000..b716499dd36 --- /dev/null +++ b/doc/api/builds.md @@ -0,0 +1,206 @@ +# Builds API + +## List project builds + +Get a list of builds in a project. + +``` +GET /projects/:id/builds +``` + +Parameters: + +- `id` (required) - The ID of a project +- `scope` (optional) - The scope of builds to show (one of: `all`, `finished`, `running`; default: `all`) + +```json +[ + { + "commit": { + "committed_at": "2015-12-28T14:34:03.814Z", + "id": 2, + "ref": null, + "sha": "6b053ad388c531c21907f022933e5e81598db388" + }, + "created_at": "2016-01-04T15:41:23.147Z", + "finished_at": null, + "id": 65, + "name": "brakeman", + "ref": "master", + "runner": null, + "stage": "test", + "started_at": null, + "status": "pending" + }, + { + "commit": { + "committed_at": "2015-12-28T14:34:03.814Z", + "id": 2, + "ref": null, + "sha": "6b053ad388c531c21907f022933e5e81598db388" + }, + "created_at": "2016-01-04T15:41:23.046Z", + "finished_at": null, + "id": 64, + "name": "rubocop", + "ref": "master", + "runner": null, + "stage": "test", + "started_at": null, + "status": "pending" + } +] +``` + +## List commit builds + +Get a list of builds for specific commit in a project. + +``` +GET /projects/:id/builds/commit/:sha +``` + +Parameters: + +- `id` (required) - The ID of a project +- `sha` (required) - The SHA id of a commit +- `scope` (optional) - The scope of builds to show (one of: `all`, `finished`, `running`; default: `all`) + + +```json +[ + { + "commit": { + "committed_at": "2015-12-28T14:34:03.814Z", + "id": 2, + "ref": null, + "sha": "6b053ad388c531c21907f022933e5e81598db388" + }, + "created_at": "2016-01-04T15:41:23.147Z", + "finished_at": null, + "id": 65, + "name": "brakeman", + "ref": "master", + "runner": null, + "stage": "test", + "started_at": null, + "status": "pending" + }, + { + "commit": { + "committed_at": "2015-12-28T14:34:03.814Z", + "id": 2, + "ref": null, + "sha": "6b053ad388c531c21907f022933e5e81598db388" + }, + "created_at": "2016-01-04T15:41:23.046Z", + "finished_at": null, + "id": 64, + "name": "rubocop", + "ref": "master", + "runner": null, + "stage": "test", + "started_at": null, + "status": "pending" + } +] +``` + +## Get a single build + +Get a single build of a project + +``` +GET /projects/:id/builds/:build_id +``` + +Parameters: + +- `id` (required) - The ID of a project +- `build_id` (required) - The ID of a build + +```json +{ + "commit": { + "committed_at": "2015-12-28T14:34:03.814Z", + "id": 2, + "ref": null, + "sha": "6b053ad388c531c21907f022933e5e81598db388" + }, + "created_at": "2016-01-04T15:41:23.046Z", + "finished_at": null, + "id": 64, + "name": "rubocop", + "ref": "master", + "runner": null, + "stage": "test", + "started_at": null, + "status": "pending" +} +``` + +## Cancel a build + +Cancel a single build of a project + +``` +POST /projects/:id/builds/:build_id/cancel +``` + +Parameters: + +- `id` (required) - The ID of a project +- `build_id` (required) - The ID of a build + +```json +{ + "commit": { + "committed_at": "2015-12-28T14:34:03.814Z", + "id": 2, + "ref": null, + "sha": "6b053ad388c531c21907f022933e5e81598db388" + }, + "created_at": "2016-01-05T15:33:25.936Z", + "finished_at": "2016-01-05T15:33:47.553Z", + "id": 66, + "name": "rubocop", + "ref": "master", + "runner": null, + "stage": "test", + "started_at": null, + "status": "canceled" +} +``` + +## Retry a build + +Retry a single build of a project + +``` +POST /projects/:id/builds/:build_id/retry +``` + +Parameters: + +- `id` (required) - The ID of a project +- `build_id` (required) - The ID of a build + +```json +{ + "commit": { + "committed_at": "2015-12-28T14:34:03.814Z", + "id": 2, + "ref": null, + "sha": "6b053ad388c531c21907f022933e5e81598db388" + }, + "created_at": "2016-01-05T15:33:25.936Z", + "finished_at": null, + "id": 66, + "name": "rubocop", + "ref": "master", + "runner": null, + "stage": "test", + "started_at": null, + "status": "pending" +} +``` diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 92bf849824c..6b0edcff820 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -8,7 +8,7 @@ module API # # Parameters: # id (required) - The ID of a project - # scope (optional) - The scope of builds to show (one of: all, finished, running) + # scope (optional) - The scope of builds to show (one of: all, finished, running; default: all) # page (optional) - The page number for pagination # per_page (ooptional) - The value of items per page to show # Example Request: @@ -24,6 +24,7 @@ module API # Parameters: # id (required) - The ID of a project # sha (required) - The SHA id of a commit + # scope (optional) - The scope of builds to show (one of: all, finished, running; default: all) # Example Request: # GET /projects/:id/builds/commit/:sha get ':id/builds/commit/:sha' do -- cgit v1.2.1 From 549a2fa7873366b52e9ba3caa849073b7b958b73 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Fri, 8 Jan 2016 14:01:31 +0100 Subject: Modify builds scope filtering in builds API --- app/models/ci/build.rb | 4 ++++ doc/api/builds.md | 5 ++--- lib/api/builds.rb | 31 +++++++++++++++++++------------ spec/requests/api/builds_spec.rb | 15 ++++++++++++++- 4 files changed, 39 insertions(+), 16 deletions(-) diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 3e67b2771c1..8fb68743a9b 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -94,6 +94,10 @@ module Ci new_build.save new_build end + + def available_statuses + state_machines[:status].states.map &:value + end end state_machine :status, initial: :pending do diff --git a/doc/api/builds.md b/doc/api/builds.md index b716499dd36..c52266714d0 100644 --- a/doc/api/builds.md +++ b/doc/api/builds.md @@ -11,7 +11,7 @@ GET /projects/:id/builds Parameters: - `id` (required) - The ID of a project -- `scope` (optional) - The scope of builds to show (one of: `all`, `finished`, `running`; default: `all`) +- `scope` (optional) - The scope of builds to show (one or array of: pending, running, failed, success, canceled; if none provided showing all builds) ```json [ @@ -64,8 +64,7 @@ Parameters: - `id` (required) - The ID of a project - `sha` (required) - The SHA id of a commit -- `scope` (optional) - The scope of builds to show (one of: `all`, `finished`, `running`; default: `all`) - +- `scope` (optional) - The scope of builds to show (one or array of: pending, running, failed, success, canceled; if none provided showing all builds) ```json [ diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 6b0edcff820..6aae1856953 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -8,9 +8,8 @@ module API # # Parameters: # id (required) - The ID of a project - # scope (optional) - The scope of builds to show (one of: all, finished, running; default: all) - # page (optional) - The page number for pagination - # per_page (ooptional) - The value of items per page to show + # scope (optional) - The scope of builds to show (one or array of: pending, running, failed, success, canceled; + # if none provided showing all builds) # Example Request: # GET /projects/:id/builds get ':id/builds' do @@ -24,7 +23,8 @@ module API # Parameters: # id (required) - The ID of a project # sha (required) - The SHA id of a commit - # scope (optional) - The scope of builds to show (one of: all, finished, running; default: all) + # scope (optional) - The scope of builds to show (one or array of: pending, running, failed, success, canceled; + # if none provided showing all builds) # Example Request: # GET /projects/:id/builds/commit/:sha get ':id/builds/commit/:sha' do @@ -112,14 +112,21 @@ module API end def filter_builds(builds, scope) - case scope - when 'finished' - builds.finished - when 'running' - builds.running - else - builds - end + available_scopes = Ci::Build.available_statuses + scope = + if scope.is_a?(String) || scope.is_a?(Symbol) + available_scopes & [scope.to_s] + elsif scope.is_a?(Array) + available_scopes & scope + elsif scope.respond_to?(:to_h) + available_scopes & scope.to_h.values + else + [] + end + + return builds if scope.empty? + + builds.where(status: scope) end def authorize_manage_builds! diff --git a/spec/requests/api/builds_spec.rb b/spec/requests/api/builds_spec.rb index d4af7639d4b..a953eb2fac2 100644 --- a/spec/requests/api/builds_spec.rb +++ b/spec/requests/api/builds_spec.rb @@ -18,7 +18,20 @@ describe API::API, api: true do it 'should return project builds' do get api("/projects/#{project.id}/builds", user) - puts json_response + expect(response.status).to eq(200) + expect(json_response).to be_an Array + end + + it 'should filter project with one scope element' do + get api("/projects/#{project.id}/builds?scope=pending", user) + + expect(response.status).to eq(200) + expect(json_response).to be_an Array + end + + it 'should filter project with array of scope elements' do + get api("/projects/#{project.id}/builds?scope[0]=pending&scope[1]=running", user) + expect(response.status).to eq(200) expect(json_response).to be_an Array end -- cgit v1.2.1 From 1eb7b5ee8d5afeeea74ccbd5627e5a235dffe9fd Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Fri, 8 Jan 2016 22:57:42 +0100 Subject: Modify entities for builds API --- lib/api/builds.rb | 16 +++++++++++----- lib/api/entities.rb | 37 ++++++++++++++++++------------------- spec/requests/api/builds_spec.rb | 1 - 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 6aae1856953..33e6ed24101 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -15,7 +15,9 @@ module API get ':id/builds' do builds = user_project.builds.order('id DESC') builds = filter_builds(builds, params[:scope]) - present paginate(builds), with: Entities::Build + + present paginate(builds), with: Entities::Build, + user_can_download_artifacts: can?(current_user, :download_build_artifacts, user_project) end # Get builds for a specific commit of a project @@ -33,7 +35,8 @@ module API builds = commit.builds.order('id DESC') builds = filter_builds(builds, params[:scope]) - present paginate(builds), with: Entities::Build + present paginate(builds), with: Entities::Build, + user_can_download_artifacts: can?(current_user, :download_build_artifacts, user_project) end # Get a specific build of a project @@ -47,7 +50,8 @@ module API build = get_build(params[:build_id]) return not_found!(build) unless build - present build, with: Entities::Build + present build, with: Entities::Build, + user_can_download_artifacts: can?(current_user, :download_build_artifacts, user_project) end # Get a trace of a specific build of a project @@ -84,7 +88,8 @@ module API build.cancel - present build, with: Entities::Build + present build, with: Entities::Build, + user_can_download_artifacts: can?(current_user, :download_build_artifacts, user_project) end # Retry a specific build of a project @@ -102,7 +107,8 @@ module API build = Ci::Build.retry(build) - present build, with: Entities::Build + present build, with: Entities::Build, + user_can_download_artifacts: can?(current_user, :download_build_artifacts, user_project) end end diff --git a/lib/api/entities.rb b/lib/api/entities.rb index f21da54b8fc..cb00b392db9 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -366,16 +366,8 @@ module API expose :id, :variables end - class CiCommit < Grape::Entity + class Runner < Grape::Entity expose :id - expose :ref - expose :sha - expose :committed_at - end - - class CiRunner < Grape::Entity - expose :id - expose :token expose :description expose :active expose :is_shared @@ -383,16 +375,23 @@ module API end class Build < Grape::Entity - expose :id - expose :status - expose :stage - expose :name - expose :ref - expose :commit, with: CiCommit - expose :runner, with: CiRunner - expose :created_at - expose :started_at - expose :finished_at + expose :id, :status, :stage, :name, :ref, :tag, :coverage, :user + expose :created_at, :started_at, :finished_at + expose :download_url do |repo_obj, options| + if options[:user_can_download_artifacts] + repo_obj.download_url + else + nil + end + end + expose :commit, with: RepoCommit do |repo_obj, _options| + if repo_obj.respond_to?(:commit) + repo_obj.commit.commit_data + else + nil + end + end + expose :runner, with: Runner end end end diff --git a/spec/requests/api/builds_spec.rb b/spec/requests/api/builds_spec.rb index a953eb2fac2..1e58e18fad9 100644 --- a/spec/requests/api/builds_spec.rb +++ b/spec/requests/api/builds_spec.rb @@ -74,7 +74,6 @@ describe API::API, api: true do expect(response.status).to eq(200) expect(json_response['name']).to eq('test') - expect(json_response['commit']['sha']).to eq(commit.sha) end it 'should return specific build trace' do -- cgit v1.2.1 From d54bff2a770c1030056866a47097aee9937390ef Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Fri, 8 Jan 2016 23:04:44 +0100 Subject: Change test access level from MASTER to DEVELOPER This should help us detect potential regressions in the future. --- spec/requests/api/builds_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/requests/api/builds_spec.rb b/spec/requests/api/builds_spec.rb index 1e58e18fad9..b6a1154cf76 100644 --- a/spec/requests/api/builds_spec.rb +++ b/spec/requests/api/builds_spec.rb @@ -6,7 +6,7 @@ describe API::API, api: true do let(:user) { create(:user) } let(:user2) { create(:user) } let!(:project) { create(:project, creator_id: user.id) } - let!(:master) { create(:project_member, user: user, project: project, access_level: ProjectMember::MASTER) } + let!(:developer) { create(:project_member, user: user, project: project, access_level: ProjectMember::DEVELOPER) } let!(:reporter) { create(:project_member, user: user2, project: project, access_level: ProjectMember::REPORTER) } let(:commit) { create(:ci_commit, project: project)} let(:build) { create(:ci_build, commit: commit) } -- cgit v1.2.1 From 4eb27d7c72d57015c7551a00e34a54cefc2d3db9 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Fri, 8 Jan 2016 23:33:45 +0100 Subject: Add some modifications to builds API and specs --- lib/api/builds.rb | 2 +- spec/requests/api/builds_spec.rb | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 33e6ed24101..05d1b8d92ea 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -103,7 +103,7 @@ module API authorize_manage_builds! build = get_build(params[:build_id]) - return not_found!(build) unless build && build.retryable? + return forbidden!('Build is not retryable') unless build && build.retryable? build = Ci::Build.retry(build) diff --git a/spec/requests/api/builds_spec.rb b/spec/requests/api/builds_spec.rb index b6a1154cf76..799558d1bdd 100644 --- a/spec/requests/api/builds_spec.rb +++ b/spec/requests/api/builds_spec.rb @@ -50,7 +50,7 @@ describe API::API, api: true do context 'authorized user' do it 'should return project builds for specific commit' do project.ensure_ci_commit(commit.sha) - get api("/projects/#{project.id}/builds/commit/#{project.ci_commits.first.sha}", user) + get api("/projects/#{project.id}/builds/commit/#{commit.sha}", user) expect(response.status).to eq(200) expect(json_response).to be_an Array @@ -60,7 +60,7 @@ describe API::API, api: true do context 'unauthorized user' do it 'should not return project builds' do project.ensure_ci_commit(commit.sha) - get api("/projects/#{project.id}/builds/commit/#{project.ci_commits.first.sha}") + get api("/projects/#{project.id}/builds/commit/#{commit.sha}") expect(response.status).to eq(401) end @@ -99,7 +99,7 @@ describe API::API, api: true do end end - describe 'GET /projects/:id/builds/:build_id/cancel' do + describe 'POST /projects/:id/builds/:build_id/cancel' do context 'authorized user' do context 'user with :manage_builds persmission' do it 'should cancel running or pending build' do @@ -128,7 +128,7 @@ describe API::API, api: true do end end - describe 'GET /projects/:id/builds/:build_id/retry' do + describe 'POST /projects/:id/builds/:build_id/retry' do context 'authorized user' do context 'user with :manage_builds persmission' do it 'should retry non-running build' do -- cgit v1.2.1 From 96bbc145f31ad029e080ad8903445d81d6c31968 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Mon, 11 Jan 2016 10:20:45 +0100 Subject: Change commit builds URL in builds API --- lib/api/builds.rb | 4 ++-- spec/requests/api/builds_spec.rb | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 05d1b8d92ea..8c21754596b 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -28,8 +28,8 @@ module API # scope (optional) - The scope of builds to show (one or array of: pending, running, failed, success, canceled; # if none provided showing all builds) # Example Request: - # GET /projects/:id/builds/commit/:sha - get ':id/builds/commit/:sha' do + # GET /projects/:id/repository/commits/:sha/builds + get ':id/repository/commits/:sha/builds' do commit = user_project.ci_commits.find_by_sha(params[:sha]) return not_found! unless commit diff --git a/spec/requests/api/builds_spec.rb b/spec/requests/api/builds_spec.rb index 799558d1bdd..587fb74750d 100644 --- a/spec/requests/api/builds_spec.rb +++ b/spec/requests/api/builds_spec.rb @@ -46,11 +46,11 @@ describe API::API, api: true do end end - describe 'GET /projects/:id/builds/commit/:sha' do + describe 'GET /projects/:id/repository/commits/:sha/builds' do context 'authorized user' do it 'should return project builds for specific commit' do project.ensure_ci_commit(commit.sha) - get api("/projects/#{project.id}/builds/commit/#{commit.sha}", user) + get api("/projects/#{project.id}/repository/commits/#{commit.sha}/builds", user) expect(response.status).to eq(200) expect(json_response).to be_an Array @@ -60,7 +60,7 @@ describe API::API, api: true do context 'unauthorized user' do it 'should not return project builds' do project.ensure_ci_commit(commit.sha) - get api("/projects/#{project.id}/builds/commit/#{commit.sha}") + get api("/projects/#{project.id}/repository/commits/#{commit.sha}/builds") expect(response.status).to eq(401) end -- cgit v1.2.1 From 4e70f2519bba83d5f9d6fd0bed80e9837e8b5fc5 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Mon, 11 Jan 2016 11:15:04 +0100 Subject: Update ./doc/api/builds.md --- doc/api/builds.md | 301 ++++++++++++++++++++++++++++++++++++++++------------ lib/api/entities.rb | 3 +- 2 files changed, 234 insertions(+), 70 deletions(-) diff --git a/doc/api/builds.md b/doc/api/builds.md index c52266714d0..64efe6bb3b1 100644 --- a/doc/api/builds.md +++ b/doc/api/builds.md @@ -17,37 +17,97 @@ Parameters: [ { "commit": { - "committed_at": "2015-12-28T14:34:03.814Z", - "id": 2, - "ref": null, - "sha": "6b053ad388c531c21907f022933e5e81598db388" + "author_email": "admin@example.com", + "author_name": "Administrator", + "created_at": "2015-12-24T16:51:14.000+01:00", + "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", + "message": "Test the CI integration.", + "short_id": "0ff3ae19", + "title": "Test the CI integration." }, - "created_at": "2016-01-04T15:41:23.147Z", - "finished_at": null, - "id": 65, - "name": "brakeman", + "coverage": null, + "created_at": "2015-12-24T15:51:21.802Z", + "download_url": null, + "finished_at": "2015-12-24T17:54:27.895Z", + "id": 7, + "name": "teaspoon", "ref": "master", "runner": null, "stage": "test", - "started_at": null, - "status": "pending" + "started_at": "2015-12-24T17:54:27.722Z", + "status": "failed", + "tag": false, + "user": { + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "bio": null, + "can_create_group": true, + "can_create_project": true, + "color_scheme_id": 2, + "created_at": "2015-12-21T13:14:24.077Z", + "current_sign_in_at": "2016-01-11T09:31:40.472Z", + "email": "admin@example.com", + "id": 1, + "identities": [], + "is_admin": true, + "linkedin": "", + "name": "Administrator", + "projects_limit": 100, + "skype": "", + "state": "active", + "theme_id": 3, + "twitter": "", + "two_factor_enabled": false, + "username": "root", + "web_url": "http://gitlab.dev/u/root", + "website_url": "" + } }, { "commit": { - "committed_at": "2015-12-28T14:34:03.814Z", - "id": 2, - "ref": null, - "sha": "6b053ad388c531c21907f022933e5e81598db388" + "author_email": "admin@example.com", + "author_name": "Administrator", + "created_at": "2015-12-24T16:51:14.000+01:00", + "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", + "message": "Test the CI integration.", + "short_id": "0ff3ae19", + "title": "Test the CI integration." }, - "created_at": "2016-01-04T15:41:23.046Z", - "finished_at": null, - "id": 64, - "name": "rubocop", + "coverage": null, + "created_at": "2015-12-24T15:51:21.727Z", + "download_url": null, + "finished_at": "2015-12-24T17:54:24.921Z", + "id": 6, + "name": "spinach:other", "ref": "master", "runner": null, "stage": "test", - "started_at": null, - "status": "pending" + "started_at": "2015-12-24T17:54:24.729Z", + "status": "failed", + "tag": false, + "user": { + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "bio": null, + "can_create_group": true, + "can_create_project": true, + "color_scheme_id": 2, + "created_at": "2015-12-21T13:14:24.077Z", + "current_sign_in_at": "2016-01-11T09:31:40.472Z", + "email": "admin@example.com", + "id": 1, + "identities": [], + "is_admin": true, + "linkedin": "", + "name": "Administrator", + "projects_limit": 100, + "skype": "", + "state": "active", + "theme_id": 3, + "twitter": "", + "two_factor_enabled": false, + "username": "root", + "web_url": "http://gitlab.dev/u/root", + "website_url": "" + } } ] ``` @@ -57,7 +117,7 @@ Parameters: Get a list of builds for specific commit in a project. ``` -GET /projects/:id/builds/commit/:sha +GET /projects/:id/repository/commits/:sha/builds ``` Parameters: @@ -67,45 +127,104 @@ Parameters: - `scope` (optional) - The scope of builds to show (one or array of: pending, running, failed, success, canceled; if none provided showing all builds) ```json -[ - { - "commit": { - "committed_at": "2015-12-28T14:34:03.814Z", - "id": 2, - "ref": null, - "sha": "6b053ad388c531c21907f022933e5e81598db388" + +``` + +## Get a single build +mmit": { + "author_email": "admin@example.com", + "author_name": "Administrator", + "created_at": "2015-12-24T16:51:14.000+01:00", + "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", + "message": "Test the CI integration.", + "short_id": "0ff3ae19", + "title": "Test the CI integration." }, - "created_at": "2016-01-04T15:41:23.147Z", - "finished_at": null, - "id": 65, + "coverage": null, + "created_at": "2015-12-24T15:51:21.957Z", + "download_url": null, + "finished_at": "2015-12-24T17:54:33.913Z", + "id": 9, "name": "brakeman", "ref": "master", "runner": null, "stage": "test", - "started_at": null, - "status": "pending" + "started_at": "2015-12-24T17:54:33.727Z", + "status": "failed", + "tag": false, + "user": { + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "bio": null, + "can_create_group": true, + "can_create_project": true, + "color_scheme_id": 2, + "created_at": "2015-12-21T13:14:24.077Z", + "current_sign_in_at": "2016-01-11T09:31:40.472Z", + "email": "admin@example.com", + "id": 1, + "identities": [], + "is_admin": true, + "linkedin": "", + "name": "Administrator", + "projects_limit": 100, + "skype": "", + "state": "active", + "theme_id": 3, + "twitter": "", + "two_factor_enabled": false, + "username": "root", + "web_url": "http://gitlab.dev/u/root", + "website_url": "" + } }, { "commit": { - "committed_at": "2015-12-28T14:34:03.814Z", - "id": 2, - "ref": null, - "sha": "6b053ad388c531c21907f022933e5e81598db388" + "author_email": "admin@example.com", + "author_name": "Administrator", + "created_at": "2015-12-24T16:51:14.000+01:00", + "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", + "message": "Test the CI integration.", + "short_id": "0ff3ae19", + "title": "Test the CI integration." }, - "created_at": "2016-01-04T15:41:23.046Z", - "finished_at": null, - "id": 64, + "coverage": null, + "created_at": "2015-12-24T15:51:21.880Z", + "download_url": null, + "finished_at": "2015-12-24T17:54:31.198Z", + "id": 8, "name": "rubocop", "ref": "master", "runner": null, "stage": "test", - "started_at": null, - "status": "pending" + "started_at": "2015-12-24T17:54:30.733Z", + "status": "failed", + "tag": false, + "user": { + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "bio": null, + "can_create_group": true, + "can_create_project": true, + "color_scheme_id": 2, + "created_at": "2015-12-21T13:14:24.077Z", + "current_sign_in_at": "2016-01-11T09:31:40.472Z", + "email": "admin@example.com", + "id": 1, + "identities": [], + "is_admin": true, + "linkedin": "", + "name": "Administrator", + "projects_limit": 100, + "skype": "", + "state": "active", + "theme_id": 3, + "twitter": "", + "two_factor_enabled": false, + "username": "root", + "web_url": "http://gitlab.dev/u/root", + "website_url": "" + } } ] -``` - -## Get a single build Get a single build of a project @@ -121,20 +240,50 @@ Parameters: ```json { "commit": { - "committed_at": "2015-12-28T14:34:03.814Z", - "id": 2, - "ref": null, - "sha": "6b053ad388c531c21907f022933e5e81598db388" + "author_email": "admin@example.com", + "author_name": "Administrator", + "created_at": "2015-12-24T16:51:14.000+01:00", + "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", + "message": "Test the CI integration.", + "short_id": "0ff3ae19", + "title": "Test the CI integration." }, - "created_at": "2016-01-04T15:41:23.046Z", - "finished_at": null, - "id": 64, + "coverage": null, + "created_at": "2015-12-24T15:51:21.880Z", + "download_url": null, + "finished_at": "2015-12-24T17:54:31.198Z", + "id": 8, "name": "rubocop", "ref": "master", "runner": null, "stage": "test", - "started_at": null, - "status": "pending" + "started_at": "2015-12-24T17:54:30.733Z", + "status": "failed", + "tag": false, + "user": { + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "bio": null, + "can_create_group": true, + "can_create_project": true, + "color_scheme_id": 2, + "created_at": "2015-12-21T13:14:24.077Z", + "current_sign_in_at": "2016-01-11T09:31:40.472Z", + "email": "admin@example.com", + "id": 1, + "identities": [], + "is_admin": true, + "linkedin": "", + "name": "Administrator", + "projects_limit": 100, + "skype": "", + "state": "active", + "theme_id": 3, + "twitter": "", + "two_factor_enabled": false, + "username": "root", + "web_url": "http://gitlab.dev/u/root", + "website_url": "" + } } ``` @@ -154,20 +303,27 @@ Parameters: ```json { "commit": { - "committed_at": "2015-12-28T14:34:03.814Z", - "id": 2, - "ref": null, - "sha": "6b053ad388c531c21907f022933e5e81598db388" + "author_email": "admin@example.com", + "author_name": "Administrator", + "created_at": "2015-12-24T16:51:14.000+01:00", + "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", + "message": "Test the CI integration.", + "short_id": "0ff3ae19", + "title": "Test the CI integration." }, - "created_at": "2016-01-05T15:33:25.936Z", - "finished_at": "2016-01-05T15:33:47.553Z", - "id": 66, + "coverage": null, + "created_at": "2016-01-11T10:13:33.506Z", + "download_url": null, + "finished_at": "2016-01-11T10:14:09.526Z", + "id": 69, "name": "rubocop", "ref": "master", "runner": null, "stage": "test", "started_at": null, - "status": "canceled" + "status": "canceled", + "tag": false, + "user": null } ``` @@ -187,19 +343,26 @@ Parameters: ```json { "commit": { - "committed_at": "2015-12-28T14:34:03.814Z", - "id": 2, - "ref": null, - "sha": "6b053ad388c531c21907f022933e5e81598db388" + "author_email": "admin@example.com", + "author_name": "Administrator", + "created_at": "2015-12-24T16:51:14.000+01:00", + "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", + "message": "Test the CI integration.", + "short_id": "0ff3ae19", + "title": "Test the CI integration." }, - "created_at": "2016-01-05T15:33:25.936Z", + "coverage": null, + "created_at": "2016-01-11T10:13:33.506Z", + "download_url": null, "finished_at": null, - "id": 66, + "id": 69, "name": "rubocop", "ref": "master", "runner": null, "stage": "test", "started_at": null, - "status": "pending" + "status": "pending", + "tag": false, + "user": null } ``` diff --git a/lib/api/entities.rb b/lib/api/entities.rb index cb00b392db9..a1a886d6fea 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -375,8 +375,9 @@ module API end class Build < Grape::Entity - expose :id, :status, :stage, :name, :ref, :tag, :coverage, :user + expose :id, :status, :stage, :name, :ref, :tag, :coverage expose :created_at, :started_at, :finished_at + expose :user, with: UserFull expose :download_url do |repo_obj, options| if options[:user_can_download_artifacts] repo_obj.download_url -- cgit v1.2.1 From 5dcfd7d06754fecb245475cc005c112677693801 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Mon, 11 Jan 2016 15:49:25 +0100 Subject: Add TODO notice to build trace feature in CI API --- lib/api/builds.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 8c21754596b..d3f4e33ebbf 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -61,6 +61,10 @@ module API # build_id (required) - The ID of a build # Example Request: # GET /projects/:id/build/:build_id/trace + # + # TODO: We should use `present_file!` and leave this implementation for backward compatibility (when build trace + # is saved in the DB instead of file). But before that, we need to consider how to replace the value of + # `runners_token` with some mask (like `xxxxxx`) when sending trace file directly by workhorse. get ':id/builds/:build_id/trace' do build = get_build(params[:build_id]) return not_found!(build) unless build -- cgit v1.2.1 From 5ba0232f7905a0c2a55ff80cbb97ddf2404fa22c Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Mon, 11 Jan 2016 16:30:01 +0100 Subject: Fix :ci_build_with_trace factory --- spec/factories/ci/builds.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb index ce68457f86b..558598d4d5c 100644 --- a/spec/factories/ci/builds.rb +++ b/spec/factories/ci/builds.rb @@ -58,7 +58,9 @@ FactoryGirl.define do factory :ci_build_with_trace do id 999 - trace 'BUILD TRACE' + after(:build) do |build, evaluator| + build.trace = 'BUILD TRACE' + end end factory :ci_build_canceled do -- cgit v1.2.1 From 470b3a482a06c733665abcf2d92ad4d898b2efe0 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Tue, 12 Jan 2016 11:50:14 +0100 Subject: Fix doc/api/builds.md --- doc/api/builds.md | 60 ++++++++++++++++++------------------------------------- 1 file changed, 19 insertions(+), 41 deletions(-) diff --git a/doc/api/builds.md b/doc/api/builds.md index 64efe6bb3b1..99ef0882c16 100644 --- a/doc/api/builds.md +++ b/doc/api/builds.md @@ -127,11 +127,9 @@ Parameters: - `scope` (optional) - The scope of builds to show (one or array of: pending, running, failed, success, canceled; if none provided showing all builds) ```json - -``` - -## Get a single build -mmit": { +[ + { + "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2015-12-24T16:51:14.000+01:00", @@ -141,41 +139,18 @@ mmit": { "title": "Test the CI integration." }, "coverage": null, - "created_at": "2015-12-24T15:51:21.957Z", + "created_at": "2016-01-11T10:13:33.506Z", "download_url": null, - "finished_at": "2015-12-24T17:54:33.913Z", - "id": 9, - "name": "brakeman", + "finished_at": "2016-01-11T10:14:09.526Z", + "id": 69, + "name": "rubocop", "ref": "master", "runner": null, "stage": "test", - "started_at": "2015-12-24T17:54:33.727Z", - "status": "failed", + "started_at": null, + "status": "canceled", "tag": false, - "user": { - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", - "bio": null, - "can_create_group": true, - "can_create_project": true, - "color_scheme_id": 2, - "created_at": "2015-12-21T13:14:24.077Z", - "current_sign_in_at": "2016-01-11T09:31:40.472Z", - "email": "admin@example.com", - "id": 1, - "identities": [], - "is_admin": true, - "linkedin": "", - "name": "Administrator", - "projects_limit": 100, - "skype": "", - "state": "active", - "theme_id": 3, - "twitter": "", - "two_factor_enabled": false, - "username": "root", - "web_url": "http://gitlab.dev/u/root", - "website_url": "" - } + "user": null }, { "commit": { @@ -188,15 +163,15 @@ mmit": { "title": "Test the CI integration." }, "coverage": null, - "created_at": "2015-12-24T15:51:21.880Z", + "created_at": "2015-12-24T15:51:21.957Z", "download_url": null, - "finished_at": "2015-12-24T17:54:31.198Z", - "id": 8, - "name": "rubocop", + "finished_at": "2015-12-24T17:54:33.913Z", + "id": 9, + "name": "brakeman", "ref": "master", "runner": null, "stage": "test", - "started_at": "2015-12-24T17:54:30.733Z", + "started_at": "2015-12-24T17:54:33.727Z", "status": "failed", "tag": false, "user": { @@ -206,7 +181,7 @@ mmit": { "can_create_project": true, "color_scheme_id": 2, "created_at": "2015-12-21T13:14:24.077Z", - "current_sign_in_at": "2016-01-11T09:31:40.472Z", + "current_sign_in_at": "2016-01-12T10:30:48.315Z", "email": "admin@example.com", "id": 1, "identities": [], @@ -225,6 +200,9 @@ mmit": { } } ] +``` + +## Get a single build Get a single build of a project -- cgit v1.2.1 From ab2c6cc01ff26e07db15110e037e72159c48dc53 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Tue, 12 Jan 2016 18:32:18 +0100 Subject: Add some fixes --- lib/api/api.rb | 1 - lib/api/entities.rb | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/api/api.rb b/lib/api/api.rb index 266b5f48f8f..1a1340c428c 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -54,7 +54,6 @@ module API mount Keys mount Tags mount Triggers - mount Builds end end diff --git a/lib/api/entities.rb b/lib/api/entities.rb index a1a886d6fea..e19f9f8d75a 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -377,7 +377,7 @@ module API class Build < Grape::Entity expose :id, :status, :stage, :name, :ref, :tag, :coverage expose :created_at, :started_at, :finished_at - expose :user, with: UserFull + expose :user, with: User expose :download_url do |repo_obj, options| if options[:user_can_download_artifacts] repo_obj.download_url -- cgit v1.2.1 From 97338496188add9ec8d192c7e78f6a6040befffa Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Wed, 13 Jan 2016 15:17:59 +0100 Subject: Add some fixes after review --- doc/api/builds.md | 36 ------------------------------------ lib/api/builds.rb | 24 +++++++++++++----------- lib/api/entities.rb | 6 ++---- spec/requests/api/builds_spec.rb | 6 ++++++ 4 files changed, 21 insertions(+), 51 deletions(-) diff --git a/doc/api/builds.md b/doc/api/builds.md index 99ef0882c16..06ff89bea00 100644 --- a/doc/api/builds.md +++ b/doc/api/builds.md @@ -40,23 +40,14 @@ Parameters: "user": { "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "bio": null, - "can_create_group": true, - "can_create_project": true, - "color_scheme_id": 2, "created_at": "2015-12-21T13:14:24.077Z", - "current_sign_in_at": "2016-01-11T09:31:40.472Z", - "email": "admin@example.com", "id": 1, - "identities": [], "is_admin": true, "linkedin": "", "name": "Administrator", - "projects_limit": 100, "skype": "", "state": "active", - "theme_id": 3, "twitter": "", - "two_factor_enabled": false, "username": "root", "web_url": "http://gitlab.dev/u/root", "website_url": "" @@ -87,23 +78,14 @@ Parameters: "user": { "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "bio": null, - "can_create_group": true, - "can_create_project": true, - "color_scheme_id": 2, "created_at": "2015-12-21T13:14:24.077Z", - "current_sign_in_at": "2016-01-11T09:31:40.472Z", - "email": "admin@example.com", "id": 1, - "identities": [], "is_admin": true, "linkedin": "", "name": "Administrator", - "projects_limit": 100, "skype": "", "state": "active", - "theme_id": 3, "twitter": "", - "two_factor_enabled": false, "username": "root", "web_url": "http://gitlab.dev/u/root", "website_url": "" @@ -177,23 +159,14 @@ Parameters: "user": { "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "bio": null, - "can_create_group": true, - "can_create_project": true, - "color_scheme_id": 2, "created_at": "2015-12-21T13:14:24.077Z", - "current_sign_in_at": "2016-01-12T10:30:48.315Z", - "email": "admin@example.com", "id": 1, - "identities": [], "is_admin": true, "linkedin": "", "name": "Administrator", - "projects_limit": 100, "skype": "", "state": "active", - "theme_id": 3, "twitter": "", - "two_factor_enabled": false, "username": "root", "web_url": "http://gitlab.dev/u/root", "website_url": "" @@ -241,23 +214,14 @@ Parameters: "user": { "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "bio": null, - "can_create_group": true, - "can_create_project": true, - "color_scheme_id": 2, "created_at": "2015-12-21T13:14:24.077Z", - "current_sign_in_at": "2016-01-11T09:31:40.472Z", - "email": "admin@example.com", "id": 1, - "identities": [], "is_admin": true, "linkedin": "", "name": "Administrator", - "projects_limit": 100, "skype": "", "state": "active", - "theme_id": 3, "twitter": "", - "two_factor_enabled": false, "username": "root", "web_url": "http://gitlab.dev/u/root", "website_url": "" diff --git a/lib/api/builds.rb b/lib/api/builds.rb index d3f4e33ebbf..1337e1bb452 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -35,6 +35,7 @@ module API builds = commit.builds.order('id DESC') builds = filter_builds(builds, params[:scope]) + present paginate(builds), with: Entities::Build, user_can_download_artifacts: can?(current_user, :download_build_artifacts, user_project) end @@ -118,25 +119,26 @@ module API helpers do def get_build(id) - user_project.builds.where(id: id).first + user_project.builds.find_by(id: id.to_i) end def filter_builds(builds, scope) - available_scopes = Ci::Build.available_statuses + return builds if scope.nil? || scope.empty? + + available_statuses = Ci::Build.available_statuses scope = - if scope.is_a?(String) || scope.is_a?(Symbol) - available_scopes & [scope.to_s] - elsif scope.is_a?(Array) - available_scopes & scope - elsif scope.respond_to?(:to_h) - available_scopes & scope.to_h.values + if scope.is_a?(String) + [scope] + elsif scope.is_a?(Hashie::Mash) + scope.values else - [] + ['unknown'] end - return builds if scope.empty? + unknown = scope - available_statuses + render_api_error!('Scope contains invalid value(s)', 400) unless unknown.empty? - builds.where(status: scope) + builds.where(status: available_statuses && scope) end def authorize_manage_builds! diff --git a/lib/api/entities.rb b/lib/api/entities.rb index e19f9f8d75a..f0816a46529 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -378,18 +378,16 @@ module API expose :id, :status, :stage, :name, :ref, :tag, :coverage expose :created_at, :started_at, :finished_at expose :user, with: User + # TODO: download_url in Ci:Build model is an GitLab Web Interface URL, not API URL. We should think on some API + # for downloading of artifacts (see: https://gitlab.com/gitlab-org/gitlab-ce/issues/4255) expose :download_url do |repo_obj, options| if options[:user_can_download_artifacts] repo_obj.download_url - else - nil end end expose :commit, with: RepoCommit do |repo_obj, _options| if repo_obj.respond_to?(:commit) repo_obj.commit.commit_data - else - nil end end expose :runner, with: Runner diff --git a/spec/requests/api/builds_spec.rb b/spec/requests/api/builds_spec.rb index 587fb74750d..4bf3d2681dc 100644 --- a/spec/requests/api/builds_spec.rb +++ b/spec/requests/api/builds_spec.rb @@ -35,6 +35,12 @@ describe API::API, api: true do expect(response.status).to eq(200) expect(json_response).to be_an Array end + + it 'should respond 400 when scope contains invalid state' do + get api("/projects/#{project.id}/builds?scope[0]=pending&scope[1]=unknown_status", user) + + expect(response.status).to eq(400) + end end context 'unauthorized user' do -- cgit v1.2.1 From 990bd06c04bebe6319968aa619990bf4cb60483c Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Wed, 13 Jan 2016 16:05:49 +0100 Subject: Change :ci_build_canceled factory to :canceled trait --- spec/factories/ci/builds.rb | 8 ++++---- spec/requests/api/builds_spec.rb | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb index 558598d4d5c..636cdbba1b8 100644 --- a/spec/factories/ci/builds.rb +++ b/spec/factories/ci/builds.rb @@ -43,6 +43,10 @@ FactoryGirl.define do commit factory: :ci_commit + trait :canceled do + status 'canceled' + end + after(:build) do |build, evaluator| build.project = build.commit.project end @@ -62,9 +66,5 @@ FactoryGirl.define do build.trace = 'BUILD TRACE' end end - - factory :ci_build_canceled do - status 'canceled' - end end end diff --git a/spec/requests/api/builds_spec.rb b/spec/requests/api/builds_spec.rb index 4bf3d2681dc..e5567d42500 100644 --- a/spec/requests/api/builds_spec.rb +++ b/spec/requests/api/builds_spec.rb @@ -11,7 +11,7 @@ describe API::API, api: true do let(:commit) { create(:ci_commit, project: project)} let(:build) { create(:ci_build, commit: commit) } let(:build_with_trace) { create(:ci_build_with_trace, commit: commit) } - let(:build_canceled) { create(:ci_build_canceled, commit: commit) } + let(:build_canceled) { create(:ci_build, :canceled, commit: commit) } describe 'GET /projects/:id/builds ' do context 'authorized user' do -- cgit v1.2.1 From 13032b713d0943c2b7e2f2a3b886ef06be8e88ef Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Wed, 13 Jan 2016 18:30:49 +0100 Subject: Add seperated 'describe' block for build trace specs --- spec/requests/api/builds_spec.rb | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/spec/requests/api/builds_spec.rb b/spec/requests/api/builds_spec.rb index e5567d42500..8c9f5a382b7 100644 --- a/spec/requests/api/builds_spec.rb +++ b/spec/requests/api/builds_spec.rb @@ -73,7 +73,7 @@ describe API::API, api: true do end end - describe 'GET /projects/:id/builds/:build_id(/trace)?' do + describe 'GET /projects/:id/builds/:build_id' do context 'authorized user' do it 'should return specific build data' do get api("/projects/#{project.id}/builds/#{build.id}", user) @@ -81,7 +81,19 @@ describe API::API, api: true do expect(response.status).to eq(200) expect(json_response['name']).to eq('test') end + end + + context 'unauthorized user' do + it 'should not return specific build data' do + get api("/projects/#{project.id}/builds/#{build.id}") + expect(response.status).to eq(401) + end + end + end + + describe 'GET /projects/:id/builds/:build_id/trace' do + context 'authorized user' do it 'should return specific build trace' do get api("/projects/#{project.id}/builds/#{build_with_trace.id}/trace", user) @@ -91,12 +103,6 @@ describe API::API, api: true do end context 'unauthorized user' do - it 'should not return specific build data' do - get api("/projects/#{project.id}/builds/#{build.id}") - - expect(response.status).to eq(401) - end - it 'should not return specific build trace' do get api("/projects/#{project.id}/builds/#{build_with_trace.id}/trace") -- cgit v1.2.1 From 9280511979caaf46e27505578818c770da9c9837 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Wed, 13 Jan 2016 20:56:04 +0100 Subject: Update CHANGELOG [ci skip] --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index b430d4981a9..615743e2a7c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -43,6 +43,7 @@ v 8.4.0 (unreleased) - API: Add support for deleting a tag via the API (Robert Schilling) - Allow subsequent validations in CI Linter - Fix Encoding::CompatibilityError bug when markdown content has some complex URL (Jason Lee) + - Add API support for managing builds of a project v 8.3.4 - Use gitlab-workhorse 0.5.4 (fixes API routing bug) -- cgit v1.2.1 From 4cdbb2f628620be90de872cf7f5cd591e17c1bd0 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Wed, 13 Jan 2016 21:19:18 +0100 Subject: Modify builds API documentation style [ci skip] --- doc/api/builds.md | 82 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 16 deletions(-) diff --git a/doc/api/builds.md b/doc/api/builds.md index 06ff89bea00..ecb50754c88 100644 --- a/doc/api/builds.md +++ b/doc/api/builds.md @@ -8,10 +8,20 @@ Get a list of builds in a project. GET /projects/:id/builds ``` -Parameters: +### Parameters -- `id` (required) - The ID of a project -- `scope` (optional) - The scope of builds to show (one or array of: pending, running, failed, success, canceled; if none provided showing all builds) +| Attribute | Type | required | Description | +|-----------|---------|----------|---------------------| +| id | integer | yes | The ID of a project | +| scope | string|array of strings | no | The scope of builds to show, one or array of: `pending`, `running`, `failed`, `success`, `canceled`; showing all builds if none provided | + +### Example of request + +``` +curl -H "PRIVATE_TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/builds" +``` + +### Example of response ```json [ @@ -102,11 +112,21 @@ Get a list of builds for specific commit in a project. GET /projects/:id/repository/commits/:sha/builds ``` -Parameters: +### Parameters + +| Attribute | Type | required | Description | +|-----------|---------|----------|---------------------| +| id | integer | yes | The ID of a project | +| sha | string | yes | The SHA id of a commit | +| scope | string|array of strings | no | The scope of builds to show, one or array of: `pending`, `running`, `failed`, `success`, `canceled`; showing all builds if none provided | -- `id` (required) - The ID of a project -- `sha` (required) - The SHA id of a commit -- `scope` (optional) - The scope of builds to show (one or array of: pending, running, failed, success, canceled; if none provided showing all builds) +### Example of request + +``` +curl -H "PRIVATE_TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/repository/commits/0ff3ae198f8601a285adcf5c0fff204ee6fba5fd/builds" +``` + +### Example of response ```json [ @@ -183,10 +203,20 @@ Get a single build of a project GET /projects/:id/builds/:build_id ``` -Parameters: +### Parameters -- `id` (required) - The ID of a project -- `build_id` (required) - The ID of a build +| Attribute | Type | required | Description | +|-----------|---------|----------|---------------------| +| id | integer | yes | The ID of a project | +| build\_id | integer | yes | The ID of a build | + +### Example of request + +``` +curl -H "PRIVATE_TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/builds/8" +``` + +### Example of response ```json { @@ -237,10 +267,20 @@ Cancel a single build of a project POST /projects/:id/builds/:build_id/cancel ``` -Parameters: +### Parameters + +| Attribute | Type | required | Description | +|-----------|---------|----------|---------------------| +| id | integer | yes | The ID of a project | +| build\_id | integer | yes | The ID of a build | + +### Example of request + +``` +curl -X POST -H "PRIVATE_TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/builds/1/cancel" +``` -- `id` (required) - The ID of a project -- `build_id` (required) - The ID of a build +### Example of response ```json { @@ -277,10 +317,20 @@ Retry a single build of a project POST /projects/:id/builds/:build_id/retry ``` -Parameters: +### Parameters + +| Attribute | Type | required | Description | +|-----------|---------|----------|---------------------| +| id | integer | yes | The ID of a project | +| build\_id | integer | yes | The ID of a build | + +### Example of request + +``` +curl -X POST -H "PRIVATE_TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/builds/1/retry" +``` -- `id` (required) - The ID of a project -- `build_id` (required) - The ID of a build +### Example of response ```json { -- cgit v1.2.1 From 6a98fb03e708070641f9fce0eaad761e859a5099 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Thu, 14 Jan 2016 12:04:44 +0100 Subject: Remove hard-coded id from builds factory --- spec/factories/ci/builds.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb index 636cdbba1b8..d2db77f6286 100644 --- a/spec/factories/ci/builds.rb +++ b/spec/factories/ci/builds.rb @@ -61,8 +61,7 @@ FactoryGirl.define do end factory :ci_build_with_trace do - id 999 - after(:build) do |build, evaluator| + after(:create) do |build, evaluator| build.trace = 'BUILD TRACE' end end -- cgit v1.2.1 From 2c7d9cfa7dbd4e7716793bdb1ee9e081f13c33b2 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Thu, 14 Jan 2016 14:59:04 +0100 Subject: Move Ci::Build#available_statuses to AVAILABLE_STATUSES constant in CommitStatus --- app/models/ci/build.rb | 4 ---- app/models/commit_status.rb | 2 ++ lib/api/builds.rb | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 90d9669faca..a4779d06de8 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -97,10 +97,6 @@ module Ci new_build.save new_build end - - def available_statuses - state_machines[:status].states.map &:value - end end state_machine :status, initial: :pending do diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index ff479493474..de1e3eb7eaf 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -56,6 +56,8 @@ class CommitStatus < ActiveRecord::Base scope :ordered, -> { order(:ref, :stage_idx, :name) } scope :for_ref, ->(ref) { where(ref: ref) } + AVAILABLE_STATUSES = ['pending', 'running', 'success', 'failed', 'canceled'] + state_machine :status, initial: :pending do event :run do transition pending: :running diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 1337e1bb452..d293f988165 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -125,7 +125,7 @@ module API def filter_builds(builds, scope) return builds if scope.nil? || scope.empty? - available_statuses = Ci::Build.available_statuses + available_statuses = ::CommitStatus::AVAILABLE_STATUSES scope = if scope.is_a?(String) [scope] -- cgit v1.2.1