Skip to content

Commit

Permalink
feat: HTML file report generation for single scan (#576)
Browse files Browse the repository at this point in the history
* feat: HTML file report generation for single scan

Signed-off-by: Oleg Kopysov <[email protected]>

* test: Add more unit tests and improve code testability

Signed-off-by: Oleg Kopysov <[email protected]>

* fix: Apply changes after code review

Signed-off-by: Oleg Kopysov <[email protected]>

---------

Signed-off-by: Oleg Kopysov <[email protected]>
  • Loading branch information
o-kopysov authored Aug 23, 2024
1 parent 8fce5a3 commit 1b69e16
Show file tree
Hide file tree
Showing 8 changed files with 1,100 additions and 162 deletions.
4 changes: 4 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@
<artifactId>jakarta.servlet-api</artifactId>
<version>6.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
534 changes: 534 additions & 0 deletions src/main/java/com/lpvs/entity/report/LPVSReportBuilder.java

Large diffs are not rendered by default.

22 changes: 18 additions & 4 deletions src/main/java/com/lpvs/service/scan/LPVSDetectService.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.Date;
import java.util.List;

import com.lpvs.entity.report.LPVSReportBuilder;
import com.lpvs.service.LPVSGitHubConnectionService;
import com.lpvs.service.LPVSGitHubService;
import com.lpvs.service.LPVSLicenseService;
Expand All @@ -32,6 +33,8 @@

import lombok.extern.slf4j.Slf4j;

import static com.lpvs.entity.report.LPVSReportBuilder.saveHTMLToFile;

/**
* Service class for detecting licenses in GitHub pull requests using a specified scanner.
*/
Expand Down Expand Up @@ -59,6 +62,11 @@ public class LPVSDetectService {
*/
private LPVSScanService scanService;

/**
* Component responsible for the generation of HTML reports.
*/
private LPVSReportBuilder reportBuilder;

/**
* Trigger value to start a single scan of a pull request (optional).
*/
Expand Down Expand Up @@ -91,6 +99,7 @@ public class LPVSDetectService {
* @param licenseService Service for license conflict analysis.
* @param gitHubService Service for GitHub connection and operation.
* @param scanServiceFactory Service for creating instance of the scanner.
* @param reportBuilder Service for generating HTML reports.
*/
@Autowired
public LPVSDetectService(
Expand All @@ -99,12 +108,14 @@ public LPVSDetectService(
LPVSGitHubConnectionService gitHubConnectionService,
LPVSLicenseService licenseService,
LPVSGitHubService gitHubService,
LPVSScanServiceFactory scanServiceFactory) {
LPVSScanServiceFactory scanServiceFactory,
LPVSReportBuilder reportBuilder) {
this.gitHubConnectionService = gitHubConnectionService;
this.licenseService = licenseService;
this.gitHubService = gitHubService;
this.scanService = scanServiceFactory.createScanService(scannerType, isInternal);
log.info("License detection scanner: " + scannerType);
this.reportBuilder = reportBuilder;
}

/**
Expand All @@ -117,6 +128,7 @@ public void runSingleScan() {
LPVSQueue webhookConfig = null;
List<LPVSFile> scanResult = null;
List<LPVSLicenseService.Conflict<String, String>> detectedConflicts = null;
String path = null;

// Error case when both pull request scan and local files scan are set to true
if (!StringUtils.isBlank(trigger) && !StringUtils.isBlank(localPath)) {
Expand All @@ -138,6 +150,7 @@ public void runSingleScan() {

detectedConflicts = licenseService.findConflicts(webhookConfig, scanResult);
generateReport = true;
path = HtmlUtils.htmlEscape(trigger);
log.info("Single scan of pull request completed.");
} catch (Exception ex) {
log.error("Single scan of pull request failed with error: " + ex.getMessage());
Expand Down Expand Up @@ -165,6 +178,7 @@ public void runSingleScan() {

detectedConflicts = licenseService.findConflicts(webhookConfig, scanResult);
generateReport = true;
path = localFile.getAbsolutePath();
log.info("Single scan of local file(s) completed.");
} else {
throw new Exception("File path does not exist: " + localPath);
Expand All @@ -187,9 +201,9 @@ public void runSingleScan() {
File folder = new File(folderPath);
if (folder.exists() && folder.isDirectory()) {
String reportFile =
LPVSCommentUtil.buildHTMLComment(
webhookConfig, scanResult, detectedConflicts);
LPVSCommentUtil.saveHTMLToFile(reportFile, report.getAbsolutePath());
reportBuilder.generateHtmlReportSingleScan(
path, scanResult, detectedConflicts, null, null);
saveHTMLToFile(reportFile, report.getAbsolutePath());
} else {
log.error("Error: The parent directory '" + folder.getPath() + "' does not exist.");
}
Expand Down
94 changes: 3 additions & 91 deletions src/main/java/com/lpvs/util/LPVSCommentUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@
*/
package com.lpvs.util;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;

import com.lpvs.entity.LPVSDetectedLicense;
Expand Down Expand Up @@ -44,6 +39,9 @@ public class LPVSCommentUtil {
*/
public static String getMatchedLinesAsLink(
LPVSQueue webhookConfig, LPVSFile file, LPVSVcs vcs) {
if (webhookConfig == null) {
return file.getMatchedLines();
}
String prefix =
LPVSPayloadUtil.getRepositoryUrl(webhookConfig)
+ "/blob/"
Expand Down Expand Up @@ -138,90 +136,4 @@ public static String reportCommentBuilder(

return commitCommentBuilder.toString();
}

/**
* Generates a formatted string for an HTML report with scan results.
*
* @param webhookConfig The {@link LPVSQueue} configuration for the webhook.
* @param scanResults List containing preformatted scan results.
* @param conflicts List containing license conflict information.
* @return A string containing scan results in HTML format.
*/
public static String buildHTMLComment(
LPVSQueue webhookConfig,
List<LPVSFile> scanResults,
List<LPVSLicenseService.Conflict<String, String>> conflicts) {
StringBuilder htmlBuilder = new StringBuilder();

htmlBuilder.append("<html><body>");

if (scanResults != null && scanResults.size() != 0) {
htmlBuilder.append("<h2>Detected licenses:</h2>");
for (LPVSFile file : scanResults) {
htmlBuilder
.append("<p><strong>File:</strong> ")
.append(file.getFilePath())
.append("</p>");
htmlBuilder
.append("<p><strong>License(s):</strong> ")
.append(file.convertLicensesToString(LPVSVcs.GITHUB))
.append("</p>");
htmlBuilder
.append("<p><strong>Component:</strong> ")
.append(file.getComponentName())
.append(" (")
.append(file.getComponentFilePath())
.append(")</p>");
htmlBuilder
.append("<p><strong>Matched Lines:</strong> ")
.append(
LPVSCommentUtil.getMatchedLinesAsLink(
webhookConfig, file, LPVSVcs.GITHUB))
.append("</p>");
htmlBuilder
.append("<p><strong>Snippet Match:</strong> ")
.append(file.getSnippetMatch())
.append("</p>");
htmlBuilder.append("<hr>");
}
}

if (conflicts != null && conflicts.size() > 0) {
htmlBuilder.append("<h2>Detected license conflicts:</h2>");
htmlBuilder.append("<ul>");
for (LPVSLicenseService.Conflict<String, String> conflict : conflicts) {
htmlBuilder
.append("<li>")
.append(conflict.l1)
.append(" and ")
.append(conflict.l2)
.append("</li>");
}
htmlBuilder.append("</ul>");
if (webhookConfig.getHubLink() != null) {
htmlBuilder.append("<p>").append(webhookConfig.getHubLink()).append("</p>");
}
}

htmlBuilder.append("</body></html>");

return htmlBuilder.toString();
}

/**
* Saves HTML report to given location.
*
* @param htmlContent The string, containing report in HTML format.
* @param filePath The path to expected html report file.
*/
public static void saveHTMLToFile(String htmlContent, String filePath) {
File file = new File(filePath);
try (BufferedWriter writer =
new BufferedWriter(new FileWriter(file, StandardCharsets.UTF_8))) {
writer.write(htmlContent);
log.info("LPVS report saved to: " + filePath);
} catch (IOException ex) {
log.error("error during saving HTML report: " + ex.getMessage());
}
}
}
141 changes: 141 additions & 0 deletions src/main/resources/templates/report_single_scan.html

Large diffs are not rendered by default.

Loading

0 comments on commit 1b69e16

Please sign in to comment.