Skip to content

Commit

Permalink
Merge pull request #689 from forcedotcom/dev-3
Browse files Browse the repository at this point in the history
@W-11163136@: Release activity for Scanner 3.1.0
  • Loading branch information
jfeingold35 authored May 18, 2022
2 parents 99dab63 + 82a84c9 commit 54cb2bc
Show file tree
Hide file tree
Showing 712 changed files with 94,028 additions and 322 deletions.
4 changes: 2 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ version: 2.1
defaults: &defaults
working_directory: ~/repo
docker:
- image: circleci/openjdk:11.0.2-jdk-node
- image: cimg/openjdk:8.0-node

orbs:
win: circleci/[email protected] # The Windows orb give you everything you need to start using the Windows executor.
Expand Down Expand Up @@ -543,7 +543,7 @@ workflows:
tag: latest-pilot-rc
filters:
<<: *publishing_filters
context:
context:
- AWS
- salesforce-cli
# Step 3: Smoke test the release candidate on both Linux and Windows.
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,4 @@ build

pmd-cataloger/bin

sfge*.log.gz
2 changes: 1 addition & 1 deletion docs/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ GEM
rb-inotify (~> 0.9, >= 0.9.10)
mercenary (0.3.6)
mini_portile2 (2.8.0)
nokogiri (1.13.3)
nokogiri (1.13.5)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
octicons (9.6.0)
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
334 changes: 334 additions & 0 deletions html-templates/dfa-simple.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,334 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/rowgroup/1.1.2/css/rowGroup.dataTables.min.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.21/css/dataTables.bootstrap4.min.css">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/rowgroup/1.1.2/css/rowGroup.bootstrap4.min.css">
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/Chart.min.css">
<style>
/* Move the search box to the left */
.dataTables_filter {
float: left !important;
padding-left: 10px;
padding-top: 10px;
}
/* Datatable should take up entire width */
.table {
width:100% !important;
}
/* Datatable column */
.scannerSeverity {
width: 10px;
text-align: center;
}
/* Datatable column. Right justify numerics. */
.scannerLocation {
text-align: right;
}
.summaryChartCell {
background-color:white;
}
.summaryChartContainer {
padding-left:10%;
padding-right:10%;
width:100%;
background-color:white
}
h1, h4 {
text-align: center;
}
#footer {
padding-top: 10px;
padding-bottom: 10px;
background-color: #e0e0e0;
font-size: 1.5em;
text-align: center;
}
#reportTitle {
margin: 25px;
}
#summaryFiles {
margin-top: 25px;
}
</style>
<script type="text/javascript" language="javascript" src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script type="text/javascript" language="javascript"
src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.min.js"></script>
<script type="text/javascript" language="javascript" src="https://cdn.datatables.net/rowgroup/1.1.2/js/dataTables.rowGroup.min.js"></script>
<script type="text/javascript" language="javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/Chart.min.js"></script>
<script type="text/javascript" class="init">
// BEGIN - Placeholders filled in by the scanner
const violations = {{{violations}}};
// END - Placeholders filled in by the scanner
// Global DataTable displayed in the report
var dataTable = null;
// Color if the severity is greater than 5
const unknownSeverityColor = '#cccccc';
// Background colors for severity
// Palette from https://www.w3schools.com/colors/colors_palettes.asp
// TODO: Accessibility
function getSeverityColor(severity) {
switch (parseInt(severity)) {
case 1:
return '#d96459';
case 2:
return '#f2ae72';
case 3:
return '#f2e394';
case 4:
return '#588c7e';
case 5:
return '#96ceb4';
default:
return '#cccccc';
}
}
// Convert a map of severity->count to a structure consumable by the chart library
// options.labelFormatter: function(severity, count) that returns a label
function sevMapToChartData(sevMap, options) {
var dataset = {
data: [],
backgroundColor: []
};
var dataLabels = [];
// Sort the entries by key order
sevMap = new Map([...sevMap.entries()].sort());
for (var severity of sevMap.keys()) {
var count = sevMap.get(severity);
dataset.data.push(count);
dataset.backgroundColor.push(getSeverityColor(severity));
if (options && options.labelFormatter) {
dataLabels.push(options.labelFormatter(severity, count));
} else {
dataLabels.push(`Sev${severity}`);
}
}
return {
datasets: [dataset],
labels: dataLabels
};
}
// Creates a horizontal bar chart below a grouping of rows. Called
// asynchronously as the rows are added/removed by the search feature.
function populateRowGroupChart(id, summary) {
const ctx = $(`#${id}`);
if (!ctx.length) {
// This can happen when the user quickly types in the search field
return;
}
const data = sevMapToChartData(summary);
new Chart(ctx, {
type: 'horizontalBar',
data: data,
options: {
aspectRatio: 20,
animation: {
duration: 0
},
legend: {
display: false
},
scales: {
xAxes: [{
ticks: { beginAtZero: true }
}]
}
},
});
}
function populateSummaryChart() {
// The number of files is determined by finding the number of row groupings
const numFiles = $('.dtrg-start').length;
var text = `${numFiles} File`;
if (numFiles !== 1) {
text += 's'
}
$('#summaryFiles').text(text);
// Number/type of violations is found by analyzing the visible data rows
var summary = new Map();
dataTable.rows({ search: 'applied' })
.data()
.pluck('severity')
.each(function (value, index) {
var count = summary.get(value);
count = count ? (count + 1) : 1;
summary.set(value, count);
});
// Calculate the total number of violations, independent of severity
const numViolations = Array.from(summary.values()).reduce((a, b) => a + b, 0);
text = `${numViolations} Violation`;
if (numViolations !== 1) {
text += 's'
}
$('#summaryViolations').text(text);
const data = sevMapToChartData(summary, {
labelFormatter: function(severity, count) {
return `Sev${severity} (${count})`;
}
});
// Create a new canvas, remove the previous canvas
const canvas = $('<canvas/>');
$('#summaryChart').empty().append(canvas);
new Chart(canvas, {
type: 'doughnut',
data: data,
options: {
aspectRatio: 6,
animation: {
duration: 0
},
legend: {
display: true,
position: 'bottom',
// Prevent a click from modifying the chart
onClick: (e) => e.stopPropagation(),
labels: {
fontSize: 18,
fontStyle: 'bold'
}
}
},
});
}
// Create a table where the first column(fileName) is hidden but used for grouping.
// Initial sort by fileName, severity, lineNumber
// fileName is used in orderFixed to force all results to sort underneath the fileName grouping
var rowSummaryIdCounter = 0;
$(document).ready(function () {
dataTable = $('#violations').DataTable({
columnDefs: [
{ 'visible': false, 'targets': [0] }
],
rowGroup: {
dataSrc: ['fileName'],
startRender: function (rows, group, level) {
return $('<tr>' +
`<td colspan="10">${group}</td>` +
'</tr>'
);
},
endRender: function (rows, group, level) {
var summary = new Map();
rows.data().pluck('severity').each( function(value, index) {
var count = summary.get(value);
count = count ? (count + 1) : 1;
summary.set(value, count);
});
const id = `summaryGroup${rowSummaryIdCounter++}`;
window.setTimeout(function() {
populateRowGroupChart(id, summary);
}, 0);
return $(
'<tr>' +
`<td colspan="10" class="summaryChartCell"><div class="summaryChartContainer"><canvas id="${id}"></canvas><div></td>` +
'</tr>');
}
},
orderFixed: [[0, 'asc']],
order: [[1, 'asc'], [6, 'asc']],
data: violations,
paging: false,
columns: [
{ data: 'fileName' },
{ data: 'severity', className: 'scannerSeverity' },
{ data: 'engine' },
{ data: 'category' },
{ data: 'ruleName',
// Convert the ruleName to a hyperlink that displays the rule information
'render': function(data, type, row, meta){
if(data && type === 'display'){
data = '<a href="' + row.url + '" target="__blank">' + data + '</a>';
}
return data;
}
},
{ data: 'message' },
// 'defaultContent' provides information to the Datatables code in cases where the row
// corresponds to something non file location specific. i.e. a tsconfig.json error
{ data: 'line', className: 'scannerLocation', defaultContent: ''},
{ data: 'column', className: 'scannerLocation', defaultContent: ''},
{ data: 'sinkFileName', className: 'scannerLocation', defaultContent: ''},
{ data: 'sinkLine', className: 'scannerLocation', defaultContent: ''},
{ data: 'sinkColumn', className: 'scannerLocation', defaultContent: ''}
],
'rowCallback': function(row, data, index) {
var severity = data['severity'];
var bgColor = getSeverityColor(severity);
if (bgColor) {
$(row).find('td:eq(0)').css('background-color', bgColor);
}
},
'infoCallback': function( settings, start, end, max, total, pre ) {
window.setTimeout(function() {
populateSummaryChart();
}, 0);
}
});
});
</script>
</head>

<body>
<h1 id="reportTitle">Salesforce CLI Scanner Report</h1>
<div id="summaryChart"/></div>
<h4 id="summaryFiles"></h4>
<h4 id="summaryViolations"></h4>
<div class="fw-container">
<div class="fw-body">
<div class="content">
<table id="violations" class="table table-striped table-bordered">
<thead>
<tr>
<th>File Name</th>
<th>Sev</th>
<th>Engine</th>
<th>Category</th>
<th>Rule Name</th>
<th>Message</th>
<th>Line</th>
<th>Column</th>
<th>Sink File</th>
<th>Sink Line</th>
<th>Sink Column</th>
</tr>
</thead>
<tbody/>
</table>
</div>
</div>
</div>
<div>
<div id="footer">This report was generated with command <b><i>{{{commandLine}}}</i></b> from working directory <b><i>{{{workingDirectory}}}</i></b></div>
</div>
</body>

</html>
Loading

0 comments on commit 54cb2bc

Please sign in to comment.