blob: af5f73a600d03d461db2f0f4777c8622b87fe340 [file] [log] [blame]
#!/usr/bin/env python
# Copyright 2014 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
Script for auto-increasing the version on bleeding_edge.
The script can be run regularly by a cron job. It will increase the build
level of the version on bleeding_edge if:
- the lkgr version is smaller than the version of the latest revision,
- the lkgr version is not a version change itself,
- the tree is not closed for maintenance.
The new version will be the maximum of the bleeding_edge and trunk versions +1.
E.g. latest bleeding_edge version: 3.22.11.0 and latest trunk 3.23.0.0 gives
the new version 3.23.1.0.
This script requires a depot tools git checkout. I.e. 'fetch v8'.
"""
import argparse
import os
import sys
from common_includes import *
CONFIG = {
PERSISTFILE_BASENAME: "/tmp/v8-bump-up-version-tempfile",
VERSION_FILE: "src/version.cc",
}
VERSION_BRANCH = "auto-bump-up-version"
class Preparation(Step):
MESSAGE = "Preparation."
def RunStep(self):
# Check for a clean workdir.
if not self.GitIsWorkdirClean(): # pragma: no cover
# This is in case a developer runs this script on a dirty tree.
self.GitStash()
# TODO(machenbach): This should be called master after the git switch.
self.GitCheckout("bleeding_edge")
self.GitPull()
# Ensure a clean version branch.
self.DeleteBranch(VERSION_BRANCH)
class GetCurrentBleedingEdgeVersion(Step):
MESSAGE = "Get latest bleeding edge version."
def RunStep(self):
# TODO(machenbach): This should be called master after the git switch.
self.GitCheckout("bleeding_edge")
# Store latest version and revision.
self.ReadAndPersistVersion()
self["latest_version"] = self.ArrayToVersion("")
self["latest"] = self.GitLog(n=1, format="%H")
print "Bleeding edge version: %s" % self["latest_version"]
# This step is pure paranoia. It forbids the script to continue if the last
# commit changed version.cc. Just in case the other bailout has a bug, this
# prevents the script from continuously commiting version changes.
class LastChangeBailout(Step):
MESSAGE = "Stop script if the last change modified the version."
def RunStep(self):
if self._config[VERSION_FILE] in self.GitChangedFiles(self["latest"]):
print "Stop due to recent version change."
return True
# TODO(machenbach): Implement this for git.
class FetchLKGR(Step):
MESSAGE = "Fetching V8 LKGR."
def RunStep(self):
lkgr_url = "https://v8-status.appspot.com/lkgr"
self["lkgr_svn"] = self.ReadURL(lkgr_url, wait_plan=[5])
# TODO(machenbach): Implement this for git. With a git lkgr we could simply
# checkout that revision. With svn, we have to search backwards until that
# revision is found.
class GetLKGRVersion(Step):
MESSAGE = "Get bleeding edge lkgr version."
def RunStep(self):
self.GitCheckout("bleeding_edge")
# If the commit was made from svn, there is a mapping entry in the commit
# message.
self["lkgr"] = self.GitLog(
grep="^git-svn-id: [^@]*@%s [A-Za-z0-9-]*$" % self["lkgr_svn"],
format="%H")
# FIXME(machenbach): http://crbug.com/391712 can lead to svn lkgrs on the
# trunk branch (rarely).
if not self["lkgr"]: # pragma: no cover
self.Die("No git hash found for svn lkgr.")
self.GitCreateBranch(VERSION_BRANCH, self["lkgr"])
self.ReadAndPersistVersion("lkgr_")
self["lkgr_version"] = self.ArrayToVersion("lkgr_")
print "LKGR version: %s" % self["lkgr_version"]
# Ensure a clean version branch.
self.GitCheckout("bleeding_edge")
self.DeleteBranch(VERSION_BRANCH)
class LKGRVersionUpToDateBailout(Step):
MESSAGE = "Stop script if the lkgr has a renewed version."
def RunStep(self):
# If a version-change commit becomes the lkgr, don't bump up the version
# again.
if self._config[VERSION_FILE] in self.GitChangedFiles(self["lkgr"]):
print "Stop because the lkgr is a version change itself."
return True
# Don't bump up the version if it got updated already after the lkgr.
if SortingKey(self["lkgr_version"]) < SortingKey(self["latest_version"]):
print("Stop because the latest version already changed since the lkgr "
"version.")
return True
class GetTrunkVersion(Step):
MESSAGE = "Get latest trunk version."
def RunStep(self):
# TODO(machenbach): This should be called trunk after the git switch.
self.GitCheckout("master")
self.GitPull()
self.ReadAndPersistVersion("trunk_")
self["trunk_version"] = self.ArrayToVersion("trunk_")
print "Trunk version: %s" % self["trunk_version"]
class CalculateVersion(Step):
MESSAGE = "Calculate the new version."
def RunStep(self):
if self["lkgr_build"] == "9999": # pragma: no cover
# If version control on bleeding edge was switched off, just use the last
# trunk version.
self["lkgr_version"] = self["trunk_version"]
# The new version needs to be greater than the max on bleeding edge and
# trunk.
max_version = max(self["trunk_version"],
self["lkgr_version"],
key=SortingKey)
# Strip off possible leading zeros.
self["new_major"], self["new_minor"], self["new_build"], _ = (
map(str, map(int, max_version.split("."))))
self["new_build"] = str(int(self["new_build"]) + 1)
self["new_patch"] = "0"
self["new_version"] = ("%s.%s.%s.0" %
(self["new_major"], self["new_minor"], self["new_build"]))
print "New version is %s" % self["new_version"]
if self._options.dry_run: # pragma: no cover
print "Dry run, skipping version change."
return True
class CheckTreeStatus(Step):
MESSAGE = "Checking v8 tree status message."
def RunStep(self):
status_url = "https://v8-status.appspot.com/current?format=json"
status_json = self.ReadURL(status_url, wait_plan=[5, 20, 300, 300])
message = json.loads(status_json)["message"]
if re.search(r"maintenance|no commits", message, flags=re.I):
print "Skip version change by tree status: \"%s\"" % message
return True
class ChangeVersion(Step):
MESSAGE = "Bump up the version."
def RunStep(self):
self.GitCreateBranch(VERSION_BRANCH, "bleeding_edge")
self.SetVersion(self.Config(VERSION_FILE), "new_")
try:
self.GitCommit("[Auto-roll] Bump up version to %s\n\nTBR=%s" %
(self["new_version"], self._options.author))
self.GitUpload(author=self._options.author,
force=self._options.force_upload,
bypass_hooks=True)
self.GitDCommit()
print "Successfully changed the version."
finally:
# Clean up.
self.GitCheckout("bleeding_edge")
self.DeleteBranch(VERSION_BRANCH)
class BumpUpVersion(ScriptsBase):
def _PrepareOptions(self, parser):
parser.add_argument("--dry_run", help="Don't commit the new version.",
default=False, action="store_true")
def _ProcessOptions(self, options): # pragma: no cover
if not options.dry_run and not options.author:
print "Specify your chromium.org email with -a"
return False
options.wait_for_lgtm = False
options.force_readline_defaults = True
options.force_upload = True
return True
def _Steps(self):
return [
Preparation,
GetCurrentBleedingEdgeVersion,
LastChangeBailout,
FetchLKGR,
GetLKGRVersion,
LKGRVersionUpToDateBailout,
GetTrunkVersion,
CalculateVersion,
CheckTreeStatus,
ChangeVersion,
]
if __name__ == "__main__": # pragma: no cover
sys.exit(BumpUpVersion(CONFIG).Run())