diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c134b59..d05d0666 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - smoother large file download&proxy support (#463) +- Add GitHub API errors to clarify what failed (#464) ### Fixed - When queriying GitHub for the list of releases, retrieve more items (#462) diff --git a/src/error.rs b/src/error.rs index d3452070..e3920b9d 100644 --- a/src/error.rs +++ b/src/error.rs @@ -7,8 +7,12 @@ pub enum Error { CreateDirectory(String), #[diagnostic(code(espup::toolchain::rust::query_github))] - #[error("Failed to query GitHub API")] - GithubQuery, + #[error("Failed to query GitHub API: Rate Limiting")] + GithubRateLimit, + + #[diagnostic(code(espup::toolchain::rust::query_github))] + #[error("Failed to query GitHub API: Invalid Github token")] + GithubTokenInvalid, #[diagnostic(code(espup::toolchain::rust::install_riscv_target))] #[error("Failed to Install RISC-V targets for '{0}' toolchain")] diff --git a/src/toolchain/mod.rs b/src/toolchain/mod.rs index 69652007..01f030e5 100644 --- a/src/toolchain/mod.rs +++ b/src/toolchain/mod.rs @@ -233,7 +233,10 @@ pub async fn install(args: InstallOpts, install_mode: InstallMode) -> Result<()> toolchain_version.clone() } } else { - XtensaRust::get_latest_version().await? + // Get the latest version of the Xtensa Rust toolchain. If that fails, return an error::GithubTokenInvalid + XtensaRust::get_latest_version() + .await + .map_err(|_| Error::GithubTokenInvalid)? }; let toolchain_dir = get_rustup_home().join("toolchains").join(args.name); let llvm: Llvm = Llvm::new( @@ -364,6 +367,7 @@ pub fn github_query(url: &str) -> Result { header::ACCEPT, "application/vnd.github+json".parse().unwrap(), ); + headers.insert("X-GitHub-Api-Version", "2022-11-28".parse().unwrap()); if let Some(token) = env::var_os("GITHUB_TOKEN") { debug!("Auth header added"); @@ -375,23 +379,27 @@ pub fn github_query(url: &str) -> Result { ); } let client = build_proxy_blocking_client()?; - let json = retry( + let json: Result = retry( Fixed::from_millis(100).take(5), || -> Result { let res = client.get(url).headers(headers.clone()).send()?.text()?; if res.contains( "https://docs.github.com/rest/overview/resources-in-the-rest-api#rate-limiting", ) { - warn!("GitHub rate limit exceeded"); - return Err(Error::GithubQuery); + return Err(Error::GithubRateLimit); } + + if res.contains("Bad credentials") { + return Err(Error::GithubTokenInvalid); + } + let json: serde_json::Value = serde_json::from_str(&res).map_err(|_| Error::SerializeJson)?; Ok(json) }, ) - .unwrap(); - Ok(json) + .map_err(|err| err.error); + json } /// Checks if the directory exists and deletes it if it does. diff --git a/src/toolchain/rust.rs b/src/toolchain/rust.rs index fb5b7678..05c83750 100644 --- a/src/toolchain/rust.rs +++ b/src/toolchain/rust.rs @@ -33,6 +33,7 @@ use tokio::fs::{remove_dir_all, remove_file}; /// Xtensa Rust Toolchain repository const DEFAULT_XTENSA_RUST_REPOSITORY: &str = "https://github.com/esp-rs/rust-build/releases/download"; + /// Xtensa Rust Toolchain API URL const XTENSA_RUST_LATEST_API_URL: &str = "https://api.github.com/repos/esp-rs/rust-build/releases/latest";