summaryrefslogtreecommitdiff
path: root/util/update_release_branch.py
diff options
context:
space:
mode:
authorTom Hughes <tomhughes@chromium.org>2022-09-21 14:10:01 -0700
committerTom Hughes <tomhughes@chromium.org>2022-09-22 12:49:33 -0700
commit2bcf863b492fe7ed8105c853814dba6ed32ba719 (patch)
treefcf6ce5810f9ff9e3c8cce434812dd75492269ed /util/update_release_branch.py
parente5fb0b9ba488614b5684e640530f00821ab7b943 (diff)
parent28712dae9d7ed1e694f7622cc083afa71090d4d5 (diff)
downloadchrome-ec-2bcf863b492fe7ed8105c853814dba6ed32ba719.tar.gz
Merge remote-tracking branch cros/main into firmware-fpmcu-bloonchipper-releasefirmware-fpmcu-bloonchipper-release
Generated by: ./util/update_release_branch.py --board bloonchipper --relevant_paths_file ./util/fingerprint-relevant-paths.txt firmware- fpmcu-bloonchipper-release Relevant changes: git log --oneline e5fb0b9ba4..28712dae9d -- board/hatch_fp board/bloonchipper common/fpsensor docs/fingerprint driver/fingerprint util/getversion.sh ded9307b79 util/getversion.sh: Fix version when not in a git repo 956055e692 board: change Google USB vendor info 71b2ef709d Update license boilerplate text in source code files 33e11afda0 Revert "fpsensor: Build fpsensor source file with C++" c8d0360723 fpsensor: Build fpsensor source file with C++ bc113abd53 fpsensor: Fix g++ compiler error 150a58a0dc fpsensor: Fix fp_set_sensor_mode return type b33b5ce85b fpsensor: Remove nested designators for C++ compatibility 2e864b2539 tree-wide: const-ify argv for console commands 56d8b360f9 test: Add test for get ikm failure when seed not set 3a3d6c3690 test: Add test for fpsensor trivial key failure 233e6bbd08 fpsensor_crypto: Abstract calls to hmac_SHA256 0a041b285b docs/fingerprint: Typo correction c03fab67e2 docs/fingerprint: Fix the path of fputils.py 0b5d4baf5a util/getversion.sh: Fix empty file list handling 6e128fe760 FPMCU dev board environment with Satlab 3eb29b6aa5 builtin: Move ssize_t to sys/types.h 345d62ebd1 docs/fingerprint: Update power numbers for latest dartmonkey release c25ffdb316 common: Conditionally support printf %l and %i modifiers 9a3c514b45 test: Add a test to check if the debugger is connected 54e603413f Move standard library tests to their own file 43fa6b4bf8 docs/fingerprint: Update power numbers for latest bloonchipper release 25536f9a84 driver/fingerprint/fpc/bep/fpc_sensor_spi.c: Format with clang-format 4face99efd driver/fingerprint/fpc/libfp/fpc_sensor_pal.h: Format with clang-format 738de2b575 trng: Rename rand to trng_rand 14b8270edd docs/fingerprint: Update dragonclaw power numbers 0b268f93d1 driver/fingerprint/fpc/libfp/fpc_private.c: Format with clang-format f80da163f2 driver/fingerprint/fpc/libfp/fpc_private.h: Format with clang-format 5e9c85c9b1 driver/fingerprint/fpc/libfp/fpc_sensor_pal.c: Format with clang-format c1f9dd3cf8 driver/fingerprint/fpc/libfp/fpc_bio_algorithm.h: Format with clang-format eb1e1bed8d driver/fingerprint/fpc/libfp/fpc1145_private.h: Format with clang-format 6e7b611821 driver/fingerprint/fpc/bep/fpc_bio_algorithm.h: Format with clang-format e0589cd5e2 driver/fingerprint/fpc/bep/fpc1035_private.h: Format with clang-format 7905e556a0 common/fpsensor/fpsensor_crypto.c: Format with clang-format 21289d170c driver/fingerprint/fpc/bep/fpc1025_private.h: Format with clang-format 98a20f937e common/fpsensor/fpsensor_state.c: Format with clang-format a2d255d8af common/fpsensor/fpsensor.c: Format with clang-format 73055eeb3f driver/fingerprint/fpc/bep/fpc_private.c: Format with clang-format 0f7b5cb509 common/fpsensor/fpsensor_private.h: Format with clang-format 1ceade6e65 driver/fingerprint/fpc/bep/fpc_private.h: Format with clang-format dc3e9008b8 board/hatch_fp/board.h: Format with clang-format dca9d74321 Revert "trng: Rename rand to trng_rand" a6b0b3554f trng: Rename rand to trng_rand 28d0b75b70 third_party/boringssl: Remove unused header BRANCH=None BUG=b:246424843 b:234181908 b:244781166 b:234181908 b:244387210 BUG=b:242720240 chromium:1098010 b:180945056 b:236025198 b:234181908 BUG=b:234181908 b:237344361 b:131913998 b:236386294 b:234143158 BUG=b:234781655 b:215613183 b:242720910 TEST=`make -j buildall` TEST=./test/run_device_tests.py --board bloonchipper Test "aes": PASSED Test "cec": PASSED Test "cortexm_fpu": PASSED Test "crc": PASSED Test "flash_physical": PASSED Test "flash_write_protect": PASSED Test "fpsensor_hw": PASSED Test "fpsensor_spi_ro": PASSED Test "fpsensor_spi_rw": PASSED Test "fpsensor_uart_ro": PASSED Test "fpsensor_uart_rw": PASSED Test "mpu_ro": PASSED Test "mpu_rw": PASSED Test "mutex": PASSED Test "pingpong": PASSED Test "printf": PASSED Test "queue": PASSED Test "rollback_region0": PASSED Test "rollback_region1": PASSED Test "rollback_entropy": PASSED Test "rtc": PASSED Test "sha256": PASSED Test "sha256_unrolled": PASSED Test "static_if": PASSED Test "stdlib": PASSED Test "system_is_locked_wp_on": PASSED Test "system_is_locked_wp_off": PASSED Test "timer_dos": PASSED Test "utils": PASSED Test "utils_str": PASSED Test "stm32f_rtc": PASSED Test "panic_data_bloonchipper_v2.0.4277": PASSED Test "panic_data_bloonchipper_v2.0.5938": PASSED Force-Relevant-Builds: all Signed-off-by: Tom Hughes <tomhughes@chromium.org> Change-Id: I264ad0ffe7afcd507a1e483c6e934a9c4fea47c3
Diffstat (limited to 'util/update_release_branch.py')
-rwxr-xr-xutil/update_release_branch.py366
1 files changed, 248 insertions, 118 deletions
diff --git a/util/update_release_branch.py b/util/update_release_branch.py
index b9063d4970..0a871724fe 100755
--- a/util/update_release_branch.py
+++ b/util/update_release_branch.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright 2021 The Chromium OS Authors. All rights reserved.
+# Copyright 2021 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Release branch updater tool.
@@ -19,11 +19,10 @@ import subprocess
import sys
import textwrap
+BUG_NONE_PATTERN = re.compile("none", flags=re.IGNORECASE)
-BUG_NONE_PATTERN = re.compile('none', flags=re.IGNORECASE)
-
-def git_commit_msg(branch, head, merge_head, rel_paths, cmd):
+def git_commit_msg(cros_main, branch, head, merge_head, rel_paths, cmd):
"""Generates a merge commit message based off of relevant changes.
This function obtains the relevant commits from the given relative paths in
@@ -31,6 +30,7 @@ def git_commit_msg(branch, head, merge_head, rel_paths, cmd):
showing the command used to find the relevant commits.
Args:
+ cros_main: String indicating the origin branch name
branch: String indicating the release branch name
head: String indicating the HEAD refspec
merge_head: String indicating the merge branch refspec.
@@ -42,18 +42,17 @@ def git_commit_msg(branch, head, merge_head, rel_paths, cmd):
A String containing the git commit message with the exception of the
Signed-Off-By field and Change-ID field.
"""
- relevant_commits_cmd, relevant_commits = get_relevant_commits(head,
- merge_head,
- '--oneline',
- rel_paths)
+ relevant_commits_cmd, relevant_commits = get_relevant_commits(
+ head, merge_head, "--oneline", rel_paths
+ )
- _, relevant_bugs = get_relevant_commits(head, merge_head, '', rel_paths)
- relevant_bugs = set(re.findall('BUG=(.*)', relevant_bugs))
+ _, relevant_bugs = get_relevant_commits(head, merge_head, "", rel_paths)
+ relevant_bugs = set(re.findall("BUG=(.*)", relevant_bugs))
# Filter out "none" from set of bugs
filtered = []
for bug_line in relevant_bugs:
- bug_line = bug_line.replace(',', ' ')
- bugs = bug_line.split(' ')
+ bug_line = bug_line.replace(",", " ")
+ bugs = bug_line.split(" ")
for bug in bugs:
if bug and not BUG_NONE_PATTERN.match(bug):
filtered.append(bug)
@@ -61,8 +60,8 @@ def git_commit_msg(branch, head, merge_head, rel_paths, cmd):
# TODO(b/179509333): remove Cq-Include-Trybots line when regular CQ and
# firmware CQ do not behave differently.
- COMMIT_MSG_TEMPLATE = """
-Merge remote-tracking branch cros/main into {BRANCH}
+ commit_msg_template = """
+Merge remote-tracking branch {CROS_MAIN} into {BRANCH}
Generated by: {COMMAND_LINE}
@@ -76,24 +75,27 @@ BRANCH=None
{BUG_FIELD}
TEST=`make -j buildall`
-Cq-Include-Trybots: chromeos/cq:cq-orchestrator
+Force-Relevant-Builds: all
"""
- # Wrap the relevant commits command and bug field such that we don't exceed
- # 72 cols.
+ # Wrap the commands and bug field such that we don't exceed 72 cols.
relevant_commits_cmd = textwrap.fill(relevant_commits_cmd, width=72)
+ cmd = textwrap.fill(cmd, width=72)
# Wrap at 68 cols to save room for 'BUG='
- bugs = textwrap.wrap(' '.join(relevant_bugs), width=68)
- bug_field = ''
+ bugs = textwrap.wrap(" ".join(relevant_bugs), width=68)
+ bug_field = ""
for line in bugs:
- bug_field += 'BUG=' + line + '\n'
+ bug_field += "BUG=" + line + "\n"
# Remove the final newline since the template adds it for us.
bug_field = bug_field[:-1]
- return COMMIT_MSG_TEMPLATE.format(BRANCH=branch,
- RELEVANT_COMMITS_CMD=relevant_commits_cmd,
- RELEVANT_COMMITS=relevant_commits,
- BUG_FIELD=bug_field,
- COMMAND_LINE=cmd)
+ return commit_msg_template.format(
+ CROS_MAIN=cros_main,
+ BRANCH=branch,
+ RELEVANT_COMMITS_CMD=relevant_commits_cmd,
+ RELEVANT_COMMITS=relevant_commits,
+ BUG_FIELD=bug_field,
+ COMMAND_LINE=cmd,
+ )
def get_relevant_boards(baseboard):
@@ -105,15 +107,16 @@ def get_relevant_boards(baseboard):
Returns:
A list of strings containing the boards based off of the baseboard.
"""
- proc = subprocess.run(['git', 'grep', 'BASEBOARD:=' + baseboard, '--',
- 'board/'],
- stdout=subprocess.PIPE,
- encoding='utf-8',
- check=True)
+ proc = subprocess.run(
+ ["git", "grep", "BASEBOARD:=" + baseboard, "--", "board/"],
+ stdout=subprocess.PIPE,
+ encoding="utf-8",
+ check=True,
+ )
boards = []
res = proc.stdout.splitlines()
for line in res:
- boards.append(line.split('/')[1])
+ boards.append(line.split("/")[1])
return boards
@@ -135,21 +138,25 @@ def get_relevant_commits(head, merge_head, fmt, relevant_paths):
stdout.
"""
if fmt:
- cmd = ['git', 'log', fmt, head + '..' + merge_head, '--',
- relevant_paths]
+ cmd = [
+ "git",
+ "log",
+ fmt,
+ head + ".." + merge_head,
+ "--",
+ relevant_paths,
+ ]
else:
- cmd = ['git', 'log', head + '..' + merge_head, '--', relevant_paths]
+ cmd = ["git", "log", head + ".." + merge_head, "--", relevant_paths]
# Pass cmd as a string to subprocess.run() since we need to run with shell
# equal to True. The reason we are using shell equal to True is to take
# advantage of the glob expansion for the relevant paths.
- cmd = ' '.join(cmd)
- proc = subprocess.run(cmd,
- stdout=subprocess.PIPE,
- encoding='utf-8',
- check=True,
- shell=True)
- return ''.join(proc.args), proc.stdout
+ cmd = " ".join(cmd)
+ proc = subprocess.run(
+ cmd, stdout=subprocess.PIPE, encoding="utf-8", check=True, shell=True
+ )
+ return "".join(proc.args), proc.stdout
def main(argv):
@@ -165,112 +172,235 @@ def main(argv):
argv: A list of the command line arguments passed to this script.
"""
# Set up argument parser.
- parser = argparse.ArgumentParser(description=('A script that generates a '
- 'merge commit from cros/main'
- ' to a desired release '
- 'branch. By default, the '
- '"recursive" merge strategy '
- 'with the "theirs" strategy '
- 'option is used.'))
- parser.add_argument('--baseboard')
- parser.add_argument('--board')
- parser.add_argument('release_branch', help=('The name of the target release'
- ' branch'))
- parser.add_argument('--relevant_paths_file',
- help=('A path to a text file which includes other '
- 'relevant paths of interest for this board '
- 'or baseboard'))
- parser.add_argument('--merge_strategy', '-s', default='recursive',
- help='The merge strategy to pass to `git merge -s`')
- parser.add_argument('--strategy_option', '-X',
- help=('The strategy option for the chosen merge '
- 'strategy'))
+ parser = argparse.ArgumentParser(
+ description=(
+ "A script that generates a "
+ "merge commit from cros/main"
+ " to a desired release "
+ "branch. By default, the "
+ '"recursive" merge strategy '
+ 'with the "theirs" strategy '
+ "option is used."
+ )
+ )
+ parser.add_argument("--baseboard")
+ parser.add_argument("--board")
+ parser.add_argument(
+ "release_branch", help=("The name of the target release" " branch")
+ )
+ parser.add_argument(
+ "--remote_prefix",
+ help=(
+ "The name of the remote branch prefix (default cros). "
+ "Private repos typically use cros-internal instead."
+ ),
+ default="cros",
+ )
+ parser.add_argument(
+ "--relevant_paths_file",
+ help=(
+ "A path to a text file which includes other "
+ "relevant paths of interest for this board "
+ "or baseboard"
+ ),
+ )
+ parser.add_argument(
+ "--merge_strategy",
+ "-s",
+ default="recursive",
+ help="The merge strategy to pass to `git merge -s`",
+ )
+ parser.add_argument(
+ "--strategy_option",
+ "-X",
+ help=("The strategy option for the chosen merge " "strategy"),
+ )
+ parser.add_argument(
+ "--remove_owners",
+ "-r",
+ action=("store_true"),
+ help=("Remove non-root OWNERS level files if present"),
+ )
opts = parser.parse_args(argv[1:])
- baseboard_dir = ''
- board_dir = ''
+ baseboard_dir = ""
+ board_dir = ""
if opts.baseboard:
# Dereference symlinks so "git log" works as expected.
- baseboard_dir = os.path.relpath('baseboard/' + opts.baseboard)
+ baseboard_dir = os.path.relpath("baseboard/" + opts.baseboard)
baseboard_dir = os.path.relpath(os.path.realpath(baseboard_dir))
boards = get_relevant_boards(opts.baseboard)
elif opts.board:
- board_dir = os.path.relpath('board/' + opts.board)
+ board_dir = os.path.relpath("board/" + opts.board)
board_dir = os.path.relpath(os.path.realpath(board_dir))
boards = [opts.board]
else:
- parser.error('You must specify a board OR a baseboard')
+ boards = []
- print('Gathering relevant paths...')
+ print("Gathering relevant paths...")
relevant_paths = []
if opts.baseboard:
relevant_paths.append(baseboard_dir)
- else:
+ elif opts.board:
relevant_paths.append(board_dir)
for board in boards:
- relevant_paths.append('board/' + board)
+ relevant_paths.append("board/" + board)
# Check for the existence of a file that has other paths of interest.
if opts.relevant_paths_file and os.path.exists(opts.relevant_paths_file):
- with open(opts.relevant_paths_file, 'r') as relevant_paths_file:
+ with open(opts.relevant_paths_file, "r") as relevant_paths_file:
for line in relevant_paths_file:
- if not line.startswith('#'):
+ if not line.startswith("#"):
relevant_paths.append(line.rstrip())
- relevant_paths.append('util/getversion.sh')
- relevant_paths = ' '.join(relevant_paths)
+ if os.path.exists("util/getversion.sh"):
+ relevant_paths.append("util/getversion.sh")
+ relevant_paths = " ".join(relevant_paths)
# Check if we are already in merge process
- result = subprocess.run(['git', 'rev-parse', '--quiet', '--verify',
- 'MERGE_HEAD'], stdout=subprocess.DEVNULL,
- stderr=subprocess.DEVNULL, check=False)
+ result = subprocess.run(
+ ["git", "rev-parse", "--quiet", "--verify", "MERGE_HEAD"],
+ stdout=subprocess.DEVNULL,
+ stderr=subprocess.DEVNULL,
+ check=False,
+ )
+
+ # Prune OWNERS files if desired
+ if opts.remove_owners:
+ prunelist = []
+ for root, dirs, files in os.walk("."):
+ for name in dirs:
+ if "build" in name:
+ continue
+ for name in files:
+ if "OWNERS" in name:
+ path = os.path.join(root, name)
+ prunelist.append(path[2:]) # Strip the "./"
+
+ # Remove the top level OWNERS file from the prunelist.
+ try:
+ prunelist.remove("OWNERS")
+ except ValueError:
+ pass
+
+ if prunelist:
+ print("Not merging the following OWNERS files:")
+ for path in prunelist:
+ print(" " + path)
+
if result.returncode:
# Let's perform the merge
- print('Updating remote...')
- subprocess.run(['git', 'remote', 'update'], check=True)
- subprocess.run(['git', 'checkout', '-B', opts.release_branch, 'cros/' +
- opts.release_branch], check=True)
- print('Attempting git merge...')
- if opts.merge_strategy == 'recursive' and not opts.strategy_option:
- opts.strategy_option = 'theirs'
- print('Using "%s" merge strategy' % opts.merge_strategy,
- ("with strategy option '%s'" % opts.strategy_option
- if opts.strategy_option else ''))
- arglist = ['git', 'merge', '--no-ff', '--no-commit', 'cros/main', '-s',
- opts.merge_strategy]
+ print("Updating remote...")
+ subprocess.run(["git", "remote", "update"], check=True)
+ subprocess.run(
+ [
+ "git",
+ "checkout",
+ "-B",
+ opts.release_branch,
+ opts.remote_prefix + "/" + opts.release_branch,
+ ],
+ check=True,
+ )
+ print("Attempting git merge...")
+ if opts.merge_strategy == "recursive" and not opts.strategy_option:
+ opts.strategy_option = "theirs"
+ print(
+ 'Using "%s" merge strategy' % opts.merge_strategy,
+ (
+ "with strategy option '%s'" % opts.strategy_option
+ if opts.strategy_option
+ else ""
+ ),
+ )
+ cros_main = opts.remote_prefix + "/" + "main"
+ arglist = [
+ "git",
+ "merge",
+ "--no-ff",
+ "--no-commit",
+ cros_main,
+ "-s",
+ opts.merge_strategy,
+ ]
if opts.strategy_option:
- arglist.append('-X' + opts.strategy_option)
- subprocess.run(arglist, check=True)
+ arglist.append("-X" + opts.strategy_option)
+ try:
+ subprocess.run(arglist, check=True)
+ except:
+ # We've likely encountered a merge conflict due to new OWNERS file
+ # modifications. If we're removing the owners, we'll delete them.
+ if opts.remove_owners and prunelist:
+ # Find the unmerged files
+ unmerged = (
+ subprocess.run(
+ ["git", "diff", "--name-only", "--diff-filter=U"],
+ stdout=subprocess.PIPE,
+ encoding="utf-8",
+ check=True,
+ )
+ .stdout.rstrip()
+ .split()
+ )
+
+ # Prune OWNERS files
+ for file in unmerged:
+ if file in prunelist:
+ subprocess.run(["git", "rm", file], check=False)
+ unmerged.remove(file)
+
+ print("Removed non-root OWNERS files.")
+ if unmerged:
+ print(
+ "Unmerged files still exist! You need to manually resolve this."
+ )
+ print("\n".join(unmerged))
+ sys.exit(1)
+ else:
+ raise
else:
- print('We have already started merge process.',
- 'Attempt to generate commit.')
-
- print('Generating commit message...')
- branch = subprocess.run(['git', 'rev-parse', '--abbrev-ref', 'HEAD'],
- stdout=subprocess.PIPE,
- encoding='utf-8',
- check=True).stdout.rstrip()
- head = subprocess.run(['git', 'rev-parse', '--short', 'HEAD'],
- stdout=subprocess.PIPE,
- encoding='utf-8',
- check=True).stdout.rstrip()
- merge_head = subprocess.run(['git', 'rev-parse', '--short',
- 'MERGE_HEAD'],
- stdout=subprocess.PIPE,
- encoding='utf-8',
- check=True).stdout.rstrip()
-
- cmd = ' '.join(argv)
- print('Typing as fast as I can...')
- commit_msg = git_commit_msg(branch, head, merge_head, relevant_paths, cmd)
- subprocess.run(['git', 'commit', '--signoff', '-m', commit_msg], check=True)
- subprocess.run(['git', 'commit', '--amend'], check=True)
- print(("Finished! **Please review the commit to see if it's to your "
- 'liking.**'))
-
-
-if __name__ == '__main__':
+ print(
+ "We have already started merge process.",
+ "Attempt to generate commit.",
+ )
+
+ print("Generating commit message...")
+ branch = subprocess.run(
+ ["git", "rev-parse", "--abbrev-ref", "HEAD"],
+ stdout=subprocess.PIPE,
+ encoding="utf-8",
+ check=True,
+ ).stdout.rstrip()
+ head = subprocess.run(
+ ["git", "rev-parse", "--short", "HEAD"],
+ stdout=subprocess.PIPE,
+ encoding="utf-8",
+ check=True,
+ ).stdout.rstrip()
+ merge_head = subprocess.run(
+ ["git", "rev-parse", "--short", "MERGE_HEAD"],
+ stdout=subprocess.PIPE,
+ encoding="utf-8",
+ check=True,
+ ).stdout.rstrip()
+
+ cmd = " ".join(argv)
+ print("Typing as fast as I can...")
+ commit_msg = git_commit_msg(
+ cros_main, branch, head, merge_head, relevant_paths, cmd
+ )
+ subprocess.run(["git", "commit", "--signoff", "-m", commit_msg], check=True)
+ subprocess.run(["git", "commit", "--amend"], check=True)
+ print(
+ (
+ "Finished! **Please review the commit to see if it's to your "
+ "liking.**"
+ )
+ )
+
+
+if __name__ == "__main__":
main(sys.argv)