use std::path::PathBuf;
use anyhow::{Context, Result};
use bonsai_sdk::blocking::Client;
use cargo_metadata::MetadataCommand;
use clap::Parser;
use risc0_build::BuildStatus;
use crate::commands::build_guest;
use crate::utils;
#[derive(Parser)]
pub struct DeployCommand {
#[arg(long)]
pub manifest_path: PathBuf,
#[arg(long, value_delimiter = ',')]
pub features: Vec<String>,
#[command(flatten)]
client_envs: utils::ClientEnvs,
}
impl DeployCommand {
pub fn run(&self) -> Result<()> {
let client = utils::get_client(&self.client_envs)?;
self.deploy(client)?;
Ok(())
}
fn deploy(&self, client: Client) -> Result<()> {
if let BuildStatus::Skipped = build_guest::build(&self.manifest_path, &self.features)? {
eprintln!("Build skipped, nothing to deploy.");
return Ok(());
}
let src_dir = std::env::current_dir().unwrap();
let meta = MetadataCommand::new()
.manifest_path(&self.manifest_path)
.exec()
.context("Manifest not found")?;
let root_pkg = meta.root_package().context("Failed to parse Cargo.toml")?;
let target_dir = src_dir.join(risc0_build::TARGET_DIR);
let pkg_name = root_pkg.name.replace('-', "_");
for target in root_pkg.targets.iter().filter(|t| t.is_bin()) {
let elf_path = target_dir.join(&pkg_name).join(&target.name);
let elf = std::fs::read(&elf_path).with_context(|| {
format!("Failed to read ELF file at path: {}", elf_path.display())
})?;
let image_id = risc0_binfmt::compute_image_id(&elf)?;
let image_id_hex = hex::encode(image_id);
client.upload_img(&image_id_hex, elf)?;
println!(
"Uploaded ELF `{}` with image ID `{}`.",
target.name, image_id_hex
);
}
Ok(())
}
}