mirror of
https://github.com/esp-rs/espup.git
synced 2026-04-19 21:35:40 +00:00
Enhance GitHub API error handling (#496)
* feat: Enhance GitHub API error handling * docs: Update changelog
This commit is contained in:
committed by
GitHub
parent
6d6e3d08d6
commit
4efd93c6a7
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
## Unreleased
|
||||
|
||||
### Changed
|
||||
- Improved GitHub API error handling (#496)
|
||||
- update `zip` dependency to 3.0.0
|
||||
|
||||
## [0.15.0] - 2025-04-08
|
||||
|
||||
@@ -14,6 +14,10 @@ pub enum Error {
|
||||
#[error("Failed to query GitHub API: Invalid Github token")]
|
||||
GithubTokenInvalid,
|
||||
|
||||
#[diagnostic(code(espup::toolchain::rust::query_github))]
|
||||
#[error("Failed to connect to GitHub API: {0}")]
|
||||
GithubConnectivityError(String),
|
||||
|
||||
#[diagnostic(code(espup::toolchain::http_error))]
|
||||
#[error("HTTP GET Error: {0}")]
|
||||
HttpError(String),
|
||||
|
||||
@@ -237,10 +237,11 @@ pub async fn install(args: InstallOpts, install_mode: InstallMode) -> Result<()>
|
||||
toolchain_version.clone()
|
||||
}
|
||||
} else {
|
||||
// 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)?
|
||||
// Get the latest version of the Xtensa Rust toolchain
|
||||
XtensaRust::get_latest_version().await.map_err(|e| {
|
||||
warn!("Failed to get latest Xtensa Rust version: {}", e);
|
||||
e
|
||||
})?
|
||||
};
|
||||
let toolchain_dir = get_rustup_home().join("toolchains").join(args.name);
|
||||
let llvm: Llvm = Llvm::new(
|
||||
@@ -382,27 +383,42 @@ pub fn github_query(url: &str) -> Result<serde_json::Value, Error> {
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
let client = build_proxy_blocking_client()?;
|
||||
|
||||
let json: Result<serde_json::Value, Error> = retry(
|
||||
Fixed::from_millis(100).take(5),
|
||||
|| -> Result<serde_json::Value, Error> {
|
||||
let res = client.get(url).headers(headers.clone()).send()?.text()?;
|
||||
let response = client.get(url).headers(headers.clone()).send()?;
|
||||
let status = response.status();
|
||||
|
||||
if !status.is_success() {
|
||||
return Err(Error::HttpError(format!(
|
||||
"GitHub API returned status code: {}",
|
||||
status
|
||||
)));
|
||||
}
|
||||
|
||||
let res = response.text()?;
|
||||
|
||||
// Check for rate limiting response
|
||||
if res.contains(
|
||||
"https://docs.github.com/rest/overview/resources-in-the-rest-api#rate-limiting",
|
||||
) {
|
||||
return Err(Error::GithubRateLimit);
|
||||
}
|
||||
|
||||
// Check for authentication errors
|
||||
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)
|
||||
// Try to parse the JSON
|
||||
serde_json::from_str(&res).map_err(|_| Error::SerializeJson)
|
||||
},
|
||||
)
|
||||
.map_err(|err| err.error);
|
||||
|
||||
json
|
||||
}
|
||||
|
||||
|
||||
@@ -72,19 +72,35 @@ pub struct XtensaRust {
|
||||
|
||||
impl XtensaRust {
|
||||
/// Get the latest version of Xtensa Rust toolchain.
|
||||
pub async fn get_latest_version() -> Result<String> {
|
||||
let json = tokio::task::spawn_blocking(|| github_query(XTENSA_RUST_LATEST_API_URL))
|
||||
.await
|
||||
.unwrap()?;
|
||||
let mut version = json["tag_name"].to_string();
|
||||
pub async fn get_latest_version() -> Result<String, Error> {
|
||||
debug!("Querying latest Xtensa Rust version from GitHub API");
|
||||
|
||||
version.retain(|c| c != 'v' && c != '"');
|
||||
let borrowed = version.clone();
|
||||
tokio::task::spawn_blocking(move || Self::parse_version(&borrowed))
|
||||
// First, handle the spawn_blocking result
|
||||
let query_result = tokio::task::spawn_blocking(|| github_query(XTENSA_RUST_LATEST_API_URL))
|
||||
.await
|
||||
.expect("Join blocking task error")?;
|
||||
debug!("Latest Xtensa Rust version: {}", version);
|
||||
Ok(version)
|
||||
.map_err(|e| {
|
||||
Error::GithubConnectivityError(format!("Failed to query GitHub API: {}", e))
|
||||
})?;
|
||||
|
||||
// Then handle the github_query result
|
||||
let json = query_result?;
|
||||
|
||||
if !json.is_object() || !json["tag_name"].is_string() {
|
||||
return Err(Error::SerializeJson);
|
||||
}
|
||||
|
||||
let mut version = json["tag_name"].to_string();
|
||||
version.retain(|c| c != 'v' && c != '"');
|
||||
|
||||
// Validate the version format - handle both spawning and parsing errors
|
||||
let parse_task = tokio::task::spawn_blocking(move || Self::parse_version(&version))
|
||||
.await
|
||||
.map_err(|_| Error::SerializeJson)?;
|
||||
|
||||
let validated_version = parse_task?;
|
||||
|
||||
debug!("Latest Xtensa Rust version: {}", validated_version);
|
||||
Ok(validated_version)
|
||||
}
|
||||
|
||||
/// Create a new instance.
|
||||
|
||||
Reference in New Issue
Block a user