Commit d4957ee7 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'git-hooks' into 'master'

Git Hooks
parents abd6d821 76155b17
class Projects::GitHooksController < Projects::ApplicationController
# Authorize
before_filter :authorize_admin_project!
respond_to :html
layout "project_settings"
def index
project.create_git_hook unless project.git_hook
@pre_receive_hook = project.git_hook
end
def update
@pre_receive_hook = project.git_hook
@pre_receive_hook.update_attributes(params[:git_hook])
if @pre_receive_hook.valid?
redirect_to project_git_hooks_path(@project)
else
render :index
end
end
end
class GitHook < ActiveRecord::Base
attr_accessible :deny_delete_tag, :delete_branch_regex, :commit_message_regex, :force_push_regex
belongs_to :project
validates :project, presence: true
end
...@@ -47,6 +47,7 @@ class Project < ActiveRecord::Base ...@@ -47,6 +47,7 @@ class Project < ActiveRecord::Base
belongs_to :group, -> { where(type: Group) }, foreign_key: "namespace_id" belongs_to :group, -> { where(type: Group) }, foreign_key: "namespace_id"
belongs_to :namespace belongs_to :namespace
has_one :git_hook, dependent: :destroy
has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event', foreign_key: 'project_id' has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event', foreign_key: 'project_id'
has_one :gitlab_ci_service, dependent: :destroy has_one :gitlab_ci_service, dependent: :destroy
has_one :campfire_service, dependent: :destroy has_one :campfire_service, dependent: :destroy
......
...@@ -19,6 +19,10 @@ ...@@ -19,6 +19,10 @@
= link_to project_hooks_path(@project) do = link_to project_hooks_path(@project) do
%i.icon-link %i.icon-link
Web Hooks Web Hooks
= nav_link(controller: :git_hooks) do
= link_to project_git_hooks_path(@project) do
%i.icon-upload
Git Hooks
= nav_link(controller: :services) do = nav_link(controller: :services) do
= link_to project_services_path(@project) do = link_to project_services_path(@project) do
%i.icon-cogs %i.icon-cogs
......
%h3.page-title
Git hooks
%p.light
Here you can set additional rules for push to repository
%hr.clearfix
= form_for [@project, @pre_receive_hook], html: { class: 'form-horizontal' } do |f|
-if @pre_receive_hook.errors.any?
.alert.alert-danger
- @pre_receive_hook.errors.full_messages.each do |msg|
%p= msg
.form-group
= f.label :deny_delete_tag, "Deny tag remove", class: 'control-label'
.col-sm-10
.checkbox
= f.check_box :deny_delete_tag
%span.descr Dont allow users to remove git tags
-#.form-group
= f.label :force_push_regex, "Force push", class: 'control-label'
.col-sm-10
= f.text_field :force_push_regex, class: "form-control"
%p.hint Regular expression for branches to allow force push. Empty - allow force push to any branch
-#.form-group
= f.label :delete_branch_regex, "Branch removal", class: 'control-label'
.col-sm-10
= f.text_field :delete_branch_regex, class: "form-control"
%p.hint Regular expression for branches that can be removed. Empty - allow remove of any branch
.form-group
= f.label :commit_message_regex, "Commit message", class: 'control-label'
.col-sm-10
= f.text_field :commit_message_regex, class: "form-control", placeholder: 'Ex. Fix \d+\..*'
%p.hint Commit message must match this regular expression to be pushed. Empty - allow remove of any commit message
.form-actions
= f.submit "Save git Hook", class: "btn btn-create"
...@@ -291,6 +291,8 @@ Gitlab::Application.routes.draw do ...@@ -291,6 +291,8 @@ Gitlab::Application.routes.draw do
end end
end end
resources :git_hooks, constraints: {id: /\d+/}
resources :hooks, only: [:index, :create, :destroy], constraints: {id: /\d+/} do resources :hooks, only: [:index, :create, :destroy], constraints: {id: /\d+/} do
member do member do
get :test get :test
......
class CreateGitHooks < ActiveRecord::Migration
def change
create_table :git_hooks do |t|
t.string :force_push_regex
t.string :delete_branch_regex
t.string :commit_message_regex
t.boolean :deny_delete_tag
t.integer :project_id
t.timestamps
end
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20140313092127) do ActiveRecord::Schema.define(version: 20140319135450) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
...@@ -74,6 +74,16 @@ ActiveRecord::Schema.define(version: 20140313092127) do ...@@ -74,6 +74,16 @@ ActiveRecord::Schema.define(version: 20140313092127) do
add_index "forked_project_links", ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true, using: :btree add_index "forked_project_links", ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true, using: :btree
create_table "git_hooks", force: true do |t|
t.string "force_push_regex"
t.string "delete_branch_regex"
t.string "commit_message_regex"
t.boolean "deny_delete_tag"
t.integer "project_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "issues", force: true do |t| create_table "issues", force: true do |t|
t.string "title" t.string "title"
t.integer "assignee_id" t.integer "assignee_id"
......
...@@ -48,12 +48,39 @@ module Gitlab ...@@ -48,12 +48,39 @@ module Gitlab
else else
:push_code :push_code
end end
user.can?(action, project)
user.can?(action, project) &&
pass_git_hooks?(user, project, ref, oldrev, newrev)
else else
false false
end end
end end
def pass_git_hooks?(user, project, ref, oldrev, newrev)
return true unless project.git_hook
git_hook = project.git_hook
# Prevent tag removal
if git_hook.deny_delete_tag
if project.repository.tag_names.include?(ref) && newrev =~ /0000000/
return false
end
end
# Check commit messages unless its branch removal
if git_hook.commit_message_regex.present? && newrev !~ /00000000/
commits = project.repository.commits_between(oldrev, newrev)
commits.each do |commit|
unless commit.safe_message =~ Regexp.new(git_hook.commit_message_regex)
return false
end
end
end
true
end
private private
def user_allowed?(user) def user_allowed?(user)
......
# Read about factories at https://github.com/thoughtbot/factory_girl
FactoryGirl.define do
factory :git_hook do
force_push_regex "MyString"
deny_delete_tag false
delete_branch_regex "MyString"
project
commit_message_regex "MyString"
end
end
require 'spec_helper'
describe GitHook do
describe "Associations" do
it { should belong_to(:project) }
end
describe "Mass assignment" do
it { should_not allow_mass_assignment_of(:project_id) }
end
describe "Validation" do
it { should validate_presence_of(:project) }
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