Skip to content

Commit e1e85ab

Browse files
authored
feat(cli): add --token option to self update command (#7279)
<!-- Thank you for contributing to uv! To help us out with reviewing, please consider the following: - Does this pull request include a summary of the change? (See below.) - Does this pull request include a descriptive title? - Does this pull request include references to any relevant issues? --> ## Summary It often reaches the GitHub API rate limit and shows error like `error: HTTP status client error (403 Forbidden) for url (https://api.github.com/repos/astral-sh/uv/releases)` when running `uv self update`. To bypass this rate limit issue, allow user to pass a GitHub token via `--token` or `UV_GITHUB_TOKEN` env. ## Test Plan <!-- How was it tested? --> --------- Signed-off-by: Frost Ming <[email protected]>
1 parent 3d2b94f commit e1e85ab

File tree

5 files changed

+40
-7
lines changed

5 files changed

+40
-7
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/uv-cli/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,11 @@ pub enum SelfCommand {
427427
pub struct SelfUpdateArgs {
428428
/// Update to the specified version. If not provided, uv will update to the latest version.
429429
pub target_version: Option<String>,
430+
431+
/// A GitHub token for authentication.
432+
/// A token is not required but can be used to reduce the chance of encountering rate limits.
433+
#[arg(long, env = "UV_GITHUB_TOKEN")]
434+
pub token: Option<String>,
430435
}
431436

432437
#[derive(Args)]

crates/uv/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ ctrlc = { workspace = true }
5555
flate2 = { workspace = true, default-features = false }
5656
fs-err = { workspace = true, features = ["tokio"] }
5757
futures = { workspace = true }
58+
http = { workspace = true }
5859
indexmap = { workspace = true }
5960
indicatif = { workspace = true }
6061
indoc = { workspace = true }

crates/uv/src/commands/self_update.rs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,18 @@ use crate::commands::ExitStatus;
1111
use crate::printer::Printer;
1212

1313
/// Attempt to update the uv binary.
14-
pub(crate) async fn self_update(version: Option<String>, printer: Printer) -> Result<ExitStatus> {
14+
pub(crate) async fn self_update(
15+
version: Option<String>,
16+
token: Option<String>,
17+
printer: Printer,
18+
) -> Result<ExitStatus> {
1519
let mut updater = AxoUpdater::new_for("uv");
1620
updater.disable_installer_output();
1721

22+
if let Some(ref token) = token {
23+
updater.set_github_token(token);
24+
}
25+
1826
// Load the "install receipt" for the current binary. If the receipt is not found, then
1927
// uv was likely installed via a package manager.
2028
let Ok(updater) = updater.load_receipt() else {
@@ -121,11 +129,25 @@ pub(crate) async fn self_update(version: Option<String>, printer: Printer) -> Re
121129
)?;
122130
}
123131
Err(err) => {
124-
return Err(if let AxoupdateError::Reqwest(err) = err {
125-
WrappedReqwestError::from(err).into()
132+
return if let AxoupdateError::Reqwest(err) = err {
133+
if err.status() == Some(http::StatusCode::FORBIDDEN) && token.is_none() {
134+
writeln!(
135+
printer.stderr(),
136+
"{}",
137+
format_args!(
138+
"{}{} GitHub API rate limit exceeded. Please provide a GitHub token via the {} option.",
139+
"error".red().bold(),
140+
":".bold(),
141+
"`--token`".green().bold()
142+
)
143+
)?;
144+
Ok(ExitStatus::Error)
145+
} else {
146+
Err(WrappedReqwestError::from(err).into())
147+
}
126148
} else {
127-
err.into()
128-
});
149+
Err(err.into())
150+
};
129151
}
130152
}
131153

crates/uv/src/lib.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -766,8 +766,12 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
766766
}
767767
#[cfg(feature = "self-update")]
768768
Commands::Self_(SelfNamespace {
769-
command: SelfCommand::Update(SelfUpdateArgs { target_version }),
770-
}) => commands::self_update(target_version, printer).await,
769+
command:
770+
SelfCommand::Update(SelfUpdateArgs {
771+
target_version,
772+
token,
773+
}),
774+
}) => commands::self_update(target_version, token, printer).await,
771775
Commands::Version { output_format } => {
772776
commands::version(output_format, &mut stdout())?;
773777
Ok(ExitStatus::Success)

0 commit comments

Comments
 (0)