Skip to content

Commit

Permalink
Add non-interactive mode to upload command (#1722)
Browse files Browse the repository at this point in the history
  • Loading branch information
messense authored Aug 9, 2023
1 parent 1801f63 commit b239fbd
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 17 deletions.
10 changes: 5 additions & 5 deletions src/ci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ jobs:\n",
MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
with:
command: upload
args: --skip-existing *
args: --non-interactive --skip-existing *
"#,
);
if platforms.contains(&Platform::Emscripten) {
Expand Down Expand Up @@ -645,7 +645,7 @@ mod tests {
MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
with:
command: upload
args: --skip-existing *
args: --non-interactive --skip-existing *
"#};
assert_eq!(conf, expected.trim());
}
Expand Down Expand Up @@ -759,7 +759,7 @@ mod tests {
MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
with:
command: upload
args: --skip-existing *
args: --non-interactive --skip-existing *
"#};
assert_eq!(conf, expected.trim());
}
Expand Down Expand Up @@ -936,7 +936,7 @@ mod tests {
MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
with:
command: upload
args: --skip-existing *
args: --non-interactive --skip-existing *
"#};
assert_eq!(conf, expected.trim());
}
Expand Down Expand Up @@ -1055,7 +1055,7 @@ mod tests {
MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
with:
command: upload
args: --skip-existing *
args: --non-interactive --skip-existing *
"#};
assert_eq!(conf, expected.trim());
}
Expand Down
28 changes: 16 additions & 12 deletions src/upload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,7 @@ pub struct PublishOpt {
/// The URL of the registry where the wheels are uploaded to. This overrides --repository.
///
/// Can also be set via MATURIN_REPOSITORY_URL environment variable.
#[arg(
long = "repository-url",
env = "MATURIN_REPOSITORY_URL",
overrides_with = "repository"
)]
#[arg(long, env = "MATURIN_REPOSITORY_URL", overrides_with = "repository")]
repository_url: Option<String>,
/// Username for pypi or your custom registry.
///
Expand All @@ -53,8 +49,13 @@ pub struct PublishOpt {
password: Option<String>,
/// Continue uploading files if one already exists.
/// (Only valid when uploading to PyPI. Other implementations may not support this.)
#[arg(long = "skip-existing")]
#[arg(long)]
skip_existing: bool,
/// Do not interactively prompt for username/password if the required credentials are missing.
///
/// Can also be set via MATURIN_NON_INTERACTIVE environment variable.
#[arg(long, env = "MATURIN_NON_INTERACTIVE")]
non_interactive: bool,
}

impl PublishOpt {
Expand Down Expand Up @@ -202,17 +203,17 @@ fn resolve_pypi_cred(
config: &Ini,
registry_name: Option<&str>,
registry_url: &str,
) -> (String, String) {
) -> Result<(String, String)> {
// API token from environment variable takes priority
if let Ok(token) = env::var("MATURIN_PYPI_TOKEN") {
return ("__token__".to_string(), token);
return Ok(("__token__".to_string(), token));
}

// Try to get a token via OIDC exchange
match resolve_pypi_token_via_oidc(registry_url) {
Ok(Some(token)) => {
eprintln!("🔐 Using trusted publisher for upload");
return ("__token__".to_string(), token);
return Ok(("__token__".to_string(), token));
}
Ok(None) => {}
Err(e) => eprintln!("⚠️ Warning: Failed to resolve PyPI token via OIDC: {}", e),
Expand All @@ -222,17 +223,20 @@ fn resolve_pypi_cred(
registry_name.and_then(|name| load_pypi_cred_from_config(config, name))
{
eprintln!("🔐 Using credential in pypirc for upload");
return (username, password);
return Ok((username, password));
}

// fallback to username and password
if opt.non_interactive {
bail!("Credentials not found and non-interactive mode is enabled");
}
let username = opt.username.clone().unwrap_or_else(get_username);
let password = opt
.password
.clone()
.or_else(|| env::var("MATURIN_PASSWORD").ok())
.unwrap_or_else(|| get_password(&username));
(username, password)
Ok((username, password))
}

#[derive(Debug, Deserialize)]
Expand Down Expand Up @@ -328,7 +332,7 @@ fn complete_registry(opt: &PublishOpt) -> Result<Registry> {
opt.repository
);
};
let (username, password) = resolve_pypi_cred(opt, &pypirc, registry_name, &registry_url);
let (username, password) = resolve_pypi_cred(opt, &pypirc, registry_name, &registry_url)?;
let registry = Registry::new(username, password, registry_url);

Ok(registry)
Expand Down
7 changes: 7 additions & 0 deletions tests/cmd/publish.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ Options:
Continue uploading files if one already exists. (Only valid when uploading to PyPI. Other
implementations may not support this.)

--non-interactive
Do not interactively prompt for username/password if the required credentials are missing.

Can also be set via MATURIN_NON_INTERACTIVE environment variable.

[env: MATURIN_NON_INTERACTIVE=]

--compatibility [<compatibility>...]
Control the platform tag on linux.

Expand Down
7 changes: 7 additions & 0 deletions tests/cmd/upload.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,12 @@ Options:
Continue uploading files if one already exists. (Only valid when uploading to PyPI. Other
implementations may not support this.)

--non-interactive
Do not interactively prompt for username/password if the required credentials are missing.

Can also be set via MATURIN_NON_INTERACTIVE environment variable.

[env: MATURIN_NON_INTERACTIVE=]

-h, --help
Print help (see a summary with '-h')

0 comments on commit b239fbd

Please sign in to comment.