@@ -458,6 +458,12 @@ def test_unknown_flag_is_skipped(self):
458458
459459
460460class TestGetPrCommitMessages (unittest .TestCase ):
461+ def setUp (self ):
462+ # Never the event of whatever CI run the tests happen to be in.
463+ patcher = patch ("main.get_pr_event" , return_value = {})
464+ patcher .start ()
465+ self .addCleanup (patcher .stop )
466+
461467 def test_non_pr_event_returns_empty (self ):
462468 with patch .dict (os .environ , {"GITHUB_EVENT_NAME" : "push" }):
463469 result = main .get_pr_commit_messages ()
@@ -502,6 +508,32 @@ def test_pull_request_target_is_supported(self):
502508 result = main .get_pr_commit_messages ()
503509 self .assertEqual (result , ["fix: first" ])
504510
511+ def test_a_range_cut_short_by_a_shallow_clone_asks_the_api (self ):
512+ with (
513+ patch .dict (os .environ , {"GITHUB_EVENT_NAME" : "pull_request" }),
514+ patch ("main.get_messages_from_event_range" , return_value = [("b2" , "fix" )]),
515+ patch ("main.get_pr_event" , return_value = {"commits" : 2 }),
516+ patch ("main.get_messages_from_api" , return_value = []) as api ,
517+ patch ("main.warn_shallow_checkout" ) as warn ,
518+ ):
519+ # The API cannot help either: check what the clone had, and say so.
520+ self .assertEqual (main .get_pr_commit_messages (), [("b2" , "fix" )])
521+ api .assert_called_once ()
522+ self .assertIn ("Only 1 of the pull request's 2 commits" , warn .call_args [0 ][0 ])
523+
524+ def test_asks_the_api_when_the_clone_holds_none_of_them (self ):
525+ with (
526+ patch .dict (
527+ os .environ ,
528+ {"GITHUB_EVENT_NAME" : "pull_request" , "GITHUB_BASE_REF" : "main" },
529+ ),
530+ patch ("main.get_messages_from_event_range" , return_value = []),
531+ patch ("main.get_messages_from_merge_ref" , return_value = []),
532+ patch ("main.get_messages_from_head_ref" , return_value = []),
533+ patch ("main.get_messages_from_api" , return_value = [("a1" , "feat: one" )]),
534+ ):
535+ self .assertEqual (main .get_pr_commit_messages (), [("a1" , "feat: one" )])
536+
505537 def test_falls_back_to_base_ref_when_merge_ref_is_unavailable (self ):
506538 with (
507539 patch .dict (
@@ -1027,6 +1059,81 @@ def test_missing_git_returns_none(self):
10271059 self .assertIsNone (main .pr_head_rev ())
10281060
10291061
1062+ class TestFetchPrHead (unittest .TestCase ):
1063+ def test_a_head_the_clone_lacks_is_fetched_without_history (self ):
1064+ # rev-parse fails, the fetch succeeds, rev-parse now resolves.
1065+ run = MagicMock (
1066+ side_effect = [
1067+ MagicMock (returncode = 1 ),
1068+ MagicMock (returncode = 0 ),
1069+ MagicMock (returncode = 0 ),
1070+ ]
1071+ )
1072+ with (
1073+ patch ("main.get_pr_head_sha" , return_value = "abc123" ),
1074+ patch ("main.subprocess.run" , run ),
1075+ ):
1076+ self .assertEqual (main .pr_head_rev (), "abc123" )
1077+ self .assertEqual (
1078+ run .call_args_list [1 ][0 ][0 ],
1079+ ["git" , "fetch" , "--no-tags" , "--quiet" , "--depth=1" , "origin" , "abc123" ],
1080+ )
1081+
1082+ def test_a_fetch_without_git_gives_up (self ):
1083+ with patch ("main.subprocess.run" , side_effect = OSError ("no git" )):
1084+ self .assertFalse (main ._fetch_commit ("abc123" ))
1085+
1086+
1087+ class TestGetMessagesFromApi (unittest .TestCase ):
1088+ """A clone without the pull request's commits lists them through the API."""
1089+
1090+ def _run (self , total , api_commits , head = "b2" ):
1091+ pull = MagicMock ()
1092+ pull .get_commits .return_value = [
1093+ MagicMock (sha = sha , commit = MagicMock (message = msg ))
1094+ for sha , msg in api_commits
1095+ ]
1096+ github_module = MagicMock ()
1097+ github_module .Github .return_value .get_repo .return_value .get_pull .return_value = (
1098+ pull
1099+ )
1100+ env = {
1101+ "GITHUB_TOKEN" : "token" ,
1102+ "GITHUB_REPOSITORY" : "owner/repo" ,
1103+ "GITHUB_API_URL" : "https://ghe.example.com/api/v3" ,
1104+ }
1105+ with (
1106+ patch .dict (os .environ , env ),
1107+ patch ("main.get_pr_event" , return_value = {"number" : 7 , "commits" : total }),
1108+ patch ("main.get_pr_head_sha" , return_value = head ),
1109+ patch .dict (sys .modules , {"github" : github_module }),
1110+ ):
1111+ return main .get_messages_from_api (), github_module
1112+
1113+ def test_lists_the_commits_oldest_first (self ):
1114+ commits = [("a1" , "feat: one" ), ("b2" , "fix: two" )]
1115+ result , github_module = self ._run (2 , commits )
1116+ self .assertEqual (result , commits )
1117+ self .assertEqual (
1118+ github_module .Github .call_args [1 ]["base_url" ],
1119+ "https://ghe.example.com/api/v3" ,
1120+ )
1121+
1122+ def test_a_list_that_ends_elsewhere_is_not_used (self ):
1123+ # A force push after the event: same count, other commits.
1124+ result , _ = self ._run (2 , [("a1" , "feat: one" ), ("c3" , "fix: other" )])
1125+ self .assertEqual (result , [])
1126+
1127+ def test_a_partial_list_is_not_used (self ):
1128+ result , _ = self ._run (3 , [("a1" , "feat: one" ), ("b2" , "fix: two" )])
1129+ self .assertEqual (result , [])
1130+
1131+ def test_more_than_the_api_returns_is_left_unlisted (self ):
1132+ result , github_module = self ._run (main .API_COMMIT_LIMIT + 1 , [])
1133+ self .assertEqual (result , [])
1134+ github_module .Github .assert_not_called ()
1135+
1136+
10301137class TestCheckoutHint (unittest .TestCase ):
10311138 def test_pull_request_names_fetch_depth (self ):
10321139 with patch .dict (os .environ , {"GITHUB_EVENT_NAME" : "pull_request" }):
0 commit comments