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