summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--PRESUBMIT.cfg1
-rw-r--r--docs/chromeos-ec-firmware-test-requirements.md3
-rwxr-xr-xutil/check_low_coverage_reason.py58
3 files changed, 61 insertions, 1 deletions
diff --git a/PRESUBMIT.cfg b/PRESUBMIT.cfg
index 8cc7ddf2cd..c925185270 100644
--- a/PRESUBMIT.cfg
+++ b/PRESUBMIT.cfg
@@ -38,3 +38,4 @@ twister_test_tags = util/twister_tags.py --validate-files ${PRESUBMIT_FILES}
check_zephyr_project_config = util/check_zephyr_project_config.py -d ${PRESUBMIT_FILES}
zephyr_check_compliance = util/zephyr_check_compliance.py ${PRESUBMIT_COMMIT}
zephyr_check_testcase_yaml = ./util/zephyr_check_testcase_yaml.py --commit ${PRESUBMIT_COMMIT} ${PRESUBMIT_FILES}
+low_coverage_reason = ./util/check_low_coverage_reason.py ${PRESUBMIT_COMMIT}
diff --git a/docs/chromeos-ec-firmware-test-requirements.md b/docs/chromeos-ec-firmware-test-requirements.md
index 2e8b461eb6..721021275a 100644
--- a/docs/chromeos-ec-firmware-test-requirements.md
+++ b/docs/chromeos-ec-firmware-test-requirements.md
@@ -56,7 +56,8 @@ reports locally on your machine.
In limited cases, you may amend your commit message to include the
`LOW_COVERAGE_REASON` tag. This tag bypasses the code coverage requirement
enforced by Gerrit. Simply add the tag followed by a description to justify
-bypassing code coverage.
+bypassing code coverage. You must include a reference to a bug (in the form
+`b:1234567` or `b/1234567`) that tracks whatever issue is impeding coverage.
```
LOW_COVERAGE_REASON=no emulator for the ANX7483 exists b/248086547
diff --git a/util/check_low_coverage_reason.py b/util/check_low_coverage_reason.py
new file mode 100755
index 0000000000..c6119f6a6a
--- /dev/null
+++ b/util/check_low_coverage_reason.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python3
+# Copyright 2023 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Ensure commit messages using LOW_COVERAGE_REASON include a bug."""
+
+import logging
+import pathlib
+import re
+import sys
+
+from chromite.lib import commandline
+from chromite.lib import cros_build_lib
+from chromite.lib import git
+
+
+# Look for LOW_COVERAGE_REASON and then an optional b{:|/}number bug reference.
+LOW_COV_REGEX = re.compile(
+ r"\s*(LOW_COVERAGE_REASON=)(?:(?!b[/|:][\d]+).)*(b[/|:]([\d]+))?"
+)
+EC_BASE = pathlib.Path(__file__).resolve().parent.parent
+
+
+def main(argv=None):
+ """Check for bug in LOW_COVERAGE_REASON."""
+ parser = commandline.ArgumentParser()
+ parser.add_argument(
+ "commit_id",
+ help="Commit whose message will be checked.",
+ )
+ opts = parser.parse_args(argv)
+
+ if opts.commit_id == "pre-submit":
+ # Only run check if verifying an actual commit.
+ return 0
+
+ try:
+ commit_log = git.Log(EC_BASE, rev=opts.commit_id, max_count=1)
+ except cros_build_lib.RunCommandError as err:
+ logging.error("Unable to query git log: %s", str(err))
+ return 1
+
+ # Search commit message for LOW_COVERAGE_REASON and bug
+ matches = LOW_COV_REGEX.findall(commit_log)
+ if matches and not any({m[2] for m in matches}):
+ # We have LOW_COVERAGE_REASON line(s) but none include a bug
+ logging.error(
+ "LOW_COVERAGE_REASON line must include one or more bugs "
+ "tracking the reason for missing coverage"
+ )
+ return 1
+
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv[1:]))