Skip to content

fix(plugin): #115 fall back to registry repository for report_broken - #118

Merged
mpiton merged 3 commits into
mainfrom
fix/issue-115-plugin-report-broken
Apr 27, 2026
Merged

fix(plugin): #115 fall back to registry repository for report_broken#118
mpiton merged 3 commits into
mainfrom
fix/issue-115-plugin-report-broken

Conversation

@mpiton

@mpiton mpiton commented Apr 27, 2026

Copy link
Copy Markdown
Owner

Closes #115.

Summary

plugin_report_broken errored on every official plugin (4/4) because their plugin.toml manifests do not declare a repository field, while the handler in application/commands/report_broken_plugin.rs requires manifest.repository_url() to be Some to build the GitHub issue URL.

This PR fixes the runtime side only:

  • Registry fallback: when the loaded manifest lacks repository, the handler now reads PluginStoreEntry.repository from the local plugin store cache (plugin-registry-cache.json, populated by plugin_store_refresh from registry.toml). The four official plugins are listed in the registry with their repository URL, so the feature works immediately without re-publishing any plugin.
  • Improved validation message: when neither manifest nor cache yields a repository URL, the error now points at the actual TOML field ([plugin].repository in plugin.toml) instead of the internal Rust struct field repository_url.

Plugin-side updates (adding repository to each manifest) were considered but dropped — the registry already carries the data, so duplicating it in every manifest is redundant for officially-listed plugins. Third-party / sideloaded plugins can still ship repository in their manifest for the standard path; that field is not introduced here, only relied on when present.

Changes

  • application/commands/mod.rs: ReportBrokenPluginCommand gains an optional store_cache_path: Option<PathBuf>.
  • application/commands/report_broken_plugin.rs: cache fallback + improved validation message + 2 new unit tests.
  • adapters/driving/tauri_ipc.rs: pass store_cache_path() through to the command.
  • CHANGELOG.md: entry under [Unreleased] / Fixed.

Test plan

  • cargo test --lib — 1012 passed, 4 ignored (15 in report_broken, was 13)
  • cargo clippy --workspace -- -D warnings — clean
  • cargo fmt --check — clean
  • npx vitest run — 582 passed
  • npm run lint — 0 warnings, 0 errors
  • After merging, run tauri-pilot ipc plugin_store_refresh then tauri-pilot ipc plugin_report_broken --args '{"pluginName":"vortex-mod-youtube"}' to confirm the GitHub issue URL is returned.

Summary by CodeRabbit

Bug Fixes

  • Fixed error handling for missing repository information – The plugin report feature no longer fails when a plugin manifest lacks repository details. It now automatically checks the plugin store cache for fallback information and provides clearer guidance if the field is still missing.

Plugin report_broken IPC errored on every official plugin because the
runtime requires `[plugin].repository` in `plugin.toml` but none of the
shipped manifests carried it. The handler now falls back to the local
plugin store cache (`PluginStoreEntry.repository`) when the manifest is
missing the field, so already-installed plugins keep working until they
upgrade. The validation message points at the actual TOML field rather
than the internal Rust struct name.

Bumps registry to the new plugin versions:

- vortex-mod-youtube     1.2.3 → 1.2.4
- vortex-mod-vimeo       1.3.1 → 1.3.2
- vortex-mod-soundcloud  1.2.1 → 1.2.2
- vortex-mod-gallery     1.0.0 → 1.0.1

Refs #115.
@github-actions github-actions Bot added documentation Improvements or additions to documentation rust labels Apr 27, 2026
@coderabbitai

coderabbitai Bot commented Apr 27, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8c12868c-6bde-49cb-b26d-addbe62f6fb6

📥 Commits

Reviewing files that changed from the base of the PR and between 6923a68 and 707a9c9.

📒 Files selected for processing (4)
  • CHANGELOG.md
  • src-tauri/src/adapters/driving/tauri_ipc.rs
  • src-tauri/src/application/commands/mod.rs
  • src-tauri/src/application/commands/report_broken_plugin.rs
✅ Files skipped from review due to trivial changes (1)
  • CHANGELOG.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • src-tauri/src/application/commands/mod.rs
  • src-tauri/src/application/commands/report_broken_plugin.rs

📝 Walkthrough

Walkthrough

The pull request implements a fallback mechanism for the plugin_report_broken command to resolve missing repository metadata. When a plugin manifest lacks a repository field, the handler now attempts to retrieve it from a local plugin store cache file (plugin-registry-cache.json) before returning a validation error.

Changes

