2015-01-30 16:46:41 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# Copyright 2015 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.
|
|
|
|
|
2019-02-19 08:28:26 +00:00
|
|
|
# for py2/py3 compatibility
|
|
|
|
from __future__ import print_function
|
|
|
|
|
2015-01-30 16:46:41 +00:00
|
|
|
import argparse
|
|
|
|
import os
|
|
|
|
import sys
|
|
|
|
import tempfile
|
|
|
|
import urllib2
|
|
|
|
|
|
|
|
from common_includes import *
|
|
|
|
|
|
|
|
class Preparation(Step):
|
|
|
|
MESSAGE = "Preparation."
|
|
|
|
|
|
|
|
def RunStep(self):
|
2016-12-15 11:48:54 +00:00
|
|
|
self.Git("fetch origin +refs/heads/*:refs/heads/*")
|
2021-09-01 11:41:17 +00:00
|
|
|
self.GitCheckout("origin/main")
|
2015-01-30 16:46:41 +00:00
|
|
|
self.DeleteBranch("work-branch")
|
|
|
|
|
|
|
|
|
|
|
|
class PrepareBranchRevision(Step):
|
|
|
|
MESSAGE = "Check from which revision to branch off."
|
|
|
|
|
|
|
|
def RunStep(self):
|
2015-03-06 13:10:22 +00:00
|
|
|
self["push_hash"] = (self._options.revision or
|
2021-09-01 11:41:17 +00:00
|
|
|
self.GitLog(n=1, format="%H", branch="origin/main"))
|
2015-01-30 16:46:41 +00:00
|
|
|
assert self["push_hash"]
|
2019-02-19 08:28:26 +00:00
|
|
|
print("Release revision %s" % self["push_hash"])
|
2015-01-30 16:46:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
class IncrementVersion(Step):
|
|
|
|
MESSAGE = "Increment version number."
|
|
|
|
|
|
|
|
def RunStep(self):
|
|
|
|
latest_version = self.GetLatestVersion()
|
|
|
|
|
2021-09-01 11:41:17 +00:00
|
|
|
# The version file on main can be used to bump up major/minor at
|
2015-01-30 16:46:41 +00:00
|
|
|
# branch time.
|
2021-09-01 11:41:17 +00:00
|
|
|
self.GitCheckoutFile(VERSION_FILE, self.vc.RemoteMainBranch())
|
|
|
|
self.ReadAndPersistVersion("main_")
|
|
|
|
main_version = self.ArrayToVersion("main_")
|
2015-01-30 16:46:41 +00:00
|
|
|
|
2021-09-01 11:41:17 +00:00
|
|
|
# Use the highest version from main or from tags to determine the new
|
2015-01-30 16:46:41 +00:00
|
|
|
# version.
|
|
|
|
authoritative_version = sorted(
|
2021-09-01 11:41:17 +00:00
|
|
|
[main_version, latest_version], key=SortingKey)[1]
|
2015-01-30 16:46:41 +00:00
|
|
|
self.StoreVersion(authoritative_version, "authoritative_")
|
|
|
|
|
|
|
|
# Variables prefixed with 'new_' contain the new version numbers for the
|
|
|
|
# ongoing candidates push.
|
|
|
|
self["new_major"] = self["authoritative_major"]
|
|
|
|
self["new_minor"] = self["authoritative_minor"]
|
|
|
|
self["new_build"] = str(int(self["authoritative_build"]) + 1)
|
|
|
|
|
|
|
|
# Make sure patch level is 0 in a new push.
|
|
|
|
self["new_patch"] = "0"
|
|
|
|
|
|
|
|
# The new version is not a candidate.
|
|
|
|
self["new_candidate"] = "0"
|
|
|
|
|
|
|
|
self["version"] = "%s.%s.%s" % (self["new_major"],
|
|
|
|
self["new_minor"],
|
|
|
|
self["new_build"])
|
|
|
|
|
|
|
|
print ("Incremented version to %s" % self["version"])
|
|
|
|
|
|
|
|
|
|
|
|
class DetectLastRelease(Step):
|
|
|
|
MESSAGE = "Detect commit ID of last release base."
|
|
|
|
|
|
|
|
def RunStep(self):
|
2021-09-01 11:41:17 +00:00
|
|
|
self["last_push_main"] = self.GetLatestReleaseBase()
|
2015-01-30 16:46:41 +00:00
|
|
|
|
|
|
|
|
2019-10-25 08:39:13 +00:00
|
|
|
class DeleteBranchRef(Step):
|
|
|
|
MESSAGE = "Delete branch ref."
|
|
|
|
|
|
|
|
def RunStep(self):
|
|
|
|
cmd = "push origin :refs/heads/%s" % self["version"]
|
|
|
|
if self._options.dry_run:
|
|
|
|
print("Dry run. Command:\ngit %s" % cmd)
|
|
|
|
else:
|
|
|
|
try:
|
|
|
|
self.Git(cmd)
|
|
|
|
except Exception:
|
|
|
|
# Be forgiving if branch ref does not exist.
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2016-12-15 11:48:54 +00:00
|
|
|
class PushBranchRef(Step):
|
|
|
|
MESSAGE = "Create branch ref."
|
|
|
|
|
|
|
|
def RunStep(self):
|
|
|
|
cmd = "push origin %s:refs/heads/%s" % (self["push_hash"], self["version"])
|
|
|
|
if self._options.dry_run:
|
2019-02-19 08:28:26 +00:00
|
|
|
print("Dry run. Command:\ngit %s" % cmd)
|
2016-12-15 11:48:54 +00:00
|
|
|
else:
|
|
|
|
self.Git(cmd)
|
|
|
|
|
|
|
|
|
2015-01-30 16:46:41 +00:00
|
|
|
class MakeBranch(Step):
|
|
|
|
MESSAGE = "Create the branch."
|
|
|
|
|
|
|
|
def RunStep(self):
|
2021-09-01 11:41:17 +00:00
|
|
|
self.Git("reset --hard origin/main")
|
2016-12-15 11:48:54 +00:00
|
|
|
self.Git("new-branch work-branch --upstream origin/%s" % self["version"])
|
2015-01-30 16:46:41 +00:00
|
|
|
self.GitCheckoutFile(VERSION_FILE, self["latest_version"])
|
|
|
|
|
|
|
|
|
|
|
|
class SetVersion(Step):
|
|
|
|
MESSAGE = "Set correct version for candidates."
|
|
|
|
|
|
|
|
def RunStep(self):
|
|
|
|
self.SetVersion(os.path.join(self.default_cwd, VERSION_FILE), "new_")
|
|
|
|
|
|
|
|
|
2016-02-04 09:02:51 +00:00
|
|
|
class EnableMergeWatchlist(Step):
|
|
|
|
MESSAGE = "Enable watchlist entry for merge notifications."
|
|
|
|
|
|
|
|
def RunStep(self):
|
|
|
|
old_watchlist_content = FileToText(os.path.join(self.default_cwd,
|
|
|
|
WATCHLISTS_FILE))
|
|
|
|
new_watchlist_content = re.sub("(# 'v8-merges@googlegroups\.com',)",
|
|
|
|
"'v8-merges@googlegroups.com',",
|
|
|
|
old_watchlist_content)
|
|
|
|
TextToFile(new_watchlist_content, os.path.join(self.default_cwd,
|
|
|
|
WATCHLISTS_FILE))
|
|
|
|
|
|
|
|
|
2015-01-30 16:46:41 +00:00
|
|
|
class CommitBranch(Step):
|
2019-11-22 12:09:44 +00:00
|
|
|
MESSAGE = "Commit version to new branch."
|
2015-01-30 16:46:41 +00:00
|
|
|
|
|
|
|
def RunStep(self):
|
2019-11-22 12:09:44 +00:00
|
|
|
self["commit_title"] = "Version %s" % self["version"]
|
2021-08-02 11:43:59 +00:00
|
|
|
text = "%s" % (self["commit_title"])
|
2015-01-30 16:46:41 +00:00
|
|
|
TextToFile(text, self.Config("COMMITMSG_FILE"))
|
|
|
|
|
2018-12-07 12:28:46 +00:00
|
|
|
self.GitCommit(file_name=self.Config("COMMITMSG_FILE"))
|
2015-01-30 16:46:41 +00:00
|
|
|
|
|
|
|
|
2017-07-03 08:29:51 +00:00
|
|
|
class LandBranch(Step):
|
|
|
|
MESSAGE = "Upload and land changes."
|
2015-01-30 16:46:41 +00:00
|
|
|
|
|
|
|
def RunStep(self):
|
2017-07-03 08:29:51 +00:00
|
|
|
if self._options.dry_run:
|
2019-02-19 08:28:26 +00:00
|
|
|
print("Dry run - upload CL.")
|
2017-07-03 08:29:51 +00:00
|
|
|
else:
|
2018-10-16 06:35:08 +00:00
|
|
|
self.GitUpload(force=True,
|
2018-09-18 17:43:27 +00:00
|
|
|
bypass_hooks=True,
|
2018-12-07 12:28:46 +00:00
|
|
|
no_autocc=True,
|
2021-08-02 11:43:59 +00:00
|
|
|
set_bot_commit=True,
|
2018-12-07 12:28:46 +00:00
|
|
|
message_file=self.Config("COMMITMSG_FILE"))
|
2021-08-02 11:43:59 +00:00
|
|
|
# TODO(crbug.com/1176141): This might need to go through CQ.
|
|
|
|
# We'd need to wait for it to land and then tag it.
|
2016-12-15 11:48:54 +00:00
|
|
|
cmd = "cl land --bypass-hooks -f"
|
2015-01-30 16:46:41 +00:00
|
|
|
if self._options.dry_run:
|
2019-02-19 08:28:26 +00:00
|
|
|
print("Dry run. Command:\ngit %s" % cmd)
|
2015-01-30 16:46:41 +00:00
|
|
|
else:
|
|
|
|
self.Git(cmd)
|
|
|
|
|
2018-12-07 12:28:46 +00:00
|
|
|
os.remove(self.Config("COMMITMSG_FILE"))
|
|
|
|
|
2015-01-30 16:46:41 +00:00
|
|
|
|
|
|
|
class TagRevision(Step):
|
|
|
|
MESSAGE = "Tag the new revision."
|
|
|
|
|
|
|
|
def RunStep(self):
|
|
|
|
if self._options.dry_run:
|
|
|
|
print ("Dry run. Tagging \"%s\" with %s" %
|
|
|
|
(self["commit_title"], self["version"]))
|
|
|
|
else:
|
|
|
|
self.vc.Tag(self["version"],
|
2015-02-12 18:34:21 +00:00
|
|
|
"origin/%s" % self["version"],
|
2015-01-30 16:46:41 +00:00
|
|
|
self["commit_title"])
|
|
|
|
|
|
|
|
|
|
|
|
class CleanUp(Step):
|
|
|
|
MESSAGE = "Done!"
|
|
|
|
|
|
|
|
def RunStep(self):
|
|
|
|
print("Congratulations, you have successfully created version %s."
|
|
|
|
% self["version"])
|
|
|
|
|
2021-09-01 11:41:17 +00:00
|
|
|
self.GitCheckout("origin/main")
|
2015-01-30 16:46:41 +00:00
|
|
|
self.DeleteBranch("work-branch")
|
|
|
|
self.Git("gc")
|
|
|
|
|
|
|
|
|
|
|
|
class CreateRelease(ScriptsBase):
|
|
|
|
def _PrepareOptions(self, parser):
|
|
|
|
group = parser.add_mutually_exclusive_group()
|
|
|
|
group.add_argument("-f", "--force",
|
|
|
|
help="Don't prompt the user.",
|
|
|
|
default=True, action="store_true")
|
|
|
|
group.add_argument("-m", "--manual",
|
|
|
|
help="Prompt the user at every important step.",
|
|
|
|
default=False, action="store_true")
|
|
|
|
parser.add_argument("-R", "--revision",
|
|
|
|
help="The git commit ID to push (defaults to HEAD).")
|
|
|
|
|
|
|
|
def _ProcessOptions(self, options): # pragma: no cover
|
|
|
|
if not options.author or not options.reviewer:
|
2019-02-19 08:28:26 +00:00
|
|
|
print("Reviewer (-r) and author (-a) are required.")
|
2015-01-30 16:46:41 +00:00
|
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
|
|
def _Config(self):
|
|
|
|
return {
|
|
|
|
"PERSISTFILE_BASENAME": "/tmp/create-releases-tempfile",
|
|
|
|
"COMMITMSG_FILE": "/tmp/v8-create-releases-tempfile-commitmsg",
|
|
|
|
}
|
|
|
|
|
|
|
|
def _Steps(self):
|
|
|
|
return [
|
|
|
|
Preparation,
|
|
|
|
PrepareBranchRevision,
|
|
|
|
IncrementVersion,
|
|
|
|
DetectLastRelease,
|
2019-10-25 08:39:13 +00:00
|
|
|
DeleteBranchRef,
|
2016-12-15 11:48:54 +00:00
|
|
|
PushBranchRef,
|
2015-01-30 16:46:41 +00:00
|
|
|
MakeBranch,
|
|
|
|
SetVersion,
|
2016-02-04 09:02:51 +00:00
|
|
|
EnableMergeWatchlist,
|
2015-01-30 16:46:41 +00:00
|
|
|
CommitBranch,
|
2017-07-03 08:29:51 +00:00
|
|
|
LandBranch,
|
2015-01-30 16:46:41 +00:00
|
|
|
TagRevision,
|
|
|
|
CleanUp,
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": # pragma: no cover
|
|
|
|
sys.exit(CreateRelease().Run())
|