mirror of
https://github.com/grafana/grafana.git
synced 2024-11-22 08:56:43 -06:00
168 lines
4.9 KiB
JavaScript
168 lines
4.9 KiB
JavaScript
/**
|
|
* @file This file exports the function `printAffectedPluginsSection`
|
|
* used to generate the affected plugins section in the report
|
|
* that is used in `levitate-parse-json-report.js`
|
|
*/
|
|
|
|
const { execSync } = require('child_process');
|
|
const fs = require('fs');
|
|
|
|
/**
|
|
* Extracts the package name from a given location string.
|
|
*
|
|
* @param {string} location - The location string containing the package information.
|
|
* @returns {string} - The extracted package name, or an empty string if no match is found.
|
|
*/
|
|
function getPackage(location) {
|
|
const match = location.match(/(.+\/)dist\//);
|
|
if (match) {
|
|
const packageJsonPath = match[1] + 'package.json';
|
|
const data = fs.readFileSync(packageJsonPath, 'utf8');
|
|
|
|
if (!data) {
|
|
return '';
|
|
}
|
|
|
|
return JSON.parse(data)?.name || '';
|
|
}
|
|
return '';
|
|
}
|
|
|
|
const PANEL_URL = 'https://ops.grafana-ops.net/d/dmb2o0xnz/imported-property-details?orgId=1';
|
|
|
|
/**
|
|
* Creates an array of HTML links for the given section and affecting properties.
|
|
*
|
|
* @param {Array} section - An array of objects, each containing `name` and `location` properties.
|
|
* @param {Set} affectingProperties - A set of property names that are affected.
|
|
* @returns {Array<string>} - An array of HTML link strings.
|
|
*/
|
|
function createLinks(section, affectingProperties) {
|
|
return section
|
|
.map(({ name, location }) => {
|
|
const package = getPackage(location);
|
|
|
|
if (!package && !affectingProperties.has(name)) {
|
|
return undefined;
|
|
}
|
|
|
|
const link = PANEL_URL + `&var-propertyName=${name}&var-packageName=${package}`;
|
|
|
|
return `<a href="${link}">${package}/${name}</a>`;
|
|
})
|
|
.filter((item) => item !== undefined);
|
|
}
|
|
|
|
/**
|
|
* Generates an SQL query to select property names, package names, and plugin IDs
|
|
* from the `plugin_imports` table based on the provided section data.
|
|
*
|
|
* @param {Array} section - An array of objects, each containing `name` and `location` properties.
|
|
* @returns {string} - The generated SQL query string.
|
|
*/
|
|
function makeQuery(section) {
|
|
const whereClause = section
|
|
.map(({ name, location }) => {
|
|
const package = getPackage(location);
|
|
|
|
if (!package) {
|
|
return undefined;
|
|
}
|
|
|
|
return `(property_name = '${name}' AND package_name = '${package}')`;
|
|
})
|
|
.filter((item) => item !== undefined)
|
|
.join(' OR ');
|
|
|
|
if (!whereClause) {
|
|
return '';
|
|
}
|
|
|
|
return `
|
|
SELECT
|
|
property_name,
|
|
package_name,
|
|
plugin_id
|
|
FROM
|
|
\\\`grafanalabs-global.plugins_data.plugin_imports\\\`
|
|
WHERE ${whereClause}
|
|
`;
|
|
}
|
|
|
|
/**
|
|
* Extracts a specific column from a table represented as an array of lines.
|
|
*
|
|
* @param {Array<string>} lines - An array of strings, each representing a row in the table.
|
|
* @param {number} columnIndex - The index of the column to extract.
|
|
* @returns {Set<string>} - A set containing the unique values from the specified column.
|
|
*/
|
|
function getColumn(lines, columnIndex) {
|
|
const set = new Set();
|
|
const tableBody = lines.slice(3);
|
|
|
|
for (let row of tableBody) {
|
|
const columns = row.split('|').map((col) => col.trim());
|
|
|
|
if (columns.length === 5) {
|
|
const content = columns[columnIndex];
|
|
|
|
set.add(content);
|
|
}
|
|
}
|
|
|
|
return set;
|
|
}
|
|
|
|
/**
|
|
* Generates a markdown section detailing the affected plugins based on the provided data.
|
|
*
|
|
* @param {Object} data - The data object containing `removals` and `changes` arrays.
|
|
* @param {Array} data.removals - An array of objects representing removed items.
|
|
* @param {Array} data.changes - An array of objects representing changed items.
|
|
* @returns {string} - The generated markdown string detailing the affected plugins.
|
|
*/
|
|
function printAffectedPluginsSection(data) {
|
|
const { removals, changes } = data;
|
|
|
|
let markdown = '';
|
|
|
|
try {
|
|
const sqlQuery = makeQuery([...removals, ...changes]);
|
|
if (!sqlQuery) {
|
|
throw new Error("Couldn't generate SQL query");
|
|
}
|
|
|
|
const cmd = `bq query --nouse_legacy_sql "${sqlQuery}"`;
|
|
const stdout = execSync(cmd, { encoding: 'utf-8' });
|
|
|
|
const rows = stdout.trim().split('\n');
|
|
|
|
if (rows.length > 3) {
|
|
const pluginsColumnIndex = 3;
|
|
const affectedPlugins = getColumn(rows, pluginsColumnIndex);
|
|
|
|
markdown += `<h3>Number of affected plugins: ${affectedPlugins.size}</h3>`;
|
|
markdown += '<p>To check the plugins affected by each import, click on the links below.</p>';
|
|
|
|
const propertiesColumnIndex = 1;
|
|
const affectingProperties = getColumn(rows, propertiesColumnIndex);
|
|
|
|
if (removals.length > 0) {
|
|
markdown += `<h4>Removals</h4>`;
|
|
markdown += createLinks(removals, affectingProperties).join('<br>\n');
|
|
}
|
|
|
|
if (changes.length > 0) {
|
|
markdown += `<h4>Changes</h4>`;
|
|
markdown += createLinks(changes, affectingProperties).join('<br>\n');
|
|
}
|
|
}
|
|
} catch (error) {
|
|
markdown += `<h4>Error generating detailed report ${error}</h4>`;
|
|
}
|
|
|
|
return markdown;
|
|
}
|
|
|
|
module.exports = printAffectedPluginsSection;
|