fix(anolisa): fallback to v1 components.toml when v2 index is unavailable - #2566
fix(anolisa): fallback to v1 components.toml when v2 index is unavailable#2566zhangtaibo wants to merge 4 commits into
Conversation
…able When the CDN mirror has not yet published components-v2.toml (HTTP 404), load_component_index() now gracefully falls back to the v1 components.toml file. This prevents 'anolisa list' from hard-failing in the transition window between schema v1 and v2 deployment. Changes: - Remove #[cfg(test)] from component_index_url() in repo_config.rs so the v1 URL is available in release builds. - Add v2→v1 fallback in load_component_index(): if v2 fetch returns HTTP 404, retry with the v1 URL. - Make ComponentIndex::validate() accept schema v1 and v2 (use matches!(1 | 2) instead of != 2). - Add #[serde(default)] to the targets field so v1 entries (which lack targets) deserialize as an empty vec. - Skip the non-empty targets check for schema v1 entries. - Extract fetch logic into fetch_index_url() helper. - Update unsupported_schema_is_rejected test to only test schema 99. Fixes alibaba#2565 Verified: cargo build -p anolisa-cli --release → exit 0 cargo test -p anolisa-cli --release → 814 passed, 0 failed anolisa -q list → exit 0 (quiet mode correct) anolisa list → exit 0, displays 9 components anolisa status → exit 0 (unaffected) Co-Authored-By: Hermes Agent <noreply@nousresearch.com>
There was a problem hiding this comment.
- v2→v1 回退逻辑依赖 404 文案字符串匹配,建议改为结构化状态码判断。
- schema v1/v2 接受策略依赖隐式 targets 默认值,后续 schema 升级需同步更新匹配逻辑与测试。
🤖 Generated by Qoder • View workflow run
|
|
||
| let cache = DownloadCache::new(layout.cache_dir.clone()); | ||
| let downloaded = match fetch_index_url(&cache, &url) { | ||
| Ok(art) => art, |
There was a problem hiding this comment.
[P1] v1 回退逻辑依赖错误文案匹配,易受服务端文案变动影响
当前 v2→v1 回退通过 reason.contains("http status 404") 识别 404,resolution.rs:752-755。一旦底层 download 层调整错误信息格式(如本地化、移除 http status 前缀),v1 回退会静默失效,重新暴露 404 硬失败。建议显式携带/匹配 HTTP 状态码(或定义结构化错误枚举),在 404 时触发回退,避免对 free-text 文案的脆弱依赖。
🤖 Generated by Qoder • Fix in Qoder
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e5c50ed5e7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let downloaded = match fetch_index_url(&cache, &url) { | ||
| Ok(art) => art, | ||
| Err(ComponentIndexError::Fetch { ref reason }) | ||
| if reason.contains("http status 404") => |
There was a problem hiding this comment.
Treat file:// missing v2 as absent
For local file:// repositories, a missing components-v2.toml is reported by DownloadCache::fetch as an I/O NotFound, not as an http status 404, so this guard never falls back to components.toml. That leaves v1-only local or mirrored repos failing to load even though the new code is meant to handle an unavailable v2 index; use typed absence detection like the raw index path does for HTTP 404/410 and file NotFound before wrapping the error.
Useful? React with 👍 / 👎.
| #[serde(default)] | ||
| pub(crate) summary: Option<String>, | ||
| /// Supported host OS/architecture combinations. | ||
| #[serde(default)] |
There was a problem hiding this comment.
Populate targets when accepting v1 indexes
When the fallback loads a schema v1 components.toml, existing v1 rows use platforms = [...] rather than targets, so defaulting targets to an empty list makes supports_target() false for every component. In particular, install --all filters through component_names_for_target() and will report nothing to install even though the fallback index was loaded; translate v1 platform data into target availability or avoid target filtering for schema v1.
Useful? React with 👍 / 👎.
kongche-jbw
left a comment
There was a problem hiding this comment.
Review baseline: a50e34de6130727d97ea89c4ff76a76d59bc9b9d...e5c50ed5e738feee9d0de769861a5e96774bb3f6
[P1] 恢复必需的 Rust 格式与 clippy 门禁
src/anolisa/crates/anolisa-cli/src/resolution.rs:16 未通过
cargo fmt --all -- --check。格式修复后,同文件 :1363 的单元素循环仍会触发
clippy::single-element-loop。当前 Test anolisa 已因此失败,后续测试步骤不会运行,
PR 无法通过必需 CI。
Possible direction: 运行 rustfmt,并将 schema 99 检查改为直接断言;随后执行
cargo clippy --all-targets --locked -- -D warnings 和完整测试。
…andling Apply cargo fmt to the multiline format!() call in the v1 fallback error message, collapsing it to a single line as rustfmt requires. This fixes the CI 'Check formatting' step failure in PR alibaba#2566. Signed-off-by: Hermes Agent <hermes@alibaba-inc.com>
- Split long import line for component_index_url/v2_url into multi-line - Collapse match arm guard pattern to single line Co-authored-by: Hermes Agent <hermes@alibaba-inc.com>
Replace for-loop over single element [99] with direct let binding as clippy recommends. The loop was originally written for multiple schema versions but was reduced to one when v1/v2 acceptance was added. Co-authored-by: Hermes Agent <hermes@alibaba-inc.com>
Problem
Fixes #2565
anolisa listhard-fails with HTTP 404 when the CDN mirror has not yet publishedcomponents-v2.toml. Commit52fa3159switched from reading v1components.tomlto v2components-v2.toml, but the v2 file is not yet deployed. The v1 URL helper was gated behind#[cfg(test)], making it inaccessible in release builds. This is a regression introduced today (2026-08-14 13:58).Fix
- #[cfg(test)] pub fn component_index_url(base_url: &str) -> String {Three coordinated changes in
resolution.rsandrepo_config.rs:Remove
#[cfg(test)]fromcomponent_index_url()inrepo_config.rs:698so the v1 URL is available in release builds.Add v2→v1 fallback in
load_component_index(): if v2 fetch returnsFetch { reason: "http status 404 ..." }, retry with the v1 URL. Extract fetch logic into afetch_index_url()helper to keep the main function readable.Make the parser accept both schemas:
#[serde(default)]totargets: Vec<ComponentTarget>so v1 entries (which lacktargets) deserialize as an empty vec.schema_version1 and 2 invalidate()(usematches!(self.schema_version, 1 | 2)instead of!= 2).self.schema_version >= 2).unsupported_schema_is_rejectedunit test to only test schema 99 (no longer 1).The v1 index on the mirror (
components.toml) usesschema_version = 1and lacks thetargetsfield introduced in v2. With#[serde(default)]the v1 rows parse successfully withtargets = [], and the validator treats them as "no target info" — acceptable for the transition window.Verification
On ALinux 4 ECS (8.217.123.80):
Verified 2/2 stable runs.
Co-Authored-By: Hermes Agent noreply@nousresearch.com