/
postreceive_controller.rb
175 lines (151 loc) · 5.3 KB
/
postreceive_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
class PostreceiveController < ApplicationController
require 'jira4r/jira_tool.rb'
require 'time'
require 'yaml'
require 'pp'
# # Examples of what you may want to do with jira_tool
# # and how you may do it inside this controller
# # when we say issue_key, we mean "MVPONE-1017" or something similar
# # when we say project_key, we mean "MVPONE" or something similar
#
# # Get details about the issue:
# pp jira.getIssue issue_key
#
# # Get actions you can perform on that issue (i.e. resolve issue):
# pp jira.getAvailableActions issue_key
#
# # Get comments about that issue:
# pp jira.getComments issue_key
#
# # Get information about a given project:
# pp jira.getProjectByKey project_key
#
# # the function jira_projects lets you know what projects are available
# # in this JIRA instance:
# pp jira_projects
def new
# The following is an example payload that github will actually post
# on to a url attached to a post-receive hook
@payload = {
:pusher => {
:name => "pariser",
:email => "pariser@gmail.com"
},
:repository => {
:name => "git_post_receive",
:size => 236,
:has_wiki => true,
:created_at => "2012/01/06 09:37:50 -0800",
:watchers => 1,
:private => false,
:url => "https://github.com/pariser/git_post_receive",
:language => "Ruby",
:fork => false,
:pushed_at => "2012/01/06 18:14:25 -0800",
:open_issues => 0,
:has_downloads => true,
:homepage => "",
:has_issues => true,
:forks => 1,
:description => "Mucking around with post-commit hooks in Git, in part to integrate with JIRA",
:owner => {
:name => "pariser",
:email => "pariser@gmail.com"
}
},
:forced => false,
:after => "9555a2b9d3e86dddec828c1ba9fb56c8510bc581",
:deleted => false,
:ref => "refs/heads/master",
:commits =>
[
{
:modified => [],
:added => ["file"],
:timestamp => "2012-01-06T18:13:56-08:00",
:removed => [],
:author => {
:name => "Andrew Pariser",
:username => "pariser",
:email => "pariser@gmail.com"
},
:url => "https://github.com/pariser/git_post_receive/commit/9555a2b9d3e86dddec828c1ba9fb56c8510bc581",
:id => "9555a2b9d3e86dddec828c1ba9fb56c8510bc581",
:distinct => true,
:message => "This commit fixes MVPONE-1017\n\nIt also starts work on MVPONE-1018"
}
],
:compare => "https://github.com/pariser/git_post_receive/compare/82ec878...9555a2b",
:before => "82ec8783077c6b5827b4b8468b6ede00f14ec098",
:created => false
}
end
def create
@payload = ActiveSupport::JSON.decode params[:payload]
@commented_issues = Set.new
@resolved_issues = Set.new
# Simple lookup for whether to resolve an issue
project_keys = jira_projects.map {|p| p.key}
r = Regexp.new('(fixe?[sd]?|resolve[sd]?)? (%s)-([0-9]+)' % [project_keys.join('|')], Regexp::IGNORECASE)
@payload["commits"].each do |commit|
begin
time = Time.parse commit["timestamp"]
rescue
time = Time.now
end
rc = Jira4R::V2::RemoteComment.new
rc.body = "Found related commit [%s] by %s (%s) at %s\n\n%s\n\n<Message auto-added by pariser's git post-receive hook magic>" \
% [ commit["url"], commit["author"]["name"], commit["author"]["email"], time.to_s, commit["message"] ]
commit["message"].scan(r) do |match|
should_resolve_issue = !match[0].nil?
issue_key = match[1] + "-" + match[2]
# Comment on this issue
begin
jira.addComment(issue_key, rc)
rescue
Rails.logger.error("Failed to add comment to issue %s" % [issue_key])
else
Rails.logger.debug("Successfully added comment to issue %s" % [issue_key])
end
# Resolve this issue, as appropriate
if should_resolve_issue
begin
available_actions = jira.getAvailableActions issue_key
resolve_action = available_actions.find {|s| s.name == 'Resolve Issue'}
if !resolve_action.nil?
jira.progressWorkflowAction(issue_key, resolve_action.id.to_s, [])
else
Rails.logger.debug("Not allowed to resolve issue %s. Allowable actions: %s" % [issue_key, (available_actions.map {|s| s.name}).to_s])
end
rescue StandardError => e
Rails.logger.error("Failed to resolve issue %s : %s" % [issue_key, e.to_s])
else
Rails.logger.debug("Successfully resolved issue %s" % [issue_key])
end
end
end
end
end
protected
def jira
# Connect to JIRA
# Load configuration
unless @jira_config
@jira_config = YAML.load(File.new "config/jira.yml", 'r')
end
# Connect to JIRA
unless @jira_connection
@jira_connection = Jira4R::JiraTool.new(2, @jira_config['address'])
@jira_connection.login(@jira_config['username'], @jira_config['password'])
end
# Return the connection
@jira_connection
end
def jira_projects
# Load the list of JIRA projects
unless @jira_projects
@jira_projects = jira.getProjectsNoSchemes()
end
@jira_projects
end
end