Skip to content

Commit 39817c1

Browse files
committed
Auto merge of #56951 - oli-obk:auto_toolstate_issue, r=kennytm
Automatically open an issue when a tool breaks cc @nikomatsakis fixes rust-lang-nursery/rust-toolstate#6 documentation about issue opening via the github api: https://developer.github.com/v3/issues/#create-an-issue
2 parents c84e797 + 6ed4401 commit 39817c1

File tree

1 file changed

+83
-3
lines changed

1 file changed

+83
-3
lines changed

src/tools/publish_toolstate.py

+83-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,17 @@
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

2839
def 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

3985
def 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

Comments
 (0)