Presubmit OEM check
Add presubmit check to `repo upload` that checks to see
if any OEM names are present in the CL description.
BUG=chromium:982868
TEST=presubmit unit tests
Change-Id: I9e83164b2e1e5a0e303f6b8cbc8fa410f540cf58
Reviewed-on: https://chromium-review.googlesource.com/1692080
Tested-by: Jack Neus <jackneus@google.com>
Commit-Ready: Jack Neus <jackneus@google.com>
Legacy-Commit-Queue: Commit Bot <commit-bot@chromium.org>
Reviewed-by: Paul Fagerburg <pfagerburg@chromium.org>
Reviewed-by: Jack Rosenthal <jrosenth@chromium.org>
Reviewed-by: Nick Crews <ncrews@chromium.org>
diff --git a/pre-upload.py b/pre-upload.py
index 2aedc8f..ed69623 100755
--- a/pre-upload.py
+++ b/pre-upload.py
@@ -634,6 +634,60 @@
return HookFailure(msg)
+def _check_change_no_include_oem(project, commit):
+ """Check that the change does not reference OEMs."""
+ ALLOWLIST = {
+ 'chromiumos/platform/ec',
+ # Used by unit tests.
+ 'project',
+ }
+ if project.name not in ALLOWLIST:
+ return None
+
+ TAGS = (
+ 'Reviewed-on',
+ 'Reviewed-by',
+ 'Signed-off-by',
+ 'Commit-Ready',
+ 'Tested-by',
+ 'Commit-Queue',
+ 'Legacy-Commit-Queue',
+ 'Acked-by',
+ 'Modified-by',
+ 'CC',
+ 'Suggested-by',
+ 'Reported-by',
+ 'Acked-for-chrome-by',
+ )
+
+ # Ignore tags, which could reasonably contain OEM names
+ # (e.g. Reviewed-by: foo@oem.corp-partner.google.com).
+ def tag_filter(x):
+ return not any(x.lower().startswith(h.lower()) for h in TAGS)
+
+ commit_message = ' '.join(
+ filter(tag_filter, _get_commit_desc(commit).splitlines()))
+ commit_message = re.sub(r'[\s_-]+', ' ', commit_message)
+
+ # Exercise caution when expanding these lists. Adding a name
+ # could indicate a new relationship with a company!
+ OEMS = ['hp', 'hewlett packard', 'dell', 'lenovo', 'acer', 'asus', 'samsung']
+ ODMS = [
+ 'bitland', 'compal', 'haier', 'huaqin', 'inventec', 'lg', 'pegatron',
+ 'pegatron(ems)', 'quanta', 'samsung', 'wistron'
+ ]
+
+ for name_type, name_list in [('OEM', OEMS), ('ODM', ODMS)]:
+ # Construct regex
+ name_re = r'\b(%s)\b' % '|'.join([re.escape(x) for x in name_list])
+ matches = [x[0] for x in re.findall(name_re, commit_message, re.IGNORECASE)]
+ if len(matches):
+ # If there's a match, throw an error.
+ error_msg = ('Changelist description contains the name of an'
+ ' %s: "%s".' % (name_type, '","'.join(matches)))
+ return HookFailure(error_msg)
+
+
def _check_for_uprev(project, commit, project_top=None):
"""Check that we're not missing a revbump of an ebuild in the given commit.
@@ -1640,9 +1694,9 @@
_check_change_has_proper_changeid,
_check_commit_message_style,
_check_change_is_contribution,
+ _check_change_no_include_oem,
]
-
# A list of hooks that are not project-specific
_COMMON_HOOKS = [
_check_cq_ini_well_formed,
diff --git a/pre-upload_unittest.py b/pre-upload_unittest.py
index 1cb9fe0..1e55864 100755
--- a/pre-upload_unittest.py
+++ b/pre-upload_unittest.py
@@ -1233,6 +1233,54 @@
self.assertMessageAccepted('foo\n\nChange-Id: I1234\nSigned-off-by: Hi\n')
+class CheckCommitMessageNoOEM(CommitMessageTestCase):
+ """Tests for _check_change_no_include_oem."""
+
+ @staticmethod
+ def CheckMessage(project, commit):
+ return pre_upload._check_change_no_include_oem(project, commit)
+
+ def testNormal(self):
+ """Accept a commit message w/o reference to an OEM/ODM."""
+ self.assertMessageAccepted('foo\n')
+
+ def testHasOEM(self):
+ """Catch commit messages referencing OEMs."""
+ self.assertMessageRejected('HP Project\n\n')
+ self.assertMessageRejected('hewlett-packard\n')
+ self.assertMessageRejected('Hewlett\nPackard\n')
+ self.assertMessageRejected('Dell Chromebook\n\n\n')
+ self.assertMessageRejected('product@acer.com\n')
+ self.assertMessageRejected('This is related to Asus\n')
+ self.assertMessageRejected('lenovo machine\n')
+
+ def testHasODM(self):
+ """Catch commit messages referencing ODMs."""
+ self.assertMessageRejected('new samsung laptop\n\n')
+ self.assertMessageRejected('pegatron(ems) project\n')
+ self.assertMessageRejected('new Wistron device\n')
+
+ def testContainsOEM(self):
+ """Check that the check handles word boundaries properly."""
+ self.assertMessageAccepted('oheahpohea')
+ self.assertMessageAccepted('Play an Asus7 guitar chord.\n\n')
+
+ def testTag(self):
+ """Check that the check ignores tags."""
+ self.assertMessageAccepted(
+ 'Harmless project\n'
+ 'Reviewed-by: partner@asus.corp-partner.google.com\n'
+ 'Tested-by: partner@hp.corp-partner.google.com\n'
+ 'Signed-off-by: partner@dell.corp-partner.google.com\n'
+ 'Commit-Queue: partner@lenovo.corp-partner.google.com\n'
+ 'Legacy-Commit-Queue: partner@acer.corp-partner.google.com\n'
+ 'CC: partner@acer.corp-partner.google.com\n'
+ 'Acked-by: partner@hewlett-packard.corp-partner.google.com\n')
+ self.assertMessageRejected(
+ 'Asus project\n'
+ 'Reviewed-by: partner@asus.corp-partner.google.com')
+
+
class CheckCommitMessageStyle(CommitMessageTestCase):
"""Tests for _check_commit_message_style."""