From 3179d98e121f6a0aae1ef92abb5dc6e8bcc5a5e9 Mon Sep 17 00:00:00 2001
From: Todd Gamblin <tgamblin@llnl.gov>
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()
-- 
GitLab