diff --git a/src/commands/external.rs b/src/commands/external.rs index e6226f4d12..5070c1688c 100644 --- a/src/commands/external.rs +++ b/src/commands/external.rs @@ -1,8 +1,8 @@ use crate::build_info::*; -use crate::commands::plugins::Install; +use crate::commands::plugins::{update, Install}; use crate::opts::PLUGIN_OVERRIDE_COMPATIBILITY_CHECK_FLAG; use anyhow::{anyhow, Result}; -use spin_plugins::{error::Error, manifest::warn_unsupported_version, PluginStore}; +use spin_plugins::{error::Error as PluginError, manifest::warn_unsupported_version, PluginStore}; use std::{collections::HashMap, env, process}; use tokio::process::Command; use tracing::log; @@ -49,7 +49,7 @@ pub async fn execute_external_subcommand( process::exit(1); } } - Err(Error::NotFound(e)) => { + Err(PluginError::NotFound(e)) => { if plugin_name == "cloud" { println!("The `cloud` plugin is required. Installing now."); let plugin_installer = Install { @@ -60,7 +60,14 @@ pub async fn execute_external_subcommand( override_compatibility_check: false, version: None, }; - plugin_installer.run().await?; + // Automatically update plugins if the cloud plugin manifest does not exist + // TODO: remove this eventually once very unlikely to not have updated + if let Err(e) = plugin_installer.run().await { + if let Some(PluginError::NotFound(_)) = e.downcast_ref::() { + update().await?; + } + plugin_installer.run().await?; + } } else { tracing::debug!("Tried to resolve {plugin_name} to plugin, got {e}"); terminal::error!("'{plugin_name}' is not a known Spin command. See spin --help.\n"); diff --git a/src/commands/plugins.rs b/src/commands/plugins.rs index 37bd112350..a0132a5ec1 100644 --- a/src/commands/plugins.rs +++ b/src/commands/plugins.rs @@ -104,11 +104,11 @@ pub struct Install { } impl Install { - pub async fn run(self) -> Result<()> { - let manifest_location = match (self.local_manifest_src, self.remote_manifest_src, self.name) { - (Some(path), None, None) => ManifestLocation::Local(path), - (None, Some(url), None) => ManifestLocation::Remote(url), - (None, None, Some(name)) => ManifestLocation::PluginsRepository(PluginLookup::new(&name, self.version)), + pub async fn run(&self) -> Result<()> { + let manifest_location = match (&self.local_manifest_src, &self.remote_manifest_src, &self.name) { + (Some(path), None, None) => ManifestLocation::Local(path.to_path_buf()), + (None, Some(url), None) => ManifestLocation::Remote(url.clone()), + (None, None, Some(name)) => ManifestLocation::PluginsRepository(PluginLookup::new(name, self.version.clone())), _ => return Err(anyhow::anyhow!("For plugin lookup, must provide exactly one of: plugin name, url to manifest, local path to manifest")), }; let manager = PluginManager::try_default()?; @@ -409,7 +409,7 @@ impl PluginDescriptor { } /// Updates the locally cached spin-plugins repository, fetching the latest plugins. -async fn update() -> Result<()> { +pub(crate) async fn update() -> Result<()> { let manager = PluginManager::try_default()?; let plugins_dir = manager.store().get_plugins_directory(); let url = plugins_repo_url()?;