24
24
'rust-by-example' : '@steveklabnik @marioidival @projektir' ,
25
25
}
26
26
27
+ REPOS = {
28
+ 'miri' : 'https://github.com/solson/miri' ,
29
+ 'clippy-driver' : 'https://github.com/rust-lang/rust-clippy' ,
30
+ 'rls' : 'https://github.com/rust-lang/rls' ,
31
+ 'rustfmt' : 'https://github.com/rust-lang/rustfmt' ,
32
+ 'book' : 'https://github.com/rust-lang/book' ,
33
+ 'nomicon' : 'https://github.com/rust-lang-nursery/nomicon' ,
34
+ 'reference' : 'https://github.com/rust-lang-nursery/reference' ,
35
+ 'rust-by-example' : 'https://github.com/rust-lang/rust-by-example' ,
36
+ }
37
+
27
38
28
39
def read_current_status (current_commit , path ):
29
40
'''Reads build status of `current_commit` from content of `history/*.tsv`
@@ -35,11 +46,48 @@ def read_current_status(current_commit, path):
35
46
return json .loads (status )
36
47
return {}
37
48
49
+ def issue (
50
+ tool ,
51
+ maintainers ,
52
+ relevant_pr_number ,
53
+ relevant_pr_user ,
54
+ pr_reviewer ,
55
+ ):
56
+ # Open an issue about the toolstate failure.
57
+ gh_url = 'https://api.github.com/repos/rust-lang/rust/issues'
58
+ assignees = [x .strip () for x in maintainers .split ('@' ) if x != '' ]
59
+ assignees .append (relevant_pr_user )
60
+ response = urllib2 .urlopen (urllib2 .Request (
61
+ gh_url ,
62
+ json .dumps ({
63
+ 'body' : textwrap .dedent ('''\
64
+ Hello, this is your friendly neighborhood mergebot.
65
+ After merging PR {}, I observed that the tool {} no longer builds.
66
+ A follow-up PR to the repository {} is needed to fix the fallout.
67
+
68
+ cc @{}, do you think you would have time to do the follow-up work?
69
+ If so, that would be great!
70
+
71
+ cc @{}, the PR reviewer, and @rust-lang/compiler -- nominating for prioritization.
72
+
73
+ ''' ).format (relevant_pr_number , tool , REPOS [tool ], relevant_pr_user , pr_reviewer ),
74
+ 'title' : '`{}` no longer builds after {}' .format (tool , relevant_pr_number ),
75
+ 'assignees' : assignees ,
76
+ 'labels' : ['T-compiler' , 'I-nominated' ],
77
+ }),
78
+ {
79
+ 'Authorization' : 'token ' + github_token ,
80
+ 'Content-Type' : 'application/json' ,
81
+ }
82
+ ))
83
+ response .read ()
38
84
39
85
def update_latest (
40
86
current_commit ,
41
87
relevant_pr_number ,
42
88
relevant_pr_url ,
89
+ relevant_pr_user ,
90
+ pr_reviewer ,
43
91
current_datetime
44
92
):
45
93
'''Updates `_data/latest.json` to match build result of the given commit.
@@ -64,19 +112,41 @@ def update_latest(
64
112
for status in latest :
65
113
tool = status ['tool' ]
66
114
changed = False
115
+ build_failed = False
67
116
68
117
for os , s in current_status .items ():
69
118
old = status [os ]
70
119
new = s .get (tool , old )
71
120
status [os ] = new
72
121
if new > old :
122
+ # things got fixed or at least the status quo improved
73
123
changed = True
74
124
message += '🎉 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n ' \
75
125
.format (tool , os , old , new , MAINTAINERS .get (tool ))
76
126
elif new < old :
127
+ # tests or builds are failing and were not failing before
77
128
changed = True
78
- message += '💔 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n ' \
79
- .format (tool , os , old , new , MAINTAINERS .get (tool ))
129
+ title = '💔 {} on {}: {} → {}' \
130
+ .format (tool , os , old , new )
131
+ message += '{} (cc {}, @rust-lang/infra).\n ' \
132
+ .format (title , MAINTAINERS .get (tool ))
133
+ # only create issues for build failures. Other failures can be spurious
134
+ if new == 'build-fail' :
135
+ build_failed = True
136
+
137
+ if build_failed :
138
+ try :
139
+ issue (
140
+ tool , MAINTAINERS .get (tool ),
141
+ relevant_pr_number , relevant_pr_user , pr_reviewer ,
142
+ )
143
+ except IOError as (errno , strerror ):
144
+ # network errors will simply end up not creating an issue, but that's better
145
+ # than failing the entire build job
146
+ print "I/O error({0}): {1}" .format (errno , strerror )
147
+ except :
148
+ print "Unexpected error:" , sys .exc_info ()[0 ]
149
+ raise
80
150
81
151
if changed :
82
152
status ['commit' ] = current_commit
@@ -99,20 +169,30 @@ def update_latest(
99
169
save_message_to_path = sys .argv [3 ]
100
170
github_token = sys .argv [4 ]
101
171
102
- relevant_pr_match = re .search ('#([0-9]+)' , cur_commit_msg )
172
+ # assume that PR authors are also owners of the repo where the branch lives
173
+ relevant_pr_match = re .search (
174
+ 'Auto merge of #([0-9]+) - ([^:]+):[^,]+ r=([^\s]+)' ,
175
+ cur_commit_msg ,
176
+ )
103
177
if relevant_pr_match :
104
178
number = relevant_pr_match .group (1 )
179
+ relevant_pr_user = relevant_pr_match .group (2 )
105
180
relevant_pr_number = 'rust-lang/rust#' + number
106
181
relevant_pr_url = 'https://github.com/rust-lang/rust/pull/' + number
182
+ pr_reviewer = relevant_pr_match .group (3 )
107
183
else :
108
184
number = '-1'
185
+ relevant_pr_user = '<unknown user>'
109
186
relevant_pr_number = '<unknown PR>'
110
187
relevant_pr_url = '<unknown>'
188
+ pr_reviewer = '<unknown reviewer>'
111
189
112
190
message = update_latest (
113
191
cur_commit ,
114
192
relevant_pr_number ,
115
193
relevant_pr_url ,
194
+ relevant_pr_user ,
195
+ pr_reviewer ,
116
196
cur_datetime
117
197
)
118
198
if not message :
0 commit comments