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) {
const match = attrs.match(new RegExp(`(?:^|\\s)${name}="([^"]*)"`));
return match ? unescapeXml(match[1]) : '';
const needle = `${name}="`;
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) {
@ -134,7 +138,7 @@ function collectSourceFiles(rootDir) {
}
function categoryForClassname(classname) {
const normalized = String(classname || '').split('\\').join('/');
const normalized = String(classname || '').split(String.fromCharCode(92)).join('/');
const relative = normalized.includes('/tests/')
? normalized.slice(normalized.indexOf('/tests/') + '/tests/'.length)
: (normalized.startsWith('tests/') ? normalized.slice('tests/'.length) : normalized);
@ -147,7 +151,7 @@ function categoryForClassname(classname) {
function parseTestCases(junit) {
const cases = [];
const re = new RegExp('<testcase\\b([^>]*)>([\\s\\S]*?)</testcase>|<testcase\\b([^>]*)/>', 'g');
const re = new RegExp('<testcase([^>]*)>(.*?)</testcase>|<testcase([^>]*)/>', 'gs');
let match;
while ((match = re.exec(junit)) !== null) {
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 sourceFiles = sourceRoots.flatMap((root) => collectSourceFiles(root));
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);
const report = {
@ -310,9 +314,9 @@ const sourceLinesOver500 = Number(quality.hygiene?.sourceLinesOver500 ?? 0);
function esc(value) {
return String(value ?? '')
.split('\\').join('\\\\')
.split('"').join('\\"')
.split('\n').join('\\n');
.split(String.fromCharCode(92)).join(String.fromCharCode(92, 92))
.split('"').join(String.fromCharCode(92) + '"')
.split(String.fromCharCode(10)).join(String.fromCharCode(92) + 'n');
}
function labelString(labels) {
@ -322,10 +326,16 @@ function labelString(labels) {
function fetchCounter(targetStatus) {
try {
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+)?)`);
const match = metrics.match(re);
if (!match) return 0;
return Number(match[1]);
for (const line of metrics.split(String.fromCharCode(10))) {
if (
line.startsWith('platform_quality_gate_runs_total{') &&
line.includes(`suite="${suite}"`) &&
line.includes(`status="${targetStatus}"`)
) {
return Number(line.trim().split(' ').filter(Boolean).pop() || 0);
}
}
return 0;
} catch {
return 0;
}
@ -392,7 +402,7 @@ const lines = [
try {
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']
});
} catch (error) {