147 lines
4.4 KiB
Ruby
147 lines
4.4 KiB
Ruby
class Hook < ActiveRecord::Base
|
|
include Modules::Models::WebHooks
|
|
include Modules::Models::UrlHelper
|
|
include Rails.application.routes.url_helpers
|
|
belongs_to :project
|
|
|
|
before_validation :cleanup_data
|
|
validates :project_id, :data, :presence => true
|
|
validates :name, :presence => true, :inclusion => {:in => NAMES}
|
|
|
|
attr_accessible :data, :name
|
|
|
|
serialize :data, Hash
|
|
|
|
scope :for_name, lambda {|name| where(:name => name) if name.present? }
|
|
|
|
def receive_issues(issue, action)
|
|
pull = issue.pull_request
|
|
return if action.to_sym == :create && pull
|
|
default_url_options
|
|
|
|
payload = meta(issue.project, issue.user)
|
|
base_params = {
|
|
:number => issue.serial_id,
|
|
:state => issue.status,
|
|
:title => issue.title,
|
|
:body => issue.body,
|
|
:user => {:login => issue.user.uname},
|
|
}
|
|
if pull
|
|
total_commits = pull.repo.commits_between(pull.to_commit, pull.from_commit).count
|
|
repo_owner = pull.to_project.owner.uname
|
|
post 'pull_request', {
|
|
:payload => payload.merge(
|
|
:action => (pull.ready? ? 'opened' : pull.status),
|
|
:pull_request => base_params.merge(
|
|
:commits => total_commits,
|
|
:head => {:label => "#{pull.from_project.owner.uname}:#{pull.from_ref}"},
|
|
:base => {:label => "#{repo_owner}:#{pull.to_ref}"},
|
|
:html_url => project_pull_request_url(pull.to_project, pull)
|
|
)
|
|
).to_json
|
|
}
|
|
else
|
|
post 'issues', {
|
|
:payload => payload.merge(
|
|
:action => (issue.closed? ? 'closed' : 'opened'),
|
|
:issue => base_params.merge(
|
|
:html_url => project_issue_url(issue.project, issue)
|
|
)
|
|
).to_json
|
|
}
|
|
end
|
|
end
|
|
later :receive_issues, :queue => :notification
|
|
|
|
def receive_push(git_hook)
|
|
default_url_options
|
|
project = Project.find(git_hook['project']['project']['id'])
|
|
user = User.find(git_hook['user']['user']['id'])
|
|
payload = meta(project, user)
|
|
oldrev, newrev, change_type = git_hook.values_at *%w(oldrev newrev change_type)
|
|
|
|
commits = []
|
|
payload.merge!(:before => oldrev, :after => newrev)
|
|
if %w(delete create).exclude? change_type
|
|
payload.merge!(
|
|
:compare => diff_url(project, "#{oldrev[0..6]}...#{newrev[0..6]}")
|
|
)
|
|
if oldrev == newrev
|
|
commits = [project.repo.commit(newrev)]
|
|
modified = commits.first.stats.files.map{|f| f[0]}
|
|
else
|
|
commits = project.repo.commits_between(oldrev, newrev)
|
|
end
|
|
end
|
|
|
|
post 'push', {
|
|
:payload => payload.merge(
|
|
:ref => git_hook['refname'],
|
|
:commits => commits.map{ |commit|
|
|
files = changed_files commit
|
|
{
|
|
:id => commit.id,
|
|
:message => commit.message,
|
|
:distinct => true,
|
|
:url => commit_url(project, commit),
|
|
:removed => files[:removed],
|
|
:added => files[:added],
|
|
:modified => files[:modified],
|
|
:timestamp => commit.committed_date,
|
|
:author => {:name => commit.committer.name, :email => commit.committer.email}
|
|
}
|
|
}
|
|
).to_json
|
|
}
|
|
end
|
|
later :receive_push, :queue => :notification
|
|
|
|
protected
|
|
|
|
def post(action, params)
|
|
github_services = APP_CONFIG['github_services']
|
|
uri = URI "http://#{github_services['ip']}:#{github_services['port']}/#{name}/#{action}"
|
|
Net::HTTP.post_form uri, params.merge(:data => data.to_json)
|
|
rescue # Dont care about it
|
|
end
|
|
|
|
def meta(project, user)
|
|
{
|
|
:repository => {
|
|
:name => project.name,
|
|
:url => project_url(project),
|
|
:owner => { :login => project.owner.uname }
|
|
},
|
|
:sender => {:login => user.uname},
|
|
:pusher => {:name => user.uname}
|
|
}
|
|
end
|
|
|
|
def cleanup_data
|
|
if self.name.present? && fields = SCHEMA[self.name.to_sym]
|
|
new_data = {}
|
|
fields.each{ |type, field| new_data[field] = self.data[field] }
|
|
self.data = new_data
|
|
end
|
|
end
|
|
|
|
def changed_files(commit)
|
|
removed, added, modified = [], [], []
|
|
commit.show.each do |diff|
|
|
if diff.renamed_file
|
|
added << diff.b_path
|
|
removed << diff.a_path
|
|
elsif diff.new_file
|
|
added << diff.b_path
|
|
elsif diff.deleted_file
|
|
removed << diff.a_path
|
|
else
|
|
modified << diff.a_path
|
|
end
|
|
end
|
|
{:removed => removed, :added => added, :modified => modified}
|
|
end
|
|
|
|
end
|