Revision: 18247
Author: machenb...@chromium.org
Date: Wed Dec 4 08:47:18 2013 UTC
Log: Add fully automated mode to push-to-trunk script.
Now there are three modes to run the script:
(1) default: semi-automated
(2) manual (-m option), like in the old script
(3) forced (-f option), no user input required no editor check
R=u...@chromium.org
Review URL: https://codereview.chromium.org/102253002
http://code.google.com/p/v8/source/detail?r=18247
Modified:
/branches/bleeding_edge/tools/push-to-trunk/auto_roll.py
/branches/bleeding_edge/tools/push-to-trunk/common_includes.py
/branches/bleeding_edge/tools/push-to-trunk/push_to_trunk.py
/branches/bleeding_edge/tools/push-to-trunk/test_scripts.py
=======================================
--- /branches/bleeding_edge/tools/push-to-trunk/auto_roll.py Mon Dec 2
09:53:28 2013 UTC
+++ /branches/bleeding_edge/tools/push-to-trunk/auto_roll.py Wed Dec 4
08:47:18 2013 UTC
@@ -96,6 +96,9 @@
def BuildOptions():
result = optparse.OptionParser()
+ result.add_option("-f", "--force", dest="f",
+ help="Don't prompt the user.",
+ default=True, action="store_true")
result.add_option("-s", "--step", dest="s",
help="Specify the step where to start work. Default:
0.",
default=0, type="int")
=======================================
--- /branches/bleeding_edge/tools/push-to-trunk/common_includes.py Tue Dec
3 12:38:25 2013 UTC
+++ /branches/bleeding_edge/tools/push-to-trunk/common_includes.py Wed Dec
4 08:47:18 2013 UTC
@@ -229,6 +229,12 @@
def Config(self, key):
return self._config[key]
+ def IsForced(self):
+ return self._options and self._options.f
+
+ def IsManual(self):
+ return self._options and self._options.m
+
def Run(self):
if self._requires:
self.RestoreIfUnset(self._requires)
@@ -271,7 +277,7 @@
def ReadLine(self, default=None):
# Don't prompt in forced mode.
- if self._options and self._options.f and default is not None:
+ if not self.IsManual() and default is not None:
print "%s (forced)" % default
return default
else:
@@ -282,8 +288,9 @@
return self.Retry(cmd, retry_on, [5, 30])
def Editor(self, args):
- return self._side_effect_handler.Command(os.environ["EDITOR"], args,
- pipe=False)
+ if not self.IsForced():
+ return self._side_effect_handler.Command(os.environ["EDITOR"], args,
+ pipe=False)
def ReadURL(self, url, retry_on=None, wait_plan=None):
wait_plan = wait_plan or [3, 60, 600]
@@ -299,9 +306,9 @@
print "Exiting"
raise Exception(msg)
- def DieInForcedMode(self, msg=""):
- if self._options and self._options.f:
- msg = msg or "Not implemented in forced mode."
+ def DieNoManualMode(self, msg=""):
+ if not self.IsManual():
+ msg = msg or "Only available in manual mode."
self.Die(msg)
def Confirm(self, msg):
@@ -340,11 +347,9 @@
if not os.path.exists(self._config[DOT_GIT_LOCATION]):
self.Die("This is not a git checkout, this script won't work for
you.")
- # TODO(machenbach): Don't use EDITOR in forced mode as soon as script
is
- # well tested.
# Cancel if EDITOR is unset or not executable.
- if (not os.environ.get("EDITOR") or
- Command("which", os.environ["EDITOR"]) is None):
+ if (not self.IsForced() and (not os.environ.get("EDITOR") or
+ Command("which", os.environ["EDITOR"]) is None)):
self.Die("Please set your EDITOR environment variable, you'll need
it.")
def CommonPrepare(self):
@@ -413,9 +418,7 @@
answer = ""
while answer != "LGTM":
print "> ",
- # TODO(machenbach): Add default="LGTM" to avoid prompt when script is
- # well tested and when prepare push cl has TBR flag.
- answer = self.ReadLine()
+ answer = self.ReadLine("LGTM" if self.IsForced() else None)
if answer != "LGTM":
print "That was not 'LGTM'."
@@ -423,7 +426,7 @@
print("Applying the patch \"%s\" failed. Either type
\"ABORT<Return>\", "
"or resolve the conflicts, stage *all* touched files with "
"'git add', and type \"RESOLVED<Return>\"")
- self.DieInForcedMode()
+ self.DieNoManualMode()
answer = ""
while answer != "RESOLVED":
if answer == "ABORT":
@@ -449,9 +452,9 @@
reviewer = self._options.r
else:
print "Please enter the email address of a V8 reviewer for your
patch: ",
- self.DieInForcedMode("A reviewer must be specified in forced mode.")
+ self.DieNoManualMode("A reviewer must be specified in forced mode.")
reviewer = self.ReadLine()
- force_flag = " -f" if self._options.f else ""
+ force_flag = " -f" if not self.IsManual() else ""
args = "cl upload -r \"%s\" --send-mail%s" % (reviewer, force_flag)
# TODO(machenbach): Check output in forced mode. Verify that all
required
# base files were uploaded, if not retry.
=======================================
--- /branches/bleeding_edge/tools/push-to-trunk/push_to_trunk.py Tue Dec 3
12:38:25 2013 UTC
+++ /branches/bleeding_edge/tools/push-to-trunk/push_to_trunk.py Wed Dec 4
08:47:18 2013 UTC
@@ -157,9 +157,6 @@
"entry, then edit its contents to your liking. When you're
done, "
"save the file and exit your EDITOR. ")
self.ReadLine(default="")
-
- # TODO(machenbach): Don't use EDITOR in forced mode as soon as script
is
- # well tested.
self.Editor(self.Config(CHANGELOG_ENTRY_FILE))
handle, new_changelog = tempfile.mkstemp()
os.close(handle)
@@ -214,7 +211,11 @@
self._state["new_minor"],
self._state["new_build"]))
self.Persist("prep_commit_msg", prep_commit_msg)
- if self.Git("commit -a -m \"%s\"" % prep_commit_msg) is None:
+
+ # Include optional TBR only in the git command. The persisted commit
+ # message is used for finding the commit again later.
+ review = "\n\nTBR=%s" % self._options.r if not self.IsManual() else ""
+ if self.Git("commit -a -m \"%s%s\"" % (prep_commit_msg, review)) is
None:
self.Die("'git commit -a' failed.")
@@ -364,7 +365,7 @@
print("Sorry, grepping for the SVN revision failed. Please look for
it "
"in the last command's output above and provide it manually
(just "
"the number, without the leading \"r\").")
- self.DieInForcedMode("Can't prompt in forced mode.")
+ self.DieNoManualMode("Can't prompt in forced mode.")
while not trunk_revision:
print "> ",
trunk_revision = self.ReadLine()
@@ -389,7 +390,7 @@
def Run(self):
chrome_path = self._options.c
if not chrome_path:
- self.DieInForcedMode("Please specify the path to a Chromium checkout
in "
+ self.DieNoManualMode("Please specify the path to a Chromium checkout
in "
"forced mode.")
print ("Do you have a \"NewGit\" Chromium checkout and want "
"this script to automate creation of the roll CL? If yes, enter
the "
@@ -457,12 +458,12 @@
rev = self._options.r
else:
print "Please enter the email address of a reviewer for the roll
CL: ",
- self.DieInForcedMode("A reviewer must be specified in forced mode.")
+ self.DieNoManualMode("A reviewer must be specified in forced mode.")
rev = self.ReadLine()
args = "commit -am \"Update V8 to version %s.\n\nTBR=%s\"" % (ver, rev)
if self.Git(args) is None:
self.Die("'git commit' failed.")
- force_flag = " -f" if self._options.f else ""
+ force_flag = " -f" if not self.IsManual() else ""
if self.Git("cl upload --send-mail%s" % force_flag, pipe=False) is
None:
self.Die("'git cl upload' failed, please try again.")
print "CL uploaded."
@@ -547,6 +548,9 @@
result.add_option("-l", "--last-push", dest="l",
help=("Manually specify the git commit ID "
"of the last push to trunk."))
+ result.add_option("-m", "--manual", dest="m",
+ help="Prompt the user at every important step.",
+ default=False, action="store_true")
result.add_option("-r", "--reviewer", dest="r",
help=("Specify the account name to be used for
reviews."))
result.add_option("-s", "--step", dest="s",
@@ -559,11 +563,14 @@
if options.s < 0:
print "Bad step number %d" % options.s
return False
- if options.f and not options.r:
- print "A reviewer (-r) is required in forced mode."
+ if not options.m and not options.r:
+ print "A reviewer (-r) is required in (semi-)automatic mode."
+ return False
+ if options.f and options.m:
+ print "Manual and forced mode cannot be combined."
return False
- if options.f and not options.c:
- print "A chromium checkout (-c) is required in forced mode."
+ if not options.m and not options.c:
+ print "A chromium checkout (-c) is required in (semi-)automatic mode."
return False
return True
=======================================
--- /branches/bleeding_edge/tools/push-to-trunk/test_scripts.py Tue Dec 3
12:38:25 2013 UTC
+++ /branches/bleeding_edge/tools/push-to-trunk/test_scripts.py Wed Dec 4
08:47:18 2013 UTC
@@ -51,6 +51,20 @@
CHROMIUM: "/tmp/test-v8-push-to-trunk-tempfile-chromium",
DEPS_FILE: "/tmp/test-v8-push-to-trunk-tempfile-chromium/DEPS",
}
+
+
+def MakeOptions(s=0, l=None, f=False, m=True, r=None, c=None):
+ """Convenience wrapper."""
+ class Options(object):
+ pass
+ options = Options()
+ options.s = s
+ options.l = l
+ options.f = f
+ options.m = m
+ options.r = r
+ options.c = c
+ return options
class ToplevelTest(unittest.TestCase):
@@ -260,12 +274,15 @@
f.write("#define IS_CANDIDATE_VERSION 0\n")
return name
- def MakeStep(self, step_class=Step, state=None):
+ def MakeStep(self, step_class=Step, state=None, options=None):
"""Convenience wrapper."""
+ options = options or MakeOptions()
return MakeStep(step_class=step_class, number=0, state=state,
- config=TEST_CONFIG, options=None,
side_effect_handler=self)
+ config=TEST_CONFIG, options=options,
+ side_effect_handler=self)
def GitMock(self, cmd, args="", pipe=True):
+ print "%s %s" % (cmd, args)
return self._git_mock.Call(args)
def LogMock(self, cmd, args=""):
@@ -555,7 +572,7 @@
patch = FileToText(TEST_CONFIG[ PATCH_FILE])
self.assertTrue(re.search(r"patch content", patch))
- def _PushToTrunk(self, force=False):
+ def _PushToTrunk(self, force=False, manual=False):
TEST_CONFIG[DOT_GIT_LOCATION] = self.MakeEmptyTempFile()
TEST_CONFIG[VERSION_FILE] = self.MakeTempVersionFile()
TEST_CONFIG[CHANGELOG_ENTRY_FILE] = self.MakeEmptyTempFile()
@@ -593,7 +610,8 @@
self.assertTrue(re.search(r"#define PATCH_LEVEL\s+0", version))
self.assertTrue(re.search(r"#define IS_CANDIDATE_VERSION\s+0",
version))
- force_flag = " -f" if force else ""
+ force_flag = " -f" if not manual else ""
+ review_suffix = "\n\nTBR=revie...@chromium.org" if not manual else ""
self.ExpectGit([
["status -s -uno", ""],
["status -s -b -uno", "## some_branch\n"],
@@ -610,7 +628,7 @@
["log -1 rev1 --format=\"%B\"", "Text\nLOG=YES\nBUG=v8:321\nText\n"],
["log -1 rev1 --format=\"%an\"", "auth...@chromium.org\n"],
[("commit -a -m \"Prepare push to trunk. "
- "Now working on version 3.22.6.\""),
+ "Now working on version 3.22.6.%s\"" % review_suffix),
" 2 files changed\n",
CheckPreparePush],
["cl upload -r \"revie...@chromium.org\" --send-mail%s" % force_flag,
@@ -641,32 +659,33 @@
["branch -D %s" % TEST_CONFIG[BRANCHNAME], ""],
["branch -D %s" % TEST_CONFIG[TRUNKBRANCH], ""],
])
- self.ExpectReadline([
- "Y", # Confirm last push.
- "", # Open editor.
- "Y", # Increment build number.
- "revie...@chromium.org", # V8 reviewer.
- "LGTX", # Enter LGTM for V8 CL (wrong).
- "LGTM", # Enter LGTM for V8 CL.
- "Y", # Sanity check.
- "revie...@chromium.org", # Chromium reviewer.
- ])
- if force:
- # TODO(machenbach): The lgtm for the prepare push is just temporary.
- # There should be no user input in "force" mode.
+
+ # Expected keyboard input in manual mode:
+ if manual:
self.ExpectReadline([
+ "Y", # Confirm last push.
+ "", # Open editor.
+ "Y", # Increment build number.
+ "revie...@chromium.org", # V8 reviewer.
+ "LGTX", # Enter LGTM for V8 CL (wrong).
"LGTM", # Enter LGTM for V8 CL.
+ "Y", # Sanity check.
+ "revie...@chromium.org", # Chromium reviewer.
])
- class Options( object ):
- pass
+ # Expected keyboard input in semi-automatic mode:
+ if not manual and not force:
+ self.ExpectReadline([
+ "LGTM", # Enter LGTM for V8 CL.
+ ])
- options = Options()
- options.s = 0
- options.l = None
- options.f = force
- options.r = "revie...@chromium.org" if force else None
- options.c = TEST_CONFIG[CHROMIUM]
+ # No keyboard input in forced mode:
+ if force:
+ self.ExpectReadline([])
+
+ options = MakeOptions(f=force, m=manual,
+ r="revie...@chromium.org" if not manual else
None,
+ c = TEST_CONFIG[CHROMIUM])
RunPushToTrunk(TEST_CONFIG, options, self)
deps = FileToText(TEST_CONFIG[DEPS_FILE])
@@ -681,7 +700,10 @@
# since the git command that merges to the bleeding edge branch is
mocked
# out.
- def testPushToTrunk(self):
+ def testPushToTrunkManual(self):
+ self._PushToTrunk(manual=True)
+
+ def testPushToTrunkSemiAutomatic(self):
self._PushToTrunk()
def testPushToTrunkForced(self):
@@ -690,9 +712,6 @@
def testAutoRoll(self):
TEST_CONFIG[DOT_GIT_LOCATION] = self.MakeEmptyTempFile()
- # TODO(machenbach): Get rid of the editor check in automatic mode.
- os.environ["EDITOR"] = "vi"
-
self.ExpectReadURL([
["https://v8-status.appspot.com/lkgr", Exception("Network problem")],
["https://v8-status.appspot.com/lkgr", "100"],
@@ -705,14 +724,7 @@
["svn log -1 --oneline", "r101 | Text"],
])
- # TODO(machenbach): Make a convenience wrapper for this.
- class Options( object ):
- pass
-
- options = Options()
- options.s = 0
-
- auto_roll.RunAutoRoll(TEST_CONFIG, options, self)
+ auto_roll.RunAutoRoll(TEST_CONFIG, MakeOptions(m=False, f=True), self)
self.assertEquals("100", self.MakeStep().Restore("lkgr"))
self.assertEquals("101", self.MakeStep().Restore("latest"))
--
--
v8-dev mailing list
v8-dev@googlegroups.com
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to v8-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.