[27284] in Source-Commits

home help back first fref pref prev next nref lref last post

scripts commit: Add a script to control Trac via XMLRPC

daemon@ATHENA.MIT.EDU (Jonathan D Reed)
Thu Sep 19 10:52:23 2013

Date: Thu, 19 Sep 2013 10:52:13 -0400
From: Jonathan D Reed <jdreed@MIT.EDU>
Message-Id: <201309191452.r8JEqDCV019715@drugstore.mit.edu>
To: source-commits@MIT.EDU

https://github.com/mit-athena/scripts/commit/f8f0a534218fb4d037060b7ece63abba398a9b94
commit f8f0a534218fb4d037060b7ece63abba398a9b94
Author: Jonathan Reed <jdreed@mit.edu>
Date:   Fri Sep 6 14:46:54 2013 -0400

    Add a script to control Trac via XMLRPC
    
    A simple XMLRPC client that will allow common operations, such as
    marking a ticket as committed, uploaded, etc.  Designed to be called
    from VCS hooks or daupload and friends

 trac-remote.py |  101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 101 insertions(+), 0 deletions(-)

diff --git a/trac-remote.py b/trac-remote.py
new file mode 100755
index 0000000..9c8c8d9
--- /dev/null
+++ b/trac-remote.py
@@ -0,0 +1,101 @@
+#!/usr/bin/python
+
+import sys, os
+import xmlrpclib
+import logging
+from optparse import OptionParser
+
+LOGGER_NAME="trac-remote"
+DEFAULT_CREDENTIALS=os.getenv('HOME', '~') + "/.trac-credentials"
+DEFAULT_SERVER="athena10.mit.edu"
+DEFAULT_RPC_PATH="/trac/login/rpc"
+
+logger = logging.getLogger(LOGGER_NAME)
+
+class Trac:
+    use_SSL = True
+
+    valid_repos = ("-development", "-proposed", "production")
+
+    def __init__(self, credentials):
+        scheme = "http"
+        if self.use_SSL:
+            scheme="https"
+        self._uri = "%s://%s:%s@%s%s" % (scheme,
+                                         credentials[0],
+                                         credentials[1],
+                                         DEFAULT_SERVER,
+                                         DEFAULT_RPC_PATH)
+        logger.debug("URI: %s", self._uri)
+        self._server = xmlrpclib.ServerProxy(self._uri)
+
+    def _update(self, ticket_id, comment, fields, notify=True, author=""):
+        # Setting author requires TICKET_ADMIN or higher for the XML
+        # RPC user, otherwise it will be ignored and the username of the
+        # XML RPC user will be substituted
+        try:
+            response = self._server.ticket.get(ticket_id)
+            # Returns [id, time_created, time_changed, attributes]
+            fields["_ts"] = response[3]["_ts"]
+            if "action" not in fields or (fields["action"] == response[3]["status"]):
+                fields["action"] = "leave"
+            self._server.ticket.update(ticket_id, comment, fields, notify, author)
+        except xmlrpclib.Fault, e:
+            print >>sys.stderr, e.message
+            sys.exit(1)
+
+    def upload_to_development(self, ticket_id, version):
+        self._update(ticket_id, "Uploaded to -development",
+                     {"fix_version": version,
+                      "action": "development"})
+
+    def upload_to_proposed(self, ticket_id, version):
+        self._update(ticket_id, "Uploaded to -proposed",
+                     {"fix_version": version,
+                      "action": "proposed"})
+
+    def upload_to_production(self, ticket_id, version):
+        self._update(ticket_id, "Uploaded to production",
+                     {"fix_version": version,
+                      "action": "resolve",
+                      "action_resolve_resolve_resolution": "fixed"})
+
+    def commit_to_master(self, ticket_id, comment, author):
+        self._update(ticket_id, comment,
+                     {"action": "committed"}, True, author)
+
+
+if __name__ == '__main__':
+    parser = OptionParser()
+    parser.set_defaults(debug=False)
+    parser.add_option("--debug", action="store_true", dest="debug")
+    parser.add_option("--credentials", action="store", type="string",
+                      default=DEFAULT_CREDENTIALS, dest="credentials")
+    (options, args) = parser.parse_args()
+    logging.basicConfig(level=logging.WARN, format='%(asctime)s %(levelname)s:%(name)s:%(message)s')
+    if options.debug:
+        logger.setLevel(logging.DEBUG)
+    if len(args) < 1:
+        print >>sys.stderr, "Syntax Error"
+        sys.exit(1)
+    try:
+        f = open(options.credentials, "r")
+        creds = f.readline().rstrip().split(':', 1)
+        f.close()
+    except IOError, e:
+        print >>sys.stderr, "Error reading credentials file:", e
+        sys.exit(1)
+    if len(creds) != 2:
+        print >>sys.stderr, "Malformatted credentials file."
+        sys.exit(1)
+    t = Trac(creds)
+    cmd = args.pop(0)
+    try:
+        getattr(t, cmd)(*args)
+    except AttributeError:
+        print >>sys.stderr, "Invalid command: " + cmd
+        sys.exit(1)
+    except TypeError, e:
+        print >>sys.stderr, "Syntax Error: " + e.message
+        sys.exit(1)
+    sys.exit(0)

home help back first fref pref prev next nref lref last post