diff --git a/pkg/packagekit/mock-updates.js b/pkg/packagekit/mock-updates.js index 1937b21c99bc..fbdf1d680c7a 100644 --- a/pkg/packagekit/mock-updates.js +++ b/pkg/packagekit/mock-updates.js @@ -13,7 +13,8 @@ export function injectMockUpdates(updates) { // some security updates - updates["security-crit;2.3-4"] = { + updates.push({ + id: "security-crit;2.3-4", name: "security-crit", version: "2.3-4", bug_urls: [], @@ -22,8 +23,9 @@ export function injectMockUpdates(updates) { "https://access.redhat.example.com/errata/RHSA-2000:0001", "https://access.redhat.example.com/errata/RHSA-2000:0002"], severity: 8, description: "This will wreck your data center!", - }; - updates["security-low;1-2+sec1"] = { + }); + updates.push({ + id: "security-low;1-2+sec1", name: "security-low", version: "1-2+sec1", bug_urls: [], @@ -32,8 +34,9 @@ export function injectMockUpdates(updates) { "https://access.redhat.com/security/updates/classification/#low", "low"], severity: 8, description: "Mostly Harmless", - }; - updates["security-imp;5-2"] = { + }); + updates.push({ + id: "security-imp;5-2", name: "security-imp", version: "5-2", bug_urls: [], @@ -41,29 +44,32 @@ export function injectMockUpdates(updates) { "https://access.redhat.com/security/updates/classification/#important", "important"], severity: 8, description: "This update will make you sleep more peacefully.", - }; - updates["security-mod;12.3-4"] = { + }); + updates.push({ + id: "security-mod;12.3-4", name: "security-mod", version: "12.3-4", bug_urls: [], vendor_urls: ["https://access.redhat.com/security/updates/classification/#moderate", "moderate"], severity: 8, description: "This update will make you sleep more peacefully.", - }; + }); // no vendor URLs, default severity - updates["security-default;42"] = { + updates.push({ + id: "security-default;42", name: "security-default", version: "42", cve_urls: ["https://cve.example.com?name=CVE-2014-54321"], vendor_urls: [], severity: 8, description: "Yet another weakness fixed.", - }; + }); // source with many binaries for (let i = 1; i < 50; ++i) { const name = `manypkgs${i}`; - updates[name + ";1-1"] = { + updates.push({ + id: name + ";1-1", name, version: "1-1", bug_urls: [], @@ -71,11 +77,12 @@ export function injectMockUpdates(updates) { severity: 4, description: "Make [everything](http://everything.example.com) *better*\n\n * more packages\n * more `bugs`\n * more fun!", markdown: true, - }; + }); } // long changelog - updates["verbose;1-1"] = { + updates.push({ + id: "verbose;1-1", name: "verbose", version: "1-1", bug_urls: [], @@ -83,9 +90,10 @@ export function injectMockUpdates(updates) { severity: 6, description: ("Some longish explanation of some boring technical change. " + "This is total technobabble gibberish for layman users.\n\n").repeat(30) - }; + }); - updates["verbose-md;1-1"] = { + updates.push({ + id: "verbose-md;1-1", name: "verbose-md", version: "1-1", bug_urls: [], @@ -94,18 +102,29 @@ export function injectMockUpdates(updates) { description: ("Some longish explanation of some *boring* technical change. " + "This is total technobabble gibberish for layman users.\n\n").repeat(30), markdown: true, - }; + }); // many bug fixes const bugs = []; for (let i = 10000; i < 10025; ++i) bugs.push("http://bugzilla.example.com/" + i); - updates["buggy;1-1"] = { + updates.push({ + id: "buggy;1-1", name: "buggy", version: "1-1", bug_urls: bugs, cve_urls: [], severity: 6, description: "This is FUBAR", - }; + }); + + updates.push({ + id: "tracker-links;1-1", + name: "tracker-links", + version: "1-1", + bug_urls: [], + cve_urls: [], + severity: 4, + description: "Fixes rhbz#12345 and RHEL-67890 in one update.", + }); } diff --git a/pkg/packagekit/updates.jsx b/pkg/packagekit/updates.jsx index 898ff7c1fd89..086fe59016b3 100644 --- a/pkg/packagekit/updates.jsx +++ b/pkg/packagekit/updates.jsx @@ -133,6 +133,62 @@ function cleanupChangelogLine(text) { return text.trim(); } +function isRedHatBasedDistribution() { + const os_release = cockpit.info?.os_release; + if (!os_release) + return false; + + const ids = [os_release.ID, ...(os_release.ID_LIKE || "").split(" ")].filter(Boolean); + return ids.some(id => ["rhel", "fedora", "centos"].includes(id)); +} + +function renderChangelogWithIssueLinks(text) { + if (!text) + return text; + + const issuePattern = /\brhbz#(\d+)(?!\w)|\bRHEL-(\d+)(?![-\w])/g; + const result = []; + let lastIndex = 0; + let match; + const redHatBased = isRedHatBasedDistribution(); + + while ((match = issuePattern.exec(text)) !== null) { + if (match.index > lastIndex) + result.push(text.slice(lastIndex, match.index)); + + const [, bugzillaId, rhelId] = match; + let href = null; + let key = null; + + if (bugzillaId) { + href = `https://bugzilla.redhat.com/show_bug.cgi?id=${bugzillaId}`; + key = `rhbz-${bugzillaId}-${match.index}`; + } else if (rhelId && redHatBased) { + href = `https://redhat.atlassian.net/browse/RHEL-${rhelId}`; + key = `RHEL-${rhelId}-${match.index}`; + } else { + result.push(match[0]); + lastIndex = issuePattern.lastIndex; + continue; + } + + result.push( + + {match[0]} + + ); + lastIndex = issuePattern.lastIndex; + } + + if (lastIndex === 0) + return text; + + if (lastIndex < text.length) + result.push(text.slice(lastIndex)); + + return result; +} + // Replace cockpit-wsinstance-https@[long_id] with a shorter string function shortenCockpitWsInstance(list) { return list.map(item => item.startsWith('cockpit-wsinstance-https') ? 'cockpit-wsinstance-https@.' : item); @@ -323,7 +379,8 @@ function updateItem(remarkable, info, pkgNames, key) { descriptionFirstLine = ; description =
; } else { - description =