From 1e437801d4fd122ea2c2feee6be6bdf6e7405a1b Mon Sep 17 00:00:00 2001 From: Eric Swanson <64809312+ericswanson-dfinity@users.noreply.github.com> Date: Fri, 29 Sep 2023 15:54:32 -0700 Subject: [PATCH] feat: install specific extension version (#3405) In order to not break CI every time we release a new dfx version, make it so we can install a specific version of an extension rather than relying on the compatibility matrix. There is no document for `dfx extension` in docs/cli-reference, so I did not update it. --- CHANGELOG.md | 4 ++++ e2e/tests-dfx/extension.bash | 2 +- e2e/tests-dfx/ledger.bash | 2 +- src/dfx-core/src/extension/manager/install.rs | 6 +++++- src/dfx/src/commands/extension/install.rs | 10 +++++++++- 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 611f15b583..4947451f75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ Generate frontend declarations for remote canisters too because frontend JS code may want to call them. +### feat: dfx extension install --version + +Install a specific version of an extension, bypassing version checks. + ### feat: Updated handling of missing values in state tree certificates The `Unknown` lookup of a path in a certificate results in an `AgentError` (the IC returns `Absent` for non-existing paths). diff --git a/e2e/tests-dfx/extension.bash b/e2e/tests-dfx/extension.bash index dd22e5b5b0..f5688d51ef 100644 --- a/e2e/tests-dfx/extension.bash +++ b/e2e/tests-dfx/extension.bash @@ -19,7 +19,7 @@ teardown() { assert_command dfx extension list assert_match 'No extensions installed' - assert_command dfx extension install sns --install-as snsx + assert_command dfx extension install sns --install-as snsx --version 0.2.1 # TODO: how to capture spinner message? # assert_match 'Successfully installed extension' diff --git a/e2e/tests-dfx/ledger.bash b/e2e/tests-dfx/ledger.bash index 6c5590fa9c..f030490dd3 100644 --- a/e2e/tests-dfx/ledger.bash +++ b/e2e/tests-dfx/ledger.bash @@ -12,7 +12,7 @@ setup() { dfx_start_for_nns_install - dfx extension install nns || true + dfx extension install nns --version 0.2.1 || true dfx nns install --ledger-accounts 345f723e9e619934daac6ae0f4be13a7b0ba57d6a608e511a00fd0ded5866752 22ca7edac648b814e81d7946e8bacea99280e07c5f51a04ba7a38009d8ad8e89 5a94fe181e9d411c58726cb87cbf2d016241b6c350bc3330e4869ca76e54ecbc } diff --git a/src/dfx-core/src/extension/manager/install.rs b/src/dfx-core/src/extension/manager/install.rs index 11d48c1716..f25b550d2d 100644 --- a/src/dfx-core/src/extension/manager/install.rs +++ b/src/dfx-core/src/extension/manager/install.rs @@ -17,6 +17,7 @@ impl ExtensionManager { &self, extension_name: &str, install_as: Option<&str>, + version: Option<&Version>, ) -> Result<(), ExtensionError> { let effective_extension_name = install_as.unwrap_or(extension_name); @@ -29,7 +30,10 @@ impl ExtensionManager { )); } - let extension_version = self.get_extension_compatible_version(extension_name)?; + let extension_version = match version { + Some(version) => version.clone(), + None => self.get_extension_compatible_version(extension_name)?, + }; let github_release_tag = get_git_release_tag(extension_name, &extension_version); let extension_archive = get_extension_archive_name(extension_name)?; let url = get_extension_download_url(&github_release_tag, &extension_archive)?; diff --git a/src/dfx/src/commands/extension/install.rs b/src/dfx/src/commands/extension/install.rs index db2abd9c95..6435915951 100644 --- a/src/dfx/src/commands/extension/install.rs +++ b/src/dfx/src/commands/extension/install.rs @@ -4,6 +4,7 @@ use crate::lib::error::DfxResult; use clap::Parser; use clap::Subcommand; use dfx_core::error::extension::ExtensionError; +use semver::Version; #[derive(Parser)] pub struct InstallOpts { @@ -12,6 +13,9 @@ pub struct InstallOpts { /// Installs the extension under different name. Useful when installing an extension with the same name as: already installed extension, or a built-in command. #[clap(long)] install_as: Option, + /// Installs a specific version of the extension, bypassing version checks + #[clap(long)] + version: Option, } pub fn exec(env: &dyn Environment, opts: InstallOpts) -> DfxResult<()> { @@ -22,7 +26,11 @@ pub fn exec(env: &dyn Environment, opts: InstallOpts) -> DfxResult<()> { return Err(ExtensionError::CommandAlreadyExists(opts.name).into()); } - mgr.install_extension(&opts.name, opts.install_as.as_deref())?; + mgr.install_extension( + &opts.name, + opts.install_as.as_deref(), + opts.version.as_ref(), + )?; spinner.finish_with_message( format!( "Extension '{}' installed successfully{}",