use std::path::{Path, PathBuf};
use serde_json::Value;
use super::nccl_diag_classifier::{
classify_doc_link, classify_exit_code, classify_schema, NcclDocLinkOutcome, NcclExitOutcome,
NcclSchemaOutcome, F15_MIN_EXIT_CODE,
};
use crate::error::{CliError, Result};
pub(crate) fn run(
diag_file: &Path,
exit_code: Option<i32>,
require_doc_link: bool,
json: bool,
) -> Result<()> {
if !diag_file.exists() {
return Err(CliError::FileNotFound(PathBuf::from(diag_file)));
}
let body_text = std::fs::read_to_string(diag_file)?;
let body: Value = serde_json::from_str(&body_text).map_err(|e| {
CliError::InvalidFormat(format!(
"apr nccl-diag-lint: failed to parse JSON from {}: {e}",
diag_file.display()
))
})?;
let schema = classify_schema(&body);
let doc_link = if require_doc_link && matches!(schema, NcclSchemaOutcome::Ok) {
Some(classify_doc_link(&body))
} else {
None
};
let exit = exit_code.map(|c| classify_exit_code(c, F15_MIN_EXIT_CODE));
print_report(diag_file, &schema, doc_link.as_ref(), exit.as_ref(), json);
if !matches!(schema, NcclSchemaOutcome::Ok) {
return Err(CliError::ValidationFailed(format!(
"nccl-diag-lint schema gate rejected body: {schema:?}"
)));
}
if let Some(o) = &doc_link {
if !matches!(o, NcclDocLinkOutcome::Ok) {
return Err(CliError::ValidationFailed(format!(
"nccl-diag-lint doc-link gate rejected body: {o:?}"
)));
}
}
if let Some(o) = &exit {
if !matches!(o, NcclExitOutcome::Ok { .. }) {
return Err(CliError::ValidationFailed(format!(
"nccl-diag-lint exit-code gate rejected: {o:?}"
)));
}
}
Ok(())
}
fn print_report(
path: &Path,
schema: &NcclSchemaOutcome,
doc_link: Option<&NcclDocLinkOutcome>,
exit: Option<&NcclExitOutcome>,
json: bool,
) {
if json {
let obj = serde_json::json!({
"file": path.display().to_string(),
"schema": format!("{schema:?}"),
"doc_link": doc_link.map(|o| format!("{o:?}")),
"exit_code": exit.map(|o| format!("{o:?}")),
});
println!("{}", serde_json::to_string_pretty(&obj).unwrap_or_default());
return;
}
println!("nccl-diag-lint report for {}", path.display());
println!(" schema : {schema:?}");
if let Some(o) = doc_link {
println!(" doc_link : {o:?}");
}
if let Some(o) = exit {
println!(" exit_code : {o:?}");
}
}