From de31e0e220ae63ee1c2897526c5502d22c6612cd Mon Sep 17 00:00:00 2001 From: HsiangNianian Date: Mon, 9 Mar 2026 20:54:14 +0800 Subject: chore: update .gitignore to include Vscode directory --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) (limited to '.gitignore') diff --git a/.gitignore b/.gitignore index 1419805..22fcb7f 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,6 @@ release/ # claude code .claude/ + +# Vscode +.vscode/ -- cgit v1.2.3-70-g09d2 From 8c913f2685383bcfa154c947a43571a8d33679ae Mon Sep 17 00:00:00 2001 From: "Begonia, HE" <163421589+BegoniaHe@users.noreply.github.com> Date: Wed, 18 Mar 2026 04:57:17 +0100 Subject: fix(modpack): 将 CurseForge API Key 改为编译期可选常量 (#118) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # fix(modpack): 将 CurseForge API Key 改为编译期可选常量 修复 `env!()` 宏在开发者本地无 `CURSEFORGE_API_KEY` 时导致编译失败的问题,改用 `option_env!()` + build.rs 中的 `dotenvy` 读取 .env 文件,实现编译期嵌入、缺失时优雅降级。 ## 更改类型 - [x] Bug 修复(修复问题的非破坏性更改) - [ ] 新功能(添加功能的非破坏性更改) - [ ] 破坏性更改(会导致现有功能无法正常工作的修复或功能) - [ ] 文档更新 - [ ] UI/UX 改进 - [ ] 性能优化 - [ ] 代码重构(无功能性更改) - [x] 配置更改 - [ ] 测试添加或更新 ## LLM 生成代码声明 - [x] 此 PR 不包含 LLM 生成的代码,我**提供**质量担保 ## 相关 Issue 相关 #110 #117 ## 更改内容 ### 后端 (Rust) - modpack.rs:将 `env!("CURSEFORGE_API_KEY")` 替换为 `const CURSEFORGE_API_KEY: Option<&str> = option_env!("CURSEFORGE_API_KEY")`,key 不存在时编译为 `None`,调用 CurseForge 功能时返回友好错误而非 panic - build.rs:添加 `dotenvy::dotenv()` 调用,允许通过 .env 文件在编译期注入 key,并注册 `cargo:rerun-if-changed` / `cargo:rerun-if-env-changed` 确保增量构建正确 ### 前端 (Svelte) - 无 ### 配置 - Cargo.toml:在 `[build-dependencies]` 中添加 `dotenvy = { version = "0.15", default-features = false }` - .gitignore:添加 .env / `.env.local` 忽略规则,防止 key 被意外提交 - .env.example:新增示例文件,说明可选配置项及获取方式 ## 测试 ### 测试环境 - **操作系统**:Fedora Linux 6.19.6-300.fc44.x86_64 x86_64 - **DropOut 版本**:0.2.0-alpha.5 - **测试的 Minecraft 版本**:N/A - **Mod 加载器**:N/A ### 测试用例 - [ ] 已在 Windows 上测试 - [ ] 已在 macOS 上测试 - [x] 已在 Linux 上测试 - [ ] 已测试原版 Minecraft - [ ] 已测试 Fabric - [ ] 已测试 Forge - [ ] 已测试游戏启动 - [ ] 已测试登录流程 - [ ] 已测试 Java 检测/下载 ### 测试步骤 1. 不设置 `CURSEFORGE_API_KEY`,不创建 .env 文件,直接执行 `cargo check` → 应编译通过(无报错) 2. 创建 .env 文件并写入 `CURSEFORGE_API_KEY=test_key`,执行 `cargo check` → 应编译通过,key 被嵌入二进制 3. 不含 key 的构建中触发 CurseForge modpack 导入 → 应返回友好错误提示而非 panic ## 检查清单 ### 代码质量 - [x] 我的代码遵循项目的代码风格指南 - [x] 我已对自己的代码进行了自审 - [ ] 我已对难以理解的区域添加了注释 - [x] 我的更改没有产生新的警告或错误 ### 测试验证 - [x] 我已在本地测试了我的更改 - [ ] 我已添加测试来证明我的修复有效或功能正常工作 - [x] 新的和现有的单元测试在本地通过 - [x] 我至少在一个目标平台上进行了测试 ### 文档更新 - [ ] 我已相应地更新了文档 - [ ] 如有需要,我已更新 README - [ ] 我已在必要处添加/更新代码注释 ### 依赖项 - [x] 我已检查没有添加不必要的依赖项 - [x] 所有新依赖项都已正确记录 - [x] Cargo.lock 已更新 ## 附加说明 `dotenvy` 仅作为 **build-dependency**,不会进入最终二进制。官方发布构建通过 CI 环境变量注入 key,普通开发者无需任何操作即可正常编译和运行。 Co-authored-by: 简律纯 --- .env.example | 7 +++++++ .gitignore | 4 ++++ src-tauri/Cargo.toml | 1 + src-tauri/build.rs | 7 +++++++ src-tauri/src/core/modpack.rs | 11 +++++------ 5 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 .env.example (limited to '.gitignore') diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..9e7e55a --- /dev/null +++ b/.env.example @@ -0,0 +1,7 @@ +# Copy this file to .env and fill in values to enable optional features at build time. +# .env is gitignored and will never be committed. + +# CurseForge API key — required only to build with CurseForge modpack support. +# Obtain one at https://console.curseforge.com/ +# If absent, CurseForge modpack import is disabled at runtime (all other features work normally). +# CURSEFORGE_API_KEY=your_key_here diff --git a/.gitignore b/.gitignore index 22fcb7f..81ca5c5 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,10 @@ __pycache__/ # Tauri artifacts artifacts/ +# Local secrets (do not commit) +.env +.env.local + # AUR Release release/ diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index b375c6e..ccec463 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -52,6 +52,7 @@ ctor = "0.6.3" inventory = "0.3.21" [build-dependencies] +dotenvy = { version = "0.15", default-features = false } tauri-build = { version = "2.0", features = [] } [target.'cfg(all(windows, target_env = "gnu"))'.build-dependencies] diff --git a/src-tauri/build.rs b/src-tauri/build.rs index 63f98e2..00f5755 100644 --- a/src-tauri/build.rs +++ b/src-tauri/build.rs @@ -1,4 +1,11 @@ fn main() { + // Load .env file if present so optional build-time vars (e.g. CURSEFORGE_API_KEY) + // are available to option_env!() without requiring CI to have a real .env file. + if let Ok(path) = dotenvy::dotenv() { + println!("cargo:rerun-if-changed={}", path.display()); + } + println!("cargo:rerun-if-env-changed=CURSEFORGE_API_KEY"); + // For MinGW targets, use embed-resource to generate proper COFF format #[cfg(all(windows, target_env = "gnu"))] { diff --git a/src-tauri/src/core/modpack.rs b/src-tauri/src/core/modpack.rs index 2998167..97d2fa1 100644 --- a/src-tauri/src/core/modpack.rs +++ b/src-tauri/src/core/modpack.rs @@ -294,6 +294,8 @@ fn parse_multimc(archive: &mut Archive) -> Result { // ── CurseForge API resolution ───────────────────────────────────────────── +const CURSEFORGE_API_KEY: Option<&str> = option_env!("CURSEFORGE_API_KEY"); + async fn resolve_curseforge_files(files: &[ModpackFile]) -> Result, String> { let file_ids: Vec = files .iter() @@ -366,12 +368,9 @@ async fn cf_post( endpoint: &str, body: &serde_json::Value, ) -> Result { - let api_key = std::env::var("CURSEFORGE_API_KEY") - .map_err(|_| "CURSEFORGE_API_KEY is not set".to_string())?; - if api_key.trim().is_empty() { - return Err("CURSEFORGE_API_KEY is empty".to_string()); - } - + let api_key = CURSEFORGE_API_KEY + .ok_or("CurseForge modpack support requires CURSEFORGE_API_KEY set at build time")?; + let resp = client .post(format!("https://api.curseforge.com{endpoint}")) .header("x-api-key", api_key) -- cgit v1.2.3-70-g09d2