Bug 754132 - Use treestatus for mercurial closure hooks (Firefox part). r=ted
authorChris AtLee <catlee@mozilla.com>
Fri, 10 Aug 2012 10:25:35 +0100
changeset 142 623817e95249555ba79e62cccb23670e1d295323
parent 141 38218ddfda343aa9099ab6ed52686a86f444ba6e
child 143 8db0fe2a5231b56351bbd7736264a533274a1504
push id72
push userbugzilla@standard8.plus.com
push dateFri, 10 Aug 2012 10:09:22 +0000
reviewersted
bugs754132
Bug 754132 - Use treestatus for mercurial closure hooks (Firefox part). r=ted
mozhghooks/treeclosure.py
runtests.py
--- a/mozhghooks/treeclosure.py
+++ b/mozhghooks/treeclosure.py
@@ -1,11 +1,11 @@
 #!/usr/bin/env python
 
-# Copyright (C) 2010 Mozilla Foundation
+# Copyright (C) 2012 Mozilla Foundation
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
 # as published by the Free Software Foundation; either version 2
 # of the License, or (at your option) any later version.
 #
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -14,76 +14,44 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 from urllib2 import urlopen
 import os.path
 import re
-
-hgNameToTinderboxURL = {
-    'birch'          : 'http://tinderbox.mozilla.org/Birch/status.html',
-    'mozilla-aurora'  : 'http://tinderbox.mozilla.org/Mozilla-Aurora/status.html',
-    'mozilla-beta'  : 'http://tinderbox.mozilla.org/Mozilla-Beta/status.html',
-    'mozilla-release'  : 'http://tinderbox.mozilla.org/Mozilla-Release/status.html',
-    'mozilla-esr10'  : 'http://tinderbox.mozilla.org/Mozilla-Esr10/status.html',
-    'mozilla-central': 'http://tinderbox.mozilla.org/Firefox/status.html',
-    'mozilla-inbound': 'http://tinderbox.mozilla.org/Mozilla-Inbound/status.html',
-    'mozilla-2.1'    : 'http://tinderbox.mozilla.org/Mobile2.0/status.html',
-    'mozilla-2.0'    : 'http://tinderbox.mozilla.org/Firefox4.0/status.html',
-    'mozilla-1.9.1'  : 'http://tinderbox.mozilla.org/Firefox3.5/status.html',
-    'mozilla-1.9.2'  : 'http://tinderbox.mozilla.org/Firefox3.6/status.html',
-    'mobile-browser' : 'http://tinderbox.mozilla.org/Mobile/status.html',
-    'mobile-2.0'     : 'http://tinderbox.mozilla.org/Mobile2.0/status.html',
-    'mobile-1.1'     : 'http://tinderbox.mozilla.org/Mobile1.1/status.html',
-    'mobile-5.0'     : 'http://tinderbox.mozilla.org/Mobile5.0/status.html',
-    'mobile-6.0'     : 'http://tinderbox.mozilla.org/Mobile6.0/status.html',
-    'mozilla-mobile-6.0'     : 'http://tinderbox.mozilla.org/Mobile6.0/status.html',
-    'mozilla-mobile-5.0' : 'http://tinderbox.mozilla.org/Mobile5.0/status.html',
-    'places'         : 'http://tinderbox.mozilla.org/Places/status.html',
-    'electrolysis'   : 'http://tinderbox.mozilla.org/Electrolysis/status.html',
-    'tracemonkey'    : 'http://tinderbox.mozilla.org/TraceMonkey/status.html',
-    'try'            : 'http://tinderbox.mozilla.org/Try/status.html',
-    'try-comm-central': 'http://tinderbox.mozilla.org/Thunderbird-Try/status.html',
-    'services-central': 'http://tinderbox.mozilla.org/Services-Central/status.html',
-    'shadow-central' : 'http://tinderbox.mozilla.org/Shadow-Central/status.html',
-}
+import json
 
 magicwords = "CLOSED TREE"
 
+treestatus_base_url = "https://treestatus.mozilla.org"
+
 def hook(ui, repo, **kwargs):
+    name = os.path.basename(repo.root)
+    url = "%s/%s?format=json" % (treestatus_base_url, name)
     try:
-        name = os.path.basename(repo.root)
-        if not hgNameToTinderboxURL.has_key(name) :
-            print "Unrecognized tree!  I don't know how to check closed status for %s." % name
-            return 1;
-        
-        url = hgNameToTinderboxURL[name];
         u = urlopen(url)
