github_concern 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.markdown +78 -0
  3. data/Rakefile +23 -0
  4. data/app/assets/javascripts/github.js +2 -0
  5. data/app/assets/stylesheets/github.css +4 -0
  6. data/app/controllers/application_controller.rb +2 -0
  7. data/app/controllers/github_controller.rb +7 -0
  8. data/app/helpers/github_helper.rb +2 -0
  9. data/app/models/git_commit.rb +4 -0
  10. data/app/models/git_push.rb +56 -0
  11. data/app/models/github_concernable_git_push.rb +4 -0
  12. data/config/routes.rb +3 -0
  13. data/db/migrate/20111204031658_create_git_pushes.rb +9 -0
  14. data/db/migrate/20111204031730_create_git_commits.rb +10 -0
  15. data/db/migrate/20111204041743_add_user_id_to_git_push.rb +5 -0
  16. data/db/migrate/20111204055027_create_github_concernable_git_pushes.rb +11 -0
  17. data/lib/github_concern/engine.rb +50 -0
  18. data/lib/github_concern/version.rb +3 -0
  19. data/lib/github_concern.rb +15 -0
  20. data/lib/tasks/github_concern_tasks.rake +4 -0
  21. data/spec/controllers/github_controller_spec.rb +29 -0
  22. data/spec/internal/app/models/project.rb +2 -0
  23. data/spec/internal/app/models/ticket.rb +6 -0
  24. data/spec/internal/app/models/user.rb +2 -0
  25. data/spec/internal/config/application.rb +1 -0
  26. data/spec/internal/config/database.yml +3 -0
  27. data/spec/internal/config/initializers/github_concern.rb +11 -0
  28. data/spec/internal/config/routes.rb +3 -0
  29. data/spec/internal/db/combustion_test.sqlite +0 -0
  30. data/spec/internal/db/schema.rb +36 -0
  31. data/spec/internal/log/test.log +2387 -0
  32. data/spec/internal/public/favicon.ico +0 -0
  33. data/spec/models/git_push.rb +57 -0
  34. data/spec/spec_helper.rb +13 -0
  35. data/spec/support/github_payload.rb +3 -0
  36. metadata +158 -0
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2011 Adam Gamble
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,78 @@
1
+ # Github Concern
2
+
3
+ Github Concern is a library to make integrating your application with github
4
+ braindead simple. It has the following useful features:
5
+
6
+ * Provides a controller to respond to github post-push service hooks.
7
+ * Provides models to store the information github sends you.
8
+ * Provides a DSL for easily specifying which objects in your system should be
9
+ associated with commits.
10
+ * Provides a DSL to specify actions in your system that should be taken as a
11
+ result of specific commits being seen. For instance, in a time tracking
12
+ system you might add something that responded to commits that had "\[HOURS:
13
+ 3.5\]" in them by creating a WorkUnit in the system, associated with that
14
+ commit, for 3.5 hours.
15
+
16
+ ## Installation
17
+
18
+ First, add github\_concern to your Gemfile:
19
+
20
+ ```ruby
21
+ gem 'github_concern', :git => 'http://github.com/adamgamble/github_concern.git'
22
+ ```
23
+
24
+ bundle install
25
+
26
+ Now github\_concern is available to your application. Next, add a service hook
27
+ to your github repo that posts to http://your\_url/github\_integration
28
+
29
+ Add this to config/initializers/github\_concern.rb:
30
+
31
+ ```ruby
32
+ GithubConcern::Engine.config do |gc|
33
+ gc.user_lambda = lambda {|email| User.find_by_email email}
34
+ gc.user_class = User
35
+ end
36
+ ```
37
+
38
+ You can adjust the lambda to fit your needs for determining a user.
39
+
40
+ You need to create tables to store the commits and pushes that the github web
41
+ hook is going to be sending you. Run this command to install the migrations:
42
+
43
+ rake github_concern_engine:install:migrations
44
+
45
+ You can configure whatever models you want to be associated with the git pushes:
46
+
47
+ ```ruby
48
+ class SomeModel < ActiveRecord::Base
49
+ github_concern :repo => :github_repo, :branch => :github_branch
50
+
51
+ def github_concern_callback git_push
52
+ end
53
+ end
54
+ ```
55
+
56
+ `:github_repo`, and `:github_branch` represent attributes on the model
57
+
58
+ Now when someone pushes to a repo that has the service hook, information about
59
+ that will be stored in the database and associated to whatever models specified.
60
+ It will also call the `github_concern_callback` method on the object if it
61
+ exists.
62
+
63
+ ## Contributing
64
+
65
+ Fork our repo, make a feature branch, push to it. Send us a pull request.
66
+ We'll communicate back and forth via the github interface. All contributions
67
+ are welcome. Plase inform us of issues via the github issue tracker
68
+
69
+ ## Authors
70
+
71
+ * Adam Gamble
72
+ * Josh Adams*
73
+
74
+ \* Hasn't actually commited any code yet
75
+
76
+ ## License
77
+
78
+ See the MIT-LICENSE file for details.
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'GithubConcern'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -0,0 +1,2 @@
1
+ class ApplicationController < ActionController::Base
2
+ end
@@ -0,0 +1,7 @@
1
+ class GithubController < ApplicationController
2
+ def payload
3
+ render :nothing => true, :status => 500 and return unless params["payload"]
4
+ GitPush.create(:payload => JSON.parse(params["payload"]))
5
+ render :nothing => true, :status => 200
6
+ end
7
+ end
@@ -0,0 +1,2 @@
1
+ module GithubHelper
2
+ end
@@ -0,0 +1,4 @@
1
+ class GitCommit < ActiveRecord::Base
2
+ belongs_to :git_push
3
+ serialize :payload
4
+ end
@@ -0,0 +1,56 @@
1
+ class GitPush < ActiveRecord::Base
2
+ before_create :associate_user
3
+ after_create :associate_git_concernables, :build_commits
4
+
5
+ serialize :payload
6
+ belongs_to GithubConcern::Engine.user_class_symbol, :foreign_key => :user_id
7
+ has_many :github_concernable_git_pushes
8
+ has_many :github_concernables, :through => :github_concernable_git_pushes
9
+ has_many :git_commits
10
+
11
+ private
12
+ def associate_user
13
+ email = payload["pusher"]["email"]
14
+ user = GithubConcern::Engine.determine_user(email)
15
+ self.user_id = user.id if user
16
+ end
17
+
18
+ def build_commits
19
+ payload["commits"].each do |commit|
20
+ git_commits.create(:payload => commit)
21
+ end
22
+ end
23
+
24
+ def associate_git_concernables
25
+ GithubConcern::Engine.github_concerns.each_pair do |class_name, github_concern_hash|
26
+ bucket = class_name.constantize
27
+ github_concern_hash.each_pair do |github_concern_key, github_concern_method|
28
+ case github_concern_key
29
+ when :repo
30
+ git_variable = payload["repository"]["name"]
31
+ when :branch
32
+ git_variable = payload["ref"].gsub("refs/heads/","")
33
+ when :class_method
34
+ objects = bucket.send(github_concern_method,payload["repository"]["name"],payload["ref"].gsub("refs/heads/",""))
35
+ if objects.respond_to?(:each)
36
+ objects.each {|object| associate_to_object object }
37
+ else
38
+ associate_to_object objects
39
+ end
40
+ next
41
+ end
42
+ bucket = bucket.where(github_concern_method => git_variable)
43
+ end
44
+ bucket.all.each do |object|
45
+ associate_to_object object
46
+ end
47
+ end
48
+ end
49
+
50
+ def associate_to_object object
51
+ github_concernable_git_push = self.github_concernable_git_pushes.new
52
+ github_concernable_git_push.github_concernable = object
53
+ github_concernable_git_push.save
54
+ object.github_concern_callback(self) if object.respond_to?(:github_concern_callback)
55
+ end
56
+ end
@@ -0,0 +1,4 @@
1
+ class GithubConcernableGitPush < ActiveRecord::Base
2
+ belongs_to :github_concernable, :polymorphic => true
3
+ belongs_to :git_push
4
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,3 @@
1
+ Rails.application.routes.draw do
2
+ post "/github_integration", :to => "github#payload"
3
+ end
@@ -0,0 +1,9 @@
1
+ class CreateGitPushes < ActiveRecord::Migration
2
+ def change
3
+ create_table :git_pushes do |t|
4
+ t.text :payload
5
+
6
+ t.timestamps
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ class CreateGitCommits < ActiveRecord::Migration
2
+ def change
3
+ create_table :git_commits do |t|
4
+ t.text :payload
5
+ t.integer :git_push_id
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ class AddUserIdToGitPush < ActiveRecord::Migration
2
+ def change
3
+ add_column :git_push, :user_id, :integer
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ class CreateGithubConcernableGitPushes < ActiveRecord::Migration
2
+ def change
3
+ create_table :github_concernable_git_pushes do |t|
4
+ t.string :github_concernable_type
5
+ t.integer :github_concernable_id
6
+ t.integer :git_push_id
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,50 @@
1
+ require 'rails/all'
2
+ module GithubConcern
3
+ class Engine < Rails::Engine
4
+ @@github_concerns = {}
5
+ def self.config
6
+ yield(self)
7
+ end
8
+
9
+ def self.add_class(class_constant, options)
10
+ @@github_concerns[class_constant.to_s] = options
11
+ end
12
+
13
+ def self.github_concerns
14
+ @@github_concerns
15
+ end
16
+
17
+ def self.user_lambda= find_user_lambda
18
+ @@user_lambda = find_user_lambda
19
+ end
20
+
21
+ def self.user_lambda
22
+ @@user_lambda
23
+ end
24
+
25
+ def self.user_class= user_class_constant
26
+ @@user_class= user_class_constant
27
+ @@user_class.class_eval { has_many :git_pushes }
28
+ @@user_class
29
+ end
30
+
31
+ def self.user_class
32
+ @@user_class
33
+ end
34
+
35
+ def self.user_class_symbol
36
+ @@user_class.try(:to_s).try(:downcase).try(:to_sym)
37
+ end
38
+
39
+ def self.determine_user(email)
40
+ @@user_lambda.call(email)
41
+ end
42
+
43
+ def self.add_github_concernable_relationship_to_class(class_constant)
44
+ class_constant.class_eval {
45
+ has_many :github_concernables, :class_name => "GithubConcernableGitPush", :as => :github_concernable
46
+ has_many :git_pushes, :through => :github_concernables
47
+ }
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,3 @@
1
+ module GithubConcern
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,15 @@
1
+ require "github_concern/engine"
2
+
3
+ module GithubConcern
4
+ extend ActiveSupport::Concern
5
+ included do
6
+ end
7
+
8
+ module ClassMethods
9
+ def github_concern(options = {})
10
+ GithubConcern::Engine.add_class(self, options)
11
+ GithubConcern::Engine.add_github_concernable_relationship_to_class(self)
12
+ end
13
+ end
14
+ end
15
+ ActiveRecord::Base.send :include, GithubConcern
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :github_concern do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe GithubController do
4
+ describe "POST payload" do
5
+ it "returns 500 when not sending a payload" do
6
+ post :payload
7
+ response.code.should == "500"
8
+ end
9
+
10
+ describe "when sending a valid payload" do
11
+ before(:each) do
12
+ payload = valid_payload_hash.to_json
13
+ post :payload, :payload => payload
14
+ end
15
+
16
+ it "returns 200 when sending a valid payload" do
17
+ response.should be_success
18
+ end
19
+
20
+ it "should create a git push" do
21
+ GitPush.count.should == 1
22
+ end
23
+
24
+ it "should set the payload of that git push to payload" do
25
+ GitPush.last.payload.should == valid_payload_hash
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,2 @@
1
+ class Project < ActiveRecord::Base
2
+ end
@@ -0,0 +1,6 @@
1
+ class Ticket < ActiveRecord::Base
2
+
3
+ def self.github_concern_class_method repo, branch
4
+
5
+ end
6
+ end
@@ -0,0 +1,2 @@
1
+ class User < ActiveRecord::Base
2
+ end
@@ -0,0 +1 @@
1
+ require 'github_concern'
@@ -0,0 +1,3 @@
1
+ test:
2
+ adapter: sqlite3
3
+ database: db/combustion_test.sqlite
@@ -0,0 +1,11 @@
1
+ GithubConcern::Engine.config do |gc|
2
+ gc.user_lambda = lambda {|email| User.find_by_email email}
3
+ gc.user_class = User
4
+ end
5
+
6
+ Module.constants.select do |constant_name|
7
+ constant = constant_name.to_s.constantize
8
+ if not constant.nil? and constant.is_a? Class and constant.superclass == ActiveRecord::Base
9
+ constant.inspect
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ Rails.application.routes.draw do
2
+ #
3
+ end
@@ -0,0 +1,36 @@
1
+ ActiveRecord::Schema.define do
2
+ create_table(:users, :force => true) do |t|
3
+ t.string :email
4
+ t.timestamps
5
+ end
6
+
7
+ create_table(:projects, :force => true) do |t|
8
+ t.string :github_repo
9
+ t.timestamps
10
+ end
11
+
12
+ create_table(:tickets, :force => true) do |t|
13
+ t.string :github_repo
14
+ t.string :github_branch
15
+ t.timestamps
16
+ end
17
+
18
+ create_table(:git_pushes, :force => true) do |t|
19
+ t.text :payload
20
+ t.integer :user_id
21
+ t.timestamps
22
+ end
23
+
24
+ create_table(:git_commits, :force => true) do |t|
25
+ t.text :payload
26
+ t.integer :git_push_id
27
+ t.timestamps
28
+ end
29
+
30
+ create_table(:github_concernable_git_pushes, :force => true) do |t|
31
+ t.string :github_concernable_type
32
+ t.integer :github_concernable_id
33
+ t.integer :git_push_id
34
+ t.timestamps
35
+ end
36
+ end