enforce cq-depend/change-id positions

The CQ rejects CLs that have Cq-Depend's in places other
than the same paragraph as Change-Id, as shown in this
rejection message:

Your CL may be incorrectly using CQ feature(s):
 * Line 19: u'Cq-Depend: chromium:1626803, chromium:1626804,
 chromium:1626805, chromium:1626806, chromium:1620554, chromium:1627304,
 chromium:1627305': CQ-Depend must be in the last paragraph (like

so checking it earlier can save one roundtrip.

TEST=tested both correct and incorrect input

Change-Id: I679785db2a62c0d1acbbf93239049588c6ae8921
Commit-Ready: Luigi Semenzato <>
Tested-by: Luigi Semenzato <>
Legacy-Commit-Queue: Commit Bot <>
Reviewed-by: Luigi Semenzato <>
diff --git a/ b/
index db6edc2..441d873 100755
--- a/
+++ b/
@@ -100,7 +100,6 @@
 # excluded from presubmit checks. Lines beginning with '#' are ignored.
 _IGNORE_FILE = '.presubmitignore'
 # Exceptions
@@ -560,12 +559,21 @@
 def _check_change_has_valid_cq_depend(_project, commit):
   """Check for a correctly formatted Cq-Depend field in the commit message."""
+  desc = _get_commit_desc(commit)
   msg = 'Changelist has invalid Cq-Depend target.'
   example = 'Example: Cq-Depend: chromium:1234, chrome-internal:2345'
-    patch.GetPaladinDeps(_get_commit_desc(commit))
+    patch.GetPaladinDeps(desc)
   except ValueError as ex:
     return HookFailure(msg, [example, str(ex)])
+  # Check that Cq-Depend is in the same paragraph as Change-Id.
+  msg = 'Cq-Depend (or CQ-DEPEND) is not in the same paragraph as Change-Id.'
+  paragraphs = desc.split('\n\n')
+  for paragraph in paragraphs:
+    if ('^Cq-Depend:', paragraph, re.M) or
+'^CQ-DEPEND=', paragraph, re.M)) \
+        and not'^Change-Id:', paragraph, re.M):
+      return HookFailure(msg)
 def _check_change_is_contribution(_project, commit):
diff --git a/ b/
index 7ad2504..99b695c 100755
--- a/
+++ b/
@@ -1053,12 +1053,13 @@
   def testNormal(self):
     """Accept valid Cq-Depends line."""
-    self.assertMessageAccepted('\nCq-Depend: chromium:1234\n')
+    self.assertMessageAccepted('\nCq-Depend: chromium:1234\nChange-Id: I123')
   def testInvalid(self):
     """Reject invalid Cq-Depends line."""
     self.assertMessageRejected('\nCq-Depend: None\n')
+    self.assertMessageRejected('\nCq-Depend: chromium:1234\n\nChange-Id: I123')
 class CheckCommitMessageContribution(CommitMessageTestCase):