ci: harden typhon telemetry publisher quoting

This commit is contained in:
Brad Stein 2026-05-16 16:28:35 -03:00
parent 5aa0b92de4
commit bcdecee1a9

36
Jenkinsfile vendored
View File

@ -107,8 +107,12 @@ function unescapeXml(value) {
} }
function attr(attrs, name) { function attr(attrs, name) {
const match = attrs.match(new RegExp(`(?:^|\\s)${name}="([^"]*)"`)); const needle = `${name}="`;
return match ? unescapeXml(match[1]) : ''; const start = attrs.indexOf(needle);
if (start < 0) return '';
const valueStart = start + needle.length;
const valueEnd = attrs.indexOf('"', valueStart);
return valueEnd < 0 ? '' : unescapeXml(attrs.slice(valueStart, valueEnd));
} }
function collectSourceFiles(rootDir) { function collectSourceFiles(rootDir) {
@ -134,7 +138,7 @@ function collectSourceFiles(rootDir) {
} }
function categoryForClassname(classname) { function categoryForClassname(classname) {
const normalized = String(classname || '').split('\\').join('/'); const normalized = String(classname || '').split(String.fromCharCode(92)).join('/');
const relative = normalized.includes('/tests/') const relative = normalized.includes('/tests/')
? normalized.slice(normalized.indexOf('/tests/') + '/tests/'.length) ? normalized.slice(normalized.indexOf('/tests/') + '/tests/'.length)
: (normalized.startsWith('tests/') ? normalized.slice('tests/'.length) : normalized); : (normalized.startsWith('tests/') ? normalized.slice('tests/'.length) : normalized);
@ -147,7 +151,7 @@ function categoryForClassname(classname) {
function parseTestCases(junit) { function parseTestCases(junit) {
const cases = []; const cases = [];
const re = new RegExp('<testcase\\b([^>]*)>([\\s\\S]*?)</testcase>|<testcase\\b([^>]*)/>', 'g'); const re = new RegExp('<testcase([^>]*)>(.*?)</testcase>|<testcase([^>]*)/>', 'gs');
let match; let match;
while ((match = re.exec(junit)) !== null) { while ((match = re.exec(junit)) !== null) {
const attrs = match[1] || match[3] || ''; const attrs = match[1] || match[3] || '';
@ -174,7 +178,7 @@ const cov = fs.existsSync(coveragePath) ? JSON.parse(fs.readFileSync(coveragePat
const total = cov.total || {}; const total = cov.total || {};
const sourceFiles = sourceRoots.flatMap((root) => collectSourceFiles(root)); const sourceFiles = sourceRoots.flatMap((root) => collectSourceFiles(root));
const overLimitFiles = sourceFiles const overLimitFiles = sourceFiles
.map((file) => ({ file, lines: fs.readFileSync(file, 'utf8').split(new RegExp('\\r?\\n')).length })) .map((file) => ({ file, lines: fs.readFileSync(file, 'utf8').split(String.fromCharCode(10)).length }))
.filter((item) => item.lines > 500); .filter((item) => item.lines > 500);
const report = { const report = {
@ -310,9 +314,9 @@ const sourceLinesOver500 = Number(quality.hygiene?.sourceLinesOver500 ?? 0);
function esc(value) { function esc(value) {
return String(value ?? '') return String(value ?? '')
.split('\\').join('\\\\') .split(String.fromCharCode(92)).join(String.fromCharCode(92, 92))
.split('"').join('\\"') .split('"').join(String.fromCharCode(92) + '"')
.split('\n').join('\\n'); .split(String.fromCharCode(10)).join(String.fromCharCode(92) + 'n');
} }
function labelString(labels) { function labelString(labels) {
@ -322,10 +326,16 @@ function labelString(labels) {
function fetchCounter(targetStatus) { function fetchCounter(targetStatus) {
try { try {
const metrics = execSync(`curl -fsS ${gateway}/metrics`, { encoding: 'utf8' }); const metrics = execSync(`curl -fsS ${gateway}/metrics`, { encoding: 'utf8' });
const re = new RegExp(`platform_quality_gate_runs_total\\{[^}]*suite=\\"${suite}\\"[^}]*status=\\"${targetStatus}\\"[^}]*\\}\\s+(\\d+(?:\\.\\d+)?)`); for (const line of metrics.split(String.fromCharCode(10))) {
const match = metrics.match(re); if (
if (!match) return 0; line.startsWith('platform_quality_gate_runs_total{') &&
return Number(match[1]); line.includes(`suite="${suite}"`) &&
line.includes(`status="${targetStatus}"`)
) {
return Number(line.trim().split(' ').filter(Boolean).pop() || 0);
}
}
return 0;
} catch { } catch {
return 0; return 0;
} }
@ -392,7 +402,7 @@ const lines = [
try { try {
execSync(`curl -fsS --data-binary @- ${gateway}/metrics/job/platform-quality-ci/suite/${suite}`, { execSync(`curl -fsS --data-binary @- ${gateway}/metrics/job/platform-quality-ci/suite/${suite}`, {
input: lines.join('\\n'), input: lines.join(String.fromCharCode(10)),
stdio: ['pipe', 'inherit', 'inherit'] stdio: ['pipe', 'inherit', 'inherit']
}); });
} catch (error) { } catch (error) {