Fix plugin install detection when update info unavailable - #541
Fix plugin install detection when update info unavailable#541swissspidy wants to merge 1 commit into
Conversation
`install_plugin_install_status()` returns an `install` status for a plugin that is already installed whenever the WordPress.org API does not offer any update information for the installed version. The installation then fails with a "Destination folder already exists" error instead of the expected "Plugin already installed" warning. This is what currently happens for the Akismet plugin bundled with WordPress, which broke the `Install dependencies with activation` scenario. Check the file system in addition to the reported status, similar to what `Theme_Command` already does via `wp_get_theme()`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NeGydmXhxbx34V4UV6M3L6
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
Included review availability: Your plan includes up to 1 review per rolling hour; 0 remain after this review. 📝 WalkthroughWalkthroughPlugin installation now checks plugin status and filesystem contents before downloading. A feature scenario verifies that an outdated Debug Bar installation is reported as already installed when update data is unavailable. ChangesPlugin installation detection
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to This is a localized plugin-install detection fix with a regression scenario; no actionable merge-blocking risk remains after the normal validation checks pass. Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
What
wp plugin install <slug>could try to install a plugin that is already installed, failing withWarning: Destination folder already exists.instead of reportingWarning: <slug>: Plugin already installed.Why
Plugin_Command::install_from_repo()relied solely oninstall_plugin_install_status(). That function only recognizes an installed plugin when it has update data to compare against:If
plugins_api()reports a version newer than the installed one and the refreshedupdate_pluginstransient still holds no entry for that slug, there is no fallback: the status staysinstallfor a plugin that is sitting on disk. WP-CLI then downloads the package and the installation fails on the existing folder.This broke the
Install dependencies with activationscenario in the nightly run of 2026-08-18 (run 32089579364) — in every job, WP latest and trunk, PHP 7.4 through nightly:Nothing changed on our side; the same commit passed the day before. What is certain is that during that run
plugins_api()offered Akismet 5.7.1 (anddownloads.wordpress.orgserved the ZIP), while theupdate_pluginstransient held no update entry for the Akismet version bundled with WordPress.A plausible explanation is the staged distribution of new plugin releases announced in Protect The Shire: Akismet 5.7.1 was released around midnight UTC, and the failing run started at 01:49 UTC. This is not confirmed — the announcement frames the hold in terms of auto-updates, and people have reported seeing such updates offered in wp-admin during the hold — but the timing matches, and re-running the very same workflow later that day passed with no changes.
Either way the fall-through in
install_plugin_install_status()is real, and it is not Akismet-specific: any plugin installed from WordPress.org can hit it in the window after a release. The same applies outside WP-CLI, where the Add Plugins screen offers "Install Now" for an already installed plugin and fails the same way on click.How
Check the file system in addition to the reported status, similar to what
Theme_Command::install_from_repo()already does viawp_get_theme( $slug )->exists(). The newis_plugin_installed()helper requires both the directory and a valid plugin file (get_plugins( '/' . $slug )), so the existingPaths aren't backslashed when destination folder already existsscenario — which deletesakismet.phpfirst — keeps working unchanged.The added scenario reproduces the state deterministically, without depending on WordPress.org timing: an mu-plugin empties
site_transient_update_plugins, and a stubdebug-bar0.1 stands in for the outdated install.🤖 Generated with Claude Code
https://claude.ai/code/session_01NeGydmXhxbx34V4UV6M3L6
Summary by CodeRabbit
New Features
--forceoption path to allow installation to proceed when needed.Bug Fixes