Re-add 3 retries in uv publish (#12041)

In the publish client, we have to set the client retries to 0 as the
retry middleware is incompatible with upload bodies. This however also
sets `client.retry_policy()` to a zero-retry policy, so we need to
construct our own policy.

Fixes #12027

---------

Co-authored-by: Zanie Blue <contact@zanie.dev>
This commit is contained in:
konsti 2025-03-10 12:38:08 +01:00 committed by GitHub
parent ba74b9ea93
commit aa629c4a54
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 20 additions and 10 deletions

View file

@ -11,6 +11,7 @@ use reqwest::header::AUTHORIZATION;
use reqwest::multipart::Part;
use reqwest::{Body, Response, StatusCode};
use reqwest_middleware::RequestBuilder;
use reqwest_retry::policies::ExponentialBackoff;
use reqwest_retry::{RetryPolicy, Retryable, RetryableStrategy};
use rustc_hash::FxHashSet;
use serde::Deserialize;
@ -23,21 +24,22 @@ use tokio::io::{AsyncReadExt, BufReader};
use tokio::sync::Semaphore;
use tokio_util::io::ReaderStream;
use tracing::{debug, enabled, trace, warn, Level};
use trusted_publishing::TrustedPublishingToken;
use url::Url;
use uv_client::{BaseClient, OwnedArchive, RegistryClientBuilder, UvRetryableStrategy};
use uv_cache::{Cache, Refresh};
use uv_client::{
BaseClient, OwnedArchive, RegistryClientBuilder, UvRetryableStrategy, DEFAULT_RETRIES,
};
use uv_configuration::{KeyringProviderType, TrustedPublishing};
use uv_distribution_filename::{DistFilename, SourceDistExtension, SourceDistFilename};
use uv_distribution_types::{IndexCapabilities, IndexUrl};
use uv_extract::hash::{HashReader, Hasher};
use uv_fs::{ProgressReader, Simplified};
use uv_metadata::read_metadata_async_seek;
use uv_pypi_types::{HashAlgorithm, HashDigest, Metadata23, MetadataError};
use uv_static::EnvVars;
use uv_warnings::{warn_user, warn_user_once};
pub use trusted_publishing::TrustedPublishingToken;
use uv_cache::{Cache, Refresh};
use uv_distribution_types::{IndexCapabilities, IndexUrl};
use uv_extract::hash::{HashReader, Hasher};
#[derive(Error, Debug)]
pub enum PublishError {
#[error("The publish path is not a valid glob pattern: `{0}`")]
@ -379,7 +381,8 @@ pub async fn upload(
let mut n_past_retries = 0;
let start_time = SystemTime::now();
let retry_policy = client.retry_policy();
// N.B. We cannot use the client policy here because it is set to zero retries
let retry_policy = ExponentialBackoff::builder().build_with_max_retries(DEFAULT_RETRIES);
loop {
let (request, idx) = build_request(
file,

View file

@ -46,7 +46,8 @@ pub(crate) async fn publish(
// * For the uploads themselves, we roll our own retries due to
// https://github.com/seanmonstar/reqwest/issues/2416, but for trusted publishing, we want
// the default retries.
// the default retries. We set the retries to 0 here and manually construct the retry policy
// in the upload loop.
// * We want to allow configuring TLS for the registry, while for trusted publishing we know the
// defaults are correct.
// * For the uploads themselves, we know we need an authorization header and we can't nor

View file

@ -181,12 +181,18 @@ def get_latest_version(project_name: str, client: httpx.Client) -> Version:
break
except httpx.HTTPError as err:
error = err
print(f"Error getting version, sleeping for 1s: {err}", file=sys.stderr)
print(
f"Error getting version for {project_name}, sleeping for 1s: {err}",
file=sys.stderr,
)
time.sleep(1)
except InvalidSdistFilename as err:
# Sometimes there's a link that says "status page"
error = err
print(f"Invalid index page, sleeping for 1s: {err}", file=sys.stderr)
print(
f"Invalid index page for {project_name}, sleeping for 1s: {err}",
file=sys.stderr,
)
time.sleep(1)
else:
raise RuntimeError(f"Failed to fetch {url}") from error