6d1825e21a
No-Try: true Bug: chromium:1292013 Change-Id: Id9966157d28528b28e820d328b4941287a310209 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3521790 Reviewed-by: Liviu Rau <liviurau@chromium.org> Auto-Submit: Michael Achenbach <machenbach@chromium.org> Commit-Queue: Michael Achenbach <machenbach@chromium.org> Cr-Commit-Position: refs/heads/main@{#79476}
237 lines
6.7 KiB
Python
Executable File
237 lines
6.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# 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.
|
|
|
|
import argparse
|
|
import os
|
|
import sys
|
|
import tempfile
|
|
|
|
from common_includes import *
|
|
|
|
import urllib.request as urllib2
|
|
|
|
|
|
class Preparation(Step):
|
|
MESSAGE = "Preparation."
|
|
|
|
def RunStep(self):
|
|
self.Git("fetch origin +refs/heads/*:refs/heads/*")
|
|
self.GitCheckout("origin/main")
|
|
self.DeleteBranch("work-branch")
|
|
|
|
|
|
class PrepareBranchRevision(Step):
|
|
MESSAGE = "Check from which revision to branch off."
|
|
|
|
def RunStep(self):
|
|
self["push_hash"] = (self._options.revision or
|
|
self.GitLog(n=1, format="%H", branch="origin/main"))
|
|
assert self["push_hash"]
|
|
print("Release revision %s" % self["push_hash"])
|
|
|
|
|
|
class IncrementVersion(Step):
|
|
MESSAGE = "Increment version number."
|
|
|
|
def RunStep(self):
|
|
latest_version = self.GetLatestVersion()
|
|
|
|
# The version file on main can be used to bump up major/minor at
|
|
# branch time.
|
|
self.GitCheckoutFile(VERSION_FILE, self.vc.RemoteMainBranch())
|
|
self.ReadAndPersistVersion("main_")
|
|
main_version = self.ArrayToVersion("main_")
|
|
|
|
# Use the highest version from main or from tags to determine the new
|
|
# version.
|
|
authoritative_version = sorted(
|
|
[main_version, latest_version], key=LooseVersion)[1]
|
|
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):
|
|
self["last_push_main"] = self.GetLatestReleaseBase()
|
|
|
|
|
|
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
|
|
|
|
|
|
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:
|
|
print("Dry run. Command:\ngit %s" % cmd)
|
|
else:
|
|
self.Git(cmd)
|
|
|
|
|
|
class MakeBranch(Step):
|
|
MESSAGE = "Create the branch."
|
|
|
|
def RunStep(self):
|
|
self.Git("reset --hard origin/main")
|
|
self.Git("new-branch work-branch --upstream origin/%s" % self["version"])
|
|
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_")
|
|
|
|
|
|
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))
|
|
|
|
|
|
class CommitBranch(Step):
|
|
MESSAGE = "Commit version to new branch."
|
|
|
|
def RunStep(self):
|
|
self["commit_title"] = "Version %s" % self["version"]
|
|
text = "%s" % (self["commit_title"])
|
|
TextToFile(text, self.Config("COMMITMSG_FILE"))
|
|
|
|
self.GitCommit(file_name=self.Config("COMMITMSG_FILE"))
|
|
|
|
|
|
class LandBranch(Step):
|
|
MESSAGE = "Upload and land changes."
|
|
|
|
def RunStep(self):
|
|
if self._options.dry_run:
|
|
print("Dry run - upload CL.")
|
|
else:
|
|
self.GitUpload(force=True,
|
|
bypass_hooks=True,
|
|
no_autocc=True,
|
|
set_bot_commit=True,
|
|
message_file=self.Config("COMMITMSG_FILE"))
|
|
# TODO(crbug.com/1176141): This might need to go through CQ.
|
|
# We'd need to wait for it to land and then tag it.
|
|
cmd = "cl land --bypass-hooks -f"
|
|
if self._options.dry_run:
|
|
print("Dry run. Command:\ngit %s" % cmd)
|
|
else:
|
|
self.Git(cmd)
|
|
|
|
os.remove(self.Config("COMMITMSG_FILE"))
|
|
|
|
|
|
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"],
|
|
"origin/%s" % self["version"],
|
|
self["commit_title"])
|
|
|
|
|
|
class CleanUp(Step):
|
|
MESSAGE = "Done!"
|
|
|
|
def RunStep(self):
|
|
print("Congratulations, you have successfully created version %s."
|
|
% self["version"])
|
|
|
|
self.GitCheckout("origin/main")
|
|
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:
|
|
print("Reviewer (-r) and author (-a) are required.")
|
|
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,
|
|
DeleteBranchRef,
|
|
PushBranchRef,
|
|
MakeBranch,
|
|
SetVersion,
|
|
EnableMergeWatchlist,
|
|
CommitBranch,
|
|
LandBranch,
|
|
TagRevision,
|
|
CleanUp,
|
|
]
|
|
|
|
|
|
if __name__ == "__main__": # pragma: no cover
|
|
sys.exit(CreateRelease().Run())
|