diff options
author | Valery Sizov <valery@gitlab.com> | 2015-02-11 09:42:15 +0000 |
---|---|---|
committer | Valery Sizov <valery@gitlab.com> | 2015-02-11 09:42:15 +0000 |
commit | 0e456d826f9eee3d84705299e322b78b92abbac7 (patch) | |
tree | 96a080e435b535a558ddbcf36973f75bc4d0b03f | |
parent | 120ac463706485981b98f87e36e76bced310942e (diff) | |
parent | 0d39bfa32967c5f2794bdf30d088b74a78fd54c2 (diff) | |
download | gitlab-ci-0e456d826f9eee3d84705299e322b78b92abbac7.tar.gz |
Merge branch 'feature_project_jobs_rest_api' into 'master'
Implemented project job get / post / delete through the rest api
The rest API allows you to manipulate a project on gitlab-ci but there is no way to manipulate build jobs through the api.
I tested it, implemented tests & updated documentation
http://feedback.gitlab.com/forums/176466-general/suggestions/7068630-expose-the-job-api-to-the-rest-api
Keep up the good work. It's the first ruby codebase I dig into and I'm impressed by it's robustness.
Congratulations!
See merge request !37
-rw-r--r-- | CHANGELOG | 1 | ||||
-rw-r--r-- | doc/api/projects.md | 36 | ||||
-rw-r--r-- | lib/api/entities.rb | 4 | ||||
-rw-r--r-- | lib/api/projects.rb | 60 | ||||
-rw-r--r-- | spec/requests/api/projects_spec.rb | 105 |
5 files changed, 206 insertions, 0 deletions
@@ -2,6 +2,7 @@ v7.8.0 - Fix OAuth login with GitLab installed in relative URL - GitLab CI has same version as GitLab since now - Allow to pass description and tag list during Runner's registration + - Added api for project jobs v5.4.2 - Fix exposure of project token via build data diff --git a/doc/api/projects.md b/doc/api/projects.md index 1a74b5c..14e84ee 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -150,3 +150,39 @@ Parameters: * `id` (required) - The ID of the Gitlab CI project * `runner_id` (required) - The ID of the Gitlab CI runner +### List All Jobs for a Project + +List the jobs associated to a Gitlab CI Project (only via +authorized user). + + GET /projects/:id/jobs + +Parameters: + + * `id` (required) - The ID of the Gitlab CI project + +### Add a Job to a Project + +Adds a Job to a Gitlab CI Project (only via +authorized user). + + POST /projects/:id/jobs + +Parameters: + + * `id` (required) - The ID of the Gitlab CI project + * `name` (required) - The name of the Job to add + * `commands` (required) - The script commands of the job + +### Remove a Job from a Project + +Removes a Job from a Gitlab CI Project (only +via authorized user). + + DELETE /projects/:id/jobs/:job_id + +Parameters: + + * `id` (required) - The ID of the Gitlab CI project + * `job_id` (required) - The ID of the Job + diff --git a/lib/api/entities.rb b/lib/api/entities.rb index dfd419a..c0bf928 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -27,5 +27,9 @@ module API class WebHook < Grape::Entity expose :id, :project_id, :url end + + class Job < Grape::Entity + expose :name, :commands + end end end diff --git a/lib/api/projects.rb b/lib/api/projects.rb index a3cc9f3..cf5dd59 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -28,6 +28,66 @@ module API end end + # Retrieve all jobs for a project + # + # Parameters + # id (required) - The ID of a project + # Example Request + # GET /projects/:id/jobs + get ":id/jobs" do + project = Project.find(params[:id]) + + not_found! if project.blank? + unauthorized! unless current_user.can_access_project?(project.gitlab_id) + + project.jobs + end + + # Add a new job to a project + # + # Parameters + # id (required) - The ID of a project + # name (required) - The job name + # commands (required) - The command line script for the job + # Example Request + # POST /projects/:id/jobs + post ":id/jobs" do + required_attributes! [:name, :commands] + + project = Project.find(params[:id]) + + not_found! if project.blank? + unauthorized! unless current_user.can_access_project?(project.gitlab_id) + + job_params = { name: params[:name], commands: params[:commands] } + job = project.jobs.new(job_params) + if job.save + present job, with: Entities::Job + else + errors = web_hook.errors.full_messages.join(", ") + render_api_error!(errors, 400) + end + end + + # Delete a job for a project + # + # Parameters + # id (required) - The ID of a project + # job_id (required) - The ID of the job to delete + # Example Request + # DELETE /projects/:id/jobs/:job_id + delete ":id/jobs/:job_id" do + required_attributes! [:job_id] + + project = Project.find(params[:id]) + job = project.jobs.find_by_id(params[:job_id]) + + not_found! if project.blank? || job.blank? + unauthorized! unless current_user.can_access_project?(project.gitlab_id) + + job.destroy + end + # Retrieve all Gitlab CI projects that the user has access to # # Example Request: diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 1209855..bee6e99 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -52,6 +52,111 @@ describe API::API do end end + describe "POST /projects/:project_id/jobs" do + let!(:project) { FactoryGirl.create(:project) } + let(:job_info) { + { + :name => "A Job Name", + :command => "ls -lad", + } + } + let(:invalid_job_info) { {} } + + context "Invalid Job Info" do + before do + options.merge!(invalid_job_info) + end + + it "should error with invalid data" do + post api("/projects/#{project.id}/jobs"), options + response.status.should == 400 + end + end + + context "Valid Job Info" do + before do + options.merge!(job_info) + end + + it "should create a job for specified project" do + post api("/projects/#{project.id}/jobs"), options + response.status.should == 201 + json_response["name"].should == job_info[:name] + json_response["commands"].should == job_info[:commands] + end + + it "fails to create job for non existsing project" do + post api("/projects/non-existant-id/jobs"), options + response.status.should == 404 + end + end + end + + describe "GET /projects/:project_id/jobs" do + let!(:project) { FactoryGirl.create(:project) } + let(:job_info) { + { + :name => "A Job Name", + :command => "ls -lad", + } + } + + before do + options.merge!(job_info) + end + + it "should list the project's jobs" do + post api("/projects/#{project.id}/jobs"), options + response.status.should == 201 + get api("/projects/#{project.id}/jobs") + response.status.should == 200 + json_response.count.should == 1 + json_response.first["project_id"].should == project.id + json_response.first["name"].should == job_info[:name] + json_response.first["commands"].should == job_info[:commands] + end + + it "fails to list jobs for non existsing project" do + get api("/projects/non-existant-id/jobs"), options + response.status.should == 404 + end + end + + describe "DELETE /projects/:id/jobs/:job_id" do + let!(:project) { FactoryGirl.create(:project) } + + let(:job_info) { + { + :name => "A Job Name", + :command => "ls -lad", + } + } + + before do + options.merge!(job_info) + end + + it "should delete a project job" do + post api("/projects/#{project.id}/jobs"), options + response.status.should == 201 + json_response["name"].should == job_info[:name] + json_response["commands"].should == job_info[:commands] + let!(:job_id) { json_response["id"] } + delete api("/projects/#{project.id}/jobs/#{job_id}") + response.status.should == 200 + end + + it "fails to delete a job for a non existsing project" do + delete api("/projects/non-existant-id/jobs/1") + response.status.should == 404 + end + + it "fails to delete a job for a non existsing job id" do + delete api("/projects/#{project.id}/jobs/1337") + response.status.should == 404 + end + end + describe "POST /projects/:project_id/webhooks" do let!(:project) { FactoryGirl.create(:project) } |