From cd85622b1364924067ac6f6834083f85f99c1f65 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Thu, 13 Jun 2024 20:50:47 +1000 Subject: [PATCH] Improve gh token auto scraping (#1746) * Log the gh-auth token retrieval failure on debug level Fixed #1733 * Make gh_token::get an async function * Improve returned err msg in gh_token::get * Update use of gh_token::get() in entry.rs * Fix typos * Fix unclosed () * Fix unclosed () * Fix gh_token.rs * Fix entry.rs * Fix fmt in entry.rs * Fix fmt in gh_token.rs * Fix fmt in gh_token.rs * Fix fmt in gh_token.rs * Fix fmt in entry.rs --- crates/bin/src/entry.rs | 43 +++++++++++++++++++++++++------------- crates/bin/src/gh_token.rs | 26 +++++++++++++++-------- 2 files changed, 45 insertions(+), 24 deletions(-) diff --git a/crates/bin/src/entry.rs b/crates/bin/src/entry.rs index f409a726..e8e30079 100644 --- a/crates/bin/src/entry.rs +++ b/crates/bin/src/entry.rs @@ -27,7 +27,7 @@ use file_format::FileFormat; use home::cargo_home; use log::LevelFilter; use miette::{miette, Report, Result, WrapErr}; -use tokio::task::block_in_place; +use tokio::{runtime::Handle, task::block_in_place}; use tracing::{debug, error, info, warn}; use crate::{ @@ -82,6 +82,28 @@ pub fn install_crates( // Launch target detection let desired_targets = get_desired_targets(args.targets); + // Launch scraping of gh token + let no_discover_github_token = args.no_discover_github_token; + let github_token = args.github_token.or_else(|| { + if args.no_discover_github_token { + None + } else { + git_credentials::try_from_home() + } + }); + let get_gh_token_task = (github_token.is_none() && !no_discover_github_token).then(|| { + AutoAbortJoinHandle::spawn(async move { + match gh_token::get().await { + Ok(token) => Some(token), + Err(err) => { + debug!(?err, "Failed to retrieve token from `gh auth token`"); + debug!("Failed to read git credential file"); + None + } + } + }) + }); + // Computer cli_overrides let cli_overrides = PkgOverride { pkg_url: args.pkg_url, @@ -109,20 +131,11 @@ pub fn install_crates( let gh_api_client = GhApiClient::new( client.clone(), - args.github_token.or_else(|| { - if args.no_discover_github_token { - None - } else { - git_credentials::try_from_home().or_else(|| match gh_token::get() { - Ok(token) => Some(token), - Err(err) => { - warn!(?err, "Failed to retrieve token from `gh auth token`"); - warn!("Failed to read git credential file"); - None - } - }) - } - }), + if let Some(task) = get_gh_token_task { + Handle::current().block_on(task)? + } else { + github_token + }, ); // Create binstall_opts diff --git a/crates/bin/src/gh_token.rs b/crates/bin/src/gh_token.rs index 172070a6..b7a46655 100644 --- a/crates/bin/src/gh_token.rs +++ b/crates/bin/src/gh_token.rs @@ -1,14 +1,19 @@ -use std::{io, process}; +use std::{ + io, + process::{Output, Stdio}, +}; use compact_str::CompactString; +use tokio::process::Command; -pub(super) fn get() -> io::Result { - let process::Output { status, stdout, .. } = process::Command::new("gh") +pub(super) async fn get() -> io::Result { + let Output { status, stdout, .. } = Command::new("gh") .args(["auth", "token"]) - .stdin(process::Stdio::null()) - .stdout(process::Stdio::piped()) - .stderr(process::Stdio::null()) - .output()?; + .stdin(Stdio::null()) + .stdout(Stdio::piped()) + .stderr(Stdio::null()) + .output() + .await?; if !status.success() { return Err(io::Error::new( @@ -19,8 +24,11 @@ pub(super) fn get() -> io::Result { // Use String here instead of CompactString here since // `CompactString::from_utf8` allocates if it's longer than 24B. - let s = String::from_utf8(stdout).map_err(|_err| { - io::Error::new(io::ErrorKind::InvalidData, "Invalid output, expected utf8") + let s = String::from_utf8(stdout).map_err(|err| { + io::Error::new( + io::ErrorKind::InvalidData, + format!("Invalid output, expected utf8: {err}"), + ) })?; Ok(s.trim().into())