diff --git a/CHANGELOG.md b/CHANGELOG.md index c5a25eab16f..f92d1a25e60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), Note: Can be used with `oxsecurity/megalinter@beta` in your GitHub Action mega-linter.yml file, or with `oxsecurity/megalinter:beta` docker image +- New reporter **MARKDOWN_SUMMARY_REPORTER**, allows saving MegaLinter results summary as a markdown file. This file can be further utilised to add comments on the pull request (PR) from Jenkins and other continuous integration (CI) tools. + - Core - mega-linter-runner: Remove container by default, except of `no-remove-container` option is sent - Upgrade base image from python:3.11.6-alpine3.18 to python:3.11.7-alpine3.18, by @echoix in [#3212](https://github.com/oxsecurity/megalinter/pull/3212) diff --git a/README.md b/README.md index 53d57e9932c..a151b7c75ee 100644 --- a/README.md +++ b/README.md @@ -1295,6 +1295,7 @@ MegaLinter can generate various reports that you can activate / deactivate and c | [Email](https://github.com/oxsecurity/megalinter/tree/main/docs/reporters/EmailReporter.md) | Receive **all reports on your e-mail**, if you can not use artifacts | Active | | [TAP files](https://github.com/oxsecurity/megalinter/tree/main/docs/reporters/TapReporter.md) | One file by linter following [**Test Anything Protocol**](https://testanything.org/) format | Active | | [Console](https://github.com/oxsecurity/megalinter/tree/main/docs/reporters/ConsoleReporter.md) | **Execution logs** visible in **console** with **summary table** and **links to other reports** at the end | Active | +| [Markdown Summary](docs/reporters/MarkdownSummaryReporter.md) | Generates a Markdown summary report file | Inactive | @@ -1724,6 +1725,10 @@ MegaLinter can be run locally thanks to [mega-linter-runner](https://megalinter. ![Screenshot](https://github.com/oxsecurity/megalinter/blob/main/docs/assets/images/AzureCommentReporter.jpg?raw=true) +- [Markdown Summary](docs/reporters/MarkdownSummaryReporter.md) + +![Screenshot](docs/assets/images/MarkdownSummaryReporter_2.png) + - [Updated sources](https://github.com/oxsecurity/megalinter/tree/main/docs/reporters/UpdatedSourcesReporter.md) - [Email](https://github.com/oxsecurity/megalinter/tree/main/docs/reporters/EmailReporter.md) - [File.io](https://github.com/oxsecurity/megalinter/tree/main/docs/reporters/FileIoReporter.md) diff --git a/docs/assets/images/MarkdownSummaryReporter_1.png b/docs/assets/images/MarkdownSummaryReporter_1.png new file mode 100644 index 00000000000..d411a68a9d4 Binary files /dev/null and b/docs/assets/images/MarkdownSummaryReporter_1.png differ diff --git a/docs/assets/images/MarkdownSummaryReporter_2.png b/docs/assets/images/MarkdownSummaryReporter_2.png new file mode 100644 index 00000000000..55c66a0dbe7 Binary files /dev/null and b/docs/assets/images/MarkdownSummaryReporter_2.png differ diff --git a/docs/reporters/MarkdownSummaryReporter.md b/docs/reporters/MarkdownSummaryReporter.md new file mode 100644 index 00000000000..5e4632747a7 --- /dev/null +++ b/docs/reporters/MarkdownSummaryReporter.md @@ -0,0 +1,25 @@ +--- +title: Markdown Summary Reporter for MegaLinter +description: Generates a summary of SAST results in Markdown within a file named 'megalinter-report.md', located in the report folder. +--- + +# Markdown Summary Reporter + +Generates a summary of SAST results in Markdown within a file named **megalinter-report.md**, located in the report folder. + +This reporter **is deactivated by default**. + +![Screenshot](../assets/images/MarkdownSummaryReporter_1.png) + +![Screenshot](../assets/images/MarkdownSummaryReporter_2.png) + +## Usage + +Activate the reporter (`MARKDOWN_SUMMARY_REPORTER: true`) to generate markdown summary report file. + +## Configuration + +| Variable | Description | Default value | +|-----------------------------------------|-------------------------------------------------------------------------------------------------------------------|----------------------------| +| MARKDOWN_SUMMARY_REPORTER | Activates/deactivates reporter | `false` | +| MARKDOWN_SUMMARY_REPORTER_FILE_NAME | File name for MARKDOWN_SUMMARY report output file | `megalinter-report.md` | diff --git a/megalinter/constants.py b/megalinter/constants.py index 2b85c3f57b9..6aceee40c84 100644 --- a/megalinter/constants.py +++ b/megalinter/constants.py @@ -19,6 +19,7 @@ DEFAULT_DOCKER_WORKSPACE_DIR = "/tmp/lint" DEFAULT_REPORT_FOLDER_NAME = "megalinter-reports" DEFAULT_SARIF_REPORT_FILE_NAME = "megalinter-report.sarif" +DEFAULT_MARKDOWN_SUMMARY_REPORT_FILE_NAME = "megalinter-report.md" DEFAULT_SARIF_SCHEMA_URI = "https://json.schemastore.org/sarif-2.1.0.json" DEFAULT_SARIF_VERSION = "2.1.0" DEFAULT_RELEASE = "v7" diff --git a/megalinter/descriptors/schemas/megalinter-configuration.jsonschema.json b/megalinter/descriptors/schemas/megalinter-configuration.jsonschema.json index da2c30540f2..b245b07cf3e 100644 --- a/megalinter/descriptors/schemas/megalinter-configuration.jsonschema.json +++ b/megalinter/descriptors/schemas/megalinter-configuration.jsonschema.json @@ -18380,6 +18380,20 @@ "title": "SQL_TSQLLINT: Unsecured env variables", "type": "array" }, + "MARKDOWN_SUMMARY_REPORTER": { + "$id": "#/properties/MARKDOWN_SUMMARY_REPORTER", + "default": false, + "description": "Generate SUMMARY reports that can be used to display issues directly in PR comment", + "title": "Activate SUMMARY reporter", + "type": "boolean" + }, + "MARKDOWN_SUMMARY_REPORTER_FILE_NAME": { + "$id": "#/properties/MARKDOWN_SUMMARY_REPORTER_FILE_NAME", + "default": "megalinter-summary.log", + "description": "Override SUMMARY output file name", + "title": "SUMMARY report file name", + "type": "string" + }, "SWIFT_FILTER_REGEX_EXCLUDE": { "$id": "#/properties/SWIFT_FILTER_REGEX_EXCLUDE", "title": "Excluding regex filter for SWIFT descriptor", diff --git a/megalinter/reporters/MarkdownSummaryReporter.py b/megalinter/reporters/MarkdownSummaryReporter.py new file mode 100644 index 00000000000..70e203cb50f --- /dev/null +++ b/megalinter/reporters/MarkdownSummaryReporter.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +""" +Produce MARKDOWN_SUMMARY report +""" +import logging +import os + +from megalinter import Reporter, config, utils +from megalinter.utils_reporter import build_markdown_summary +from megalinter.constants import DEFAULT_MARKDOWN_SUMMARY_REPORT_FILE_NAME + + + +class MarkdownSummaryReporter(Reporter): + name = "MARKDOWN_SUMMARY" + scope = "mega-linter" + + def manage_activation(self): + if not utils.can_write_report_files(self.master): + self.is_active = False + elif ( + config.get(self.master.request_id, "MARKDOWN_SUMMARY_REPORTER", "false") + == "true" + ): + self.is_active = True + else: + self.is_active = False + + + def produce_report(self): + summary = build_markdown_summary(self) + + # Write output file + summary_file_name = f"{self.report_folder}{os.path.sep}" + config.get( + self.master.request_id, + "MARKDOWN_SUMMARY_REPORTER_FILE_NAME", + DEFAULT_MARKDOWN_SUMMARY_REPORT_FILE_NAME, + ) + if os.path.isfile(summary_file_name): + # Remove from previous run + os.remove(summary_file_name) + with open(summary_file_name, "w", encoding="utf-8") as sarif_file: + sarif_file.write(summary) + logging.info( + f"[MARKDOWN_SUMMARY Reporter] Generated {self.name} report: {summary_file_name}" + ) + \ No newline at end of file diff --git a/megalinter/utils_reporter.py b/megalinter/utils_reporter.py index a0caed7e768..3c47392c98b 100644 --- a/megalinter/utils_reporter.py +++ b/megalinter/utils_reporter.py @@ -17,7 +17,7 @@ from redis import Redis -def build_markdown_summary(reporter_self, action_run_url): +def build_markdown_summary(reporter_self, action_run_url=""): table_header = ["Descriptor", "Linter", "Files", "Fixed", "Errors"] if reporter_self.master.show_elapsed_time is True: table_header += ["Elapsed time"]