1474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org#!/usr/bin/env python 2474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org# Copyright 2014 the V8 project authors. All rights reserved. 3474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org# Use of this source code is governed by a BSD-style license that can be 4474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org# found in the LICENSE file. 5474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 6474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.orgimport argparse 7474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.orgimport sys 8474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 9474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.orgfrom common_includes import * 10474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 11474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 12474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.orgclass Preparation(Step): 13474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org MESSAGE = "Preparation." 14474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 15474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org def RunStep(self): 16474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self.CommonPrepare() 17474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self.PrepareBranch() 18474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self.GitCheckout("master") 19474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self.GitSVNRebase() 20474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 21474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 22474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.orgclass GetTags(Step): 23474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org MESSAGE = "Get all V8 tags." 24474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 25474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org def RunStep(self): 2606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org self.GitCreateBranch(self._config["BRANCHNAME"]) 27474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 28474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org # Get remote tags. 29474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org tags = filter(lambda s: re.match(r"^svn/tags/[\d+\.]+$", s), 30474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self.GitRemotes()) 31474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 32474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org # Remove 'svn/tags/' prefix. 33474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self["tags"] = map(lambda s: s[9:], tags) 34474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 35474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 36474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.orgclass GetOldestUntaggedVersion(Step): 37474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org MESSAGE = "Check if there's a version on bleeding edge without a tag." 38474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 39474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org def RunStep(self): 40474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org tags = set(self["tags"]) 41474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self["candidate"] = None 42474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self["candidate_version"] = None 43474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self["next"] = None 44474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self["next_version"] = None 45474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 46474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org # Iterate backwards through all automatic version updates. 47474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org for git_hash in self.GitLog( 48474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org format="%H", grep="\\[Auto\\-roll\\] Bump up version to").splitlines(): 49474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 50474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org # Get the version. 5106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org if not self.GitCheckoutFileSafe(VERSION_FILE, git_hash): 52474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org continue 53474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 54474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self.ReadAndPersistVersion() 55474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org version = self.ArrayToVersion("") 56474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 57474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org # Strip off trailing patch level (tags don't include tag level 0). 58474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org if version.endswith(".0"): 59474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org version = version[:-2] 60474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 61474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org # Clean up checked-out version file. 6206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org self.GitCheckoutFileSafe(VERSION_FILE, "HEAD") 63474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 64474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org if version in tags: 65474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org if self["candidate"]: 66474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org # Revision "git_hash" is tagged already and "candidate" was the next 67474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org # newer revision without a tag. 68474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org break 69474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org else: 70474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org print("Stop as %s is the latest version and it has been tagged." % 71474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org version) 72474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self.CommonCleanup() 73474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org return True 74474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org else: 75474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org # This is the second oldest version without a tag. 76474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self["next"] = self["candidate"] 77474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self["next_version"] = self["candidate_version"] 78474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 79474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org # This is the oldest version without a tag. 80474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self["candidate"] = git_hash 81474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self["candidate_version"] = version 82474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 83474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org if not self["candidate"] or not self["candidate_version"]: 84474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org print "Nothing found to tag." 85474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self.CommonCleanup() 86474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org return True 87474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 88474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org print("Candidate for tagging is %s with version %s" % 89474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org (self["candidate"], self["candidate_version"])) 90474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 91474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 92474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.orgclass GetLKGRs(Step): 93474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org MESSAGE = "Get the last lkgrs." 94474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 95474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org def RunStep(self): 96474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org revision_url = "https://v8-status.appspot.com/revisions?format=json" 97474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org status_json = self.ReadURL(revision_url, wait_plan=[5, 20]) 98474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self["lkgrs"] = [entry["revision"] 99474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org for entry in json.loads(status_json) if entry["status"]] 100474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 101474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 102474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.orgclass CalculateTagRevision(Step): 103474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org MESSAGE = "Calculate the revision to tag." 104474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 105474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org def LastLKGR(self, min_rev, max_rev): 106474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org """Finds the newest lkgr between min_rev (inclusive) and max_rev 107474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org (exclusive). 108474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org """ 109474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org for lkgr in self["lkgrs"]: 110474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org # LKGRs are reverse sorted. 111474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org if int(min_rev) <= int(lkgr) and int(lkgr) < int(max_rev): 112474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org return lkgr 113f2af15a6b44ea6276bdd609ee122babe52842a42machenbach@chromium.org return None 114474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 115474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org def RunStep(self): 116474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org # Get the lkgr after the tag candidate and before the next tag candidate. 117474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org candidate_svn = self.GitSVNFindSVNRev(self["candidate"]) 118474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org if self["next"]: 119474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org next_svn = self.GitSVNFindSVNRev(self["next"]) 120474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org else: 121474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org # Don't include the version change commit itself if there is no upper 122474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org # limit yet. 123474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org candidate_svn = str(int(candidate_svn) + 1) 124474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org next_svn = sys.maxint 125474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org lkgr_svn = self.LastLKGR(candidate_svn, next_svn) 126474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 127474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org if not lkgr_svn: 128474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org print "There is no lkgr since the candidate version yet." 129474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self.CommonCleanup() 130474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org return True 131474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 132474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org # Let's check if the lkgr is at least three hours old. 133474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self["lkgr"] = self.GitSVNFindGitHash(lkgr_svn) 134474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org if not self["lkgr"]: 135474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org print "Couldn't find git hash for lkgr %s" % lkgr_svn 136474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self.CommonCleanup() 137474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org return True 138474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 139474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org lkgr_utc_time = int(self.GitLog(n=1, format="%at", git_hash=self["lkgr"])) 140474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org current_utc_time = self._side_effect_handler.GetUTCStamp() 141474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 142474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org if current_utc_time < lkgr_utc_time + 10800: 143474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org print "Candidate lkgr %s is too recent for tagging." % lkgr_svn 144474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self.CommonCleanup() 145474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org return True 146474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 147474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org print "Tagging revision %s with %s" % (lkgr_svn, self["candidate_version"]) 148474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 149474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 150474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.orgclass MakeTag(Step): 151474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org MESSAGE = "Tag the version." 152474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 153474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org def RunStep(self): 154474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org if not self._options.dry_run: 155474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self.GitReset(self["lkgr"]) 156474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self.GitSVNTag(self["candidate_version"]) 157474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 158474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 159474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.orgclass CleanUp(Step): 160474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org MESSAGE = "Clean up." 161474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 162474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org def RunStep(self): 163474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org self.CommonCleanup() 164474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 165474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 166474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.orgclass AutoTag(ScriptsBase): 167474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org def _PrepareOptions(self, parser): 168474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org parser.add_argument("--dry_run", help="Don't tag the new version.", 169474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org default=False, action="store_true") 170474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 171474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org def _ProcessOptions(self, options): # pragma: no cover 172474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org if not options.dry_run and not options.author: 173474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org print "Specify your chromium.org email with -a" 174474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org return False 175474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org options.wait_for_lgtm = False 176474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org options.force_readline_defaults = True 177474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org options.force_upload = True 178474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org return True 179474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 18006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org def _Config(self): 18106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org return { 18206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org "BRANCHNAME": "auto-tag-v8", 18306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org "PERSISTFILE_BASENAME": "/tmp/v8-auto-tag-tempfile", 18406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org } 18506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org 186474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org def _Steps(self): 187474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org return [ 188474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org Preparation, 189474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org GetTags, 190474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org GetOldestUntaggedVersion, 191474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org GetLKGRs, 192474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org CalculateTagRevision, 193474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org MakeTag, 194474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org CleanUp, 195474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org ] 196474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 197474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org 198474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.orgif __name__ == "__main__": # pragma: no cover 19906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org sys.exit(AutoTag().Run()) 200