Skip to content

Commit

Permalink
feat: Adds hc ready command (#81)
Browse files Browse the repository at this point in the history
Introduces a new `hc ready` command that checks if Hipcheck
is ready to run. This is experimental for now, but is intended to
make it easier to debug issues with Hipcheck installs in the
future, similar to `brew doctor` for Homebrew.

Signed-off-by: Andrew Lilley Brinker <[email protected]>

---------

Signed-off-by: Andrew Lilley Brinker <[email protected]>
Co-authored-by: Andrew Lilley Brinker <[email protected]>
  • Loading branch information
mchernicoff and alilleybrinker authored May 30, 2024
1 parent fbbffb9 commit 8b69c42
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 69 deletions.
23 changes: 10 additions & 13 deletions hipcheck/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,13 @@
#[command(about, disable_help_flag=true, disable_version_flag=true, long_about=None)]
pub struct Args {
/// print help text
#[arg(name="extra-help", short = 'h', long = "help")]
#[arg(name = "extra-help", short = 'h', long = "help")]
pub extra_help: bool,

/// print version information
#[arg(short = 'V', long, global = true)]
pub version: bool,

/// print the home directory for Hipcheck
#[arg(long = "print-home", global = true)]
pub print_home: bool,

/// print the config file path for Hipcheck
#[arg(long = "print-config", global = true)]
pub print_config: bool,

/// print the data folder path for Hipcheck
#[arg(long = "print-data", global = true)]
pub print_data: bool,

/// silences progress reporting
#[arg(short = 'q', long = "quiet", global = true)]
pub verbosity: bool,
Expand Down Expand Up @@ -71,6 +59,9 @@ pub enum Commands {
/// Analyzes a repository or pull/merge request
#[command(disable_help_subcommand = true)]
Check(CheckArgs),
/// Check if Hipcheck is ready to execute and reports status to user
#[command(disable_help_subcommand = true)]
Ready,
/// Print help information, optionally for a given subcommand
#[command(disable_help_subcommand = true)]
Help(HelpArgs),
Expand All @@ -79,6 +70,12 @@ pub enum Commands {
Schema(SchemaArgs),
}

impl Default for Commands {
fn default() -> Commands {
Commands::Help(HelpArgs { command: None })
}
}

#[derive(Debug, clap::Args)]
pub struct CheckArgs {
/// print help text
Expand Down
151 changes: 95 additions & 56 deletions hipcheck/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use crate::analysis::session::Check;
use crate::analysis::session::CheckType;
use crate::analysis::session::Session;
use crate::cli::Commands;
use crate::command_util::DependentProgram;
use crate::context::Context as _;
use crate::error::Error;
use crate::error::Result;
Expand All @@ -44,6 +45,7 @@ use clap::Parser as _;
use cli::CheckCommand;
use cli::HelpCommand;
use cli::SchemaCommand;
use dotenv::var;
use env_logger::Builder;
use env_logger::Env;
use schemars::schema_for;
Expand Down Expand Up @@ -178,10 +180,6 @@ impl CliArgs {
path.map(PathBuf::from)
};

if args.print_home {
print_home(home_dir.as_deref());
}

// PANIC: Optional but has a default value, so unwrap() should never panic.
let color_choice = {
let color: &String = &args.color.unwrap();
Expand All @@ -193,19 +191,11 @@ impl CliArgs {
config.map(PathBuf::from)
};

if args.print_config {
print_config(config_path.as_deref());
}

let data_path = {
let data: Option<&String> = args.data.as_ref();
data.map(PathBuf::from)
};

if args.print_data {
print_data(data_path.as_deref());
}

let format = Format::use_json(args.json);

// initialized later when the "check" subcommand is called
Expand All @@ -217,6 +207,13 @@ impl CliArgs {
Some(HelpCommand::Check) => print_check_help(),
Some(HelpCommand::Schema) => print_schema_help(),
},
Some(Commands::Ready) => {
print_readiness(
home_dir.as_deref(),
config_path.as_deref(),
data_path.as_deref(),
);
}
Some(Commands::Check(args)) => {
if args.extra_help {
print_check_help();
Expand Down Expand Up @@ -307,9 +304,6 @@ impl CliArgs {
const GLOBAL_HELP: &str = "\
FLAGS:
-V, --version print version information
--print-config print the config file path for Hipcheck
--print-data print the data folder path for Hipcheck
--print-home print the home directory for Hipcheck
OPTIONS (CONFIGURATION):
-c, --config <FILE> path to the configuration file [default: ./Hipcheck.toml]
Expand All @@ -336,6 +330,7 @@ USAGE:
TASKS:
check <SUBTASK> analyzes a repository or pull/merge request
ready print a report of whether or not Hipcheck is ready to run (experimental)
schema <SUBTASK> print the schema for JSON-format output for a specified subtarget
help [<SUBTASK>] print help information, optionally for a given subcommand
Expand Down Expand Up @@ -460,63 +455,107 @@ fn print_pypi_schema() -> ! {
print_missing()
}

/// Print the current home directory for Hipcheck.
///
/// Exits `Ok` if home directory is specified, `Err` otherwise.
fn print_home(path: Option<&Path>) -> ! {
let hipcheck_home = resolve_home(path);

let exit_code = match hipcheck_home {
Ok(path_buffer) => {
println!("{}", path_buffer.display());
Outcome::Ok.exit_code()
/// Prints a "readiness report" for Hipcheck, indicating if any dependent programs are missing or our of date
/// or if any necessary folders or files are missing. It then returns a final readiness status.
fn print_readiness(
home_dir: Option<&Path>,
config_path: Option<&Path>,
data_path: Option<&Path>,
) -> ! {
let mut failed = false;

// Print Hipcheck version
let raw_version = env!("CARGO_PKG_VERSION", "can't find Hipcheck package version");

let version_text = format!(
"{} {}",
env!("CARGO_PKG_NAME"),
version::get_version(raw_version).unwrap()
);
println!("{}", version_text);

// Check that git is installed and that its version is up to date
// Print the version number either way
let git_check = data::git::get_git_version();
match git_check {
Ok(git_version) => match DependentProgram::Git.check_version(&git_version) {
// No need to check Boolean value, because currentl check_version() only returns Ok(true) or Err()
Ok(_) => print!("Found installed {}", git_version),
Err(err) => {
print_error(&err);
failed = true;
}
},
Err(err) => {
print_error(&err);
failed = true;
}
}

// Check that git is installed and that its version is up to date
// Print the version number either way
let npm_check = data::npm::get_npm_version();
match npm_check {
Ok(npm_version) => match DependentProgram::Npm.check_version(&npm_version) {
// No need to check Boolean value, because currently check_version() only returns Ok(true) or Err()
Ok(_) => print!("Found installed NPM version {}", npm_version),
Err(err) => {
print_error(&err);
failed = true;
}
},
Err(err) => {
print_error(&err);
Outcome::Err.exit_code()
failed = true;
}
};
}

exit(exit_code);
}
// Check that the Hipcheck home folder is findable
let hipcheck_home = resolve_home(home_dir);
match hipcheck_home {
Ok(path_buffer) => println!("Hipcheck home directory: {}", path_buffer.display()),
Err(err) => {
failed = true;
print_error(&err);
}
}

/// Print the current config path for Hipcheck.
///
/// Exits `Ok` if config path is specified, `Err` otherwise.
fn print_config(config_path: Option<&Path>) -> ! {
// Check that the Hipcheck config TOML exists in the designated location
let hipcheck_config = resolve_config(config_path);

let exit_code = match hipcheck_config {
Ok(path_buffer) => {
println!("{}", path_buffer.display());
Outcome::Ok.exit_code()
}
match hipcheck_config {
Ok(path_buffer) => println!("Hipcheck config file: {}", path_buffer.display()),
Err(err) => {
failed = true;
print_error(&err);
Outcome::Err.exit_code()
}
};

exit(exit_code);
}
}

/// Print the current data folder path for Hipcheck.
///
/// Exits `Ok` if config path is specified, `Err` otherwise.
fn print_data(data_path: Option<&Path>) -> ! {
// Check that Hipcheck data folder is findable
let hipcheck_data = resolve_data(data_path);

let exit_code = match hipcheck_data {
Ok(path_buffer) => {
println!("{}", path_buffer.display());
Outcome::Ok.exit_code()
}
match hipcheck_data {
Ok(path_buffer) => println!("Hipcheck data directory: {}", path_buffer.display()),
Err(err) => {
failed = true;
print_error(&err);
Outcome::Err.exit_code()
}
};
}

// Check that a GitHub token has been provided as an environment variable
// This does not check if the token is valid or not
// The absence of a token does not trigger the failure state for the readiness check, because
// Hipcheck *can* run without a token, but some analyses will not.
match var("HC_GITHUB_TOKEN") {
Ok(_) => println!("HC_GITHUB_TOKEN system environment variable found."),
Err(_) => println!("Missing HC_GITHUB_TOKEN system environment variable. Some analyses will not run without this token set."),
}

if failed {
println!("One or more dependencies or configuration settings are missing. Hipcheck is not ready to run.");
} else {
println!("Hipcheck is ready to run!");
}

let exit_code = Outcome::Err.exit_code();
exit(exit_code);
}

Expand Down

0 comments on commit 8b69c42

Please sign in to comment.