summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG1
-rw-r--r--doc/api/projects.md36
-rw-r--r--lib/api/entities.rb4
-rw-r--r--lib/api/projects.rb63
-rw-r--r--spec/requests/api/projects_spec.rb143
5 files changed, 231 insertions, 16 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..bc21e22 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 :id, :name, :commands
+ end
end
end
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index a3cc9f3..7d94c89 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -20,7 +20,7 @@ module API
web_hook = project.web_hooks.new({url: params[:web_hook]})
if web_hook.save
- present web_hook, :with => Entities::WebHook
+ present web_hook, with: Entities::WebHook
else
errors = web_hook.errors.full_messages.join(", ")
render_api_error!(errors, 400)
@@ -28,6 +28,67 @@ 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)
+
+ # present job, with: Entities::Job
+ 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 = job.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(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..7256dfe 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -6,16 +6,16 @@ describe API::API do
let(:gitlab_url) { GitlabCi.config.gitlab_server.url }
let(:auth_opts) {
{
- :email => "test@test.com",
- :password => "123456"
+ email: "test@test.com",
+ password: "123456"
}
}
let(:private_token) { Network.new.authenticate(gitlab_url, auth_opts)["private_token"] }
let(:options) {
{
- :private_token => private_token,
- :url => gitlab_url
+ private_token: private_token,
+ url: gitlab_url
}
}
@@ -26,8 +26,8 @@ describe API::API do
context "requests for scoped projects" do
# NOTE: These ids are tied to the actual projects on demo.gitlab.com
describe "GET /projects" do
- let!(:project1) { FactoryGirl.create(:project, :name => "gitlabhq", :gitlab_id => 3) }
- let!(:project2) { FactoryGirl.create(:project, :name => "gitlab-ci", :gitlab_id => 4) }
+ let!(:project1) { FactoryGirl.create(:project, name: "gitlabhq", gitlab_id: 3) }
+ let!(:project2) { FactoryGirl.create(:project, name: "gitlab-ci", gitlab_id: 4) }
it "should return all projects on the CI instance" do
get api("/projects"), options
@@ -40,8 +40,8 @@ describe API::API do
describe "GET /projects/owned" do
# NOTE: This user doesn't own any of these projects on demo.gitlab.com
- let!(:project1) { FactoryGirl.create(:project, :name => "gitlabhq", :gitlab_id => 3) }
- let!(:project2) { FactoryGirl.create(:project, :name => "random-project", :gitlab_id => 9898) }
+ let!(:project1) { FactoryGirl.create(:project, name: "gitlabhq", gitlab_id: 3) }
+ let!(:project2) { FactoryGirl.create(:project, name: "random-project", gitlab_id: 9898) }
it "should return all projects on the CI instance" do
get api("/projects/owned"), options
@@ -52,11 +52,124 @@ 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",
+ commands: "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",
+ commands: "ls -lad",
+ }
+ }
+
+ before do
+ options.merge!(job_info)
+ end
+
+ it "should list the project's jobs" do
+ get api("/projects/#{project.id}/jobs"), options
+ response.status.should == 200
+ json_response.count.should == 1
+ json_response.first["project_id"].should == project.id
+ end
+
+ it "should add & list the project's new jobs" do
+ post api("/projects/#{project.id}/jobs"), options
+ response.status.should == 201
+ get api("/projects/#{project.id}/jobs"), options
+ response.status.should == 200
+ json_response.count.should == 2
+ 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",
+ commands: "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]
+ job_id = json_response["id"]
+ delete api("/projects/#{project.id}/jobs/#{job_id}"), options
+ response.status.should == 200
+ end
+
+ it "fails to delete a job for a non existsing project" do
+ delete api("/projects/non-existant-id/jobs/non-existant-job-id"), options
+ response.status.should == 404
+ end
+
+ it "fails to delete a job for a non existsing job id" do
+ delete api("/projects/#{project.id}/jobs/non-existant-job-id"), options
+ response.status.should == 404
+ end
+ end
+
describe "POST /projects/:project_id/webhooks" do
let!(:project) { FactoryGirl.create(:project) }
context "Valid Webhook URL" do
- let!(:webhook) { {:web_hook => "http://example.com/sth/1/ala_ma_kota" } }
+ let!(:webhook) { {web_hook: "http://example.com/sth/1/ala_ma_kota" } }
before do
options.merge!(webhook)
@@ -76,7 +189,7 @@ describe API::API do
end
context "Invalid Webhook URL" do
- let!(:webhook) { {:web_hook => "ala_ma_kota" } }
+ let!(:webhook) { {web_hook: "ala_ma_kota" } }
before do
options.merge!(webhook)
@@ -117,7 +230,7 @@ describe API::API do
describe "PUT /projects/:id" do
let!(:project) { FactoryGirl.create(:project) }
- let!(:project_info) { {:name => "An updated name!" } }
+ let!(:project_info) { {name: "An updated name!" } }
before do
options.merge!(project_info)
@@ -149,10 +262,10 @@ describe API::API do
describe "POST /projects" do
let(:project_info) {
{
- :name => "My project",
- :gitlab_id => 1,
- :gitlab_url => "http://example.com/testing/testing",
- :ssh_url_to_repo => "ssh://example.com/testing/testing.git"
+ name: "My project",
+ gitlab_id: 1,
+ gitlab_url: "http://example.com/testing/testing",
+ ssh_url_to_repo: "ssh://example.com/testing/testing.git"
}
}