2
2
require 'json'
3
3
require 'net/http'
4
4
require 'yaml'
5
+ require 'logger'
6
+
7
+ $log = Logger . new ( STDOUT )
8
+ $log. level = Logger ::WARN
5
9
6
10
class ForwardMerge
7
11
attr_reader :issue , :milestone , :message , :line
@@ -14,48 +18,71 @@ class ForwardMerge
14
18
end
15
19
16
20
def find_forward_merge ( message_file )
17
- rev = `git rev-parse -q --verify MERGE_HEAD`
21
+ $log. debug "Searching for for forward merge"
22
+ rev = `git rev-parse -q --verify MERGE_HEAD` . strip
23
+ $log. debug "Found #{ rev } from git rev-parse"
18
24
return nil unless rev
19
25
message = File . read ( message_file )
20
26
message . each_line do |line |
21
- match = /^(?:Fixes|Closes) gh-(\d +) in ([\d \. ]+(?:(?:M|RC)\d )?)$/ . match ( line )
27
+ $log. debug "Checking #{ line } for message"
28
+ match = /^(?:Fixes|Closes) gh-(\d +) in (\d \. \d \. [\d x](?:[\. \- ](?:M|RC)\d )?)$/ . match ( line )
22
29
if match then
23
30
issue = match [ 1 ]
24
31
milestone = match [ 2 ]
32
+ $log. debug "Matched reference to issue #{ issue } in milestone #{ milestone } "
25
33
return ForwardMerge . new ( issue , milestone , message , line )
26
34
end
27
35
end
36
+ $log. debug "No match in merge message"
28
37
return nil
29
38
end
30
39
31
- def find_milestone ( username , password , repository , title )
32
- uri = URI ( "https://api.github.com/repos/#{ repository } /milestones" )
40
+ def get_issue ( username , password , repository , number )
41
+ $log. debug "Getting issue #{ number } from GitHub repository #{ repository } "
42
+ uri = URI ( "https://api.github.com/repos/#{ repository } /issues/#{ number } " )
33
43
http = Net ::HTTP . new ( uri . host , uri . port )
34
44
http . use_ssl = true
35
45
request = Net ::HTTP ::Get . new ( uri . path )
36
46
request . basic_auth ( username , password )
37
47
response = http . request ( request )
38
- milestones = JSON . parse ( response . body )
39
- milestones . each do |milestone |
40
- return milestone [ 'number' ] if milestone [ 'title' ] == title
41
- end
42
- puts "Milestone #{ title } not found"
48
+ $log. debug "Get HTTP response #{ response . code } "
49
+ return JSON . parse ( response . body ) unless response . code != '200'
50
+ puts "Failed to retrieve issue #{ number } : #{ response . message } "
43
51
exit 1
44
52
end
45
53
46
- def get_issue ( username , password , repository , number )
47
- uri = URI ( "https://api.github.com/repos/#{ repository } /issues/#{ number } " )
54
+ def find_milestone ( username , password , repository , title )
55
+ $log. debug "Finding milestone #{ title } from GitHub repository #{ repository } "
56
+ uri = URI ( "https://api.github.com/repos/#{ repository } /milestones" )
48
57
http = Net ::HTTP . new ( uri . host , uri . port )
49
58
http . use_ssl = true
50
59
request = Net ::HTTP ::Get . new ( uri . path )
51
60
request . basic_auth ( username , password )
52
61
response = http . request ( request )
53
- return JSON . parse ( response . body ) unless response . code != '200'
54
- puts "Failed to retrieve issue #{ number } : #{ response . message } "
62
+ milestones = JSON . parse ( response . body )
63
+ if title . end_with? ( ".x" )
64
+ prefix = title . delete_suffix ( '.x' )
65
+ $log. debug "Finding latest milestone from candidates starting with #{ prefix } "
66
+ titles = milestones . map { |milestone | milestone [ 'title' ] }
67
+ titles = titles . select { |title | title . start_with? ( prefix ) unless title . end_with? ( '.x' ) }
68
+ titles . sort_by { |v | Gem ::Version . new ( v ) }
69
+ if ( titles . empty? )
70
+ puts "Cannot find latest for milestone #{ title } "
71
+ exit 1
72
+ end
73
+ title = titles . last
74
+ $log. debug "Found latest milestone #{ title } "
75
+ end
76
+ milestones . each do |milestone |
77
+ $log. debug "Considering #{ milestone [ 'title' ] } "
78
+ return milestone [ 'number' ] if milestone [ 'title' ] == title
79
+ end
80
+ puts "Milestone #{ title } not found"
55
81
exit 1
56
82
end
57
83
58
84
def create_issue ( username , password , repository , original , title , labels , milestone , milestone_name , dry_run )
85
+ $log. debug "Finding forward-merge issue in GitHub repository #{ repository } for '#{ title } '"
59
86
uri = URI ( "https://api.github.com/repos/#{ repository } /issues" )
60
87
http = Net ::HTTP . new ( uri . host , uri . port )
61
88
http . use_ssl = true
@@ -73,23 +100,32 @@ def create_issue(username, password, repository, original, title, labels, milest
73
100
return "dry-run"
74
101
end
75
102
response = JSON . parse ( http . request ( request ) . body )
103
+ $log. debug "Created new issue #{ response [ 'number' ] } "
76
104
return response [ 'number' ]
77
105
end
78
106
107
+ $log. debug "Running forward-merge hook script"
79
108
message_file = ARGV [ 0 ]
109
+
80
110
forward_merge = find_forward_merge ( message_file )
81
111
exit 0 unless forward_merge
112
+
113
+ $log. debug "Loading config from ~/.spring-boot/forward_merge.yml"
82
114
config = YAML . load_file ( File . join ( Dir . home , '.spring-boot' , 'forward-merge.yml' ) )
83
115
username = config [ 'github' ] [ 'credentials' ] [ 'username' ]
84
116
password = config [ 'github' ] [ 'credentials' ] [ 'password' ]
85
117
dry_run = config [ 'dry_run' ]
86
118
repository = 'spring-projects/spring-boot'
119
+
87
120
existing_issue = get_issue ( username , password , repository , forward_merge . issue )
88
121
title = existing_issue [ 'title' ]
89
122
labels = existing_issue [ 'labels' ] . map { |label | label [ 'name' ] }
90
123
labels << "status: forward-port"
124
+ $log. debug "Processing issue '#{ title } '"
125
+
91
126
milestone = find_milestone ( username , password , repository , forward_merge . milestone )
92
127
new_issue_number = create_issue ( username , password , repository , forward_merge . issue , title , labels , milestone , forward_merge . milestone , dry_run )
128
+
93
129
puts "Created gh-#{ new_issue_number } for forward port of gh-#{ forward_merge . issue } into #{ forward_merge . milestone } "
94
130
rewritten_message = forward_merge . message . sub ( forward_merge . line , "Closes gh-#{ new_issue_number } \n " )
95
131
File . write ( message_file , rewritten_message )
0 commit comments