diff options
author | Z.J. van de Weg <zegerjan@gitlab.com> | 2016-08-17 10:09:42 +0200 |
---|---|---|
committer | Z.J. van de Weg <zegerjan@gitlab.com> | 2016-08-18 16:56:39 +0200 |
commit | de7b8e51b8b7b5bfaa72ee62a4eb08497cf69b4b (patch) | |
tree | 06009695cc0888c2bf7e5cf112f241031fcd3206 | |
parent | ac73de508e21af95b473bfafc2ca2543b234430d (diff) | |
download | gitlab-ce-de7b8e51b8b7b5bfaa72ee62a4eb08497cf69b4b.tar.gz |
Add endpoints for pipelines
-rw-r--r-- | CHANGELOG | 1 | ||||
-rw-r--r-- | lib/api/api.rb | 1 | ||||
-rw-r--r-- | lib/api/entities.rb | 8 | ||||
-rw-r--r-- | lib/api/pipelines.rb | 74 | ||||
-rw-r--r-- | spec/factories/ci/pipelines.rb | 18 | ||||
-rw-r--r-- | spec/requests/api/pipelines_spec.rb | 124 |
6 files changed, 208 insertions, 18 deletions
diff --git a/CHANGELOG b/CHANGELOG index 61c654002ad..5bfd2244b9e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -51,6 +51,7 @@ v 8.11.0 (unreleased) - Show deployment status on merge requests with external URLs - Clean up unused routes (Josef Strzibny) - Fix issue on empty project to allow developers to only push to protected branches if given permission + - API: Add enpoints for pipelines - Add green outline to New Branch button. !5447 (winniehell) - Optimize generating of cache keys for issues and notes - Improve performance of syntax highlighting Markdown code blocks diff --git a/lib/api/api.rb b/lib/api/api.rb index d43af3f24e9..d9261c97908 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -56,6 +56,7 @@ module API mount ::API::Milestones mount ::API::Namespaces mount ::API::Notes + mount ::API::Pipelines mount ::API::ProjectHooks mount ::API::ProjectSnippets mount ::API::Projects diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 055716ab1e3..09c9aca1e22 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -502,6 +502,14 @@ module API expose :key, :value end + class Pipeline < Grape::Entity + expose :status, :ref, :sha, :before_sha, :tag, :yaml_errors + + expose :user, with: Entities::UserBasic + expose :created_at, :updated_at, :started_at, :finished_at, :committed_at + expose :duration + end + class Environment < Grape::Entity expose :id, :name, :external_url end diff --git a/lib/api/pipelines.rb b/lib/api/pipelines.rb new file mode 100644 index 00000000000..2aae75c471d --- /dev/null +++ b/lib/api/pipelines.rb @@ -0,0 +1,74 @@ +module API + class Pipelines < Grape::API + before { authenticate! } + + params do + requires :id, type: String, desc: 'The project ID' + end + resource :projects do + desc 'Get all Pipelines of the project' do + detail 'This feature was introduced in GitLab 8.11.' + success Entities::Pipeline + end + params do + optional :page, type: Integer, desc: 'Page number of the current request' + optional :per_page, type: Integer, desc: 'Number of items per page' + end + get ':id/pipelines' do + authorize! :read_pipeline, user_project + + present paginate(user_project.pipelines), with: Entities::Pipeline + end + + desc 'Gets a specific pipeline for the project' do + detail 'This feature was introduced in GitLab 8.11' + success Entities::Pipeline + end + params do + requires :pipeline_id, type: Integer, desc: 'The pipeline ID' + end + get ':id/pipelines/:pipeline_id' do + authorize! :read_pipeline, user_project + + present pipeline, with: Entities::Pipeline + end + + desc 'Retry failed builds in the pipeline' do + detail 'This feature was introduced in GitLab 8.11.' + success Entities::Pipeline + end + params do + requires :pipeline_id, type: Integer, desc: 'The pipeline ID' + end + post ':id/pipelines/:pipeline_id/retry' do + authorize! :update_pipeline, user_project + + pipeline.retry_failed(current_user) + + present pipeline, with: Entities::Pipeline + end + + desc 'Cancel all builds in the pipeline' do + detail 'This feature was introduced in GitLab 8.11.' + success Entities::Pipeline + end + params do + requires :pipeline_id, type: Integer, desc: 'The pipeline ID' + end + post ':id/pipelines/:pipeline_id/cancel' do + authorize! :update_pipeline, user_project + + pipeline.cancel_running + + status 200 + present pipeline.reload, with: Entities::Pipeline + end + end + + helpers do + def pipeline + @pipeline ||= user_project.pipelines.find(params[:pipeline_id]) + end + end + end +end diff --git a/spec/factories/ci/pipelines.rb b/spec/factories/ci/pipelines.rb index 04d66020c87..ac2a1ba5dff 100644 --- a/spec/factories/ci/pipelines.rb +++ b/spec/factories/ci/pipelines.rb @@ -1,21 +1,3 @@ -# == Schema Information -# -# Table name: commits -# -# id :integer not null, primary key -# project_id :integer -# ref :string(255) -# sha :string(255) -# before_sha :string(255) -# push_data :text -# created_at :datetime -# updated_at :datetime -# tag :boolean default(FALSE) -# yaml_errors :text -# committed_at :datetime -# gl_project_id :integer -# - FactoryGirl.define do factory :ci_empty_pipeline, class: Ci::Pipeline do ref 'master' diff --git a/spec/requests/api/pipelines_spec.rb b/spec/requests/api/pipelines_spec.rb new file mode 100644 index 00000000000..40f54856712 --- /dev/null +++ b/spec/requests/api/pipelines_spec.rb @@ -0,0 +1,124 @@ +require 'spec_helper' + +describe API::API, api: true do + include ApiHelpers + + let(:user) { create(:user) } + let(:non_member) { create(:user) } + let(:project) { create(:project, creator_id: user.id) } + + let!(:pipeline) do + create(:ci_empty_pipeline, project: project, sha: project.commit.id, + ref: project.default_branch) + end + + before do + project.team << [user, :master] + end + + describe 'GET /projects/:id/pipelines ' do + it_behaves_like 'a paginated resources' do + let(:request) { get api("/projects/#{project.id}/pipelines", user) } + end + + context 'authorized user' do + it 'returns project pipelines' do + get api("/projects/#{project.id}/pipelines", user) + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.first['sha']).to match /\A\h{40}\z/ + end + end + + context 'unauthorized user' do + it 'does not return project pipelines' do + get api("/projects/#{project.id}/pipelines", non_member) + + expect(response).to have_http_status(404) + end + end + end + + describe 'GET /projects/:id/pipelines/:pipeline_id' do + context 'authorized user' do + it 'returns project pipelines' do + get api("/projects/#{project.id}/pipelines/#{pipeline.id}", user) + + expect(response).to have_http_status(200) + expect(json_response['sha']).to match /\A\h{40}\z/ + end + + it 'returns 404 when it does not exist' do + get api("/projects/#{project.id}/pipelines/123456", user) + + expect(response).to have_http_status(404) + end + end + + context 'unauthorized user' do + it 'should not return a project pipeline' do + get api("/projects/#{project.id}/pipelines/#{pipeline.id}", non_member) + + expect(response).to have_http_status(404) + end + end + end + + describe 'POST /projects/:id/pipelines/:pipeline_id/retry' do + context 'authorized user' do + let!(:pipeline) do + create(:ci_pipeline, project: project, sha: project.commit.id, + ref: project.default_branch) + end + + let!(:build) { create(:ci_build, :failed, pipeline: pipeline) } + + it 'retries failed builds' do + expect do + post api("/projects/#{project.id}/pipelines/#{pipeline.id}/retry", user) + end.to change { pipeline.builds.count }.from(1).to(2) + + expect(response).to have_http_status(201) + end + end + + context 'unauthorized user' do + it 'should not return a project pipeline' do + post api("/projects/#{project.id}/pipelines/#{pipeline.id}/retry", non_member) + + expect(response).to have_http_status(404) + end + end + end + + describe 'POST /projects/:id/pipelines/:pipeline_id/cancel' do + let!(:pipeline) do + create(:ci_empty_pipeline, project: project, sha: project.commit.id, + ref: project.default_branch) + end + + let!(:build) { create(:ci_build, :running, pipeline: pipeline) } + + context 'authorized user' do + it 'retries failed builds' do + post api("/projects/#{project.id}/pipelines/#{pipeline.id}/cancel", user) + + expect(response).to have_http_status(200) + expect(json_response['status']).to eq('canceled') + end + end + + context 'user without proper access rights' do + let!(:reporter) { create(:user) } + + before { project.team << [reporter, :reporter] } + + it 'rejects the action' do + post api("/projects/#{project.id}/pipelines/#{pipeline.id}/cancel", reporter) + + expect(response).to have_http_status(403) + end + end + end +end |