diff --git a/scripts/dependabot_merge.py b/scripts/dependabot_merge.py index 00204b7..1cb079b 100644 --- a/scripts/dependabot_merge.py +++ b/scripts/dependabot_merge.py @@ -33,6 +33,21 @@ def eligible_commits(commits): return False types = re.findall(r"(?m)^ update-type: (\S+)\s*$", metadata[1]) dependencies = re.findall(r"(?m)^- dependency-name: ", metadata[1]) + + # Requirement-only bumps omit update-type; trust only the signed, + # single-dependency subject with an unambiguous same-major increase. + if not types and len(dependencies) == 1 and "update-type:" not in metadata[1]: + subject = data["message"].splitlines()[0] + bump = re.fullmatch( + r"(?:[\w()/-]+: )?update (\S+) requirement from " + r">=(\d+\.\d+\.\d+) to >=(\d+\.\d+\.\d+)", subject, + re.IGNORECASE) + name = re.search(r"(?m)^- dependency-name: (\S+)\s*$", metadata[1]) + if bump and name and bump[1] == name[1]: + before = tuple(map(int, bump[2].split("."))) + after = tuple(map(int, bump[3].split("."))) + if after > before and after[0] == before[0]: + types = ["version-update:semver-minor"] if not types or len(types) != len(dependencies): return False if any(t not in {"version-update:semver-patch", diff --git a/scripts/dependabot_merge_test.py b/scripts/dependabot_merge_test.py index 6803783..d5384e9 100644 --- a/scripts/dependabot_merge_test.py +++ b/scripts/dependabot_merge_test.py @@ -57,6 +57,24 @@ def test_unknown_update_type(self): "version-update:semver-minor", "unknown") self.assertFalse(eligible_commits([self.commit])) + + def test_signed_requirement_bump_without_update_type(self): + self.commit["commit"]["message"] = ( + "chore: update example requirement from >=7.6.0 to >=7.7.0\n\n" + "---\nupdated-dependencies:\n- dependency-name: example\n" + " dependency-type: direct:production\n...\n") + self.assertTrue(eligible_commits([self.commit])) + original = self.commit["commit"]["message"] + for old, new in [("7.7.0", "8.0.0"), ("7.7.0", "7.5.0"), + ("7.7.0", "7.7.0rc1"), ("update example", "update other"), + (">=7.7.0", "<8"), + ("...\n", " update-type: unknown\n...\n")]: + self.commit["commit"]["message"] = original.replace(old, new) + self.assertFalse(eligible_commits([self.commit]), new) + self.commit["commit"]["message"] = original + self.commit["commit"]["verification"]["verified"] = False + self.assertFalse(eligible_commits([self.commit])) + def test_empty_commits(self): self.assertFalse(eligible_commits([]))