auths_cli/commands/
publish.rs1use anyhow::Result;
2use std::path::PathBuf;
3
4use crate::commands::artifact::publish::handle_publish;
5use crate::commands::executable::ExecutableCommand;
6use crate::config::CliConfig;
7
8#[derive(Debug, clap::Args)]
10#[command(
11 about = "Publish a signed artifact attestation to the Auths registry.",
12 after_help = "Examples:
13 auths publish package.tar.gz # Sign and publish
14 auths publish --signature package.tar.gz.auths.json # Publish existing signature
15 auths publish package.tar.gz --package npm:react@18.3.0
16
17Related:
18 auths sign — Sign an artifact without publishing
19 auths verify — Verify a signed artifact"
20)]
21pub struct PublishCommand {
22 #[arg(help = "Artifact file to sign and publish.")]
24 pub file: Option<PathBuf>,
25
26 #[arg(long, value_name = "PATH")]
28 pub signature: Option<PathBuf>,
29
30 #[arg(long)]
32 pub package: Option<String>,
33
34 #[arg(long, env = "AUTHS_REGISTRY_URL")]
36 pub registry: Option<String>,
37}
38
39impl ExecutableCommand for PublishCommand {
40 fn execute(&self, ctx: &CliConfig) -> Result<()> {
41 let sig_path = match (&self.signature, &self.file) {
42 (Some(sig), _) => sig.clone(),
43 (None, Some(file)) => {
44 let mut p = file.clone();
45 p.set_file_name(format!(
46 "{}.auths.json",
47 p.file_name().unwrap_or_default().to_string_lossy()
48 ));
49 if !p.exists() {
50 crate::commands::artifact::sign::handle_sign(
51 file,
52 None,
53 None,
54 &crate::commands::key_detect::auto_detect_device_key(
55 ctx.repo_path.as_deref(),
56 &ctx.env_config,
57 )?,
58 None,
59 None,
60 None,
63 ctx.repo_path.clone(),
64 ctx.passphrase_provider.clone(),
65 &ctx.env_config,
66 &None,
67 false,
68 false,
69 )?;
70 }
71 p
72 }
73 (None, None) => anyhow::bail!("Provide an artifact file or --signature path"),
74 };
75
76 let registry = crate::commands::verify_helpers::require_registry(self.registry.clone())?;
77 handle_publish(&sig_path, self.package.as_deref(), ®istry)
78 }
79}