feat: add proxy support for SDK downloads (v1.1.0)

Add --proxy and --no-proxy global flags to control HTTP/HTTPS proxy
usage for all network operations (SDK installs, FTC SDK clone/fetch,
Android SDK download).

Proxy resolution priority:
  1. --no-proxy          → go direct, ignore everything
  2. --proxy <url>       → use the specified proxy
  3. HTTPS_PROXY / HTTP_PROXY env vars (auto-detected)
  4. Nothing             → go direct

Key implementation details:
- reqwest client is always built through ProxyConfig::client() rather
  than Client::new(), so --no-proxy actively suppresses env-var
  auto-detection instead of just being a no-op.
- git2/libgit2 has its own HTTP transport that doesn't use reqwest.
  GitProxyGuard is an RAII guard that temporarily sets/clears the
  HTTPS_PROXY env vars around clone and fetch operations, then restores
  the previous state on drop. This avoids mutating ~/.gitconfig.
- Gradle wrapper reads HTTPS_PROXY natively; no programmatic
  intervention needed.
- All network failure paths now print offline/air-gapped installation
  instructions automatically, covering manual SDK installs and Gradle
  distribution download.

Closes: v1.1.0 proxy support milestone
This commit is contained in:
Eric Ratliff
2026-02-01 09:44:53 -06:00
parent 5596f5bade
commit 54647a47b1
9 changed files with 1161 additions and 48 deletions

View File

@@ -1,60 +1,61 @@
use anyhow::Result;
use colored::*;
use crate::sdk::SdkConfig;
use crate::sdk::proxy::ProxyConfig;
pub fn install_sdks() -> Result<()> {
pub fn install_sdks(proxy: &ProxyConfig) -> Result<()> {
println!("{}", "Installing SDKs...".bright_yellow().bold());
println!();
let config = SdkConfig::new()?;
// Install FTC SDK
crate::sdk::ftc::install(&config.ftc_sdk_path, &config.android_sdk_path)?;
crate::sdk::ftc::install(&config.ftc_sdk_path, &config.android_sdk_path, proxy)?;
// Install Android SDK
crate::sdk::android::install(&config.android_sdk_path)?;
crate::sdk::android::install(&config.android_sdk_path, proxy)?;
println!();
println!("{} All SDKs installed successfully", "".green().bold());
config.print_status();
Ok(())
}
pub fn show_status() -> Result<()> {
let config = SdkConfig::new()?;
config.print_status();
// Verify SDKs
println!();
println!("{}", "Verification:".bright_yellow().bold());
match crate::sdk::ftc::verify(&config.ftc_sdk_path) {
Ok(_) => println!("{} FTC SDK is valid", "".green()),
Err(e) => println!("{} FTC SDK: {}", "".red(), e),
}
match crate::sdk::android::verify(&config.android_sdk_path) {
Ok(_) => println!("{} Android SDK is valid", "".green()),
Err(e) => println!("{} Android SDK: {}", "".red(), e),
}
println!();
Ok(())
}
pub fn update_sdks() -> Result<()> {
pub fn update_sdks(proxy: &ProxyConfig) -> Result<()> {
println!("{}", "Updating SDKs...".bright_yellow().bold());
println!();
let config = SdkConfig::new()?;
// Update FTC SDK
crate::sdk::ftc::update(&config.ftc_sdk_path)?;
crate::sdk::ftc::update(&config.ftc_sdk_path, proxy)?;
println!();
println!("{} SDKs updated successfully", "".green().bold());
Ok(())
}
}