Skip to content

Commit

Permalink
feat: User friendly command line report for single scan (#577)
Browse files Browse the repository at this point in the history
Signed-off-by: Oleg Kopysov <o.kopysov@samsung.com>
  • Loading branch information
o-kopysov authored Aug 27, 2024
1 parent 1b69e16 commit 62d4c96
Show file tree
Hide file tree
Showing 10 changed files with 238 additions and 226 deletions.
79 changes: 44 additions & 35 deletions src/main/java/com/lpvs/entity/LPVSFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
* Represents a file in the LPVS system.
Expand Down Expand Up @@ -105,45 +108,51 @@ public class LPVSFile {
* @return A formatted string representing the licenses.
*/
public String convertLicensesToString(LPVSVcs vcs) {
String licenseNames = "";
for (LPVSLicense license : this.licenses) {
String licSpdxId = license.getSpdxId();
// Check if the license SPDX ID has scanner-specific name
if (licSpdxId.startsWith("LicenseRef")) {
StringBuilder licenseNames = new StringBuilder();
Map<String, List<LPVSLicense>> groupedLicenses =
licenses.stream().collect(Collectors.groupingBy(LPVSLicense::getAccess));

for (Map.Entry<String, List<LPVSLicense>> entry : groupedLicenses.entrySet()) {
String accessType = entry.getKey();
List<LPVSLicense> licensesWithAccessType = entry.getValue();
licenseNames.append("\n").append("- ").append(accessType.toUpperCase()).append(":\n");

for (LPVSLicense license : licensesWithAccessType) {
String licSpdxId = license.getSpdxId();
// Check if the license SPDX ID has scanner-specific name.
// Change the name of the license that will be displayed in PR comment to
// scanner-independent
licSpdxId =
"UNREVIEWED LICENSE : "
+ licSpdxId
.replaceAll("LicenseRef-scancode-", "")
.replaceAll("LicenseRef-scanoss-", "");
}
if (vcs != null && vcs.equals(LPVSVcs.GITHUB)) {
licenseNames +=
(license.getChecklistUrl() != null
? "<a target=\"_blank\" href=\""
+ license.getChecklistUrl()
+ "\">"
: "")
+ licSpdxId
+ (license.getChecklistUrl() != null ? "</a>" : "")
+ " ("
+ license.getAccess().toLowerCase()
+ "), ";
} else {
licenseNames +=
licSpdxId
+ (license.getChecklistUrl() != null
? " (" + license.getChecklistUrl() + ")"
: "")
+ " - "
+ license.getAccess().toLowerCase()
+ ", ";
.replaceAll("LicenseRef-scancode-", "")
.replaceAll("LicenseRef-scanoss-", "");

if (vcs != null && vcs.equals(LPVSVcs.GITHUB)) {
licenseNames
.append(" : ")
.append(
license.getChecklistUrl() != null
? "<a target=\"_blank\" href=\""
+ license.getChecklistUrl()
+ "\">"
: "")
.append(licSpdxId)
.append(license.getChecklistUrl() != null ? "</a>" : "")
.append("\n");
} else {
licenseNames
.append(" : ")
.append(licSpdxId)
.append(
license.getChecklistUrl() != null
? " (" + license.getChecklistUrl() + ")"
: "")
.append("\n");
}
}
}
if (licenseNames.endsWith(", "))
licenseNames = licenseNames.substring(0, licenseNames.length() - 2);
return licenseNames;

return licenseNames.toString();
}

/**
Expand Down Expand Up @@ -183,7 +192,7 @@ public String convertBytesToLinesNumbers() {
while (byteCounter < endByte) {
String line = sourceFile.readLine();
if (line == null) {
if (startLine > 0 && endLine == 0) endLine = currentLine;
if (startLine > 0) endLine = currentLine;
break;
}
byteCounter += line.getBytes(StandardCharsets.UTF_8).length + 1;
Expand All @@ -198,7 +207,7 @@ public String convertBytesToLinesNumbers() {
}

// Construct the string representing start and end line numbers in the range
if (result.length() > 0) {
if (!result.isEmpty()) {
result.append(",");
}
result.append(startLine);
Expand Down
84 changes: 84 additions & 0 deletions src/main/java/com/lpvs/entity/report/LPVSReportBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ public LPVSReportBuilder(TemplateEngine templateEngine) {
private final String restricted = "RESTRICTED";
private final String prohibited = "PROHIBITED";
private final String unreviewed = "UNREVIEWED";
private final String boldStart = "\033[1m";
private final String boldEnd = "\033[0m";

/**
* A class representing a group of elements with a count.
Expand Down Expand Up @@ -147,6 +149,88 @@ public String generateHtmlReportSingleScan(
return templateEngine.process("report_single_scan", context);
}

/**
* Generates a formatted string for an LPVS command line comment.
*
* @param path The path to the source folder for scan or pull request URL
* @param scanResults the results of the license scan
* @param conflicts a list of license conflicts found during the scan
* @return A string containing scan results in command line friendly format.
*/
public String generateCommandLineComment(
String path,
List<LPVSFile> scanResults,
List<LPVSLicenseService.Conflict<String, String>> conflicts) {
StringBuilder commentBuilder = new StringBuilder();
String date = sdf.format(new Date());
commentBuilder.append("\n");
commentBuilder.append(boldStart + "Scan date: " + boldEnd + date + "\n");
commentBuilder.append(boldStart + "Source code location: " + boldEnd + path + "\n");
commentBuilder.append(boldStart + "Used scanner: " + boldEnd + scannerType + "\n");
commentBuilder.append(boldStart + "Version of LPVS: " + boldEnd + lpvsVersion + "\n\n");

commentBuilder.append(boldStart + "Detected Licenses" + boldEnd + "\n\n");

Map<String, GroupInfo<?>> detectedLicenseInfo =
groupScanResultsForLicenseTable(scanResults);
long prohibitedLicenses = getDetectedLicenseCountByType(detectedLicenseInfo, prohibited);
long restrictedLicenses = getDetectedLicenseCountByType(detectedLicenseInfo, restricted);
long unreviewedLicenses = getDetectedLicenseCountByType(detectedLicenseInfo, unreviewed);
long licenseDetected = prohibitedLicenses + restrictedLicenses + unreviewedLicenses;

if (licenseDetected > 0) {
commentBuilder.append(
"Potential license problem(s) detected: " + licenseDetected + "\n");
if (prohibitedLicenses > 0) {
commentBuilder.append(" - Prohibited license(s): " + prohibitedLicenses + "\n");
}
if (restrictedLicenses > 0) {
commentBuilder.append(" - Restricted license(s): " + restrictedLicenses + "\n");
}
if (unreviewedLicenses > 0) {
commentBuilder.append(" - Unreviewed license(s): " + unreviewedLicenses + "\n");
}
} else {
commentBuilder.append("No license problems detected.\n");
}

if (scanResults != null && !scanResults.isEmpty()) {
commentBuilder.append("\n");
for (LPVSFile file : scanResults) {
commentBuilder.append(boldStart + "File: " + boldEnd);
commentBuilder.append(file.getFilePath());
commentBuilder.append("\n");
commentBuilder.append(boldStart + "License(s): " + boldEnd);
commentBuilder.append(file.convertLicensesToString(null));
commentBuilder.append(boldStart + "Component: " + boldEnd);
commentBuilder.append(file.getComponentName());
commentBuilder.append(" (");
commentBuilder.append(file.getComponentFilePath());
commentBuilder.append(")\n");
commentBuilder.append(boldStart + "Matched Lines: " + boldEnd);
commentBuilder.append(file.getMatchedLines());
commentBuilder.append("\n");
commentBuilder.append(boldStart + "Snippet Match: " + boldEnd);
commentBuilder.append(file.getSnippetMatch());
commentBuilder.append("\n\n");
}
}

commentBuilder.append("\n");
commentBuilder.append(boldStart + "Detected License Conflicts" + boldEnd + "\n\n");
if (conflicts != null && !conflicts.isEmpty()) {
commentBuilder.append(
"Potential license conflict(s) detected: " + conflicts.size() + "\n");
for (LPVSLicenseService.Conflict<String, String> conflict : conflicts) {
commentBuilder.append(" - " + conflict.l1 + " and " + conflict.l2 + "\n");
}
} else {
commentBuilder.append("No license conflicts detected.\n");
}

return commentBuilder.toString();
}

/**
* Saves HTML report to given location.
*
Expand Down
3 changes: 1 addition & 2 deletions src/main/java/com/lpvs/service/LPVSGitHubService.java
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,7 @@ public void commentResults(
commitComment = "**Detected licenses:**\n\n\n";
for (LPVSFile file : scanResults) {
commitComment += "**File:** " + file.getFilePath() + "\n";
commitComment +=
"**License(s):** " + file.convertLicensesToString(LPVSVcs.GITHUB) + "\n";
commitComment += "**License(s):** " + file.convertLicensesToString(LPVSVcs.GITHUB);
commitComment +=
"**Component:** "
+ file.getComponentName()
Expand Down
4 changes: 1 addition & 3 deletions src/main/java/com/lpvs/service/scan/LPVSDetectService.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@

import com.lpvs.entity.LPVSFile;
import com.lpvs.entity.LPVSQueue;
import com.lpvs.util.LPVSCommentUtil;

import lombok.extern.slf4j.Slf4j;

Expand Down Expand Up @@ -211,8 +210,7 @@ public void runSingleScan() {
} else if (generateReport) {
// 2. Command line output
String report =
LPVSCommentUtil.reportCommentBuilder(
webhookConfig, scanResult, detectedConflicts);
reportBuilder.generateCommandLineComment(path, scanResult, detectedConflicts);
if (!report.isEmpty()) {
log.info(report);
}
Expand Down
62 changes: 0 additions & 62 deletions src/main/java/com/lpvs/util/LPVSCommentUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,9 @@
*/
package com.lpvs.util;

import java.util.List;

import com.lpvs.entity.LPVSDetectedLicense;
import com.lpvs.entity.LPVSFile;
import com.lpvs.entity.LPVSQueue;
import com.lpvs.entity.enums.LPVSVcs;
import com.lpvs.service.LPVSLicenseService;

import lombok.extern.slf4j.Slf4j;

Expand Down Expand Up @@ -78,62 +74,4 @@ public static String getMatchedLinesAsLink(
log.debug("MatchedLines: " + matchedLines);
return matchedLines;
}

/**
* Generates a formatted string for an LPVS GitHub comment.
*
* @param webhookConfig The {@link LPVSQueue} configuration for the webhook.
* @param scanResults List containing preformatted scan results.
* @param conflicts List of conflicts, containing license conflict information.
* @return A string containing scan results in GitHub-friendly format.
*/
public static String reportCommentBuilder(
LPVSQueue webhookConfig,
List<LPVSFile> scanResults,
List<LPVSLicenseService.Conflict<String, String>> conflicts) {

StringBuilder commitCommentBuilder = new StringBuilder();

if (scanResults != null && scanResults.size() != 0) {
commitCommentBuilder.append("**Detected licenses:**\n\n\n");
for (LPVSFile file : scanResults) {
commitCommentBuilder.append("**File:** ");
commitCommentBuilder.append(file.getFilePath());
commitCommentBuilder.append("\n");
commitCommentBuilder.append("**License(s):** ");
commitCommentBuilder.append(file.convertLicensesToString(LPVSVcs.GITHUB));
commitCommentBuilder.append("\n");
commitCommentBuilder.append("**Component:** ");
commitCommentBuilder.append(file.getComponentName());
commitCommentBuilder.append(" (");
commitCommentBuilder.append(file.getComponentFilePath());
commitCommentBuilder.append(")\n");
commitCommentBuilder.append("**Matched Lines:** ");
commitCommentBuilder.append(
LPVSCommentUtil.getMatchedLinesAsLink(webhookConfig, file, LPVSVcs.GITHUB));
commitCommentBuilder.append("\n");
commitCommentBuilder.append("**Snippet Match:** ");
commitCommentBuilder.append(file.getSnippetMatch());
commitCommentBuilder.append("\n\n\n\n");
}
}

if (conflicts != null && conflicts.size() > 0) {
commitCommentBuilder.append("**Detected license conflicts:**\n\n\n");
commitCommentBuilder.append("<ul>");
for (LPVSLicenseService.Conflict<String, String> conflict : conflicts) {
commitCommentBuilder.append("<li>" + conflict.l1 + " and " + conflict.l2 + "</li>");
LPVSDetectedLicense detectedIssue = new LPVSDetectedLicense();
detectedIssue.setIssue(true);
}
commitCommentBuilder.append("</ul>");
if (null != webhookConfig.getHubLink()) {
commitCommentBuilder.append("(");
commitCommentBuilder.append(webhookConfig.getHubLink());
commitCommentBuilder.append(")");
}
}

return commitCommentBuilder.toString();
}
}
10 changes: 4 additions & 6 deletions src/test/java/com/lpvs/entity/LPVSFileTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ public void convertLicensesToStringBaseTest() {
lpvsFile.setLicenses(licenses);
assertEquals(
lpvsFile.convertLicensesToString(LPVSVcs.GITHUB),
"<a target=\"_blank\" href=\"checklistUrl\">spdxId</a> (access)");
"\n- ACCESS:\n : <a target=\"_blank\" href=\"checklistUrl\">spdxId</a>\n");
}

@Test
Expand Down Expand Up @@ -189,7 +189,7 @@ public void convertLicenseToStringCheckListUrlNullTest() {
lpvsFile.setLicenses(licenses);
assertEquals(
lpvsFile.convertLicensesToString(LPVSVcs.GITHUB),
"spdxId (access), spdxId (access)");
"\n- ACCESS:\n : spdxId\n : spdxId\n");
}

@Test
Expand All @@ -211,9 +211,7 @@ public void convertLicenseToStringCheckListUrlLicenseRef() {

Set<LPVSLicense> licenses = new HashSet<>(Arrays.asList(lpvsLicense3));
lpvsFile.setLicenses(licenses);
assertEquals(
lpvsFile.convertLicensesToString(LPVSVcs.GITHUB),
"UNREVIEWED LICENSE : spdxId (access)");
assertEquals(lpvsFile.convertLicensesToString(LPVSVcs.GITHUB), "\n- ACCESS:\n : spdxId\n");

licenses = new HashSet<>();
lpvsFile.setLicenses(licenses);
Expand Down Expand Up @@ -251,7 +249,7 @@ public void convertLicenseToStringCheckListUrlTwoTest() {
lpvsFile.setLicenses(licenses);
assertEquals(
lpvsFile.convertLicensesToString(LPVSVcs.GITHUB),
"<a target=\"_blank\" href=\"checklistUrl\">spdxId</a> (access), <a target=\"_blank\" href=\"checklistUrl\">spdxId</a> (access)");
"\n- ACCESS:\n : <a target=\"_blank\" href=\"checklistUrl\">spdxId</a>\n : <a target=\"_blank\" href=\"checklistUrl\">spdxId</a>\n");
}

@Test
Expand Down
Loading

0 comments on commit 62d4c96

Please sign in to comment.