Cohort / File(s) Summary
Documentation
CHANGELOG.md
Added entry documenting the fix for plugin_report_broken handler to use fallback repository from plugin store cache when manifest omits the field.
Command Structure
src-tauri/src/application/commands/mod.rs
Added optional store_cache_path: Option<std::path::PathBuf> field to ReportBrokenPluginCommand to carry the local cache path to the handler.
IPC Adapter
src-tauri/src/adapters/driving/tauri_ipc.rs
Updated plugin_report_broken handler to compute and pass the plugin store cache path to the command, with graceful fallback if resolution fails.
Handler Logic
src-tauri/src/application/commands/report_broken_plugin.rs
Refactored handle_report_broken_plugin to fall back to cache lookup when manifest repository is unavailable; added read_repository_from_cache helper; improved validation error message to reference the correct TOML field name; updated tests for optional cache path and success/error cases.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A manifest without a home,
Now finds its way through cache to roam,
The registry knows where to look,
No more errors in the book!
GitHub issues report with cheer,
The broken plugins needn't fear! 🌟

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(plugin): #115 fall back to registry repository for report_broken' clearly identifies the primary change: implementing a fallback to the registry repository when the plugin manifest lacks the repository field, directly addressing issue #115.
Linked Issues check ✅ Passed The PR successfully implements the core objective from issue #115: restoring plugin_report_broken functionality by falling back to registry cache when manifests lack repository fields, improving error messages to reference the correct TOML field, and avoiding mandatory plugin republishing.
Out of Scope Changes check ✅ Passed All changes are scoped to issue #115: ReportBrokenPluginCommand gains store_cache_path field, the handler implements cache fallback logic, validation messaging is improved, and CHANGELOG is updated accordingly. No unrelated modifications are present.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/issue-115-plugin-report-broken

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
src-tauri/src/application/commands/report_broken_plugin.rs (1)

116-120: Normalize cached repository values before use.

At Line 116-120, trimming whitespace avoids avoidable validation failures from slightly malformed cache data.

