Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Readme updater Merged two vulnerability charts into one svg #898

Merged
merged 2 commits into from
Nov 6, 2024
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
7 changes: 2 additions & 5 deletions community_images/common/templates/image_readme.j2
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,8 @@ RapidFort has optimized and hardened this {{ official_name }} container image. T
This optimized image is functionally equivalent to [{{- source_image_provider }} {{ official_name -}}][source-image-repo-link] image but more secure with a significantly smaller software attack surface.

<p style="display: flex; justify-content: center; gap: 16px;">
<a href="{{ report_url -}}?utm_source=github&utm_medium=ci_view_report&utm_campaign=sep_01_sprint&utm_term={{- name -}}&utm_content=vulns_count_chart">
<img src="https://raw.githubusercontent.com/rapidfort/community-images/refs/heads/main/community_images/ {{- github_location -}} /assets/vulns_count_chart.svg" alt="Vulnerabilities by severity" width="46.5%" />
</a>
<a href="{{ report_url -}}?utm_source=github&utm_medium=ci_view_report&utm_campaign=sep_01_sprint&utm_term={{- name -}}&utm_content=original_vs_hardened_vulns_chart">
<img src="https://raw.githubusercontent.com/rapidfort/community-images/refs/heads/main/community_images/ {{- github_location -}} /assets/original_vs_hardened_vulns_chart.svg" alt="Original vs. this image" width="46.5%" />
<a href="{{ report_url -}}?utm_source=github&utm_medium=ci_view_report&utm_campaign=sep_01_sprint&utm_term={{- name -}}&utm_content=vulns_charts">
<img src="https://raw.githubusercontent.com/rapidfort/community-images/refs/heads/main/community_images/ {{- github_location -}} /assets/vulns_charts.svg" alt="Vulnerabilities by severity" width="100%" />
</a>
</p>

Expand Down
63 changes: 57 additions & 6 deletions report_shots/shots.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ const generateCharts = async (imageName, platform, imageSavePath) => {

saveSVGToFile(vulnsCountChartSVG, util.format('%s/vulns_count_chart.svg', imageSavePath));
saveSVGToFile(vulnsOriginalHardenedChartSVG, util.format('%s/original_vs_hardened_vulns_chart.svg', imageSavePath));
const vulnsChartMergedSvg = await mergeSvgHorizontally([vulnsCountChartSVG, vulnsOriginalHardenedChartSVG], 24);

saveSVGToFile(vulnsChartMergedSvg, util.format('%s/vulns_charts.svg', imageSavePath));

const savingsSVG = await generateSavingsCardsCompound([
{
type:'vulns',
Expand All @@ -102,7 +106,6 @@ const generateCharts = async (imageName, platform, imageSavePath) => {
}
]);
saveSVGToFile(savingsSVG, util.format('%s/savings.svg', imageSavePath));

// save individual charts as svg
// saveSVGToFile(vulnsSavingsChartSVG, util.format('%s/savings_chart_vulns.svg', imageSavePath));
// saveSVGToFile(packagesSavingsChartSVG, util.format('%s/savings_chart_pkgs.svg', imageSavePath));
Expand Down Expand Up @@ -608,7 +611,6 @@ async function generateVulnsCountChart(vulnsCount) {
draw.findOne("#vulns_count_mask").attr('width', contentWidth)
draw.findOne("#external-link").attr('transform', `translate(${contentWidth - initialContentWidth}, 0)`)
draw.findOne("#vulns_count_mask_rect").attr('width', contentWidth)
console.log('contentWidth', contentWidth)
drawVulnsChart(draw, 'vulns_count_view', contentWidth, vulnsCount, vulnsCount.total);
// Update the total count text
updateText(draw, '#vulns_total', vulnsCount.total);
Expand Down Expand Up @@ -642,10 +644,6 @@ async function generateVulnsOriginalHardenedChart(cardWidth, original, hardened)
const originalValueTextWidth = originalValueText.bbox().width;
originalValueText.remove(); // remove text after measure
const initialContentWidth = 365;
const overflowWidth = parseInt(cardWidth) - (337 + originalValueTextWidth);
console.log('originalValueTextWidth', originalValueTextWidth)
console.log('overflowWidth', overflowWidth)
console.log('cardWidth', cardWidth)
draw.findOne("#external-link").attr('transform', `translate(${cardWidth - initialContentWidth}, 0)`)
draw.findOne(`#original_value_tspan`).attr('x', cardWidth - originalValueTextWidth - 24)
draw.findOne(`#original_mask`).attr('width', cardWidth - originalValueTextWidth - 24 - 10 - 106)
Expand Down Expand Up @@ -721,6 +719,59 @@ async function generateSavingsCardsCompound(savingsData) {
return draw.svg();
}


async function mergeSvgHorizontally(svgStrings, gap) {
const { SVG, registerWindow } = await import('@svgdotjs/svg.js');
const { createSVGWindow } = await import('svgdom');
const window = createSVGWindow();
const document = window.document;
registerWindow(window, document);

const remainingCSSList = []
const canvas = SVG(document.documentElement);
const uniqueCSSRules = new Set();
let totalWidth = 0;
let maxHeight = 0;
let fontFaceCaptured = false; // Track if font-face has already been captured

svgStrings.forEach((svgString, index) => {
// Extract all styles content
const styleMatch = svgString.match(/<style[^>]*>([\s\S]*?)<\/style>/);
if (styleMatch && styleMatch[1]) {
let styleContent = styleMatch[1];
// Extract `@font-face` and other CSS rules separately
const fontFaceRules = styleContent.match(/@font-face\s*{[^}]*}/g) || [];
const remainingCSS = styleContent.replace(/@font-face\s*{[^}]*}/g, '').trim();
// Add only the first set of `@font-face` rules
if (!fontFaceCaptured) {
fontFaceRules.forEach(rule => uniqueCSSRules.add(rule));
fontFaceCaptured = true;
}
remainingCSSList.push(remainingCSS);
}

const svgWithoutStyle = svgString.replace(/<style[^>]*>([\s\S]*?)<\/style>/, '');
const svg = SVG(svgWithoutStyle);

const width = svg.width();
const height = svg.height();

if (index > 0) totalWidth += gap;
totalWidth += width;
maxHeight = Math.max(maxHeight, height);

svg.move(totalWidth - width, 0);
canvas.add(svg);
});
// Construct the final style tag with unique rules
const combinedStyle = `<style>${[...uniqueCSSRules, ...remainingCSSList].join('\n')}</style>`;

// Add the combined styles to the canvas and set the final canvas size
canvas.svg(combinedStyle + canvas.svg());
canvas.size(totalWidth, maxHeight);

return canvas.svg();
}
async function main() {
const imgListPath = process.argv[2]
const platform = process.argv[3]
Expand Down