diff --git a/CHANGELOG.md b/CHANGELOG.md index b2d0e4fcdd..fad6bf3b98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,12 @@ # UNRELEASED +### feat: `skip_cargo_audit` flag in dfx.json to skip `cargo audit` build step + ### fix: `dfx canister install` and `dfx deploy` with `--no-asset-upgrade` no longer hang indefinitely when wasm is not up to date +### fix: `dfx` downloads `.did` files for remote canisters + ### feat: streamlined output during asset synchronization # 0.25.0 diff --git a/docs/dfx-json-schema.json b/docs/dfx-json-schema.json index 6f6fdc505f..808d531979 100644 --- a/docs/dfx-json-schema.json +++ b/docs/dfx-json-schema.json @@ -246,6 +246,12 @@ "description": "Name of the Rust package that compiles this canister's Wasm.", "type": "string" }, + "skip_cargo_audit": { + "title": "`cargo-audit` check", + "description": "If set to true, does not run `cargo audit` before building.", + "default": false, + "type": "boolean" + }, "type": { "type": "string", "enum": [ diff --git a/e2e/assets/remote/download_did/canister_ids.json b/e2e/assets/remote/download_did/canister_ids.json new file mode 100644 index 0000000000..037eb88944 --- /dev/null +++ b/e2e/assets/remote/download_did/canister_ids.json @@ -0,0 +1,5 @@ +{ + "hello_backend": { + "ic": "aaaaa-aa" + } +} \ No newline at end of file diff --git a/e2e/assets/remote/download_did/dfx.json b/e2e/assets/remote/download_did/dfx.json new file mode 100644 index 0000000000..55b735ac6d --- /dev/null +++ b/e2e/assets/remote/download_did/dfx.json @@ -0,0 +1,25 @@ +{ + "canisters": { + "hello_backend": { + "main": "main.mo", + "type": "motoko", + "dependencies": [ + "internet_identity" + ] + }, + "internet_identity": { + "type": "custom", + "candid": "https://github.com/dfinity/internet-identity/releases/download/release-2024-12-13/internet_identity.did", + "wasm": "https://github.com/dfinity/internet-identity/releases/download/release-2024-12-13/internet_identity_dev.wasm.gz", + "init_arg": "(opt record { captcha_config = opt record { max_unsolved_captchas= 50:nat64; captcha_trigger = variant {Static = variant {CaptchaDisabled}}}})", + "remote": { + "id": { + "ic": "rdmx6-jaaaa-aaaaa-aaadq-cai" + } + }, + "frontend": {} + } + }, + "output_env_file": ".env", + "version": 1 +} \ No newline at end of file diff --git a/e2e/assets/remote/download_did/main.mo b/e2e/assets/remote/download_did/main.mo new file mode 100644 index 0000000000..608acadb27 --- /dev/null +++ b/e2e/assets/remote/download_did/main.mo @@ -0,0 +1,3 @@ +import II "canister:internet_identity"; + +actor {}; diff --git a/e2e/tests-dfx/build_rust.bash b/e2e/tests-dfx/build_rust.bash index 60dc5f19a1..6df5a8cb18 100644 --- a/e2e/tests-dfx/build_rust.bash +++ b/e2e/tests-dfx/build_rust.bash @@ -34,4 +34,7 @@ teardown() { dfx canister create --all assert_command dfx build assert_match "Audit found vulnerabilities" + jq '.canisters.hello.skip_cargo_audit=true' dfx.json | sponge dfx.json + assert_command dfx build + assert_not_match "Audit found vulnerabilities" } diff --git a/e2e/tests-dfx/remote.bash b/e2e/tests-dfx/remote.bash index 8e8bc5568e..105a35e53f 100644 --- a/e2e/tests-dfx/remote.bash +++ b/e2e/tests-dfx/remote.bash @@ -345,3 +345,9 @@ teardown() { assert_match "CANISTER_ID_REMOTE: qoctq-giaaa-aaaaa-aaaea-cai" assert_contains "CANISTER_CANDID_PATH_REMOTE: $(pwd -P)/remotecandid.did" } + +@test "build step downloads dependency .did files" { + install_asset remote/download_did + assert_command dfx build --ic -v + assert_not_contains ".did file for canister 'internet_identity' does not exist" +} diff --git a/src/dfx-core/src/config/model/dfinity.rs b/src/dfx-core/src/config/model/dfinity.rs index d657a1858c..1593a470d5 100644 --- a/src/dfx-core/src/config/model/dfinity.rs +++ b/src/dfx-core/src/config/model/dfinity.rs @@ -355,6 +355,11 @@ pub enum CanisterTypeProperties { /// # Candid File /// Path of this canister's candid interface declaration. candid: PathBuf, + + /// # `cargo-audit` check + /// If set to true, does not run `cargo audit` before building. + #[serde(default)] + skip_cargo_audit: bool, }, /// # Asset-Specific Properties Assets { @@ -1296,6 +1301,7 @@ impl<'de> Visitor<'de> for PropertiesVisitor { let mut wasm = None; let mut candid = None; let mut package = None; + let mut skip_cargo_audit = None; let mut crate_name = None; let mut source = None; let mut build = None; @@ -1313,6 +1319,7 @@ impl<'de> Visitor<'de> for PropertiesVisitor { "type" => r#type = Some(map.next_value::()?), "id" => id = Some(map.next_value()?), "workspace" => workspace = Some(map.next_value()?), + "skip_cargo_audit" => skip_cargo_audit = Some(map.next_value()?), _ => continue, } } @@ -1321,6 +1328,7 @@ impl<'de> Visitor<'de> for PropertiesVisitor { Some("rust") => CanisterTypeProperties::Rust { candid: PathBuf::from(candid.ok_or_else(|| missing_field("candid"))?), package: package.ok_or_else(|| missing_field("package"))?, + skip_cargo_audit: skip_cargo_audit.unwrap_or(false), crate_name, }, Some("assets") => CanisterTypeProperties::Assets { diff --git a/src/dfx/src/lib/canister_info.rs b/src/dfx/src/lib/canister_info.rs index 95b4808af9..b217041d91 100644 --- a/src/dfx/src/lib/canister_info.rs +++ b/src/dfx/src/lib/canister_info.rs @@ -145,6 +145,7 @@ impl CanisterInfo { package: _, crate_name: _, candid, + skip_cargo_audit: _, } => workspace_root.join(candid), CanisterTypeProperties::Assets { .. } => output_root.join("assetstorage.did"), CanisterTypeProperties::Custom { @@ -360,6 +361,10 @@ impl CanisterInfo { matches!(self.type_specific, CanisterTypeProperties::Rust { .. }) } + pub fn should_cargo_audit(&self) -> bool { + matches!(self.type_specific, CanisterTypeProperties::Rust { skip_cargo_audit, .. } if !skip_cargo_audit) + } + pub fn is_assets(&self) -> bool { matches!(self.type_specific, CanisterTypeProperties::Assets { .. }) } diff --git a/src/dfx/src/lib/canister_info/rust.rs b/src/dfx/src/lib/canister_info/rust.rs index de6cdd01ad..1d933b31a9 100644 --- a/src/dfx/src/lib/canister_info/rust.rs +++ b/src/dfx/src/lib/canister_info/rust.rs @@ -34,14 +34,13 @@ impl CanisterInfoFactory for RustCanisterInfo { bail!("`cargo metadata` was unsuccessful"); } - let (package, crate_name) = if let CanisterTypeProperties::Rust { + let CanisterTypeProperties::Rust { package, crate_name, candid: _, + skip_cargo_audit: _, } = info.type_specific.clone() - { - (package, crate_name) - } else { + else { bail!( "Attempted to construct a custom canister from a type:{} canister config", info.type_specific.name() diff --git a/src/dfx/src/lib/models/canister.rs b/src/dfx/src/lib/models/canister.rs index f4f1412cef..0084143514 100644 --- a/src/dfx/src/lib/models/canister.rs +++ b/src/dfx/src/lib/models/canister.rs @@ -682,13 +682,13 @@ impl CanisterPool { if self .canisters_to_build(build_config) .iter() - .any(|can| can.info.is_rust()) + .any(|can| can.info.should_cargo_audit()) { self.run_cargo_audit()?; } else { trace!( self.logger, - "No canister of type 'rust' found. Not trying to run 'cargo audit'." + "No canister of type 'rust' found (or it disabled the audit step). Not trying to run 'cargo audit'." ) } @@ -839,7 +839,7 @@ impl CanisterPool { log: &Logger, build_config: &BuildConfig, ) -> DfxResult<()> { - self.download(build_config).await?; + self.download().await?; let outputs = self.build(env, log, build_config)?; for output in outputs { @@ -849,8 +849,8 @@ impl CanisterPool { Ok(()) } - async fn download(&self, build_config: &BuildConfig) -> DfxResult { - for canister in self.canisters_to_build(build_config) { + async fn download(&self) -> DfxResult { + for canister in self.canisters.iter() { let info = canister.get_info(); if info.is_custom() {