2424 'rust-by-example' : '@steveklabnik @marioidival @projektir' ,
2525}
2626
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+
2738
2839def read_current_status (current_commit , path ):
2940 '''Reads build status of `current_commit` from content of `history/*.tsv`
@@ -35,11 +46,48 @@ def read_current_status(current_commit, path):
3546 return json .loads (status )
3647 return {}
3748
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 ()
3884
3985def update_latest (
4086 current_commit ,
4187 relevant_pr_number ,
4288 relevant_pr_url ,
89+ relevant_pr_user ,
90+ pr_reviewer ,
4391 current_datetime
4492):
4593 '''Updates `_data/latest.json` to match build result of the given commit.
@@ -64,19 +112,41 @@ def update_latest(
64112 for status in latest :
65113 tool = status ['tool' ]
66114 changed = False
115+ build_failed = False
67116
68117 for os , s in current_status .items ():
69118 old = status [os ]
70119 new = s .get (tool , old )
71120 status [os ] = new
72121 if new > old :
122+ # things got fixed or at least the status quo improved
73123 changed = True
74124 message += '🎉 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n ' \
75125 .format (tool , os , old , new , MAINTAINERS .get (tool ))
76126 elif new < old :
127+ # tests or builds are failing and were not failing before
77128 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
80150
81151 if changed :
82152 status ['commit' ] = current_commit
@@ -99,20 +169,30 @@ def update_latest(
99169 save_message_to_path = sys .argv [3 ]
100170 github_token = sys .argv [4 ]
101171
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+ )
103177 if relevant_pr_match :
104178 number = relevant_pr_match .group (1 )
179+ relevant_pr_user = relevant_pr_match .group (2 )
105180 relevant_pr_number = 'rust-lang/rust#' + number
106181 relevant_pr_url = 'https://github.com/rust-lang/rust/pull/' + number
182+ pr_reviewer = relevant_pr_match .group (3 )
107183 else :
108184 number = '-1'
185+ relevant_pr_user = '<unknown user>'
109186 relevant_pr_number = '<unknown PR>'
110187 relevant_pr_url = '<unknown>'
188+ pr_reviewer = '<unknown reviewer>'
111189
112190 message = update_latest (
113191 cur_commit ,
114192 relevant_pr_number ,
115193 relevant_pr_url ,
194+ relevant_pr_user ,
195+ pr_reviewer ,
116196 cur_datetime
117197 )
118198 if not message :
0 commit comments