Files
cdesouza-chromium 5f4207624a [brockit] Fixing dos-and-donts violations (#36416)
This PR corrects several of the dos-and-donts violations under
`tools/cr`. This is particularly useful to prevent future bugs with file
reads and writes that have been persistent from time to time.
2026-05-13 17:04:36 +01:00

196 lines
6.9 KiB
Python
Executable File

#!/usr/bin/env python3
# Copyright (c) 2025 The Brave Authors. All rights reserved.
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at https://mozilla.org/MPL/2.0/.
# Notice: Keep this script as *standalone*, with no deps to `tools/cr` code, so
# users can install it with little effort and no deps surprises.
# This script has several convenience features when committing changes to
# brave-core.
#
# 1. Chromium upgrade branches automatically added as tags
#
# Any branch that starts with "cr" and is followed by a number will be added
# to the commit message as a tag (e.g. [cr100] Some change).
#
# 2. Tags can be passed in via the environment variable tags
#
# For instance `tags=CodeHealth,canary git commit -m "Some change"` will
# add [CodeHealth] and [canary] to the commit message.
#
# 3. Labels in the branch name behind '+' will be added as tags
#
# This means that a branch `canary+fix-failure` will have [canary] added to
# the commit message.
#
# 4. `culprit` environment variable for google source links
#
# If the culprit environment variable is set, it will be used to add links to
# the commit message. The culprit variable should be a comma-separated list
# of commit hashes. The script will look up the commit messages for each hash
# and add them to the commit message. The links will be in the format
# https://chromium.googlesource.com/chromium/src/+/{hash}.
#
# 5. `issue` environment variable for "Resolves" links
#
# The `issue` environment variable can be set to a comma-separated list of
# issue numbers. The script will add "Resolves" links at the end of the
# commit message.
#
# 6. `fixup!` commits are ignored
#
# If the commit message starts with "fixup!", the script will not add any
# tags or links to the commit message.
#
# 7. Issue numbers in the branch name
#
# If the branch name contains "issue-" followed by a number, the script will
# add a "Resolves" link to the commit message. For example, if the branch
# name is "codehealth+fix-issue-123", the commit message will include a link
# to "Resolves https://github.com/brave/brave-browser/issues/123".
#
# This script can be set up either as a commit-msg hook, or as a
# prepare-commit-msg hook. The difference is that the commit-msg hook will run
# after the commit message is created, while the prepare-commit-msg hook will
# run before the commit message is created, which allows you to inspect the
# insertions.
#
# To install this script as a commit-msg hook, run the following command:
# cp tools/cr/commit-msg.py .git/hooks/commit-msg
#
import os
import sys
import subprocess
import re
from pathlib import Path
PREFIXES_FOR_UPGRADE_COMMITS = [
'Update from Chromium ',
'Apply-fixed 🩹 patches from Chromium ',
'Conflict-resolved patches from Chromium ',
'Update patches from Chromium ',
'Updated strings for Chromium ',
]
def main():
if (os.path.exists('.git/rebase-merge')
or os.path.exists('.git/rebase-apply')
or os.path.exists('.git/CHERRY_PICK_HEAD')):
# There should be no changes to commit messages during a rebase or
# cherry-pick.
return 0
commit_msg_file = Path(sys.argv[1])
# Read the message provided so we can check for duplicate insertions
# beforehand.
commit_message = commit_msg_file.read_bytes().decode('utf-8')
if not commit_message or not commit_message.split('\n', 1)[0].strip():
# We should not commmit if the commit message first line is empty as
# this will cause any tags to become the effective message.
return 1
# Skip fixup! changes.
if commit_message.startswith('fixup!') or commit_message.startswith(
'amend!'):
return 0
first_line = commit_message.split('\n', 1)[0]
# Getting the branch name to see if there's any tags that can be deduced
# from it.
branch_name = subprocess.check_output(
['git', 'rev-parse', '--abbrev-ref', 'HEAD']).strip().decode()
tags = set()
# Checking for chromium upgrade branches
cr_branch_pattern = r"^cr\d+$"
if re.fullmatch(cr_branch_pattern, branch_name):
# The branch tag is excluded from the upgrade commit messages.
if not any(suffix in first_line
for suffix in PREFIXES_FOR_UPGRADE_COMMITS):
tags.add(branch_name)
elif '+' in branch_name:
# This is the simple case where `canary+fix-failure` produces a
# [canary] tag.
tags.update(branch_name.split('+')[:-1])
# Checking for tags passed in via the environment variable tags
tags_env = os.getenv("tags")
if tags_env:
tags.update(tags_env.split(','))
# Making sure we are not re-inserting tags that are already in the commit
# message
tags = [f'[{tag}]' for tag in tags if f'[{tag}]' not in first_line]
# These are the report links that are added to the commit message when
# there's an upstream culprit.
culprit_hashes = []
if os.getenv("culprit"):
culprit_hashes = os.getenv("culprit").split(',')
culprit_hashes = [
culprit_hash for culprit_hash in culprit_hashes
if culprit_hash not in commit_message
]
culprit_output = []
for culprit_hash in culprit_hashes:
culprit_output.append(
subprocess.check_output(
['git', '-C', '../', 'log', '-1',
culprit_hash]).decode().strip())
if tags:
if commit_message[0] == '[':
# If the commit message already starts with a tag, do not add a
# space in between them.
commit_message = f'{"".join(tags)}{commit_message}'
else:
commit_message = f'{"".join(tags)} {commit_message}'
issues = os.getenv("issue")
if issues:
issues = issues.split(',')
else:
issues = []
# Extract issue numbers from the branch name
issue_pattern = r"issue-(\d+)"
branch_issues = re.findall(issue_pattern, branch_name)
issues.extend(branch_issues)
# Remove duplicates
issues = list(set(issues))
if issues:
commit_message += '\n\n' + '\n'.join([
f"Resolves https://github.com/brave/brave-browser/issues/{issue}"
for issue in issues
if f'brave-browser/issues/{issue}' not in commit_message
])
if culprit_output:
chromium_links = [
f"https://chromium.googlesource.com/chromium/src/+/{culprit_hash}"
for culprit_hash in culprit_hashes
]
commit_message += ('\n\nChromium changes:'
'\n{chromium_links}\n\n{culprits}'.format(
chromium_links="\n".join(chromium_links),
culprits="\n\n".join(culprit_output)))
with commit_msg_file.open('w', encoding='utf-8', newline='') as f:
f.write(commit_message)
return 0
if __name__ == "__main__":
sys.exit(main())