libverify_github/
pr_api.rs1use anyhow::{Context, Result};
2
3use crate::client::GitHubClient;
4use crate::types::{
5 CheckRunsResponse, CombinedStatusResponse, PrCommit, PrFile, PrMetadata, PullRequestListItem,
6 Review, SearchPrItem,
7};
8
9pub fn get_pr_files(
11 client: &GitHubClient,
12 owner: &str,
13 repo: &str,
14 pr_number: u32,
15) -> Result<Vec<PrFile>> {
16 client.paginate(&format!(
17 "/repos/{owner}/{repo}/pulls/{pr_number}/files?per_page=100"
18 ))
19}
20
21pub fn get_pr_metadata(
23 client: &GitHubClient,
24 owner: &str,
25 repo: &str,
26 pr_number: u32,
27) -> Result<PrMetadata> {
28 let path = format!("/repos/{owner}/{repo}/pulls/{pr_number}");
29 let body = client.get(&path)?;
30 serde_json::from_str(&body).context("failed to parse PR metadata")
31}
32
33pub fn list_recent_merged_prs(
35 client: &GitHubClient,
36 owner: &str,
37 repo: &str,
38 limit: usize,
39) -> Result<Vec<PullRequestListItem>> {
40 let all: Vec<PullRequestListItem> = client.paginate(&format!(
41 "/repos/{owner}/{repo}/pulls?state=closed&sort=updated&direction=desc&per_page=100"
42 ))?;
43 Ok(all
44 .into_iter()
45 .filter(|pr| pr.merged_at.is_some())
46 .take(limit)
47 .collect())
48}
49
50pub fn get_pr_reviews(
52 client: &GitHubClient,
53 owner: &str,
54 repo: &str,
55 pr_number: u32,
56) -> Result<Vec<Review>> {
57 client.paginate(&format!(
58 "/repos/{owner}/{repo}/pulls/{pr_number}/reviews?per_page=100"
59 ))
60}
61
62pub fn get_pr_commits(
64 client: &GitHubClient,
65 owner: &str,
66 repo: &str,
67 pr_number: u32,
68) -> Result<Vec<PrCommit>> {
69 client.paginate(&format!(
70 "/repos/{owner}/{repo}/pulls/{pr_number}/commits?per_page=100"
71 ))
72}
73
74pub fn get_commit_check_runs(
76 client: &GitHubClient,
77 owner: &str,
78 repo: &str,
79 git_ref: &str,
80) -> Result<CheckRunsResponse> {
81 let path = format!("/repos/{owner}/{repo}/commits/{git_ref}/check-runs?per_page=100");
82 let body = client
83 .get(&path)
84 .context("failed to fetch commit check runs")?;
85 serde_json::from_str(&body).context("failed to parse check runs response")
86}
87
88pub fn get_commit_status(
90 client: &GitHubClient,
91 owner: &str,
92 repo: &str,
93 git_ref: &str,
94) -> Result<CombinedStatusResponse> {
95 let path = format!("/repos/{owner}/{repo}/commits/{git_ref}/status");
96 let body = client.get(&path).context("failed to fetch commit status")?;
97 serde_json::from_str(&body).context("failed to parse combined status response")
98}
99
100pub fn search_merged_prs(
102 client: &GitHubClient,
103 owner: &str,
104 repo: &str,
105 since: &str,
106 until: &str,
107) -> Result<Vec<u32>> {
108 let path = format!(
109 "/search/issues?q=repo:{owner}/{repo}+is:pr+is:merged+merged:{since}..{until}&sort=created&per_page=100"
110 );
111 let items: Vec<SearchPrItem> = client
112 .paginate_search(&path)
113 .context("failed to search merged PRs by date")?;
114 Ok(items.into_iter().map(|item| item.number).collect())
115}
116
117pub fn search_merged_prs_in_range(
119 client: &GitHubClient,
120 owner: &str,
121 repo: &str,
122 start: u32,
123 end: u32,
124) -> Result<Vec<u32>> {
125 let path = format!(
126 "/search/issues?q=repo:{owner}/{repo}+is:pr+is:merged+number:{start}..{end}&sort=created&per_page=100"
127 );
128 let items: Vec<SearchPrItem> = client
129 .paginate_search(&path)
130 .context("failed to search merged PRs by number range")?;
131 Ok(items.into_iter().map(|item| item.number).collect())
132}