diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2024-12-06 22:16:44 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2024-12-06 22:16:44 +0000 |
| commit | f0d0e1ba1cba11d3a98a5ab0c7f1dc72b6bc4e17 (patch) | |
| tree | a7f459091dd2fa6da7f3805a864dbc530f422e24 /tests/git_remote_nostr | |
| parent | cabbdea4ae39a57cbff10d24084a888ca9948083 (diff) | |
feat(push): send fast-forward merge status event
when a proposal was merged using fast-forward status rather than
by creating a three way merge commit.
if there are multiple revisions, the first one that contains merged
proposal tip will be referenced.
if there are multiple proposals that contain one of the commits,
they will all be marked as merged.
the nip needs to be updated as there is no single `merge-commit-id`
so that tag needs to support multiple values
Diffstat (limited to 'tests/git_remote_nostr')
| -rw-r--r-- | tests/git_remote_nostr/push.rs | 193 |
1 files changed, 183 insertions, 10 deletions
diff --git a/tests/git_remote_nostr/push.rs b/tests/git_remote_nostr/push.rs index b93475c..4dc2c1d 100644 --- a/tests/git_remote_nostr/push.rs +++ b/tests/git_remote_nostr/push.rs | |||
| @@ -894,7 +894,8 @@ async fn pushes_to_all_git_servers_listed_and_ok_printed() -> Result<()> { | |||
| 894 | 894 | ||
| 895 | #[tokio::test] | 895 | #[tokio::test] |
| 896 | #[serial] | 896 | #[serial] |
| 897 | async fn proposal_merge_commit_pushed_to_main_leads_to_status_event_issued() -> Result<()> { | 897 | async fn proposal_three_way_merge_commit_pushed_to_main_leads_to_status_event_issued() -> Result<()> |
| 898 | { | ||
| 898 | // | 899 | // |
| 899 | let (events, source_git_repo) = prep_source_repo_and_events_including_proposals().await?; | 900 | let (events, source_git_repo) = prep_source_repo_and_events_including_proposals().await?; |
| 900 | let source_path = source_git_repo.dir.to_str().unwrap().to_string(); | 901 | let source_path = source_git_repo.dir.to_str().unwrap().to_string(); |
| @@ -958,11 +959,14 @@ async fn proposal_merge_commit_pushed_to_main_leads_to_status_event_issued() -> | |||
| 958 | r57.listen_until_close(), | 959 | r57.listen_until_close(), |
| 959 | ); | 960 | ); |
| 960 | 961 | ||
| 961 | let (output, oid) = cli_tester_handle.join().unwrap()?; | 962 | let (output, merge_oid) = cli_tester_handle.join().unwrap()?; |
| 962 | 963 | ||
| 963 | assert_eq!( | 964 | assert_eq!( |
| 964 | output, | 965 | output, |
| 965 | format!(" 431b84e..{} main -> main\r\n", &oid.to_string()[..7]) | 966 | format!( |
| 967 | " 431b84e..{} main -> main\r\n", | ||
| 968 | &merge_oid.to_string()[..7] | ||
| 969 | ) | ||
| 966 | ); | 970 | ); |
| 967 | 971 | ||
| 968 | let new_events = r55 | 972 | let new_events = r55 |
| @@ -976,7 +980,7 @@ async fn proposal_merge_commit_pushed_to_main_leads_to_status_event_issued() -> | |||
| 976 | 980 | ||
| 977 | assert_eq!(new_events.len(), 2, "{new_events:?}"); | 981 | assert_eq!(new_events.len(), 2, "{new_events:?}"); |
| 978 | 982 | ||
| 979 | let proposal = r55 | 983 | let proposal_cover_letter_event = r55 |
| 980 | .events | 984 | .events |
| 981 | .iter() | 985 | .iter() |
| 982 | .find(|e| { | 986 | .find(|e| { |
| @@ -993,14 +997,15 @@ async fn proposal_merge_commit_pushed_to_main_leads_to_status_event_issued() -> | |||
| 993 | .unwrap(); | 997 | .unwrap(); |
| 994 | 998 | ||
| 995 | assert_eq!( | 999 | assert_eq!( |
| 996 | oid.to_string(), | 1000 | vec!["merge-commit-id".to_string(), merge_oid.to_string()], |
| 997 | merge_status | 1001 | merge_status |
| 998 | .tags | 1002 | .tags |
| 999 | .iter() | 1003 | .iter() |
| 1000 | .find(|t| t.as_slice()[0].eq("merge-commit-id")) | 1004 | .find(|t| t.as_slice()[0].eq("merge-commit-id")) |
| 1001 | .unwrap() | 1005 | .unwrap() |
| 1002 | .as_slice()[1], | 1006 | .clone() |
| 1003 | "status sets correct merge-commit-id tag" | 1007 | .to_vec(), |
| 1008 | "status sets correct merge-commit-id tag {merge_status:?}" | ||
| 1004 | ); | 1009 | ); |
| 1005 | 1010 | ||
| 1006 | let proposal_tip = r55 | 1011 | let proposal_tip = r55 |
| @@ -1009,7 +1014,7 @@ async fn proposal_merge_commit_pushed_to_main_leads_to_status_event_issued() -> | |||
| 1009 | .filter(|e| { | 1014 | .filter(|e| { |
| 1010 | e.tags | 1015 | e.tags |
| 1011 | .iter() | 1016 | .iter() |
| 1012 | .any(|t| t.as_slice()[1].eq(&proposal.id.to_string())) | 1017 | .any(|t| t.as_slice()[1].eq(&proposal_cover_letter_event.id.to_string())) |
| 1013 | && e.kind.eq(&Kind::GitPatch) | 1018 | && e.kind.eq(&Kind::GitPatch) |
| 1014 | }) | 1019 | }) |
| 1015 | .last() | 1020 | .last() |
| @@ -1029,7 +1034,175 @@ async fn proposal_merge_commit_pushed_to_main_leads_to_status_event_issued() -> | |||
| 1029 | ); | 1034 | ); |
| 1030 | 1035 | ||
| 1031 | assert_eq!( | 1036 | assert_eq!( |
| 1032 | proposal.id.to_string(), | 1037 | proposal_cover_letter_event.id.to_string(), |
| 1038 | merge_status | ||
| 1039 | .tags | ||
| 1040 | .iter() | ||
| 1041 | .find(|t| t.is_root()) | ||
| 1042 | .unwrap() | ||
| 1043 | .as_slice()[1], | ||
| 1044 | "status tags proposal id as root \r\nmerge status:\r\n{}\r\nproposal:\r\n{}", | ||
| 1045 | merge_status.as_json(), | ||
| 1046 | proposal_cover_letter_event.as_json(), | ||
| 1047 | ); | ||
| 1048 | |||
| 1049 | Ok(()) | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | #[tokio::test] | ||
| 1053 | #[serial] | ||
| 1054 | async fn proposal_fast_forward_merge_commits_pushed_to_main_leads_to_status_event_issued() | ||
| 1055 | -> Result<()> { | ||
| 1056 | // | ||
| 1057 | let (events, source_git_repo) = prep_source_repo_and_events_including_proposals().await?; | ||
| 1058 | let source_path = source_git_repo.dir.to_str().unwrap().to_string(); | ||
| 1059 | |||
| 1060 | let (mut r51, mut r52, mut r53, mut r55, mut r56, mut r57) = ( | ||
| 1061 | Relay::new(8051, None, None), | ||
| 1062 | Relay::new(8052, None, None), | ||
| 1063 | Relay::new(8053, None, None), | ||
| 1064 | Relay::new(8055, None, None), | ||
| 1065 | Relay::new(8056, None, None), | ||
| 1066 | Relay::new(8057, None, None), | ||
| 1067 | ); | ||
| 1068 | r51.events = events.clone(); | ||
| 1069 | r55.events = events.clone(); | ||
| 1070 | |||
| 1071 | #[allow(clippy::mutable_key_type)] | ||
| 1072 | let before = r55.events.iter().cloned().collect::<HashSet<Event>>(); | ||
| 1073 | |||
| 1074 | let cli_tester_handle = std::thread::spawn(move || -> Result<(String, Oid)> { | ||
| 1075 | let branch_name = get_proposal_branch_name_from_events(&events, FEATURE_BRANCH_NAME_1)?; | ||
| 1076 | |||
| 1077 | let git_repo = clone_git_repo_with_nostr_url()?; | ||
| 1078 | git_repo.checkout_remote_branch(&branch_name)?; | ||
| 1079 | git_repo.checkout("refs/heads/main")?; | ||
| 1080 | |||
| 1081 | CliTester::new_git_with_remote_helper_from_dir( | ||
| 1082 | &git_repo.dir, | ||
| 1083 | ["merge", &branch_name, "-m", "proposal merge commit message"], | ||
| 1084 | ) | ||
| 1085 | .expect_end_eventually_and_print()?; | ||
| 1086 | |||
| 1087 | let oid = git_repo.get_tip_of_local_branch("main")?; | ||
| 1088 | |||
| 1089 | let mut p = CliTester::new_git_with_remote_helper_from_dir(&git_repo.dir, ["push"]); | ||
| 1090 | cli_expect_nostr_fetch(&mut p)?; | ||
| 1091 | p.expect(format!("fetching {} ref list over filesystem...\r\n", source_path).as_str())?; | ||
| 1092 | p.expect("list: connecting...\r\n")?; | ||
| 1093 | p.expect_eventually(format!( | ||
| 1094 | "fast-forward merge: create nostr proposal status event for {branch_name}\r\n" | ||
| 1095 | ))?; | ||
| 1096 | // status updates printed here | ||
| 1097 | p.expect_eventually(format!("To {}\r\n", get_nostr_remote_url()?).as_str())?; | ||
| 1098 | let output = p.expect_end_eventually()?; | ||
| 1099 | |||
| 1100 | for p in [51, 52, 53, 55, 56, 57] { | ||
| 1101 | relay::shutdown_relay(8000 + p)?; | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | Ok((output, oid)) | ||
| 1105 | }); | ||
| 1106 | // launch relays | ||
| 1107 | let _ = join!( | ||
| 1108 | r51.listen_until_close(), | ||
| 1109 | r52.listen_until_close(), | ||
| 1110 | r53.listen_until_close(), | ||
| 1111 | r55.listen_until_close(), | ||
| 1112 | r56.listen_until_close(), | ||
| 1113 | r57.listen_until_close(), | ||
| 1114 | ); | ||
| 1115 | |||
| 1116 | let (output, tip_oid) = cli_tester_handle.join().unwrap()?; | ||
| 1117 | |||
| 1118 | assert_eq!( | ||
| 1119 | output, | ||
| 1120 | format!( | ||
| 1121 | " 431b84e..{} main -> main\r\n", | ||
| 1122 | &tip_oid.to_string()[..7] | ||
| 1123 | ) | ||
| 1124 | ); | ||
| 1125 | |||
| 1126 | let new_events = r55 | ||
| 1127 | .events | ||
| 1128 | .iter() | ||
| 1129 | .cloned() | ||
| 1130 | .collect::<HashSet<Event>>() | ||
| 1131 | .difference(&before) | ||
| 1132 | .cloned() | ||
| 1133 | .collect::<Vec<Event>>(); | ||
| 1134 | |||
| 1135 | assert_eq!(new_events.len(), 2, "{new_events:?}"); | ||
| 1136 | |||
| 1137 | let proposal_cover_letter_event = r55 | ||
| 1138 | .events | ||
| 1139 | .iter() | ||
| 1140 | .find(|e| { | ||
| 1141 | e.tags | ||
| 1142 | .iter() | ||
| 1143 | .find(|t| t.as_slice()[0].eq("branch-name")) | ||
| 1144 | .is_some_and(|t| t.as_slice()[1].eq(FEATURE_BRANCH_NAME_1)) | ||
| 1145 | }) | ||
| 1146 | .unwrap(); | ||
| 1147 | |||
| 1148 | let proposal_patches: Vec<&Event> = r55 | ||
| 1149 | .events | ||
| 1150 | .iter() | ||
| 1151 | .filter(|e| { | ||
| 1152 | e.kind == Kind::GitPatch | ||
| 1153 | && e.tags | ||
| 1154 | .iter() | ||
| 1155 | .any(|t| t.as_slice()[1].eq(&proposal_cover_letter_event.id.to_string())) | ||
| 1156 | }) | ||
| 1157 | .collect(); | ||
| 1158 | |||
| 1159 | let merge_status = new_events | ||
| 1160 | .iter() | ||
| 1161 | .find(|e| e.kind.eq(&Kind::GitStatusApplied)) | ||
| 1162 | .unwrap(); | ||
| 1163 | // println!("{:?}", proposal_cover_letter_event); | ||
| 1164 | // println!("merge status"); | ||
| 1165 | // println!("{:?}", merge_status); | ||
| 1166 | |||
| 1167 | let patch_commit_ids = proposal_patches | ||
| 1168 | .iter() | ||
| 1169 | .map(|e| { | ||
| 1170 | e.tags | ||
| 1171 | .iter() | ||
| 1172 | .find(|t| t.as_slice()[0].eq("commit")) | ||
| 1173 | .unwrap() | ||
| 1174 | .as_slice()[1] | ||
| 1175 | .to_string() | ||
| 1176 | }) | ||
| 1177 | .collect::<Vec<String>>(); | ||
| 1178 | assert_eq!( | ||
| 1179 | [vec!["merge-commit-id".to_string()], patch_commit_ids].concat(), | ||
| 1180 | merge_status | ||
| 1181 | .tags | ||
| 1182 | .iter() | ||
| 1183 | .find(|t| t.as_slice()[0].eq("merge-commit-id")) | ||
| 1184 | .unwrap() | ||
| 1185 | .clone() | ||
| 1186 | .to_vec(), | ||
| 1187 | "status sets correct merge-commit-id tag {merge_status:?}" | ||
| 1188 | ); | ||
| 1189 | |||
| 1190 | for patch_id in proposal_patches | ||
| 1191 | .iter() | ||
| 1192 | .map(|e| e.id.to_string()) | ||
| 1193 | .collect::<Vec<String>>() | ||
| 1194 | { | ||
| 1195 | assert!( | ||
| 1196 | merge_status.tags.iter().any(|t| t.as_slice().len().eq(&4) | ||
| 1197 | && t.as_slice()[1] == patch_id | ||
| 1198 | && t.as_slice()[3].eq("mention")), | ||
| 1199 | "merge status doesnt mention proposal patch {patch_id} \r\nmerge status:\r\n{}", | ||
| 1200 | merge_status.as_json(), | ||
| 1201 | ); | ||
| 1202 | } | ||
| 1203 | |||
| 1204 | assert_eq!( | ||
| 1205 | proposal_cover_letter_event.id.to_string(), | ||
| 1033 | merge_status | 1206 | merge_status |
| 1034 | .tags | 1207 | .tags |
| 1035 | .iter() | 1208 | .iter() |
| @@ -1038,7 +1211,7 @@ async fn proposal_merge_commit_pushed_to_main_leads_to_status_event_issued() -> | |||
| 1038 | .as_slice()[1], | 1211 | .as_slice()[1], |
| 1039 | "status tags proposal id as root \r\nmerge status:\r\n{}\r\nproposal:\r\n{}", | 1212 | "status tags proposal id as root \r\nmerge status:\r\n{}\r\nproposal:\r\n{}", |
| 1040 | merge_status.as_json(), | 1213 | merge_status.as_json(), |
| 1041 | proposal.as_json(), | 1214 | proposal_cover_letter_event.as_json(), |
| 1042 | ); | 1215 | ); |
| 1043 | 1216 | ||
| 1044 | Ok(()) | 1217 | Ok(()) |