use crate::{
commands::{
package::{
common::{wait::*, *},
push::PackagePush,
tag::PackageTag,
},
AsyncCliCommand,
},
config::WasmerEnv,
};
use colored::Colorize;
use is_terminal::IsTerminal;
use std::path::{Path, PathBuf};
use wasmer_backend_api::WasmerClient;
use wasmer_config::package::{Manifest, PackageIdent};
#[derive(Debug, clap::Parser)]
pub struct PackagePublish {
#[clap(flatten)]
pub env: WasmerEnv,
#[clap(long, name = "dry-run")]
pub dry_run: bool,
#[clap(long)]
pub quiet: bool,
#[clap(long = "namespace")]
pub package_namespace: Option<String>,
#[clap(long = "name")]
pub package_name: Option<String>,
#[clap(long = "version")]
pub package_version: Option<semver::Version>,
#[clap(long)]
pub no_validate: bool,
#[clap(name = "path", default_value = ".")]
pub package_path: PathBuf,
#[clap(
long,
require_equals = true,
num_args = 0..=1,
default_value_t = PublishWait::None,
default_missing_value = "container",
value_enum
)]
pub wait: PublishWait,
#[clap(long, default_value = "5m")]
pub timeout: humantime::Duration,
#[clap(long, conflicts_with = "package_version")]
pub bump: bool,
#[clap(long, default_value_t = !std::io::stdin().is_terminal())]
pub non_interactive: bool,
}
impl PackagePublish {
pub async fn publish(
&self,
client: &WasmerClient,
manifest_path: &Path,
manifest: &Manifest,
allow_unnamed: bool,
) -> anyhow::Result<PackageIdent> {
let (package_namespace, package_hash) = {
let push_cmd = PackagePush {
env: self.env.clone(),
dry_run: self.dry_run,
quiet: self.quiet,
package_name: self.package_name.clone(),
package_namespace: self.package_namespace.clone(),
timeout: self.timeout,
non_interactive: self.non_interactive,
package_path: self.package_path.clone(),
};
push_cmd.push(client, manifest, manifest_path).await?
};
PackageTag {
wait: self.wait,
env: self.env.clone(),
dry_run: self.dry_run,
quiet: self.quiet,
package_namespace: Some(package_namespace),
package_name: self.package_name.clone(),
package_version: self.package_version.clone(),
timeout: self.timeout,
bump: self.bump,
non_interactive: self.non_interactive,
package_path: self.package_path.clone(),
package_hash,
package_id: None,
}
.tag(
client,
Some(manifest),
Some(manifest_path),
true,
allow_unnamed,
)
.await
}
}
#[async_trait::async_trait]
impl AsyncCliCommand for PackagePublish {
type Output = PackageIdent;
async fn run_async(self) -> Result<Self::Output, anyhow::Error> {
tracing::info!("Checking if user is logged in");
let client = login_user(&self.env, !self.non_interactive, "publish a package").await?;
tracing::info!("Loading manifest");
let (manifest_path, manifest) = get_manifest(&self.package_path)?;
tracing::info!("Got manifest at path {}", manifest_path.display());
let ident = self
.publish(&client, &manifest_path, &manifest, false)
.await?;
match ident {
PackageIdent::Named(ref n) => {
let url = make_package_url(&client, n);
eprintln!("\n{} Package URL: {url}", "ð–¥”".yellow().bold());
}
PackageIdent::Hash(ref h) => {
eprintln!(
"\n{} Succesfully published package ({h})",
"✔".green().bold()
);
}
}
Ok(ident)
}
}