♻️ Suggested tweak
-        let repo = entry.get("repository")?.as_str()?;
-        if repo.is_empty() {
+        let repo = entry.get("repository")?.as_str()?.trim();
+        if repo.is_empty() {
             None
         } else {
             Some(repo.to_string())
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src-tauri/src/application/commands/report_broken_plugin.rs` around lines 116
- 120, Normalize the cached repository string before validation: when retrieving
the value from entry.get("repository")?.as_str()? assign or use a trimmed
version (e.g., call .trim() on the &str), then check trimmed.is_empty() and
return Some(trimmed.to_string()) when non-empty; update the repo handling in
report_broken_plugin logic to use the trimmed value so leading/trailing
whitespace in cached "repository" entries doesn't cause false empty checks.
src-tauri/src/adapters/driving/tauri_ipc.rs (1)

626-626: Keep a trace when cache-path resolution fails.

At Line 626, .ok() silently discards the error. Logging it (debug/warn) would make fallback behavior easier to diagnose without changing runtime semantics.

♻️ Suggested tweak
-    let store_cache_path = store_cache_path().ok();
+    let store_cache_path = match store_cache_path() {
+        Ok(path) => Some(path),
+        Err(error) => {
+            tracing::debug!(
+                error = %error,
+                "plugin_report_broken: store cache path unavailable; continuing without cache fallback"
+            );
+            None
+        }
+    };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src-tauri/src/adapters/driving/tauri_ipc.rs` at line 626, The call to
store_cache_path() currently swallows errors with .ok(); change it to capture
the Result, log the Err before falling back, and keep the same semantics (None
on error). Specifically, replace the .ok() usage around the store_cache_path()
call so you match on its Result (or use .map_err(|e| { debug!/warn!(...), None
})) and log the error via your crate logger (e.g., debug! or warn!) while still
assigning None to the variable store_cache_path on failure; reference the
store_cache_path() function and the store_cache_path variable to locate the
change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src-tauri/src/adapters/driving/tauri_ipc.rs`:
- Line 626: The call to store_cache_path() currently swallows errors with .ok();
change it to capture the Result, log the Err before falling back, and keep the
same semantics (None on error). Specifically, replace the .ok() usage around the
store_cache_path() call so you match on its Result (or use .map_err(|e| {
debug!/warn!(...), None })) and log the error via your crate logger (e.g.,
debug! or warn!) while still assigning None to the variable store_cache_path on
failure; reference the store_cache_path() function and the store_cache_path
variable to locate the change.

In `@src-tauri/src/application/commands/report_broken_plugin.rs`:
- Around line 116-120: Normalize the cached repository string before validation:
when retrieving the value from entry.get("repository")?.as_str()? assign or use
a trimmed version (e.g., call .trim() on the &str), then check
trimmed.is_empty() and return Some(trimmed.to_string()) when non-empty; update
the repo handling in report_broken_plugin logic to use the trimmed value so
leading/trailing whitespace in cached "repository" entries doesn't cause false
empty checks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b3d7c3b4-3ed6-4b9a-ae32-0d048a6ad444

📥 Commits

Reviewing files that changed from the base of the PR and between 4a23eab and 6923a68.

📒 Files selected for processing (5)
  • CHANGELOG.md
  • registry/registry.toml
  • src-tauri/src/adapters/driving/tauri_ipc.rs
  • src-tauri/src/application/commands/mod.rs
  • src-tauri/src/application/commands/report_broken_plugin.rs

Plugin-side change abandoned — Path B (registry fallback in the
report_broken_plugin handler) suffices for the four official plugins
listed in the registry. Reverting the registry bump keeps this PR
focused on the runtime fix and avoids coupling it to plugin releases.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 5 files

@mpiton mpiton changed the title fix(plugin): #115 surface repository_url with registry fallback fix(plugin): #115 fall back to registry repository for report_broken Apr 27, 2026
@greptile-apps

greptile-apps Bot commented Apr 27, 2026

Copy link
Copy Markdown

Greptile Summary

Fixes plugin_report_broken erroring on all official plugins by adding a registry-cache fallback: when a plugin's manifest lacks a repository field, the handler reads it from the local plugin-registry-cache.json (populated by plugin_store_refresh). The improved validation error message now names the actual TOML field instead of the internal Rust struct field.

Confidence Score: 4/5

Safe to merge; only a P2 doc-comment typo present, no logic or correctness issues found.

The fallback logic is correct — JSON keys name and repository are single words and serialize unchanged under camelCase, so the dynamic field access in read_repository_from_cache matches what write_cache produces. Path derivation is consistent with all other store commands. The two new tests cover the primary happy path and the empty-cache edge case. The only finding is a wrong filename in a doc comment (registry-cache.json vs plugin-registry-cache.json).

src-tauri/src/application/commands/mod.rs (doc comment filename mismatch)

Important Files Changed

Filename Overview
src-tauri/src/application/commands/report_broken_plugin.rs Adds registry-cache fallback for missing manifest repository field; JSON key access is correct (both name and repository are single words, unaffected by camelCase rename); two new tests cover the happy path and the empty-cache edge case; logic is clean.
src-tauri/src/application/commands/mod.rs Adds store_cache_path: Option<PathBuf> to ReportBrokenPluginCommand; doc comment names the file registry-cache.json instead of the actual plugin-registry-cache.json.
src-tauri/src/adapters/driving/tauri_ipc.rs Wires store_cache_path().ok() into the command; path derivation is consistent with every other store command that uses the same helper; silently degrades to None when config dir is unavailable.
CHANGELOG.md Accurate entry under [Unreleased] / Fixed describing the manifest-missing-repository bug and its cache-fallback fix.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[plugin_report_broken IPC] --> B[store_cache_path.ok]
    B --> C[handle_report_broken_plugin]
    C --> D{list_loaded finds plugin?}
    D -- yes --> E[Use loaded PluginInfo as manifest]
    D -- no --> F{find_installed_manifest?}
    F -- Some --> E
    F -- None --> G[AppError::NotFound]
    E --> H{manifest.repository_url is Some?}
    H -- yes --> K[build_report_broken_url]
    H -- no --> I{store_cache_path is Some?}
    I -- None --> J[AppError::Validation]
    I -- Some --> L[read_repository_from_cache]
    L --> M{entry found in cache?}
    M -- yes --> K
    M -- no --> J
    K --> N[opener.open_url]
    N --> O[Return issue URL]
Loading

Fix All in Claude Code

Prompt To Fix All With AI
This is a comment left during a code review.
Path: src-tauri/src/application/commands/mod.rs
Line: 199-202

Comment:
**Incorrect filename in doc comment**

The doc comment says `` `registry-cache.json` `` but the actual file written by `store_cache_path()` is `plugin-registry-cache.json`. A reader following this comment to locate the cache on disk would look for the wrong file.

```suggestion
    /// Local path to the plugin store cache (`plugin-registry-cache.json`). When
    /// the plugin's manifest does not surface a `repository` field, the
    /// handler falls back to this cache so plugins installed before the
    /// field was required keep working.
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "revert: drop registry version bump for #..." | Re-trigger Greptile

Comment on lines +199 to +202
/// Local path to the plugin store cache (`registry-cache.json`). When
/// the plugin's manifest does not surface a `repository` field, the
/// handler falls back to this cache so plugins installed before the
/// field was required keep working.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Incorrect filename in doc comment

The doc comment says `registry-cache.json` but the actual file written by store_cache_path() is plugin-registry-cache.json. A reader following this comment to locate the cache on disk would look for the wrong file.

Suggested change
/// Local path to the plugin store cache (`registry-cache.json`). When
/// the plugin's manifest does not surface a `repository` field, the
/// handler falls back to this cache so plugins installed before the
/// field was required keep working.
/// Local path to the plugin store cache (`plugin-registry-cache.json`). When
/// the plugin's manifest does not surface a `repository` field, the
/// handler falls back to this cache so plugins installed before the
/// field was required keep working.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src-tauri/src/application/commands/mod.rs
Line: 199-202

Comment:
**Incorrect filename in doc comment**

The doc comment says `` `registry-cache.json` `` but the actual file written by `store_cache_path()` is `plugin-registry-cache.json`. A reader following this comment to locate the cache on disk would look for the wrong file.

```suggestion
    /// Local path to the plugin store cache (`plugin-registry-cache.json`). When
    /// the plugin's manifest does not surface a `repository` field, the
    /// handler falls back to this cache so plugins installed before the
    /// field was required keep working.
```

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="registry/registry.toml">

<violation number="1">
P1: This change rolls back multiple official plugin versions in the registry, so clients will resolve and download older plugin releases instead of the latest published ones.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

- Doc comment: `registry-cache.json` → `plugin-registry-cache.json`
  (greptile P2 on commands/mod.rs).
- Trim cached `repository` value before the empty-check so leading or
  trailing whitespace in cache entries doesn't trip the fallback
  (coderabbit nitpick on report_broken_plugin.rs).
- Log a debug trace when `store_cache_path()` fails instead of
  silently dropping the error with `.ok()`, so the fallback path is
  diagnosable (coderabbit nitpick on tauri_ipc.rs).
@mpiton

mpiton commented Apr 27, 2026

Copy link
Copy Markdown
Owner Author

@cubic-dev-ai re. registry rollback flag (P1): the version revert in 9618c1d is intentional. The four official plugin manifests in their respective repos do not declare [plugin].repository, so bumping the registry without first re-publishing the plugins would advertise versions whose released artifacts still ship the bug. This PR therefore keeps the registry pinned to the currently-released versions and relies on the runtime fallback (reading PluginStoreEntry.repository from the local cache) to fix the IPC for already-installed plugins. A separate set of plugin PRs (now closed) was the alternative path.

@cubic-dev-ai

cubic-dev-ai Bot commented Apr 27, 2026

Copy link
Copy Markdown

@cubic-dev-ai re. registry rollback flag (P1): the version revert in 9618c1d is intentional. The four official plugin manifests in their respective repos do not declare [plugin].repository, so bumping the registry without first re-publishing the plugins would advertise versions whose released artifacts still ship the bug. This PR therefore keeps the registry pinned to the currently-released versions and relies on the runtime fallback (reading PluginStoreEntry.repository from the local cache) to fix the IPC for already-installed plugins. A separate set of plugin PRs (now closed) was the alternative path.

@mpiton That makes total sense. I suggested checking the registry bump because typically fixing a "missing field" bug involves updating the source manifests, but your runtime fallback approach is a much cleaner way to fix this for official plugins without forcing a cascade of new plugin releases.

Since registry.toml already contains the repository URLs for the official plugins, your implementation of read_repository_from_cache in report_broken_plugin.rs effectively bridges the gap for every user who has run a plugin_store_refresh.

The logic in 9618c1d to keep the registry pinned is correct here: advertising a new version before the plugin artifact actually contains the repository field in its plugin.toml would be misleading and wouldn't solve the manifest-read path anyway.

I've noted that:

  • The fallback to PluginStoreEntry.repository handles all four official plugins immediately.
  • The validation message now correctly points to the TOML field name, which is much better for third-party developers.
  • The debug trace in tauri_ipc.rs ensures we can see if the cache path resolution fails.

This is a solid middle-ground fix.

Learn more about how I handle learnings | Configure my review settings

@mpiton
mpiton merged commit e571225 into main Apr 27, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation rust

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[QA] MEDIUM: P0.16 plugin_report_broken errors on every plugin — repository_url missing in all manifests

1 participant