Skip to content
Merged
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
1 change: 1 addition & 0 deletions tool/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,7 @@ def generate_static_report(analysis_results, project_info, is_old_version):
project_info["enabled_checks"],
project_info["gradual_report"],
summary_filename=summary_file,
config=project_info["config"],
)


Expand Down
98 changes: 91 additions & 7 deletions tool/report_static.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ def aliased_package(aliased_package_df, md_file, amount, package_manager):


def write_summary(
df, project_name, release_version, package_manager, filename, enabled_checks, gradual_report, mode="w"
df, project_name, release_version, package_manager, filename, enabled_checks, gradual_report, mode="w", config={}
):
"""
Write a summary of the static analysis results to a markdown file.
Expand Down Expand Up @@ -485,18 +485,80 @@ def write_summary(
preamble += "\n"
md_file.write(preamble)

md_file.write(
"""
## 📚 Table of Contents

- [Enabled Checks](#enabled-checks)
- [Ignore Configuration Summary](#ignore-configuration-summary)
- [Summary of Findings](#summary-of-findings)
- [Fine Grained Information](#fine-grained-information)
- [Call to Action](#call-to-action)
- [Notes](#notes)
- [Glossary](#glossary)
"""
)

# Section showing which checks were performed
any_specific = any(enabled_checks.values())
if any_specific and not gradual_report:
md_file.write("## Enabled Checks\n")
md_file.write("The following checks were specifically requested:\n\n")
md_file.write("## Enabled Checks\n\n")
md_file.write("The following checks were requested project-wide:\n\n")
md_file.write("| Check | Status |\n")
md_file.write("|-------|--------|\n")
for check, enabled in enabled_checks.items():
if enabled:
md_file.write(f"- {check.replace('_', ' ').title()}: `{check}`\n")
status = "✅" if enabled else "❌"
md_file.write(f"| {check.replace('_', ' ').title()}: `{check}` | {status} |\n")
md_file.write("\n---\n\n")
else:
md_file.write("All available checks were performed.\n\n---\n\n")

if config:
md_file.write("## Ignore Configuration Summary\n\n")

if "ignore" in config and config["ignore"]:
md_file.write(
"<details>\n"
"<summary>Ignored Checks Per Dependency 🔧</summary>\n\n"
"These dependencies had specific checks excluded based on the configuration file. \n"
"**Note**: If `all` is listed, every check is ignored for that dependency.\n\n"
)
md_file.write("| Dependency Pattern | Ignored Checks |\n")
md_file.write("|--------------------|----------------|\n")

for dep_pattern in sorted(config["ignore"]):
ignored = config["ignore"][dep_pattern]
if ignored == "all":
checks_str = "`all`"
else:
checks_str = ", ".join(f"`{chk}`" for chk in ignored)
md_file.write(f"| `{dep_pattern}` | {checks_str} |\n")

md_file.write("\n</details>\n\n")

if "ignore-if-parent" in config and config["ignore-if-parent"]:
md_file.write(
"<details>\n"
"<summary>Ignored Checks If Dependency is a Parent 📦➡️👶</summary>\n\n"
"Checks will be ignored **if the listed dependency is a parent of another package**. \n"
)
md_file.write("| Parent Dependency Pattern | Ignored Checks |\n")
md_file.write("|---------------------------|----------------|\n")

for parent_pattern in sorted(config["ignore-if-parent"]):
ignored = config["ignore-if-parent"][parent_pattern]
if ignored == "all":
checks_str = "`all`"
else:
checks_str = ", ".join(f"`{chk}`" for chk in ignored)
md_file.write(f"| `{parent_pattern}` | {checks_str} |\n")

md_file.write("\n</details>\n\n")

md_file.write("---\n\n")

md_file.write("## Summary of Findings\n\n")

md_file.write(
"""
<details>
Expand All @@ -522,7 +584,7 @@ def write_summary(

md_file.write("\n### Fine grained information\n")
md_file.write(
"\n:dolphin: For further information about software supply chain smells in your project, take a look at the following tables.\n"
"\n🐬 For further information about software supply chain smells in your project, take a look at the following tables.\n"
)
reports = {
"no_source_code": {
Expand Down Expand Up @@ -662,6 +724,19 @@ def write_summary(
md_file.write(markdown_text)
md_file.write("\n</details>\n\n\n")

md_file.write("\n## Glossary\n\n")
md_file.write(
"""
- `source_code`: Whether a repo URL is present and valid
- `source_code_sha`: Whether a commit SHA is available and valid
- `forks`: Whether the repo is a fork
- `deprecated`: Whether the package is marked deprecated
- `provenance`: Whether build provenance/attestation is provided
- `code_signature`: Whether a code signature is present and valid
- `aliased_packages`: Whether a package is aliased under a different name
"""
)

md_file.write("---\n")
md_file.write("\nReport created by [dirty-waters](https://github.com/chains-project/dirty-waters/).\n")
md_file.write(f"\nReport created on {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
Expand All @@ -676,7 +751,15 @@ def write_summary(


def get_s_summary(
data, deps_list, project_name, release_version, package_manager, enabled_checks, gradual_report, summary_filename
data,
deps_list,
project_name,
release_version,
package_manager,
enabled_checks,
gradual_report,
summary_filename,
config={},
):
"""
Get a summary of the static analysis results.
Expand All @@ -692,4 +775,5 @@ def get_s_summary(
enabled_checks=enabled_checks,
gradual_report=gradual_report,
mode="w",
config=config,
)