Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --output-format=json-full #351

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,15 @@ pub enum OutputFormat {
Human,
/// Print output in a machine-readable form with minimal extra context.
Json,
/// Print output in a machine-readable form with as much additional context
/// as possible to enable another tool to operate on that information.
///
/// Extra information will be stored in a top-level 'context' field and
/// include:
///
/// * criteria: The custom criteria this project defines (and their descriptions)
/// * store: The location of the store (supply-chain dir)
JsonFull,
}

#[derive(Clone, Debug)]
Expand Down
13 changes: 13 additions & 0 deletions src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -657,10 +657,21 @@ pub struct CommandHistory {
/// up as miette-style json errors.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JsonReport {
/// Additional optional context for automation. Only enabled with `--output-format=json-full`
pub context: Option<JsonReportContext>,
#[serde(flatten)]
pub conclusion: JsonReportConclusion,
}

/// Additional context for automation
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JsonReportContext {
/// Where the store (supply-chain) is located
pub store_path: String,
/// The currently defined criteria (currently excludes builtins criteria like `safe-to-deploy`).
pub criteria: SortedMap<CriteriaName, CriteriaEntry>,
}

/// The conclusion of running `check` or `suggest`
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "conclusion")]
Expand Down Expand Up @@ -740,6 +751,8 @@ pub struct JsonSuggestItem {
/// The diff (or full version) we recommend auditing
// FIXME(SCHEMA): we probably shouldn't expose this internal type
pub suggested_diff: DiffRecommendation,
/// Whether the suggestion is confident or a guess (de-emphasize guesses)
pub confident: bool,
}

/// A string of the form "package:version"
Expand Down
25 changes: 19 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ use crate::format::{
};
use crate::git_tool::Pager;
use crate::out::{indeterminate_spinner, Out, StderrLogWriter, MULTIPROGRESS};
use crate::resolver::{CriteriaMapper, CriteriaNamespace, DepGraph};
use crate::resolver::{CriteriaMapper, CriteriaNamespace, DepGraph, ReportContext};
use crate::storage::{Cache, Store};

mod cli;
Expand Down Expand Up @@ -1262,7 +1262,15 @@ fn cmd_suggest(
OutputFormat::Human => report
.print_suggest_human(out, cfg, suggest.as_ref())
.into_diagnostic()?,
OutputFormat::Json => report.print_json(out, suggest.as_ref())?,
OutputFormat::Json => report.print_json(out, suggest.as_ref(), None)?,
OutputFormat::JsonFull => report.print_json(
out,
suggest.as_ref(),
Some(ReportContext {
store: &suggest_store,
cfg,
}),
)?,
}

