refactor: migrate to github gql api

This commit is contained in:
2026-05-08 02:23:28 +08:00
parent 7de0039d38
commit 19769a7b75
11 changed files with 177422 additions and 228 deletions

View File

@@ -145,7 +145,7 @@ fn render_github_fixtures(fixture_root: &Path) -> String {
continue;
};
issue_fixtures.insert((filter, page), read_json_fixture(&entry.path()));
issue_fixtures.insert((filter, page), read_issue_fixture(&entry.path()));
}
let mut output = String::new();
@@ -160,7 +160,9 @@ fn render_github_fixtures(fixture_root: &Path) -> String {
output.push_str(&string_literal(&repo_list));
output.push_str("\n}\n\n");
output.push_str("pub fn issues_pull_requests(filter: &str, page: u32) -> Option<&'static str> {\n");
output.push_str(
"pub fn issues_pull_requests(filter: &str, page: u32) -> Option<&'static str> {\n",
);
output.push_str(" match (filter, page) {\n");
for ((filter, page), json) in issue_fixtures {
output.push_str(" (");
@@ -187,6 +189,85 @@ fn read_json_fixture(path: &Path) -> String {
.unwrap_or_else(|err| panic!("failed to serialize fixture {}: {err}", path.display()))
}
fn read_issue_fixture(path: &Path) -> String {
let raw = fs::read_to_string(path)
.unwrap_or_else(|err| panic!("failed to read fixture {}: {err}", path.display()));
let value: serde_json::Value = serde_json::from_str(&raw)
.unwrap_or_else(|err| panic!("invalid json fixture {}: {err}", path.display()));
let issues = value
.as_array()
.unwrap_or_else(|| panic!("issue fixture {} must be a json array", path.display()));
let items = issues.iter().map(map_issue_fixture).collect::<Vec<_>>();
let start_cursor = issues.first().and_then(issue_fixture_cursor);
let end_cursor = issues.last().and_then(issue_fixture_cursor);
serde_json::to_string(&serde_json::json!({
"items": items,
"start_cursor": start_cursor,
"end_cursor": end_cursor,
}))
.unwrap_or_else(|err| {
panic!(
"failed to serialize mapped issue fixture {}: {err}",
path.display()
)
})
}
fn map_issue_fixture(issue: &serde_json::Value) -> serde_json::Value {
serde_json::json!({
"title": required_string(issue, &["title"]),
"state": issue_fixture_state(issue),
"is_draft": issue.get("draft").and_then(serde_json::Value::as_bool).unwrap_or(false),
"repo_slug": required_string(issue, &["repository", "full_name"]),
})
}
fn issue_fixture_state(issue: &serde_json::Value) -> &'static str {
if issue
.get("pull_request")
.and_then(|pull_request| pull_request.get("merged_at"))
.and_then(serde_json::Value::as_str)
.is_some()
{
return "Merged";
}
match required_string(issue, &["state"]) {
"open" => "Open",
"closed" => "Closed",
_ => "Unknown",
}
}
fn issue_fixture_cursor(issue: &serde_json::Value) -> Option<String> {
issue
.get("node_id")
.and_then(serde_json::Value::as_str)
.map(str::to_owned)
.or_else(|| {
issue
.get("id")
.and_then(serde_json::Value::as_u64)
.map(|id| id.to_string())
})
}
fn required_string<'a>(value: &'a serde_json::Value, path: &[&str]) -> &'a str {
let mut current = value;
for key in path {
current = current
.get(*key)
.unwrap_or_else(|| panic!("missing key {} in fixture", path.join(".")));
}
current
.as_str()
.unwrap_or_else(|| panic!("expected string at {} in fixture", path.join(".")))
}
fn parse_issue_fixture_name(file_name: &str) -> Option<(String, u32)> {
let name = file_name.strip_suffix(".json")?;
let rest = name.strip_prefix("issues.pull_requests.")?;