-        text = ''.join(u.readlines()).strip()
-        if re.compile('<span id="tree-?status".*CLOSED.*<span id="extended-status">').search(text) :
-            print "Tree %s is CLOSED! (%s)" % (name, url)
-            
+        data = json.load(u)
+        if data['status'] == 'closed':
+            print "Tree %s is CLOSED! (%s) - %s" % (name, url, data['reason'])
+
             # Block the push unless they know the magic words
             if repo.changectx('tip').description().find(magicwords) == -1:
                 print "To push despite the closed tree, include \"%s\" in your push comment" % magicwords
                 return 1
 
             print "But you included the magic words.  Hope you had permission!"
             return 0
-        elif re.compile('<span id="tree-?status".*APPROVAL REQUIRED.*<span id="extended-status">').search(text) :
+        elif data['status'] == 'approval required':
             # Block the push unless they have approval
             if re.search('a\S*=', repo.changectx('tip').description().lower()) :
                 return 0
 
             print "Pushing to an APPROVAL REQUIRED tree requires your top changeset comment to include: a=... (or, more accurately, a\\S*=...)"
             return 1
-        elif not re.compile('<span id="tree-?status".*<span id="extended-status">').search(text):
-            print "The extended status span must be on the same line as the treestatus."
-            return 1
-            
-    except IOError, (err):
-        # fail open, I guess. no sense making hg unavailable
-        # if the wiki is down
-        print "IOError: %s" % err
+
+    except (ValueError, IOError), (err):
+        # fail open. no sense making hg unavailable
+        # if treestatus is down
+        print "Error: %s" % err, url
         pass
     return 0
--- a/runtests.py
+++ b/runtests.py
@@ -222,111 +222,111 @@ class TestTreeClosureHook(ClosureHookTes
 
   def tearDown(self):
     shutil.rmtree(self.repodirbase)
     shutil.rmtree(self.clonedir)
     ClosureHookTestHelpers.tearDown(self)
 
   def testOpen(self):
     """Pushing to an OPEN tree should succeed."""
-    self.redirect("http://tinderbox.mozilla.org/Firefox/status.html",
-                  '<span id="treestatus">OPEN</span><span id="extended-status">')
+    self.redirect("https://treestatus.mozilla.org/mozilla-central?format=json",
+                '{"status": "open", "reason": null}')
 
     # pushing something should now succeed
     u = self.ui
     appendFile(join(self.clonedir, "testfile"), "checkin 1")
     add(u, self.clonerepo, join(self.clonedir, "testfile"))
     commit(u, self.clonerepo, message="checkin 1")
     push(u, self.clonerepo, dest=self.repodir)
     self.assertEqual(self.director.opened, 1)
 
   def testClosed(self):
     """Pushing to a CLOSED tree should fail."""
-    self.redirect("http://tinderbox.mozilla.org/Firefox/status.html",
-                         '<span id="treestatus">CLOSED</span><span id="extended-status">')
+    self.redirect("https://treestatus.mozilla.org/mozilla-central?format=json",
+                '{"status": "closed", "reason": "splines won\'t reticulate"}')
     # pushing something should now fail
     u = self.ui
     appendFile(join(self.clonedir, "testfile"), "checkin 1")
     add(u, self.clonerepo, join(self.clonedir, "testfile"))
     commit(u, self.clonerepo, message="checkin 1")
     self.assertRaises(util.Abort, push, u, self.clonerepo, dest=self.repodir)
     self.assertEqual(self.director.opened, 1)
 
   def testClosedMagicWords(self):
     """
     Pushing to a CLOSED tree with 'CLOSED TREE' in the commit message
     should succeed.
     """
-    self.redirect("http://tinderbox.mozilla.org/Firefox/status.html",
-                         '<span id="treestatus">CLOSED</span><span id="extended-status">')
+    self.redirect("https://treestatus.mozilla.org/mozilla-central?format=json",
+                '{"status": "closed", "reason": "too many widgets"}')
     u = self.ui
     appendFile(join(self.clonedir, "testfile"), "checkin 1")
     add(u, self.clonerepo, join(self.clonedir, "testfile"))
     commit(u, self.clonerepo, message="checkin 1 CLOSED TREE")
     push(u, self.clonerepo, dest=self.repodir)
     self.assertEqual(self.director.opened, 1)
 
   def testClosedMagicWordsTip(self):
     """
     Pushing multiple changesets to a CLOSED tree with 'CLOSED TREE'
     in the commit message of the tip changeset should succeed.
     """
-    self.redirect("http://tinderbox.mozilla.org/Firefox/status.html",
-                         '<span id="treestatus">CLOSED</span><span id="extended-status">')
+    self.redirect("https://treestatus.mozilla.org/mozilla-central?format=json",
+                '{"status": "closed", "reason": "the end of the world as we know it"}')
     u = self.ui
     appendFile(join(self.clonedir, "testfile"), "checkin 1")
     add(u, self.clonerepo, join(self.clonedir, "testfile"))
     commit(u, self.clonerepo, message="checkin 1")
     appendFile(join(self.clonedir, "testfile"), "checkin 2")
     commit(u, self.clonerepo, message="checkin 2 CLOSED TREE")
 
     push(u, self.clonerepo, dest=self.repodir)
     self.assertEqual(self.director.opened, 1)
 
   def testApprovalRequired(self):
     """Pushing to an APPROVAL REQUIRED tree should fail."""
-    self.redirect("http://tinderbox.mozilla.org/Firefox/status.html",
-                         '<span id="treestatus">APPROVAL REQUIRED</span><span id="extended-status">')
+    self.redirect("https://treestatus.mozilla.org/mozilla-central?format=json",
+                '{"status": "approval required", "reason": "be verrrry careful"}')
     # pushing something should now fail
     u = self.ui
     appendFile(join(self.clonedir, "testfile"), "checkin 1")
     add(u, self.clonerepo, join(self.clonedir, "testfile"))
     commit(u, self.clonerepo, message="checkin 1")
     self.assertRaises(util.Abort, push, u, self.clonerepo, dest=self.repodir)
     self.assertEqual(self.director.opened, 1)
 
   def testApprovalRequiredMagicWords(self):
     """
     Pushing to an APPROVAL REQUIRED tree with a=foo
     in the commit message should succeed.
     """
-    self.redirect("http://tinderbox.mozilla.org/Firefox/status.html",
-                         '<span id="treestatus">APPROVAL REQUIRED</span><span id="extended-status">')
+    self.redirect("https://treestatus.mozilla.org/mozilla-central?format=json",
+                '{"status": "approval required", "reason": "trees are fragile"}')
     u = self.ui
     appendFile(join(self.clonedir, "testfile"), "checkin 1")
     add(u, self.clonerepo, join(self.clonedir, "testfile"))
     commit(u, self.clonerepo, message="checkin 1 a=someone")
     push(u, self.clonerepo, dest=self.repodir)
     self.assertEqual(self.director.opened, 1)
 
     # also check that approval of the form a1.2=foo works
-    self.redirect("http://tinderbox.mozilla.org/Firefox/status.html",
-                         '<span id="treestatus">APPROVAL REQUIRED</span><span id="extended-status">')
+    self.redirect("https://treestatus.mozilla.org/mozilla-central?format=json",
+                '{"status": "approval required", "reason": "like they\'re made of glass"}')
     appendFile(join(self.clonedir, "testfile"), "checkin 2")
     commit(u, self.clonerepo, message="checkin 2 a1.2=someone")
     push(u, self.clonerepo, dest=self.repodir)
     self.assertEqual(self.director.opened, 2)
 
   def testApprovalRequiredMagicWordsTip(self):
     """
     Pushing to an APPROVAL REQUIRED tree with a=foo
     in the commit message of the tip changeset should succeed.
     """
-    self.redirect("http://tinderbox.mozilla.org/Firefox/status.html",
-                         '<span id="treestatus">APPROVAL REQUIRED</span><span id="extended-status">')
+    self.redirect("https://treestatus.mozilla.org/mozilla-central?format=json",
+                '{"status": "approval required", "reason": "stained glass"}')
     u = self.ui
     appendFile(join(self.clonedir, "testfile"), "checkin 1")
     add(u, self.clonerepo, join(self.clonedir, "testfile"))
     commit(u, self.clonerepo, message="checkin 1")
     appendFile(join(self.clonedir, "testfile"), "checkin 1")
     commit(u, self.clonerepo, message="checkin 2 a=someone")
 
     push(u, self.clonerepo, dest=self.repodir)