Skip to content

Commit 58c9412

Browse files
committed
Add forward merge issue creation hook
Closes gh-16458
1 parent c7746fb commit 58c9412

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed

git/hooks/forward-merge

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#!/usr/bin/ruby
2+
require 'json'
3+
require 'net/http'
4+
require 'yaml'
5+
6+
class ForwardMerge
7+
attr_reader :issue, :milestone, :message, :line
8+
def initialize(issue, milestone, message, line)
9+
@issue = issue
10+
@milestone = milestone
11+
@message = message
12+
@line = line
13+
end
14+
end
15+
16+
def find_forward_merge(message_file)
17+
rev=`git rev-parse -q --verify MERGE_HEAD`
18+
return nil unless rev
19+
message = File.read(message_file)
20+
message.each_line do |line|
21+
match = /^(?:Fixes|Closes) gh-(\d+) in ([\d\.]+(?:(?:M|RC)\d)?)$/.match(line)
22+
if match then
23+
issue = match[1]
24+
milestone = match[2]
25+
return ForwardMerge.new(issue, milestone, message, line)
26+
end
27+
end
28+
return nil
29+
end
30+
31+
def find_milestone(repository, title)
32+
milestones = JSON.parse(Net::HTTP.get(URI("https://api.github.com/repos/#{repository}/milestones")))
33+
milestones.each do |milestone|
34+
return milestone['number'] if milestone['title'] == title
35+
end
36+
puts "Milestone #{title} not found"
37+
exit 1
38+
end
39+
40+
def get_issue(repository, number)
41+
uri = URI("https://api.github.com/repos/#{repository}/issues/#{number}")
42+
http = Net::HTTP.new(uri.host, uri.port)
43+
http.use_ssl=true
44+
request = Net::HTTP::Get.new(uri.path)
45+
response = http.request(request)
46+
return JSON.parse(response.body) unless response.code != '200'
47+
puts "Failed to retrieve issue #{number}: #{response.message}"
48+
exit 1
49+
end
50+
51+
def create_issue(username, password, repository, original, title, labels, milestone, dry_run)
52+
uri = URI("https://api.github.com/repos/#{repository}/issues")
53+
http = Net::HTTP.new(uri.host, uri.port)
54+
http.use_ssl=true
55+
request = Net::HTTP::Post.new(uri.path, 'Content-Type' => 'application/json')
56+
request.basic_auth(username, password)
57+
request.body = {
58+
title: title,
59+
labels: labels,
60+
milestone: milestone.to_i,
61+
body: "See original issue ##{original}."
62+
}.to_json
63+
if dry_run then
64+
puts "Dry run"
65+
puts "POSTing to #{uri} with body #{request.body}"
66+
return "dry-run"
67+
end
68+
response = JSON.parse(http.request(request).body)
69+
return response['number']
70+
end
71+
72+
message_file=ARGV[0]
73+
forward_merge = find_forward_merge(message_file)
74+
exit 0 unless forward_merge
75+
repository = 'spring-projects/spring-boot'
76+
existing_issue = get_issue(repository, forward_merge.issue)
77+
title = existing_issue['title']
78+
labels = existing_issue['labels'].map { |label| label['name'] }
79+
milestone = find_milestone(repository, forward_merge.milestone)
80+
config = YAML.load_file(File.join(Dir.home, '.spring-boot', 'forward-merge.yml'))
81+
username = config['github']['credentials']['username']
82+
password = config['github']['credentials']['password']
83+
dry_run = config['dry_run']
84+
new_issue_number = create_issue(username, password, repository, forward_merge.issue, title, labels, milestone, dry_run)
85+
rewritten_message = forward_merge.message.sub(forward_merge.line, "Closes gh-#{new_issue_number}")
86+
File.write(message_file, rewritten_message)

0 commit comments

Comments
 (0)