wasmer_cli/commands/package/
publish.rs1use crate::{
2 commands::{
3 AsyncCliCommand,
4 package::{
5 common::{wait::*, *},
6 push::PackagePush,
7 tag::PackageTag,
8 },
9 },
10 config::WasmerEnv,
11};
12use colored::Colorize;
13use is_terminal::IsTerminal;
14use std::path::{Path, PathBuf};
15use wasmer_backend_api::WasmerClient;
16use wasmer_config::package::{Manifest, PackageIdent};
17
18#[derive(Debug, clap::Parser)]
20pub struct PackagePublish {
21 #[clap(flatten)]
22 pub env: WasmerEnv,
23
24 #[clap(long, name = "dry-run")]
26 pub dry_run: bool,
27
28 #[clap(long)]
30 pub quiet: bool,
31
32 #[clap(long = "namespace")]
34 pub package_namespace: Option<String>,
35
36 #[clap(long = "name")]
38 pub package_name: Option<String>,
39
40 #[clap(long = "version")]
42 pub package_version: Option<semver::Version>,
43
44 #[clap(long)]
46 pub no_validate: bool,
47
48 #[clap(name = "path", default_value = ".")]
52 pub package_path: PathBuf,
53
54 #[clap(
56 long,
57 require_equals = true,
58 num_args = 0..=1,
59 default_value_t = PublishWait::None,
60 default_missing_value = "container",
61 value_enum
62 )]
63 pub wait: PublishWait,
64
65 #[clap(long, default_value = "5m")]
70 pub timeout: humantime::Duration,
71
72 #[clap(long, conflicts_with = "package_version")]
74 pub bump: bool,
75
76 #[clap(long, default_value_t = !std::io::stdin().is_terminal())]
78 pub non_interactive: bool,
79}
80
81impl PackagePublish {
82 pub async fn publish(
83 &self,
84 client: &WasmerClient,
85 manifest_path: &Path,
86 manifest: &Manifest,
87 allow_unnamed: bool,
88 ) -> anyhow::Result<PackageIdent> {
89 let (package_namespace, package_hash) = {
90 let push_cmd = PackagePush {
91 env: self.env.clone(),
92 dry_run: self.dry_run,
93 quiet: self.quiet,
94 package_name: self.package_name.clone(),
95 package_namespace: self.package_namespace.clone(),
96 timeout: self.timeout,
97 non_interactive: self.non_interactive,
98 package_path: self.package_path.clone(),
99 };
100
101 push_cmd.push(client, manifest, manifest_path).await?
102 };
103
104 PackageTag {
105 wait: self.wait,
106 env: self.env.clone(),
107 dry_run: self.dry_run,
108 quiet: self.quiet,
109 package_namespace: Some(package_namespace),
110 package_name: self.package_name.clone(),
111 package_version: self.package_version.clone(),
112 timeout: self.timeout,
113 bump: self.bump,
114 non_interactive: self.non_interactive,
115 package_path: self.package_path.clone(),
116 package_hash,
117 package_id: None,
118 }
119 .tag(
120 client,
121 Some(manifest),
122 Some(manifest_path),
123 true,
124 allow_unnamed,
125 )
126 .await
127 }
128}
129
130#[async_trait::async_trait]
131impl AsyncCliCommand for PackagePublish {
132 type Output = PackageIdent;
133
134 async fn run_async(self) -> Result<Self::Output, anyhow::Error> {
135 tracing::info!("Checking if user is logged in");
136 let client = login_user(&self.env, !self.non_interactive, "publish a package").await?;
137
138 tracing::info!("Loading manifest");
139 let (manifest_path, manifest) = get_manifest(&self.package_path)?;
140 tracing::info!("Got manifest at path {}", manifest_path.display());
141
142 let ident = self
143 .publish(&client, &manifest_path, &manifest, false)
144 .await?;
145
146 match ident {
147 PackageIdent::Named(ref n) => {
148 let url = make_package_url(&client, n);
149 eprintln!("\n{} Package URL: {url}", "ð–¥”".yellow().bold());
150 }
151 PackageIdent::Hash(ref h) => {
152 eprintln!(
153 "\n{} Succesfully published package ({h})",
154 "✔".green().bold()
155 );
156 }
157 }
158
159 Ok(ident)
160 }
161}