Commit f238323b authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'git_hook_api' into 'master'

Git hook api

Fixes #176

Fixes #169

See merge request !229
parents 994c2b1c e020dca1
......@@ -2,6 +2,8 @@ v 7.5.0
- Added an ability to check each author commit's email by regex
- Added an abulity to restrict commit authors to existing Gitlab users
- Add an option for automatic daily LDAP user sync
- Added git hook for preventing tag removal to API
- Added git hook for setting commit message regex to API
v 7.4.0
- Support for multiple LDAP servers
......
......@@ -628,3 +628,72 @@ Parameters:
- query (required) - A string contained in the project name
- per_page (optional) - number of projects to return per page
- page (optional) - the page to retrieve
## Git Hooks (EE only)
### Show project git hooks
Get a project git hook.
```
GET /projects/:id/git_hooks
```
Parameters:
- `id` (required) - The ID of a project
```json
{
"id": 1,
"project_id": 3,
"commit_message_regex": "Fixes \d +\",
"deny_delete_tag": false,
"created_at": "2012-10-12T17:04:47Z"
}
```
### Add project git hook
Adds a git hook to a specified project.
```
POST /projects/:id/git_hooks
```
Parameters:
- `id` (required) - The ID of a project
- `deny_delete_tag` - Do not allow users to remove git tags with git push
- `commit_message_regex` - Commit message regex
### Edit project git hook
Edits a git hook for a specified project.
```
PUT /projects/:id/git_hooks
```
Parameters:
- `id` (required) - The ID of a project
- `deny_delete_tag` - Do not allow users to remove git tags with git push
- `commit_message_regex` - Commit message regex
### Delete project git hook
Removes a git hook from a project. This is an idempotent method and can be called multiple times.
Either the git hook is available or not.
```
DELETE /projects/:id/git_hooks
```
Parameters:
- `id` (required) - The ID of a project
Note the JSON response differs if the hook is available or not. If the project hook
is available before it is returned in the JSON response or an empty response is returned.
......@@ -41,6 +41,7 @@ module API
mount ProjectMembers
mount DeployKeys
mount ProjectHooks
mount ProjectGitHook
mount Ldap
mount Services
mount Files
......
......@@ -34,6 +34,11 @@ module API
expose :issues_events, :merge_requests_events, :tag_push_events
end
class ProjectGitHook < Grape::Entity
expose :id, :project_id, :created_at
expose :commit_message_regex, :deny_delete_tag
end
class ForkedFromProject < Grape::Entity
expose :id
expose :name, :name_with_namespace
......
module API
# Projects git hook API
class ProjectGitHook < Grape::API
before { authenticate! }
before { authorize_admin_project }
resource :projects do
# Get project git hook
#
# Parameters:
# id (required) - The ID of a project
# Example Request:
# GET /projects/:id/git_hook
get ":id/git_hook" do
@git_hooks = user_project.git_hook
present @git_hooks, with: Entities::ProjectGitHook
end
# Add git hook to project
#
# Parameters:
# id (required) - The ID of a project
# Example Request:
# POST /projects/:id/git_hook
post ":id/git_hook" do
attrs = attributes_for_keys [
:commit_message_regex,
:deny_delete_tag
]
if user_project.git_hook
error!("Project git hook exists", 422)
else
@git_hook = user_project.create_git_hook(attrs)
present @git_hook, with: Entities::ProjectGitHook
end
end
# Update an existing project git hook
#
# Parameters:
# id (required) - The ID of a project
# Example Request:
# PUT /projects/:id/git_hook
put ":id/git_hook" do
@git_hook = user_project.git_hook
attrs = attributes_for_keys [
:commit_message_regex,
:deny_delete_tag
]
if @git_hook && @git_hook.update_attributes(attrs)
present @git_hook, with: Entities::ProjectGitHook
else
not_found!
end
end
# Deletes project git hook. This is an idempotent function.
#
# Parameters:
# id (required) - The ID of a project
# Example Request:
# DELETE /projects/:id/git_hook
delete ":id/git_hook" do
@git_hook = user_project.git_hook
if @git_hook
@git_hook.destroy
else
not_found!
end
end
end
end
end
require 'spec_helper'
describe API::API, 'ProjectGitHook', api: true do
include ApiHelpers
let(:user) { create(:user) }
let(:user3) { create(:user) }
let!(:project) { create(:project, creator_id: user.id, namespace: user.namespace) }
before do
project.team << [user, :master]
project.team << [user3, :developer]
end
describe "GET /projects/:id/git_hook" do
before do
create(:git_hook, project: project)
end
context "authorized user" do
it "should return project git hook" do
get api("/projects/#{project.id}/git_hook", user)
response.status.should eq(200)
json_response.should be_an Hash
json_response['project_id'].should eq(project.id)
end
end
context "unauthorized user" do
it "should not access project git hooks" do
get api("/projects/#{project.id}/git_hook", user3)
response.status.should eq(403)
end
end
end
describe "POST /projects/:id/git_hook" do
context "authorized user" do
it "should add git hook to project" do
post api("/projects/#{project.id}/git_hook", user),
deny_delete_tag: true
response.status.should eq(201)
json_response.should be_an Hash
json_response['project_id'].should eq(project.id)
json_response['deny_delete_tag'].should eq(true)
end
end
context "unauthorized user" do
it "should not add git hook to project" do
post api("/projects/#{project.id}/git_hook", user3),
deny_delete_tag: true
response.status.should eq(403)
end
end
end
describe "POST /projects/:id/git_hook" do
before do
create(:git_hook, project: project)
end
context "with existing git hook" do
it "should not add git hook to project" do
post api("/projects/#{project.id}/git_hook", user),
deny_delete_tag: true
response.status.should eq(422)
end
end
end
describe "PUT /projects/:id/git_hook" do
before do
create(:git_hook, project: project)
end
it "should update an existing project git hook" do
put api("/projects/#{project.id}/git_hook", user),
deny_delete_tag: false, commit_message_regex: 'Fixes \d+\..*'
response.status.should eq(200)
json_response['deny_delete_tag'].should eq(false)
json_response['commit_message_regex'].should eq('Fixes \d+\..*')
end
end
describe "PUT /projects/:id/git_hook" do
it "should error on non existing project git hook" do
put api("/projects/#{project.id}/git_hook", user),
deny_delete_tag: false, commit_message_regex: 'Fixes \d+\..*'
response.status.should eq(404)
end
it "should not update git hook for unauthorized user" do
post api("/projects/#{project.id}/git_hook", user3),
deny_delete_tag: true
response.status.should eq(403)
end
end
describe "DELETE /projects/:id/git_hook" do
before do
create(:git_hook, project: project)
end
context "authorized user" do
it "should delete git hook from project" do
delete api("/projects/#{project.id}/git_hook", user)
response.status.should eq(200)
json_response.should be_an Hash
end
end
context "unauthorized user" do
it "should return a 403 error" do
delete api("/projects/#{project.id}/git_hook", user3)
response.status.should eq(403)
end
end
end
describe "DELETE /projects/:id/git_hook" do
context "for non existing git hook" do
it "should delete git hook from project" do
delete api("/projects/#{project.id}/git_hook", user)
response.status.should eq(404)
json_response.should be_an Hash
json_response['message'].should eq("404 Not Found")
end
it "should return a 403 error if not authorized" do
delete api("/projects/#{project.id}/git_hook", user3)
response.status.should eq(403)
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment