From 775201dbd1be45184c57d1f82e4c1ca43a82673d Mon Sep 17 00:00:00 2001 From: "machenbach@chromium.org" Date: Mon, 18 Nov 2013 14:10:47 +0000 Subject: [PATCH] Add initial auto-roll script. To be called with a cron job. TEST=tools/push-to-trunk/auto_roll.py TODO: Add a revision filter to allow "MIPS" related changes to take over the lkgr. R=jkummerow@chromium.org Review URL: https://codereview.chromium.org/70373002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17833 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- tools/push-to-trunk/auto_roll.py | 119 +++++++++++++++++++++++++++++++++ tools/push-to-trunk/common_includes.py | 27 +++++++- tools/push-to-trunk/push_to_trunk.py | 25 ++----- tools/push-to-trunk/test_scripts.py | 9 ++- 4 files changed, 156 insertions(+), 24 deletions(-) create mode 100755 tools/push-to-trunk/auto_roll.py diff --git a/tools/push-to-trunk/auto_roll.py b/tools/push-to-trunk/auto_roll.py new file mode 100755 index 0000000..9547301 --- /dev/null +++ b/tools/push-to-trunk/auto_roll.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python +# Copyright 2013 the V8 project authors. All rights reserved. +# 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 Google Inc. 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 optparse +import re +import sys +import urllib2 + +from common_includes import * + +CONFIG = { + PERSISTFILE_BASENAME: "/tmp/v8-auto-roll-tempfile", + DOT_GIT_LOCATION: ".git", +} + + +class Preparation(Step): + def __init__(self): + Step.__init__(self, "Preparation.") + + def RunStep(self): + self.InitialEnvironmentChecks() + self.CommonPrepare() + + +class FetchLatestRevision(Step): + def __init__(self): + Step.__init__(self, "Fetching latest V8 revision.") + + def RunStep(self): + log = self.Git("svn log -1 --oneline").strip() + match = re.match(r"^r(\d+) ", log) + if not match: + self.Die("Could not extract current svn revision from log.") + self.Persist("latest", match.group(1)) + + +class FetchLKGR(Step): + def __init__(self): + Step.__init__(self, "Fetching V8 LKGR.") + + def RunStep(self): + lkgr_url = "https://v8-status.appspot.com/lkgr" + try: + # pylint: disable=E1121 + url_fh = urllib2.urlopen(lkgr_url, None, 60) + except urllib2.URLError: + self.Die("URLException while fetching %s" % lkgr_url) + try: + self.Persist("lkgr", url_fh.read()) + finally: + url_fh.close() + + +class PushToTrunk(Step): + def __init__(self): + Step.__init__(self, "Pushing to trunk if possible.") + + def RunStep(self): + self.RestoreIfUnset("latest") + self.RestoreIfUnset("lkgr") + latest = int(self._state["latest"]) + lkgr = int(self._state["lkgr"]) + if latest == lkgr: + print "ToT (r%d) is clean. Pushing to trunk." % latest + # TODO(machenbach): Call push to trunk script. + else: + print("ToT (r%d) is ahead of the LKGR (r%d). Skipping push to trunk." + % (latest, lkgr)) + + +def BuildOptions(): + result = optparse.OptionParser() + result.add_option("-s", "--step", dest="s", + help="Specify the step where to start work. Default: 0.", + default=0, type="int") + return result + + +def Main(): + parser = BuildOptions() + (options, args) = parser.parse_args() + + step_classes = [ + Preparation, + FetchLatestRevision, + FetchLKGR, + PushToTrunk, + ] + + RunScript(step_classes, CONFIG, options, DEFAULT_SIDE_EFFECT_HANDLER) + +if __name__ == "__main__": + sys.exit(Main()) diff --git a/tools/push-to-trunk/common_includes.py b/tools/push-to-trunk/common_includes.py index 669aa6b..06b7ebe 100644 --- a/tools/push-to-trunk/common_includes.py +++ b/tools/push-to-trunk/common_includes.py @@ -244,8 +244,10 @@ class Step(object): if self.Git("svn fetch") is None: self.Die("'git svn fetch' failed.") + def PrepareBranch(self): # Get ahold of a safe temporary branch and check it out. - if current_branch != self._config[TEMP_BRANCH]: + self.RestoreIfUnset("current_branch") + if self._state["current_branch"] != self._config[TEMP_BRANCH]: self.DeleteBranch(self._config[TEMP_BRANCH]) self.Git("checkout -b %s" % self._config[TEMP_BRANCH]) @@ -323,3 +325,26 @@ class UploadStep(Step): args = "cl upload -r \"%s\" --send-mail" % reviewer if self.Git(args,pipe=False) is None: self.Die("'git cl upload' failed, please try again.") + + +def RunScript(step_classes, + config, + options, + side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER): + state = {} + steps = [] + number = 0 + + for step_class in step_classes: + # TODO(machenbach): Factory methods. + step = step_class() + step.SetNumber(number) + step.SetConfig(config) + step.SetOptions(options) + step.SetState(state) + step.SetSideEffectHandler(side_effect_handler) + steps.append(step) + number += 1 + + for step in steps[options.s:]: + step.Run() diff --git a/tools/push-to-trunk/push_to_trunk.py b/tools/push-to-trunk/push_to_trunk.py index 04e992d..2aa32cd 100755 --- a/tools/push-to-trunk/push_to_trunk.py +++ b/tools/push-to-trunk/push_to_trunk.py @@ -59,6 +59,7 @@ class Preparation(Step): def RunStep(self): self.InitialEnvironmentChecks() self.CommonPrepare() + self.PrepareBranch() self.DeleteBranch(self.Config(TRUNKBRANCH)) @@ -487,9 +488,9 @@ class CleanUp(Step): self.Git("branch -D %s" % self.Config(TRUNKBRANCH)) -def RunScript(config, - options, - side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER): +def RunPushToTrunk(config, + options, + side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER): step_classes = [ Preparation, FreshBranch, @@ -517,23 +518,7 @@ def RunScript(config, CleanUp, ] - state = {} - steps = [] - number = 0 - - for step_class in step_classes: - # TODO(machenbach): Factory methods. - step = step_class() - step.SetNumber(number) - step.SetConfig(config) - step.SetOptions(options) - step.SetState(state) - step.SetSideEffectHandler(side_effect_handler) - steps.append(step) - number += 1 - - for step in steps[options.s:]: - step.Run() + RunScript(step_classes, config, options, side_effect_handler) def BuildOptions(): diff --git a/tools/push-to-trunk/test_scripts.py b/tools/push-to-trunk/test_scripts.py index 727e93b..b9d762d 100644 --- a/tools/push-to-trunk/test_scripts.py +++ b/tools/push-to-trunk/test_scripts.py @@ -160,6 +160,7 @@ class ScriptTest(unittest.TestCase): ] self._rl_recipe = ["Y"] self.MakeStep().CommonPrepare() + self.MakeStep().PrepareBranch() self.assertEquals("some_branch", self.MakeStep().Restore("current_branch")) def testCommonPrepareNoConfirm(self): @@ -170,7 +171,8 @@ class ScriptTest(unittest.TestCase): ["branch", " branch1\n* %s" % TEST_CONFIG[TEMP_BRANCH]], ] self._rl_recipe = ["n"] - self.assertRaises(Exception, self.MakeStep().CommonPrepare) + self.MakeStep().CommonPrepare() + self.assertRaises(Exception, self.MakeStep().PrepareBranch) self.assertEquals("some_branch", self.MakeStep().Restore("current_branch")) def testCommonPrepareDeleteBranchFailure(self): @@ -182,7 +184,8 @@ class ScriptTest(unittest.TestCase): ["branch -D %s" % TEST_CONFIG[TEMP_BRANCH], None], ] self._rl_recipe = ["Y"] - self.assertRaises(Exception, self.MakeStep().CommonPrepare) + self.MakeStep().CommonPrepare() + self.assertRaises(Exception, self.MakeStep().PrepareBranch) self.assertEquals("some_branch", self.MakeStep().Restore("current_branch")) def testInitialEnvironmentChecks(self): @@ -428,7 +431,7 @@ class ScriptTest(unittest.TestCase): options.s = 0 options.l = None options.c = TEST_CONFIG[CHROMIUM] - RunScript(TEST_CONFIG, options, self) + RunPushToTrunk(TEST_CONFIG, options, self) deps = FileToText(TEST_CONFIG[DEPS_FILE]) self.assertTrue(re.search("\"v8_revision\": \"123456\"", deps)) -- 2.7.4