summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorValery Sizov <valery@gitlab.com>2015-02-11 09:42:15 +0000
committerValery Sizov <valery@gitlab.com>2015-02-11 09:42:15 +0000
commit0e456d826f9eee3d84705299e322b78b92abbac7 (patch)
tree96a080e435b535a558ddbcf36973f75bc4d0b03f
parent120ac463706485981b98f87e36e76bced310942e (diff)
parent0d39bfa32967c5f2794bdf30d088b74a78fd54c2 (diff)
downloadgitlab-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--CHANGELOG1
-rw-r--r--doc/api/projects.md36
-rw-r--r--lib/api/entities.rb4
-rw-r--r--lib/api/projects.rb60
-rw-r--r--spec/requests/api/projects_spec.rb105
5 files changed, 206 insertions, 0 deletions
diff --git a/CHANGELOG b/CHANGELOG
index fbcff57..c17fb74 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -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) }