Commit b621958c authored by Leszek Swirski's avatar Leszek Swirski Committed by V8 LUCI CQ

[tools] Add a roll_merge using the Gerrit API

roll_merge.py manually checks out V8 into a temporary directory, locally
builds a cherrypick, and uploads this to Gerrit. However, Gerrit has its
own REST API which allows cherrypicking. Using this API directly has two
advantages:

  1) We don't need to perform any local checkouts, so it's much faster,
     and
  2) The cherry-picked commit is marked as a cherry-pick by Gerrit,
     which means Rubber-Stamper-Bot will treat it as a cherry-pick.

The implementation for now is very simple, and doesn't support things
like cherry-picking multiple revisions or applying an additional local
patch. It does, however, increment the patch value in v8-version.h, and
tries to set Owners-Override +1.

Bug: v8:12849
Change-Id: Ie242dbec6b3d24f5118d601e9d326465d190a8f0
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3644609
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarMichael Achenbach <machenbach@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81072}
parent 436f0889
#!/usr/bin/env python3
# Copyright 2022 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 logging
import os
import re
import sys
# Add depot tools to the sys path, for gerrit_util
sys.path.append(
os.path.abspath(
os.path.join(
os.path.dirname(os.path.abspath(__file__)),
'../../third_party/depot_tools')))
import gerrit_util
from common_includes import VERSION_FILE
GERRIT_HOST = 'chromium-review.googlesource.com'
def ExtractVersion(include_file_text):
version = {}
for line in include_file_text.split('\n'):
def ReadAndPersist(var_name, def_name):
match = re.match(r"^#define %s\s+(\d*)" % def_name, line)
if match:
value = match.group(1)
version[var_name] = int(value)
for (var_name, def_name) in [("major", "V8_MAJOR_VERSION"),
("minor", "V8_MINOR_VERSION"),
("build", "V8_BUILD_NUMBER"),
("patch", "V8_PATCH_LEVEL")]:
ReadAndPersist(var_name, def_name)
return version
def main():
parser = argparse.ArgumentParser(
description="Use the gerrit API to cherry-pick a revision")
parser.add_argument(
"-a",
"--author",
default="",
help="The author email used for code review.")
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("--branch", help="The branch to merge to (e.g. 10.3.171)")
# TODO(leszeks): Add support for more than one revision. This will need to
# cherry pick one of them using the gerrit API, then somehow applying the rest
# onto it as additional patches.
parser.add_argument("revision", nargs=1, help="The revision to merge.")
options = parser.parse_args()
# Get the original commit.
revision = options.revision[0]
print("Cherry-picking %s onto %s" % (revision, options.branch))
# Create a cherry pick commit from the original commit.
cherry_pick = gerrit_util.CherryPick(GERRIT_HOST, revision, options.branch)
cherry_pick_id = cherry_pick['id']
print("Created cherry-pick: https://%s/c/%s" %
(GERRIT_HOST, cherry_pick['_number']))
print("Extracting target version...")
# Get the version out of the cherry-picked commit's v8-version.h
include_file_text = gerrit_util.GetFileContents(GERRIT_HOST, cherry_pick_id,
VERSION_FILE).decode('utf-8')
version = ExtractVersion(include_file_text)
print("... version is %s" % str(version))
new_patch = version['patch'] + 1
# Add the 'roll_merge' hashtag so that Rubberstamper knows that this is a
# benign cherry pick.
print("Setting 'roll-merge' hashtag...")
gerrit_util.CallGerritApi(
GERRIT_HOST,
'changes/%s/hashtags' % cherry_pick_id,
reqtype='POST',
body={'add': ["roll-merge"]})
# Increment the patch number in v8-version.h
print("Updating %s to patch level %d..." % (VERSION_FILE, new_patch))
include_file_text = re.sub(
r"(?<=#define V8_PATCH_LEVEL)(?P<space>\s+)\d*$",
r"\g<space>%d" % new_patch,
include_file_text,
flags=re.MULTILINE)
gerrit_util.ChangeEdit(GERRIT_HOST, cherry_pick_id, VERSION_FILE,
include_file_text)
# Create the commit message, using the new version and information about the
# original commit.
print("Updating commit message...")
original_commit = gerrit_util.GetChangeCommit(GERRIT_HOST, revision)
commit_msg = "\n".join([
"Version %d.%d.%d.%d (cherry-pick)" %
(version["major"], version["minor"], version["build"], new_patch), #
"", #
"Merged %s" % original_commit['commit'], #
"", #
"%s" % original_commit['subject'], #
])
gerrit_util.SetChangeEditMessage(GERRIT_HOST, cherry_pick_id, commit_msg)
# Publish the change edit with the v8-version.h and commit message changes.
print("Publishing changes...")
gerrit_util.PublishChangeEdit(GERRIT_HOST, cherry_pick_id)
# Set Owners-Override +1
print("Setting 'Owners-Override +1'...")
try:
gerrit_util.SetReview(
GERRIT_HOST, cherry_pick_id, labels={"Owners-Override": 1})
except:
logging.WARNING("Could not set Owners-Override +1")
print("Adding Rubber Stamper as a reviewer...")
gerrit_util.AddReviewers(
GERRIT_HOST,
cherry_pick_id,
reviewers=['rubber-stamper@appspot.gserviceaccount.com'])
print("Cherry-pick created successfully: https://%s/c/%s" %
(GERRIT_HOST, cherry_pick['_number']))
if __name__ == "__main__": # pragma: no cover
sys.exit(main())
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment