Skip to content

Commit

Permalink
Add error handling for jinja report rendering, remove empty post-report.
Browse files Browse the repository at this point in the history
Signed-off-by: Caroline Russell <[email protected]>
  • Loading branch information
cerrussell committed Nov 2, 2024
1 parent d87d575 commit 6957d91
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 45 deletions.
48 changes: 23 additions & 25 deletions custom_json_diff/lib/bom_diff_template.j2
Original file line number Diff line number Diff line change
Expand Up @@ -589,17 +589,17 @@
<summary>{{ item['short_ref'] }}</summary>
<ul>
<li>ref: {{ item['ref'] }}</li>
{% if item['dependsOn']|length > 0 %}
<li>dependencies:</li>
<ul>
{% for dep in item['dependsOn'] %}
<li>{{ dep }}</li>
{% endfor %}
</ul>
{% endif %}
{% if item['dependsOn']|length == 0 %}
<li>dependencies: N/A</li>
{% for key, value in item|items %}
{% if key == "dependsOn" %}
<li>dependencies:
<ul>
{% for dep in item['dependsOn'] %}
<li>{{ dep }}</li>
{% endfor %}
</ul>
</li>
{% endif %}
{% endfor %}
</ul>
</details>
{% endfor %}</td>
Expand All @@ -608,19 +608,18 @@
<summary>{{ item['short_ref'] }}</summary>
<ul>
<li>ref: {{ item['ref'] }}</li>
{% if item['dependsOn']|length > 0 %}
<li>dependencies:</li>
<ul>
{% for dep in item['dependsOn'] %}
<li>{{ dep }}</li>
{% endfor %}
</ul>
{% endif %}
{% if item['dependsOn']|length == 0 %}
<li>dependencies: N/A</li>
{% for key, value in item|items %}
{% if key == "dependsOn" %}
<li>dependencies:
<ul>
{% for dep in item['dependsOn'] %}
<li>{{ dep }}</li>
{% endfor %}
</ul>
</li>
{% endif %}
{% endfor %}
</ul>

</details>
{% endfor %}</td>
</tr>
Expand Down Expand Up @@ -1160,7 +1159,8 @@
<summary>{{ item['short_ref'] }}</summary>
<ul>
<li>ref: {{ item['ref'] }}</li>
{% if item['dependsOn']|length >0 %}
{% for key, value in item|items %}
{% if key == "dependsOn" %}
<li>dependencies:
<ul>
{% for dep in item['dependsOn'] %}
Expand All @@ -1169,9 +1169,7 @@
</ul>
</li>
{% endif %}
{% if item['dependsOn']|length == 0 %}
<li>dependencies: N/A</li>
{% endif %}
{% endfor %}
</ul>
</details>
{% endfor %}</td>
Expand Down
13 changes: 5 additions & 8 deletions custom_json_diff/lib/custom_diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ def add_short_ref_for_report(diffs: Dict, options: "Options") -> Dict:
diffs["diff_summary"][options.file_2].get("dependencies", []), purl_regex)
diffs["common_summary"]["dependencies"] = parse_purls(
diffs["common_summary"].get("dependencies", []), purl_regex)
diffs["diff_summary"][options.file_1] = filter_empty(options.include_empty, diffs["diff_summary"][options.file_1])
diffs["diff_summary"][options.file_2] = filter_empty(options.include_empty, diffs["diff_summary"][options.file_2])
diffs["common_summary"] = filter_empty(options.include_empty, diffs["common_summary"])
return diffs


Expand Down Expand Up @@ -108,7 +105,6 @@ def generate_bom_diff(bom: BomDicts, commons: BomDicts, common_refs: Dict) -> Di
case _:
diff_summary["components"]["other_components"].append(i.to_dict()) #type: ignore
diff_summary["misc_data"] = (bom.misc_data - commons.misc_data).to_dict()
diff_summary["components"] = filter_empty(bom.options.include_empty, diff_summary["components"]) #type: ignore
return diff_summary


Expand Down Expand Up @@ -223,7 +219,7 @@ def parse_purls(deps: List[Dict], regex: re.Pattern) -> List[Dict]:
def perform_bom_diff(bom_1: BomDicts, bom_2: BomDicts) -> Tuple[int, Dict]:
b1, b2 = order_documents(bom_1, bom_2)
common_bom = b1.intersection(b2, "common_summary")
output = filter_empty(common_bom.options.include_empty, common_bom.to_summary())
output = common_bom.to_summary()
status, diffs = summarize_bom_diffs(b1, b2, common_bom)
output |= {"diff_summary": diffs}
return status, output
Expand Down Expand Up @@ -253,6 +249,8 @@ def report_results(status: int, diffs: Dict, options: Options, j1: BomDicts, j2:
elif options.preconfig_type == "csaf":
export_html_report(report_file, diffs, options, status)
if options.output:
if not options.include_empty:
diffs = filter_empty(options.include_empty, diffs)
json_dump(options.output, diffs,
error_msg=f"Failed to export diff results to {options.output}.",
success_msg=f"Diff results written to {options.output}.")
Expand Down Expand Up @@ -293,8 +291,7 @@ def summarize_bom_diffs(bom_1: BomDicts, bom_2: BomDicts, commons: BomDicts) ->
summary_1 = generate_bom_diff(bom_1, commons, common_refs)
summary_2 = generate_bom_diff(bom_2, commons_2, common_refs)
status = max(get_bom_status(summary_1), get_bom_status(summary_2))
return status, {bom_1.filename: filter_empty(bom_1.options.include_empty, summary_1),
bom_2.filename: filter_empty(bom_1.options.include_empty, summary_2)}
return status, {bom_1.filename: summary_1, bom_2.filename: summary_2}


def summarize_csaf_diffs(csaf_1: CsafDicts, csaf_2: CsafDicts, commons: CsafDicts) -> Tuple[int, Dict]:
Expand All @@ -304,4 +301,4 @@ def summarize_csaf_diffs(csaf_1: CsafDicts, csaf_2: CsafDicts, commons: CsafDict
diff_summary = generate_csaf_diff(csaf_1, commons, common_refs)
diff_summary |= generate_csaf_diff(csaf_2, commons_2, common_refs)
status = max(get_csaf_status(diff_summary[csaf_1.filename]), get_csaf_status(diff_summary[csaf_2.filename]))
return status, filter_empty(csaf_1.options.include_empty, diff_summary)
return status, diff_summary
12 changes: 8 additions & 4 deletions custom_json_diff/lib/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,14 @@ def export_html_report(outfile: str, diffs: Dict, options: "Options", status: in
template = file_read(template_file)
jinja_env = Environment(autoescape=True)
jinja_tmpl = jinja_env.from_string(str(template))
if options.preconfig_type == "bom":
report_result = render_bom_template(diffs, jinja_tmpl, options, stats_summary, status)
else:
report_result = render_csaf_template(diffs, jinja_tmpl, options, status)
try:
if options.preconfig_type == "bom":
report_result = render_bom_template(diffs, jinja_tmpl, options, stats_summary, status)
else:
report_result = render_csaf_template(diffs, jinja_tmpl, options, status)
except TypeError:
logger.warning(f"Could not render html report for {options.file_1} and {options.file_2} BOM diff. Likely an expected key is missing.")
return
file_write(outfile, report_result, error_msg=f"Unable to generate HTML report at {outfile}.",
success_msg=f"HTML report generated: {outfile}")

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "custom-json-diff"
version = "2.1.1"
version = "2.1.2"
description = "CycloneDx BOM and Oasis CSAF diffing and comparison tool."
authors = [
{ name = "Caroline Russell", email = "[email protected]" },
Expand Down
5 changes: 4 additions & 1 deletion test/test_bom_diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from custom_json_diff.lib.custom_diff_classes import (
BomComponent, BomDependency, BomDicts, FlatDicts, Options, BomVdr, BomVdrAffects
)
from custom_json_diff.lib.utils import filter_empty, json_dump


@pytest.fixture
Expand Down Expand Up @@ -347,7 +348,7 @@ def test_bom_diff(results, options_1):
'other_components': 0, 'services': 8, 'vulnerabilities': 0}
assert add_short_ref_for_report(result_summary, j1.options).get("diff_summary", {}).get(
j2.filename, {}).get("dependencies") == [
{'ref': 'pkg:maven/javax.activation/[email protected]?type=jar',
{'dependsOn': [], 'ref': 'pkg:maven/javax.activation/[email protected]?type=jar',
'short_ref': 'javax.activation/[email protected]'}]


Expand All @@ -368,6 +369,8 @@ def test_bom_diff_component_options(results, bom_dicts_1, bom_dicts_2, bom_dicts
_, result_summary = perform_bom_diff(bom_dicts_7, bom_dicts_8)
assert result_summary == results["result_5"]

json_dump("test/test_data.json", results, compact=True)


def test_bom_diff_vdr_options(options_1):
# test don't allow --allow-new-data or --allow-new-versions
Expand Down
7 changes: 6 additions & 1 deletion test/test_csaf_diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from custom_json_diff.lib.custom_diff import compare_dicts, perform_csaf_diff
from custom_json_diff.lib.custom_diff_classes import (CsafVulnerability, Options, BomVdr, BomVdrAffects
)
from custom_json_diff.lib.utils import filter_empty, json_dump


@pytest.fixture
Expand All @@ -32,15 +33,19 @@ def results():
def test_csaf_diff(results, options_1, options_2):
result, j1, j2 = compare_dicts(options_1)
_, result_summary = perform_csaf_diff(j1, j2)
results["result_13"] = result_summary
assert result_summary == results["result_13"]

result, j2, j1 = compare_dicts(options_1)
_, result_summary = perform_csaf_diff(j2, j1)
results["result_14"] = result_summary
assert result_summary == results["result_14"]

result, j1, j2 = compare_dicts(options_2)
_, result_summary = perform_csaf_diff(j2, j1)
assert result_summary["diff_summary"] == {"test/csaf_3.json": {}, "test/csaf_4.json": {}}
assert filter_empty(False, result_summary["diff_summary"]) == {"test/csaf_3.json": {}, "test/csaf_4.json": {}}

json_dump("test/results.json", results, compact=True)


def test_csaf_diff_vuln_options(options_1):
Expand Down
2 changes: 1 addition & 1 deletion test/test_data.json

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions test/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,10 @@ def test_json_dump():

def test_json_load():
assert list(json_load("test/test_data.json").keys()) == ['result_1', 'result_10', 'result_11',
'result_12', 'result_2', 'result_3',
'result_4', 'result_5', 'result_6',
'result_7', 'result_8', 'result_9',
'result_13', 'result_14']
'result_12', 'result_13', 'result_14',
'result_2', 'result_3', 'result_4',
'result_5', 'result_6', 'result_7',
'result_8', 'result_9']
assert json_load("notafile.json") == {}


Expand Down

0 comments on commit 6957d91

Please sign in to comment.