From 3179d98e121f6a0aae1ef92abb5dc6e8bcc5a5e9 Mon Sep 17 00:00:00 2001 From: Todd Gamblin Date: Sat, 3 Aug 2019 21:48:19 -0700 Subject: [PATCH] actions: add maintainers as PR reviewers for their packages (#12269) Use `spack pkg changed` and `spack maintainers` to figure out which packages changed and who their maintainers are in a PR. Add any maintainers to the PR as reviewers. --- .../add-maintainers-as-reviewers/Dockerfile | 6 ++ .../entrypoint.py | 85 +++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 .github/actions/add-maintainers-as-reviewers/Dockerfile create mode 100755 .github/actions/add-maintainers-as-reviewers/entrypoint.py diff --git a/.github/actions/add-maintainers-as-reviewers/Dockerfile b/.github/actions/add-maintainers-as-reviewers/Dockerfile new file mode 100644 index 0000000000..9370cfed83 --- /dev/null +++ b/.github/actions/add-maintainers-as-reviewers/Dockerfile @@ -0,0 +1,6 @@ +FROM python:3.7-alpine + +RUN pip install pygithub + +ADD entrypoint.py /entrypoint.py +ENTRYPOINT ["/entrypoint.py"] diff --git a/.github/actions/add-maintainers-as-reviewers/entrypoint.py b/.github/actions/add-maintainers-as-reviewers/entrypoint.py new file mode 100755 index 0000000000..53f7318f82 --- /dev/null +++ b/.github/actions/add-maintainers-as-reviewers/entrypoint.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python +# +# Copyright 2013-2019 Lawrence Livermore National Security, LLC and other +# Spack Project Developers. See the top-level COPYRIGHT file for details. +# +# SPDX-License-Identifier: (Apache-2.0 OR MIT) + +"""Maintainer review action. + +This action checks which packages have changed in a PR, and adds their +maintainers to the pull request for review. +""" + +import json +import os +import re +import subprocess + +from github import Github + + +def spack(*args): + """Run the spack executable with arguments, and return the output split. + + This does just enough to run `spack pkg` and `spack maintainers`, the + two commands used by this action. + """ + github_workspace = os.environ['GITHUB_WORKSPACE'] + spack = os.path.join(github_workspace, 'bin', 'spack') + output = subprocess.check_output([spack] + list(args)) + split = re.split(r'\s*', output.decode('utf-8').strip()) + return [s for s in split if s] + + +def main(): + # get these first so that we'll fail early + token = os.environ['GITHUB_TOKEN'] + event_path = os.environ['GITHUB_EVENT_PATH'] + + with open(event_path) as file: + data = json.load(file) + + # make sure it's a pull_request event + assert 'pull_request' in data + + # only request reviews on open, edit, or reopen + action = data['action'] + if action not in ('opened', 'edited', 'reopened'): + return + + # get data from the event payload + pr_data = data['pull_request'] + base_branch_name = pr_data['base']['ref'] + full_repo_name = pr_data['base']['repo']['full_name'] + pr_number = pr_data['number'] + requested_reviewers = pr_data['requested_reviewers'] + author = pr_data['user']['login'] + + # get a list of packages that this PR modified + changed_pkgs = spack( + 'pkg', 'changed', '--type', 'ac', '%s...' % base_branch_name) + + # get maintainers for all modified packages + maintainers = set() + for pkg in changed_pkgs: + pkg_maintainers = set(spack('maintainers', pkg)) + maintainers |= pkg_maintainers + + # remove any maintainers who are already on the PR, and the author, + # as you can't review your own PR) + maintainers -= set(requested_reviewers) + maintainers -= set([author]) + + if not maintainers: + return + + # request reviews from each maintainer + gh = Github(token) + repo = gh.get_repo(full_repo_name) + pr = repo.get_pull(pr_number) + pr.create_review_request(list(maintainers)) + + +if __name__ == "__main__": + main()