Conversation
chore: merge dev into preview
chore(scripts): 跟踪版本同步脚本
chore: merge dev into preview
chore(ci): 支持macOS构建与便携版exe
chore: 合并 dev 到 preview
Summary of ChangesHello @YueerMoe, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! 此拉取请求将 Highlights
Changelog
Ignored Files
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
本次 PR 将 preview 分支的改动合并到 master 以进行正式发布,包含了大量改进。主要有:
- 构建流程改进:切换到
yarn作为包管理器,并新增了set-version.ps1脚本来同步项目各处的版本号。 - 文档更新:
README.md中更新了开发指南,并增加了新的分支与发布流程说明。 - 更新逻辑重构:对
updater.ts进行了重大重构,引入semver库进行更可靠的版本比较,并增加了对预发布版本的支持。 - 后端支持:在 Rust 后端增加了相应接口来从 GitHub 获取预发布版本信息。
整体来看,这些改动大大提升了项目的发布流程自动化程度和更新功能的健壮性。我的审查意见主要针对新引入的脚本和后端服务,提出了一些关于代码可维护性和鲁棒性的建议。
scripts/set-version.ps1
Outdated
| $indent = ($line -replace '^(\s*).+$', '$1') | ||
| $lines[$i] = ($indent + 'version = "' + $NewVersion + '"') |
| pub async fn fetch_latest_prerelease(client: &reqwest::Client) -> Result<LatestRelease, String> { | ||
| let url = "https://api.github.com/repos/BoxCatTeam/endfield-cat/releases?per_page=20"; | ||
| let resp = client | ||
| .get(url) | ||
| .header("Accept", "application/vnd.github+json") | ||
| .header("User-Agent", "endfield-cat/tauri") | ||
| .send() | ||
| .await | ||
| .map_err(|e| e.to_string())?; | ||
|
|
||
| let status = resp.status(); | ||
| if !status.is_success() { | ||
| return Err(format!("GitHub API status {}", status)); | ||
| } | ||
|
|
||
| let json: serde_json::Value = resp.json().await.map_err(|e| e.to_string())?; | ||
| let releases = json.as_array().ok_or("Invalid GitHub response: expected array")?; | ||
|
|
||
| let target = releases.iter().find(|r| { | ||
| r.get("draft").and_then(|v| v.as_bool()) == Some(false) | ||
| && r.get("prerelease").and_then(|v| v.as_bool()) == Some(true) | ||
| }); | ||
|
|
||
| let Some(target) = target else { | ||
| return Err("No prerelease found".to_string()); | ||
| }; | ||
|
|
||
| let tag_name = target | ||
| .get("tag_name") | ||
| .or_else(|| target.get("name")) | ||
| .and_then(|v| v.as_str()) | ||
| .unwrap_or("") | ||
| .to_string(); | ||
|
|
||
| if tag_name.is_empty() { | ||
| return Err("Missing tag_name in GitHub response".to_string()); | ||
| } | ||
|
|
||
| let name = target.get("name").and_then(|v| v.as_str()).map(|s| s.to_string()); | ||
| let html_url = target.get("html_url").and_then(|v| v.as_str()).map(|s| s.to_string()); | ||
| let body = target.get("body").and_then(|v| v.as_str()).map(|s| s.to_string()); | ||
|
|
||
| let download_url = if cfg!(target_os = "windows") { | ||
| target | ||
| .get("assets") | ||
| .and_then(|v| v.as_array()) | ||
| .and_then(|assets| { | ||
| assets.iter().find_map(|asset| { | ||
| let name = asset.get("name").and_then(|v| v.as_str())?; | ||
| if name.ends_with(".exe") { | ||
| asset.get("browser_download_url").and_then(|v| v.as_str()).map(|s| s.to_string()) | ||
| } else { | ||
| None | ||
| } | ||
| }) | ||
| }) | ||
| } else { | ||
| None | ||
| }; | ||
|
|
||
| Ok(LatestRelease { tag_name, name, html_url, download_url, body }) | ||
| } |
There was a problem hiding this comment.
新增的 fetch_latest_prerelease 函数与 fetch_latest_release 内部的 fetch 函数存在大量重复代码,特别是从 serde_json::Value 解析成 LatestRelease 结构体的逻辑。为了提高代码的可维护性并减少冗余,建议将这部分解析逻辑提取到一个独立的辅助函数中。
例如,可以创建一个这样的函数:
fn latest_release_from_json(json: &serde_json::Value) -> Result<LatestRelease, String> {
let tag_name = json
.get("tag_name")
.or_else(|| json.get("name"))
.and_then(|v| v.as_str())
.ok_or("Missing tag_name in GitHub response")?
.to_string();
if tag_name.is_empty() {
return Err("Missing tag_name in GitHub response".to_string());
}
let name = json.get("name").and_then(|v| v.as_str()).map(|s| s.to_string());
let html_url = json.get("html_url").and_then(|v| v.as_str()).map(|s| s.to_string());
let body = json.get("body").and_then(|v| v.as_str()).map(|s| s.to_string());
let download_url = if cfg!(target_os = "windows") {
json.get("assets")
.and_then(|v| v.as_array())
.and_then(|assets| {
assets.iter().find_map(|asset| {
let name = asset.get("name").and_then(|v| v.as_str())?;
if name.ends_with(".exe") {
asset.get("browser_download_url").and_then(|v| v.as_str()).map(|s| s.to_string())
} else {
None
}
})
})
} else {
None
};
Ok(LatestRelease { tag_name, name, html_url, download_url, body })
}然后 fetch_latest_release 和 fetch_latest_prerelease 都可以调用这个函数来解析 Release 信息。
将 preview 分支的改动合并到 master,用于正式发布。