diff options
| author | bors <bors@rust-lang.org> | 2019-02-13 13:08:30 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2019-02-13 13:08:30 +0000 |
| commit | e54494727855cd14229f5d456591ed2a2f027c46 (patch) | |
| tree | e86e6492fcbd4a5b6201cd1e2c486bee5ad77947 | |
| parent | c005afcb1ea399ac60f20c784c0833757bb84bc5 (diff) | |
| parent | 6ed4401609817e18a0ff781529e35b2a209ff0da (diff) | |
| download | rust-e54494727855cd14229f5d456591ed2a2f027c46.tar.gz rust-e54494727855cd14229f5d456591ed2a2f027c46.zip | |
Auto merge of #56951 - oli-obk:auto_toolstate_issue, r=kennytm
Automatically open an issue when a tool breaks cc @nikomatsakis fixes https://github.com/rust-lang-nursery/rust-toolstate/issues/6 documentation about issue opening via the github api: https://developer.github.com/v3/issues/#create-an-issue
| -rwxr-xr-x | src/tools/publish_toolstate.py | 86 |
1 files changed, 83 insertions, 3 deletions
diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index 323f8118168..ed697fc5425 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -24,6 +24,17 @@ MAINTAINERS = { 'rust-by-example': '@steveklabnik @marioidival @projektir', } +REPOS = { + 'miri': 'https://github.com/solson/miri', + 'clippy-driver': 'https://github.com/rust-lang/rust-clippy', + 'rls': 'https://github.com/rust-lang/rls', + 'rustfmt': 'https://github.com/rust-lang/rustfmt', + 'book': 'https://github.com/rust-lang/book', + 'nomicon': 'https://github.com/rust-lang-nursery/nomicon', + 'reference': 'https://github.com/rust-lang-nursery/reference', + 'rust-by-example': 'https://github.com/rust-lang/rust-by-example', +} + def read_current_status(current_commit, path): '''Reads build status of `current_commit` from content of `history/*.tsv` @@ -35,11 +46,48 @@ def read_current_status(current_commit, path): return json.loads(status) return {} +def issue( + tool, + maintainers, + relevant_pr_number, + relevant_pr_user, + pr_reviewer, +): + # Open an issue about the toolstate failure. + gh_url = 'https://api.github.com/repos/rust-lang/rust/issues' + assignees = [x.strip() for x in maintainers.split('@') if x != ''] + assignees.append(relevant_pr_user) + response = urllib2.urlopen(urllib2.Request( + gh_url, + json.dumps({ + 'body': textwrap.dedent('''\ + Hello, this is your friendly neighborhood mergebot. + After merging PR {}, I observed that the tool {} no longer builds. + A follow-up PR to the repository {} is needed to fix the fallout. + + cc @{}, do you think you would have time to do the follow-up work? + If so, that would be great! + + cc @{}, the PR reviewer, and @rust-lang/compiler -- nominating for prioritization. + + ''').format(relevant_pr_number, tool, REPOS[tool], relevant_pr_user, pr_reviewer), + 'title': '`{}` no longer builds after {}'.format(tool, relevant_pr_number), + 'assignees': assignees, + 'labels': ['T-compiler', 'I-nominated'], + }), + { + 'Authorization': 'token ' + github_token, + 'Content-Type': 'application/json', + } + )) + response.read() def update_latest( current_commit, relevant_pr_number, relevant_pr_url, + relevant_pr_user, + pr_reviewer, current_datetime ): '''Updates `_data/latest.json` to match build result of the given commit. @@ -64,19 +112,41 @@ def update_latest( for status in latest: tool = status['tool'] changed = False + build_failed = False for os, s in current_status.items(): old = status[os] new = s.get(tool, old) status[os] = new if new > old: + # things got fixed or at least the status quo improved changed = True message += '🎉 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n' \ .format(tool, os, old, new, MAINTAINERS.get(tool)) elif new < old: + # tests or builds are failing and were not failing before changed = True - message += '💔 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n' \ - .format(tool, os, old, new, MAINTAINERS.get(tool)) + title = '💔 {} on {}: {} → {}' \ + .format(tool, os, old, new) + message += '{} (cc {}, @rust-lang/infra).\n' \ + .format(title, MAINTAINERS.get(tool)) + # only create issues for build failures. Other failures can be spurious + if new == 'build-fail': + build_failed = True + + if build_failed: + try: + issue( + tool, MAINTAINERS.get(tool), + relevant_pr_number, relevant_pr_user, pr_reviewer, + ) + except IOError as (errno, strerror): + # network errors will simply end up not creating an issue, but that's better + # than failing the entire build job + print "I/O error({0}): {1}".format(errno, strerror) + except: + print "Unexpected error:", sys.exc_info()[0] + raise if changed: status['commit'] = current_commit @@ -99,20 +169,30 @@ if __name__ == '__main__': save_message_to_path = sys.argv[3] github_token = sys.argv[4] - relevant_pr_match = re.search('#([0-9]+)', cur_commit_msg) + # assume that PR authors are also owners of the repo where the branch lives + relevant_pr_match = re.search( + 'Auto merge of #([0-9]+) - ([^:]+):[^,]+ r=([^\s]+)', + cur_commit_msg, + ) if relevant_pr_match: number = relevant_pr_match.group(1) + relevant_pr_user = relevant_pr_match.group(2) relevant_pr_number = 'rust-lang/rust#' + number relevant_pr_url = 'https://github.com/rust-lang/rust/pull/' + number + pr_reviewer = relevant_pr_match.group(3) else: number = '-1' + relevant_pr_user = '<unknown user>' relevant_pr_number = '<unknown PR>' relevant_pr_url = '<unknown>' + pr_reviewer = '<unknown reviewer>' message = update_latest( cur_commit, relevant_pr_number, relevant_pr_url, + relevant_pr_user, + pr_reviewer, cur_datetime ) if not message: |