Ok(())
Expand Down Expand Up @@ -1516,8 +1524,8 @@ fn cmd_check(
// DO THE THING!!!!
let report = resolver::resolve(&cfg.metadata, cfg.cli.filter_graph.as_ref(), &store);

// Bare `cargo vet` shouldn't suggest in CI
let suggest = if !cfg.cli.locked {
// Bare `cargo vet` shouldn't suggest in CI (unless you want --output-format=json-full)
let suggest = if !cfg.cli.locked || cfg.cli.output_format == OutputFormat::JsonFull {
report.compute_suggest(cfg, network.as_ref(), true)?
} else {
None
Expand All @@ -1527,7 +1535,12 @@ fn cmd_check(
OutputFormat::Human => report
.print_human(out, cfg, suggest.as_ref())
.into_diagnostic()?,
OutputFormat::Json => report.print_json(out, suggest.as_ref())?,
OutputFormat::Json => report.print_json(out, suggest.as_ref(), None)?,
OutputFormat::JsonFull => report.print_json(
out,
suggest.as_ref(),
Some(ReportContext { store: &store, cfg }),
)?,
}

// Only save imports if we succeeded, to avoid any modifications on error.
Expand Down Expand Up @@ -1747,7 +1760,7 @@ fn cmd_dump_graph(
let graph = resolver::DepGraph::new(&cfg.metadata, cfg.cli.filter_graph.as_ref(), None);
match cfg.cli.output_format {
OutputFormat::Human => graph.print_mermaid(out, sub_args).into_diagnostic()?,
OutputFormat::Json => {
OutputFormat::Json | OutputFormat::JsonFull => {
serde_json::to_writer_pretty(&**out, &graph.nodes).into_diagnostic()?
}
}
Expand Down
20 changes: 16 additions & 4 deletions src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@ use tracing::{error, trace, trace_span};
use crate::errors::{RegenerateExemptionsError, SuggestError};
use crate::format::{
self, AuditKind, AuditsFile, CriteriaName, CriteriaStr, Delta, DiffStat, ExemptedDependency,
ImportName, JsonPackage, JsonReport, JsonReportConclusion, JsonReportFailForVet,
JsonReportFailForViolationConflict, JsonReportSuccess, JsonSuggest, JsonSuggestItem,
JsonVetFailure, PackageName, PackageStr, PolicyEntry, RemoteImport, VetVersion, SAFE_TO_DEPLOY,
SAFE_TO_RUN,
ImportName, JsonPackage, JsonReport, JsonReportConclusion, JsonReportContext,
JsonReportFailForVet, JsonReportFailForViolationConflict, JsonReportSuccess, JsonSuggest,
JsonSuggestItem, JsonVetFailure, PackageName, PackageStr, PolicyEntry, RemoteImport,
VetVersion, SAFE_TO_DEPLOY, SAFE_TO_RUN,
};
use crate::format::{FastMap, FastSet, SortedMap, SortedSet};
use crate::network::Network;
Expand Down Expand Up @@ -2499,6 +2499,12 @@ fn visit_failures<T>(
Ok(())
}

/// Additional optional context for printing a json Report for automation.
pub struct ReportContext<'a> {
pub cfg: &'a Config,
pub store: &'a Store,
}

impl<'a> ResolveReport<'a> {
pub fn has_errors(&self) -> bool {
// Just check the conclusion
Expand Down Expand Up @@ -2816,8 +2822,13 @@ impl<'a> ResolveReport<'a> {
&self,
out: &Arc<dyn Out>,
suggest: Option<&Suggest>,
context: Option<ReportContext>,
) -> Result<(), miette::Report> {
let result = JsonReport {
context: context.map(|c| JsonReportContext {
store_path: c.cfg.metacfg.store_path().display().to_string(),
criteria: c.store.audits.criteria.clone(),
}),
conclusion: match &self.conclusion {
Conclusion::Success(success) => {
let json_package = |pkgidx: &PackageIdx| {
Expand Down Expand Up @@ -2869,6 +2880,7 @@ impl<'a> ResolveReport<'a> {
.map(|s| s.to_owned())
.collect(),
suggested_diff: item.suggested_diff.clone(),
confident: item.suggested_criteria.is_fully_confident(),
}
};
JsonReportConclusion::FailForVet(JsonReportFailForVet {
Expand Down
2 changes: 1 addition & 1 deletion src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1013,7 +1013,7 @@ fn get_reports(metadata: &Metadata, report: ResolveReport) -> (String, String) {
.unwrap();
let json_output = BasicTestOutput::new();
report
.print_json(&json_output.clone().as_dyn(), suggest.as_ref())
.print_json(&json_output.clone().as_dyn(), suggest.as_ref(), None)
.unwrap();
(human_output.to_string(), json_output.to_string())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ source: src/tests/vet.rs
expression: json
---
{
"context": null,
"conclusion": "success",
"vetted_fully": [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ source: src/tests/vet.rs
expression: json
---
{
"context": null,
"conclusion": "success",
"vetted_fully": [],
"vetted_partially": [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ source: src/tests/vet.rs
expression: json
---
{
"context": null,
"conclusion": "success",
"vetted_fully": [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ source: src/tests/vet.rs
expression: json
---
{
"context": null,
"conclusion": "fail (vetting)",
"failures": [
{
Expand Down Expand Up @@ -50,7 +51,8 @@ expression: json
"deletions": 0,
"files_changed": 1
}
}
},
"confident": true
},
{
"name": "third-core",
Expand All @@ -66,7 +68,8 @@ expression: json
"deletions": 0,
"files_changed": 1
}
}
},
"confident": true
},
{
"name": "thirdA",
Expand All @@ -82,7 +85,8 @@ expression: json
"deletions": 0,
"files_changed": 1
}
}
},
"confident": true
},
{
"name": "thirdAB",
Expand All @@ -98,7 +102,8 @@ expression: json
"deletions": 0,
"files_changed": 1
}
}
},
"confident": true
}
],
"suggest_by_criteria": {
Expand All @@ -117,7 +122,8 @@ expression: json
"deletions": 0,
"files_changed": 1
}
}
},
"confident": true
},
{
"name": "third-core",
Expand All @@ -133,7 +139,8 @@ expression: json
"deletions": 0,
"files_changed": 1
}
}
},
"confident": true
},
{
"name": "thirdA",
Expand All @@ -149,7 +156,8 @@ expression: json
"deletions": 0,
"files_changed": 1
}
}
},
"confident": true
},
{
"name": "thirdAB",
Expand All @@ -165,7 +173,8 @@ expression: json
"deletions": 0,
"files_changed": 1
}
}
},
"confident": true
}
]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ source: src/tests/vet.rs
expression: json
---
{
"context": null,
"conclusion": "success",
"vetted_fully": [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ source: src/tests/vet.rs
expression: json
---
{
"context": null,
"conclusion": "success",
"vetted_fully": [],
"vetted_partially": [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ source: src/tests/vet.rs
expression: json
---
{
"context": null,
"conclusion": "success",
"vetted_fully": [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ source: src/tests/vet.rs
expression: json
---
{
"context": null,
"conclusion": "fail (vetting)",
"failures": [
{
Expand Down Expand Up @@ -36,7 +37,8 @@ expression: json
"deletions": 0,
"files_changed": 1
}
}
},
"confident": true
},
{
"name": "normal",
Expand All @@ -52,7 +54,8 @@ expression: json
"deletions": 0,
"files_changed": 1
}
}
},
"confident": true
}
],
"suggest_by_criteria": {
Expand All @@ -71,7 +74,8 @@ expression: json
"deletions": 0,
"files_changed": 1
}
}
},
"confident": true
}
],
"safe-to-run": [
Expand All @@ -89,7 +93,8 @@ expression: json
"deletions": 0,
"files_changed": 1
}
}
},
"confident": true
}
]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ source: src/tests/vet.rs
expression: json
---
{
"context": null,
"conclusion": "success",
"vetted_fully": [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ source: src/tests/vet.rs
expression: json
---
{
"context": null,
"conclusion": "success",
"vetted_fully": [
{
Expand Down
Loading