summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Sørensen <johan@johansorensen.com>2009-06-16 14:38:53 +0200
committerJohan Sørensen <johan@johansorensen.com>2009-06-17 12:21:21 +0200
commitd2c36407a76f6946f366916882726ce0fca496d2 (patch)
tree8ce1fadd46bbb9b9718c131f10e4f6e8a104849a
parent4793b6e94da496a732262f81e77e61746e8ee98c (diff)
downloadgitorious-mainline-outdated-d2c36407a76f6946f366916882726ce0fca496d2.zip
gitorious-mainline-outdated-d2c36407a76f6946f366916882726ce0fca496d2.tar.gz
gitorious-mainline-outdated-d2c36407a76f6946f366916882726ce0fca496d2.tar.bz2
Added Web Hook model
-rw-r--r--app/controllers/application_controller.rb16
-rw-r--r--app/controllers/hooks_controller.rb57
-rw-r--r--app/controllers/repositories_controller.rb18
-rw-r--r--app/helpers/hooks_helper.rb2
-rw-r--r--app/models/hook.rb25
-rw-r--r--app/models/repository.rb1
-rw-r--r--app/views/hooks/index.html.erb53
-rw-r--r--app/views/hooks/new.html.erb50
-rw-r--r--config/locales/en.rb4
-rw-r--r--config/routes.rb1
-rw-r--r--db/migrate/20090616085408_create_web_hooks.rb17
-rw-r--r--test/functional/hooks_controller_test.rb108
-rw-r--r--test/unit/helpers/hooks_helper_test.rb4
-rw-r--r--test/unit/hook_test.rb29
-rw-r--r--test/unit/repository_test.rb2
15 files changed, 370 insertions, 17 deletions
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index c67362d..f0e1b3f 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -158,6 +158,22 @@ class ApplicationController < ActionController::Base
@repository = Repository.find_by_name_and_project_id!(params[:repository_id], @project.id)
end
+ def require_owner_adminship
+ unless @owner.admin?(current_user)
+ respond_to do |format|
+ format.html {
+ flash[:error] = I18n.t "repositories_controller.adminship_error"
+ redirect_to(@owner)
+ }
+ format.xml {
+ render :text => I18n.t( "repositories_controller.adminship_error"),
+ :status => :forbidden
+ }
+ end
+ return
+ end
+ end
+
def check_repository_for_commits
unless @repository.has_commits?
flash[:notice] = I18n.t "application.no_commits_notice"
diff --git a/app/controllers/hooks_controller.rb b/app/controllers/hooks_controller.rb
new file mode 100644
index 0000000..132da5f
--- /dev/null
+++ b/app/controllers/hooks_controller.rb
@@ -0,0 +1,57 @@
+# encoding: utf-8
+#--
+# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#++
+
+class HooksController < ApplicationController
+ before_filter :login_required
+ before_filter :find_repository
+ before_filter :require_owner_adminship
+ renders_in_global_context
+
+ def index
+ @hooks = @repository.hooks
+ @root = @repository
+ end
+
+ def new
+ @hook = @repository.hooks.new
+ @hook.user = current_user
+ @root = @repository
+ end
+
+ def create
+ @hook = @repository.hooks.new(params[:hook])
+ @hook.user = current_user
+ @root = @repository
+ if @hook.save
+ redirect_to repo_owner_path(@repository, :project_repository_hooks_path,
+ @repository.project, @repository)
+ else
+ render "new"
+ end
+ end
+ #
+ # def destroy
+ #
+ # end
+
+ protected
+ def find_repository
+ find_repository_owner
+ @repository = @owner.repositories.find_by_name!(params[:repository_id])
+ end
+end
diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb
index c79aa7c..945bd4c 100644
--- a/app/controllers/repositories_controller.rb
+++ b/app/controllers/repositories_controller.rb
@@ -23,7 +23,7 @@
class RepositoriesController < ApplicationController
before_filter :login_required, :except => [:index, :show, :writable_by]
before_filter :find_repository_owner
- before_filter :require_adminship, :only => [:edit, :update, :new, :create, :edit, :update, :committers]
+ before_filter :require_owner_adminship, :only => [:edit, :update, :new, :create, :edit, :update, :committers]
before_filter :require_user_has_ssh_keys, :only => [:clone, :create_clone]
before_filter :only_projects_can_add_new_repositories, :only => [:new, :create]
skip_before_filter :public_and_logged_in, :only => [:writable_by]
@@ -202,22 +202,6 @@ class RepositoriesController < ApplicationController
end
private
- def require_adminship
- unless @owner.admin?(current_user)
- respond_to do |format|
- format.html {
- flash[:error] = I18n.t "repositories_controller.adminship_error"
- redirect_to(@owner)
- }
- format.xml {
- render :text => I18n.t( "repositories_controller.adminship_error"),
- :status => :forbidden
- }
- end
- return
- end
- end
-
def only_projects_can_add_new_repositories
if !@owner.is_a?(Project)
respond_to do |format|
diff --git a/app/helpers/hooks_helper.rb b/app/helpers/hooks_helper.rb
new file mode 100644
index 0000000..14354af
--- /dev/null
+++ b/app/helpers/hooks_helper.rb
@@ -0,0 +1,2 @@
+module HooksHelper
+end
diff --git a/app/models/hook.rb b/app/models/hook.rb
new file mode 100644
index 0000000..5434cc6
--- /dev/null
+++ b/app/models/hook.rb
@@ -0,0 +1,25 @@
+# encoding: utf-8
+#--
+# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#++
+
+class Hook < ActiveRecord::Base
+ belongs_to :repository
+ belongs_to :user
+
+ validates_presence_of :repository, :user, :url
+
+end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 1fbb263..ee01b8a 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -50,6 +50,7 @@ class Repository < ActiveRecord::Base
:class_name => 'MergeRequest', :order => "id desc", :dependent => :destroy
has_many :cloners, :dependent => :destroy
has_many :events, :as => :target, :dependent => :destroy
+ has_many :hooks, :dependent => :destroy
NAME_FORMAT = /[a-z0-9_\-]+/i.freeze
validates_presence_of :user_id, :name, :owner_id, :project_id
diff --git a/app/views/hooks/index.html.erb b/app/views/hooks/index.html.erb
new file mode 100644
index 0000000..eabde40
--- /dev/null
+++ b/app/views/hooks/index.html.erb
@@ -0,0 +1,53 @@
+<%
+#--
+# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#++
+%>
+
+<% @page_title = t("views.hooks.repository_web_hooks") -%>
+<%= breadcrumbs_from(@root) -%>
+
+<h1><%= t("views.hooks.repository_web_hooks") %></h1>
+
+<table class="listing">
+ <thead>
+ <th>Created</th>
+ <th>URL</th>
+ <th>Last response</th>
+ <th></th>
+ </thead>
+ <% @hooks.each do |hook| -%>
+ <tr class="<%= cycle('even', 'odd') -%>">
+ <td><%= hook.created_at.to_s(:short) -%></td>
+ <td><%=h hook.url -%></td>
+ <td><code><%=h hook.last_response -%></code></td>
+ <td>
+ <%= button_to t("views.common.delete"), repo_owner_path(@repository,
+ :project_repository_hook_path, @repository.project, @repository, hook),
+ :confirm => t("views.common.confirm"), :method => :delete, :class => "inline" -%>
+ </td>
+ </tr>
+ <% end -%>
+</table>
+
+<% content_for :sidebar do -%>
+ <ul class="links">
+ <li class="new_hook">
+ <%= link_to t("views.hooks.add_hook"), repo_owner_path(@repository,
+ :new_project_repository_hook_path, @repository.project, @repository) -%></li>
+ </ul>
+<% end -%>
+
diff --git a/app/views/hooks/new.html.erb b/app/views/hooks/new.html.erb
new file mode 100644
index 0000000..58ef4bb
--- /dev/null
+++ b/app/views/hooks/new.html.erb
@@ -0,0 +1,50 @@
+<%
+#--
+# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#++
+%>
+
+<% help_box do -%>
+<p>
+ A <em>hook</em> is a callback URL Gitorious will post the contents of a push
+ to. The contents and format is described
+ <a href="http://gitorious.org/gitorious/pages/WebHooks">here</a>
+</p>
+<p>
+ In a nutshell, a JSON hash i POSTed to the url you give here whenever a set
+ of commits is pushed to this repository
+</p>
+<% end -%>
+
+<%= error_messages_for :hook -%>
+<% form_for :hook,
+ :url => repo_owner_path(@repository, [@repository.project, @repository, @hook]) do |f| -%>
+ <p>
+ <%= f.label :url %>: <br />
+ <%= f.text_field :url %>
+ </p>
+ <p><%= f.submit "Add commit callback URL" -%></p>
+<% end -%>
+
+<% content_for(:sidebar) do -%>
+ <% content_for :sidebar do -%>
+ <ul class="links">
+ <li class="repository">
+ <%= link_to "Back to repository", repo_owner_path(@repository,
+ :project_repository_path, @repository.project, @repository) -%></li>
+ </ul>
+ <% end -%>
+<% end -%> \ No newline at end of file
diff --git a/config/locales/en.rb b/config/locales/en.rb
index 69d6ebc..ed52d23 100644
--- a/config/locales/en.rb
+++ b/config/locales/en.rb
@@ -210,6 +210,10 @@
:your_public_key => "Your public key",
:hint => "It's generally located in ~/.ssh/id_rsa.pub or ~/.ssh/id_dsa.pub. If you want to use multiple keys you'll have to add each of them seperately. <br />The key should be in the format of: <br /><code>ssh-algorithm base64-content you@somehost</code>",
},
+ :hooks => {
+ :repository_web_hooks => "Repository Web Hooks",
+ :add_hook => "Add Hook"
+ },
:users => {
:activated => "Activated?",
:suspended => "Suspended?",
diff --git a/config/routes.rb b/config/routes.rb
index 6dcd998..53e6d96 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -53,6 +53,7 @@ ActionController::Routing::Routes.draw do |map|
:auto_complete_for_group_name => :post,
:auto_complete_for_user_login => :post
}
+ repo.resources :hooks
repo.formatted_commits_feed "commits/*branch/feed.:format",
:controller => "commits", :action => "feed", :conditions => {:feed => :get}
diff --git a/db/migrate/20090616085408_create_web_hooks.rb b/db/migrate/20090616085408_create_web_hooks.rb
new file mode 100644
index 0000000..c3739cd
--- /dev/null
+++ b/db/migrate/20090616085408_create_web_hooks.rb
@@ -0,0 +1,17 @@
+class CreateWebHooks < ActiveRecord::Migration
+ def self.up
+ create_table :hooks do |t|
+ t.integer :user_id
+ t.integer :repository_id
+ t.string :url
+ t.string :last_response
+
+ t.timestamps
+ end
+ add_index :hooks, :repository_id
+ end
+
+ def self.down
+ drop_table :hooks
+ end
+end
diff --git a/test/functional/hooks_controller_test.rb b/test/functional/hooks_controller_test.rb
new file mode 100644
index 0000000..b918899
--- /dev/null
+++ b/test/functional/hooks_controller_test.rb
@@ -0,0 +1,108 @@
+# encoding: utf-8
+#--
+# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#++
+
+require File.dirname(__FILE__) + '/../test_helper'
+
+class HooksControllerTest < ActionController::TestCase
+
+ def setup
+ @project = projects(:johans)
+ @repository = @project.repositories.mainlines.first
+ login_as :johan
+ end
+
+ should_render_in_global_context
+
+ context "index" do
+ should "require login" do
+ session[:user_id] = nil
+ get :index, :project_id => @project.to_param, :repository_id => @repository.to_param
+ assert_redirected_to(new_sessions_path)
+ end
+
+ should "require reposítory adminship" do
+ login_as :moe
+ get :index, :project_id => @project.to_param, :repository_id => @repository.to_param
+ assert_match(/only repository admins are allowed/, flash[:error])
+ assert_redirected_to(project_path(@project))
+ end
+
+ should "set find the correct owner and repository" do
+ get :index, :project_id => @project.to_param, :repository_id => @repository.to_param
+ assert_equal @project, assigns(:owner)
+ assert_equal @repository, assigns(:repository)
+ end
+
+ should "be successfull" do
+ get :index, :project_id => @project.to_param, :repository_id => @repository.to_param
+ assert_response :success
+ assert_not_nil assigns(:hooks)
+ end
+ end
+
+ context "new / create" do
+ setup do
+ @project = projects(:johans)
+ @repository = @project.repositories.mainlines.first
+ login_as :johan
+ end
+
+ should "require login" do
+ session[:user_id] = nil
+ get :new, :project_id => @project.to_param, :repository_id => @repository.to_param
+ assert_redirected_to(new_sessions_path)
+ end
+
+ should "require reposítory adminship" do
+ login_as :moe
+ get :new, :project_id => @project.to_param, :repository_id => @repository.to_param
+ assert_match(/only repository admins are allowed/, flash[:error])
+ assert_redirected_to(project_path(@project))
+ end
+
+ should "be successfull" do
+ get :new, :project_id => @project.to_param, :repository_id => @repository.to_param
+ assert_response :success
+ assert assigns(:hook).new_record?
+ assert_equal users(:johan), assigns(:hook).user
+ end
+
+ should "create a new hook" do
+ assert_difference("@repository.hooks.count") do
+ post :create, :project_id => @project.to_param,
+ :repository_id => @repository.to_param, :hook => {
+ :url => "http://google.com"
+ }
+ assert_response :redirect
+ end
+ assert_redirected_to project_repository_hooks_path(@project, @repository)
+ assert_equal users(:johan), assigns(:hook).user
+ end
+
+ should "not create a new hook when invalid data is submitted" do
+ assert_no_difference("@repository.hooks.count") do
+ post :create, :project_id => @project.to_param,
+ :repository_id => @repository.to_param, :hook => {
+ :url => ''
+ }
+ end
+ assert_response :success
+ assert_template "new"
+ end
+ end
+end
diff --git a/test/unit/helpers/hooks_helper_test.rb b/test/unit/helpers/hooks_helper_test.rb
new file mode 100644
index 0000000..24c0cc4
--- /dev/null
+++ b/test/unit/helpers/hooks_helper_test.rb
@@ -0,0 +1,4 @@
+require 'test_helper'
+
+class HooksHelperTest < ActionView::TestCase
+end
diff --git a/test/unit/hook_test.rb b/test/unit/hook_test.rb
new file mode 100644
index 0000000..0ec4f5c
--- /dev/null
+++ b/test/unit/hook_test.rb
@@ -0,0 +1,29 @@
+# encoding: utf-8
+#--
+# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#++
+
+require File.dirname(__FILE__) + '/../test_helper'
+
+class HookTest < ActiveSupport::TestCase
+
+ should_belong_to :repository
+ should_validate_presence_of :user, :repository, :url
+
+ should_eventually "only allow N hooks per repository" do
+ flunk
+ end
+end
diff --git a/test/unit/repository_test.rb b/test/unit/repository_test.rb
index 9ee37ac..66c5172 100644
--- a/test/unit/repository_test.rb
+++ b/test/unit/repository_test.rb
@@ -39,6 +39,8 @@ class RepositoryTest < ActiveSupport::TestCase
should_validate_uniqueness_of :hashed_path
should_validate_uniqueness_of :name, :scoped_to => :project_id, :case_sensitive => false
+ should_have_many :hooks, :dependent => :destroy
+
should " only accept names with alphanum characters in it" do
@repository.name = "foo bar"
assert !@repository.valid?, 'valid? should be false'