Skip to content

Commit

Permalink
feat: consistency with pop up parachains to handle versioning for `…
Browse files Browse the repository at this point in the history
…contracts-node` (#262)

* feat(contracts-e2e): auto-source contracts-node binary if not present

* chore(contract-e2e): deprecate --features e2e-tests

* fix: remove unnecessary async function

* refactor(contracts-node): reduce duplicated code with binary sourcing (#255)

* refactor(up-contract): use Binary struct from parachains -> up -> sourcing to auto-launch contracts-node

* refactor(contracts_node): reduce duplicated code -- checkpoint, not working

* refactor(contracts_node): use Binary and Source structs for substrate-contracts-node

* chore: small changes

* chore: small changes

* chore: add e2e help, prevent cmd output, and cleanup

* refactor(contracts_node): introduce helper to download contracts node if it does not exist

* refactor(sourcing): move sourcing functionality to `pop-common` (#258)

* refactor(sourcing): move sourcing to pop-common

* refactor(sourcing-tests): move sourcing tests to pop-common

* refactor(sourcing): better imports

* refactor(sourcing): clean sourcing module with better component categorization. Other cleanups

* fix: failing tests

* fix: needed to download contracts_node for test

* refactor: consistency with pop up parachains to recover contracts-node

* refactor: improvements

* test: unit test for new methods

* fix: comment

* refactor: remove support for standalone binary

* refactor: duplicate code after merge and docs

* refactor: remove code from merge

* fix: unit test

* fix: merge regressions

* fix: ui

* chore: add license missing in new files

* chore: add license missing in new files

* refactor: imports

* refactor: remove warnings

---------

Co-authored-by: Peter White <[email protected]>
Co-authored-by: Peter White <[email protected]>
  • Loading branch information
3 people authored Jul 26, 2024
1 parent 5d2a940 commit 336544d
Show file tree
Hide file tree
Showing 9 changed files with 198 additions and 116 deletions.
36 changes: 19 additions & 17 deletions crates/pop-cli/src/commands/test/contract.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
// SPDX-License-Identifier: GPL-3.0

use crate::{common::contracts::check_contracts_node_and_prompt, style::style};
use crate::{
cli::{traits::Cli as _, Cli},
common::contracts::check_contracts_node_and_prompt,
};
use clap::Args;
use cliclack::{clear_screen, intro, log::warning, outro};
use cliclack::{clear_screen, log::warning, outro};
use pop_contracts::{test_e2e_smart_contract, test_smart_contract};
use std::path::PathBuf;
#[cfg(not(test))]
Expand All @@ -24,6 +27,9 @@ pub(crate) struct TestContractCommand {
help = "Path to the contracts node to run e2e tests [default: none]"
)]
node: Option<PathBuf>,
/// Automatically source the needed binary required without prompting for confirmation.
#[clap(short('y'), long)]
skip_confirm: bool,
}

impl TestContractCommand {
Expand All @@ -35,34 +41,30 @@ impl TestContractCommand {
if self.features.is_some() && self.features.clone().unwrap().contains("e2e-tests") {
show_deprecated = true;
self.e2e = true;
#[cfg(not(test))]
sleep(Duration::from_secs(3)).await;
}

if self.e2e {
intro(format!(
"{}: Starting end-to-end tests",
style(" Pop CLI ").black().on_magenta()
))?;
Cli.intro("Starting end-to-end tests")?;

if show_deprecated {
warning("NOTE: --features e2e-tests is deprecated. Use --e2e instead.")?;
#[cfg(not(test))]
sleep(Duration::from_secs(3)).await;
}

let maybe_node_path = check_contracts_node_and_prompt().await?;
if let Some(node_path) = maybe_node_path {
if node_path != PathBuf::new() {
self.node = Some(node_path);
}
} else {
warning("🚫 substrate-contracts-node is necessary to run e2e tests. Will try to run tests anyway...")?;
}
self.node = match check_contracts_node_and_prompt(self.skip_confirm).await {
Ok(binary_path) => Some(binary_path),
Err(_) => {
warning("🚫 substrate-contracts-node is necessary to run e2e tests. Will try to run tests anyway...")?;
Some(PathBuf::new())
},
};

test_e2e_smart_contract(self.path.as_deref(), self.node.as_deref())?;
outro("End-to-end testing complete")?;
Ok("e2e")
} else {
intro(format!("{}: Starting unit tests", style(" Pop CLI ").black().on_magenta()))?;
Cli.intro("Starting unit tests")?;
test_smart_contract(self.path.as_deref())?;
outro("Unit testing complete")?;
Ok("unit")
Expand Down
25 changes: 10 additions & 15 deletions crates/pop-cli/src/commands/up/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ pub struct UpContractCommand {
/// Uploads the contract only, without instantiation.
#[clap(short('u'), long)]
upload_only: bool,
/// Before starting a local node, do not ask the user for confirmation.
/// Automatically source or update the needed binary required without prompting for confirmation.
#[clap(short('y'), long)]
skip_confirm: bool,
}
Expand Down Expand Up @@ -127,21 +127,16 @@ impl UpContractCommand {

let log = NamedTempFile::new()?;

// default to standalone binary, if it exists.
let mut binary_path = PathBuf::from("substrate-contracts-node");

// uses the cache location
let maybe_node_path = check_contracts_node_and_prompt().await?;
if let Some(node_path) = maybe_node_path {
if node_path != PathBuf::new() {
binary_path = node_path;
}
} else {
Cli.outro_cancel(
"🚫 You need to specify an accessible endpoint to deploy the contract.",
)?;
return Ok(());
}
let binary_path = match check_contracts_node_and_prompt(self.skip_confirm).await {
Ok(binary_path) => binary_path,
Err(_) => {
Cli.outro_cancel(
"🚫 You need to specify an accessible endpoint to deploy the contract.",
)?;
return Ok(());
},
};

let spinner = spinner();
spinner.start("Starting local node...");
Expand Down
66 changes: 46 additions & 20 deletions crates/pop-cli/src/common/contracts.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
// SPDX-License-Identifier: GPL-3.0

use cliclack::{confirm, log::warning, spinner};
use pop_contracts::{does_contracts_node_exist, download_contracts_node};
use pop_contracts::contracts_node_generator;
use std::path::PathBuf;

/// Helper function to check if the contracts node binary exists, and if not download it.
/// returns:
/// - Some("") if the standalone binary exists
/// - Some(binary_cache_location) if the binary exists in pop's cache
/// - None if the binary does not exist
pub async fn check_contracts_node_and_prompt() -> anyhow::Result<Option<PathBuf>> {
let mut node_path = None;

// if the contracts node binary does not exist, prompt the user to download it
let maybe_contract_node_path = does_contracts_node_exist(crate::cache()?);
if maybe_contract_node_path == None {
/// Checks the status of the `substrate-contracts-node` binary, sources it if necessary, and prompts the user to update it if the existing binary is not the latest version.
///
/// # Arguments
/// * `skip_confirm`: A boolean indicating whether to skip confirmation prompts.
pub async fn check_contracts_node_and_prompt(skip_confirm: bool) -> anyhow::Result<PathBuf> {
let cache_path: PathBuf = crate::cache()?;
let mut binary = contracts_node_generator(cache_path, None).await?;
let mut node_path = binary.path();
if !binary.exists() {
warning("⚠️ The substrate-contracts-node binary is not found.")?;
if confirm("📦 Would you like to source it automatically now?")
.initial_value(true)
Expand All @@ -21,19 +21,45 @@ pub async fn check_contracts_node_and_prompt() -> anyhow::Result<Option<PathBuf>
let spinner = spinner();
spinner.start("📦 Sourcing substrate-contracts-node...");

let cache_path = crate::cache()?;
let binary = download_contracts_node(cache_path.clone()).await?;
binary.source(false, &(), true).await?;

spinner.stop(format!(
"✅ substrate-contracts-node successfully sourced. Cached at: {}",
"✅ substrate-contracts-node successfully sourced. Cached at: {}",
binary.path().to_str().unwrap()
));
node_path = Some(binary.path());
node_path = binary.path();
}
}
if binary.stale() {
warning(format!(
"ℹ️ There is a newer version of {} available:\n {} -> {}",
binary.name(),
binary.version().unwrap_or("None"),
binary.latest().unwrap_or("None")
))?;
let latest;
if !skip_confirm {
latest = confirm(
"📦 Would you like to source it automatically now? It may take some time..."
.to_string(),
)
.initial_value(true)
.interact()?;
} else {
latest = true;
}
} else {
if let Some(contract_node_path) = maybe_contract_node_path {
// If the node_path is not empty (cached binary). Otherwise, the standalone binary will be used by cargo-contract.
node_path = Some(contract_node_path.0);
if latest {
let spinner = spinner();
spinner.start("📦 Sourcing substrate-contracts-node...");

binary.use_latest();
binary.source(false, &(), true).await?;

spinner.stop(format!(
"✅ substrate-contracts-node successfully sourced. Cached at: {}",
binary.path().to_str().unwrap()
));
node_path = binary.path();
}
}

Expand Down
2 changes: 2 additions & 0 deletions crates/pop-cli/src/common/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
// SPDX-License-Identifier: GPL-3.0

#[cfg(feature = "contract")]
pub mod contracts;
10 changes: 5 additions & 5 deletions crates/pop-cli/tests/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ use anyhow::Result;
use assert_cmd::Command;
use pop_common::templates::Template;
use pop_contracts::{
download_contracts_node, dry_run_gas_estimate_instantiate, instantiate_smart_contract,
contracts_node_generator, dry_run_gas_estimate_instantiate, instantiate_smart_contract,
run_contracts_node, set_up_deployment, Contract, UpOpts,
};
use std::{env::temp_dir, path::Path, process::Command as Cmd};
use std::{path::Path, process::Command as Cmd};
use strum::VariantArray;
use url::Url;

Expand Down Expand Up @@ -42,9 +42,9 @@ async fn contract_lifecycle() -> Result<()> {
assert!(temp_dir.join("test_contract/target/ink/test_contract.wasm").exists());
assert!(temp_dir.join("test_contract/target/ink/test_contract.json").exists());

// Run the contracts node
let node_path = download_contracts_node(temp_dir.to_path_buf().clone()).await?;
let process = run_contracts_node(node_path.path(), None).await?;
let binary = contracts_node_generator(temp_dir.to_path_buf().clone(), None).await?;
binary.source(false, &(), true).await?;
let process = run_contracts_node(binary.path(), None).await?;

// Only upload the contract
// pop up contract --upload-only
Expand Down
7 changes: 4 additions & 3 deletions crates/pop-contracts/src/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ pub async fn call_smart_contract(
mod tests {
use super::*;
use crate::{
create_smart_contract, download_contracts_node, dry_run_gas_estimate_instantiate,
contracts_node_generator, create_smart_contract, dry_run_gas_estimate_instantiate,
errors::Error, instantiate_smart_contract, run_contracts_node, set_up_deployment, Contract,
UpOpts,
};
Expand Down Expand Up @@ -313,8 +313,9 @@ mod tests {

let cache = temp_dir.path().join("");

let node_path = download_contracts_node(cache.clone()).await?;
let process = run_contracts_node(node_path.path(), None).await?;
let binary = contracts_node_generator(cache.clone(), None).await?;
binary.source(false, &(), true).await?;
let process = run_contracts_node(binary.path(), None).await?;
// Instantiate a Smart Contract.
let instantiate_exec = set_up_deployment(UpOpts {
path: Some(temp_dir.path().join("testing")),
Expand Down
4 changes: 1 addition & 3 deletions crates/pop-contracts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ pub use call::{
call_smart_contract, dry_run_call, dry_run_gas_estimate_call, set_up_call, CallOpts,
};
pub use new::{create_smart_contract, is_valid_contract_name};
pub use node::{
does_contracts_node_exist, download_contracts_node, is_chain_alive, run_contracts_node,
};
pub use node::{contracts_node_generator, is_chain_alive, run_contracts_node};
pub use templates::{Contract, ContractType};
pub use test::{test_e2e_smart_contract, test_smart_contract};
pub use up::{
Expand Down
Loading

0 comments on commit 336544d

Please sign in to comment.