Skip to main content

auths_cli/commands/
publish.rs

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