diff options
-rwxr-xr-x | close-all-github-pull-requests.sh | 11 | ||||
-rwxr-xr-x | close-github-pull-requests | 156 | ||||
-rw-r--r-- | close-github-pull-requests.service | 7 | ||||
-rw-r--r-- | close-github-pull-requests.timer | 7 | ||||
-rwxr-xr-x | enable-github-mirror.sh | 2 |
5 files changed, 183 insertions, 0 deletions
diff --git a/close-all-github-pull-requests.sh b/close-all-github-pull-requests.sh new file mode 100755 index 0000000..904964c --- /dev/null +++ b/close-all-github-pull-requests.sh @@ -0,0 +1,11 @@ +#!/bin/sh +cd /git +find -path './users' -prune -o -name config -print | while read repo_config; do + pushd $(dirname $repo_config) + + if [ -e git-daemon-export-ok -a -e HEAD -a -e $(awk '{ print $2 }' HEAD) ]; then + /git/bin/close-github-pull-requests + fi + + popd +done diff --git a/close-github-pull-requests b/close-github-pull-requests new file mode 100755 index 0000000..6362446 --- /dev/null +++ b/close-github-pull-requests @@ -0,0 +1,156 @@ +#!/usr/bin/python2 +# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 +""" +Copyright (c) 2013 Alberto Ruiz <aruiz@gnome.org> +All rights reserved. + +Hacked up to work for freedesktop.org by Ray Strode <rstrode@redhat.com> + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Pioneers of the Inevitable, Songbird, nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +""" +import codecs +import os +import sys +import requests +import subprocess +import shlex +import ConfigParser +import xml.etree.ElementTree as et +import smtplib +from email.mime.text import MIMEText +import tempfile +import json + +ORGANIZATION="freedesktop" +name_maps = {"gtk+": "gtk", + "libxml++": "libxmlmm"} + +class GitHub: + def __init__ (self): + config = ConfigParser.ConfigParser() + try: + config.read(os.path.expanduser('/etc/github-mirror/mirror.cfg')) + self.user = config.get('Github', 'user') + self.pw = config.get('Github', 'password') + except ConfigParser.NoSectionError: + raise Exception ("~/.gitmirrorrc non existant or missing [Github] section with user and password keys") + except ConfigParser.NoOptionError: + raise Exception ("~/.gitmirrorrc misses user or/and password keys in the [Github] section") + + def check_if_repo_exists (self, name): + rq = requests.get('https://api.github.com/repos/'+ORGANIZATION+'/'+name, + auth=(self.user, self.pw)) + if rq.status_code != 200: + return False + + return True + + def close_pull_request (self, name, pull_request): + payload = json.dumps({ + 'body': ORGANIZATION+' doesn\'t allow pull requests on its mirrors. This is an automated message.', + }) + rq = requests.post(pull_request['comments_url'], + auth=(self.user, self.pw), + data=payload) + if rq.status_code != 201: + raise Exception("There was an error attempting to comment on the repo %s pull request %s in github:\n\nStatus: %d\nText:\n%s" % (name, pull_request['url'], rq.status_code, rq.text)) + + payload = json.dumps({ + 'state': 'closed' + }) + rq = requests.post(pull_request['url'], + auth=(self.user, self.pw), + data=payload) + if rq.status_code != 200: + raise Exception("There was an error attempting to the close repo %s pull request %s in github:\n\nStatus: %d\nText:\n%s" % (name, pull_request['url'], rq.status_code, rq.text)) + + def close_pull_requests (self, name): + response = requests.get('https://api.github.com/repos/'+ORGANIZATION+'/'+name+'/pulls', + auth=(self.user, self.pw)) + + if response.status_code != 200: + raise Exception("There was an error attempting to close open pull requests for repo %s in github:\n\n Status %d\nText: \n%s" % (name, response.status_code, response.text)) + + pull_requests = json.loads(response.content) + + for pull_request in pull_requests: + if pull_request['state'] != 'open': + continue + + self.close_pull_request (name, pull_request) + + def normalize_name (self, name): + if name in name_maps.keys(): + return name_maps[name] + + if "+" in name: + raise Exception("%s has a '+' character in it which is unsupported by Github.\nYou have to add it to the exception maps in the post-update hook." % name) + + return name + +def get_repo_name (): + repo_namespace = os.getcwd ().split("/")[-2] + + if repo_namespace == "git": + repo_namespace = None + + repo_parts = "".join(os.getcwd ().split("/git/")[1:]).split('/') + + if repo_namespace and repo_parts[1].startswith(repo_namespace + '-'): + repo_parts[1] = repo_parts[1].replace(repo_namespace + '-', '', 1) + elif repo_namespace and repo_parts[1] == repo_namespace + ".git": + repo_parts.remove(repo_parts[1]) + elif repo_namespace and repo_parts[1] == repo_namespace: + repo_parts.remove(repo_parts[1]) + + if repo_parts[-1] == ".git": + repo_parts = repo_parts[:-1] + + repo_name = "-".join(repo_parts) + + if repo_name.endswith(".git"): + repo_name = repo_name[0:-4] + + return repo_name + +def main (): + gh = GitHub () + repo_name = get_repo_name () + github_name = gh.normalize_name (repo_name) + if gh.check_if_repo_exists(repo_name): + gh.close_pull_requests (repo_name) + +if __name__ == "__main__": + try: + main () + except Exception as e: + msg = MIMEText(str(e)) + msg['Subject'] = "[GITHUB HOOK] ERROR trying to close pull requests for %s" % os.getcwd () + msg['From'] = "noreply@freedesktop.org" + msg['To'] = "halfline+fdo-github-mirror@freedesktop.org" + msg['X-FDO-SERVICE'] = "github-mirror" + server = smtplib.SMTP("localhost") + server.sendmail (msg['From'], msg['To'], msg.as_string()) + server.quit () diff --git a/close-github-pull-requests.service b/close-github-pull-requests.service new file mode 100644 index 0000000..3db7870 --- /dev/null +++ b/close-github-pull-requests.service @@ -0,0 +1,7 @@ +[Unit] +Description=close github mirror pull requests + +[Service] +User=github-mirror +ExecStart=/git/bin/close-all-github-pull-requests.sh +Type=oneshot diff --git a/close-github-pull-requests.timer b/close-github-pull-requests.timer new file mode 100644 index 0000000..6fc87c4 --- /dev/null +++ b/close-github-pull-requests.timer @@ -0,0 +1,7 @@ +[Unit] +Description=Close all pull requests from github mirror every hour + +[Timer] +OnBootSec=1h +OnUnitInactiveSec=1h +Unit=close-github-pull-requests.service diff --git a/enable-github-mirror.sh b/enable-github-mirror.sh index a18d0eb..580542c 100755 --- a/enable-github-mirror.sh +++ b/enable-github-mirror.sh @@ -4,4 +4,6 @@ mkdir -p /run/github-mirror cd /etc/systemd/system ln -s /git/bin/github-mirror.socket ln -s /git/bin/github-mirror.service +ln -s /git/bin/close-github-pull-requests.service +ln -s /git/bin/close-github-pull-requests.timer systemctl daemon-reload |