Fix Plugin Manager links without wiki URL (#26976)

Fix plugin manager links without wiki URL
This commit is contained in:
Alex Tumanov authored and GitHub committed 2026-07-03 08:59:07 -06:00
1 parent fab7b78606
commit afadae6df5
3 files changed
+109 -13

No files matched your search

@@ -10,11 +10,19 @@
{{/if}}
<td>
<div>
<a href="{{ this.wiki }}" class="jenkins-table__link" target="_blank" rel="noopener noreferrer">
{{ this.displayName }}
<span class="jenkins-visually-hidden">Version</span>
<span class="jenkins-label jenkins-label--tertiary" style="margin-left: 1ch;">{{ this.version }}</span>
</a>
{{#if this.wiki }}
<a href="{{ this.wiki }}" class="jenkins-table__link" target="_blank" rel="noopener noreferrer">
{{ this.displayName }}
<span class="jenkins-visually-hidden">Version</span>
<span class="jenkins-label jenkins-label--tertiary" style="margin-left: 1ch;">{{ this.version }}</span>
</a>
{{else}}
<span>
{{ this.displayName }}
<span class="jenkins-visually-hidden">Version</span>
<span class="jenkins-label jenkins-label--tertiary" style="margin-left: 1ch;">{{ this.version }}</span>
</span>
{{/if}}
</div>
{{#if this.categories }}
<div class="app-plugin-manager__categories">
@@ -73,11 +81,17 @@
<td style="width: 15%">
<div>
{{#if this.healthScore }}
<a href="{{ this.wiki }}/healthScore"
class="jenkins-healthScore--badge jenkins-healthScore--{{ this.healthScoreClass }}"
target="_blank" rel="noopener noreferrer">
{{ this.healthScore }}
</a>
{{#if this.wiki }}
<a href="{{ this.wiki }}/healthScore"
class="jenkins-healthScore--badge jenkins-healthScore--{{ this.healthScoreClass }}"
target="_blank" rel="noopener noreferrer">
{{ this.healthScore }}
</a>
{{else}}
<span class="jenkins-healthScore--badge jenkins-healthScore--{{ this.healthScoreClass }}">
{{ this.healthScore }}
</span>
{{/if}}
{{else}}
<div class="icon-lg">
<!-- symbol: status-aborted -->
@@ -92,7 +92,6 @@ import net.sf.json.JSONObject;
import org.apache.commons.io.FileUtils;
import org.htmlunit.AlertHandler;
import org.htmlunit.Page;
import org.htmlunit.html.HtmlAnchor;
import org.htmlunit.html.HtmlForm;
import org.htmlunit.html.HtmlPage;
import org.junit.jupiter.api.AfterEach;
@@ -855,14 +854,37 @@ class PluginManagerTest {
.getTextContent().contains("This plugin is built for Jenkins 9999999"));
wc.waitForBackgroundJavaScript(100);
HtmlAnchor anchor = available.querySelector(".jenkins-table__link");
anchor.click(true, false, false);
assertNull(available.querySelector(".jenkins-table__link"));
wc.waitForBackgroundJavaScript(100);
assertTrue(alertHandler.messages.isEmpty());
}
});
}
@Test
@Issue("JENKINS-70794")
void pluginsSearchReturnsAvailablePluginWithoutWikiUrl() throws Throwable {
session.then(r -> {
DownloadService.signatureCheck = false;
Jenkins.get().getUpdateCenter().getSites().clear();
UpdateSite us = new UpdateSite("NoWiki", Jenkins.get().getRootUrl() + "noWikiUpdateCenter/update-center.json");
Jenkins.get().getUpdateCenter().getSites().add(us);
assertEquals(FormValidation.ok(), us.updateDirectly(false).get());
assertNotNull(us.getData());
JenkinsRule.JSONWebResponse response = r.getJSON("pluginManager/pluginsSearch?query=plugin-without-wiki&limit=5");
JSONObject json = response.getJSONObject();
assertTrue(json.has("data"));
JSONArray data = json.getJSONArray("data");
assertEquals(1, data.size(), "Should be one search hit for plugin-without-wiki");
JSONObject plugin = data.getJSONObject(0);
assertEquals("plugin-without-wiki", plugin.getString("name"));
assertEquals("Plugin Without Wiki", plugin.getString("displayName"));
assertEquals("", plugin.getString("wiki"));
assertEquals(100, plugin.getInt("healthScore"));
});
}
@Test
@Issue("SECURITY-3072")
void verifyUploadedPluginFromURLPermission() throws Throwable {
@@ -936,6 +958,31 @@ class PluginManagerTest {
}
}
@TestExtension("pluginsSearchReturnsAvailablePluginWithoutWikiUrl")
public static final class NoWikiUpdateCenter implements RootAction {
@Override
public String getIconFileName() {
return "gear2.png";
}
@Override
public String getDisplayName() {
return "no-wiki-update-center";
}
@Override
public String getUrlName() {
return "noWikiUpdateCenter";
}
public void doDynamic(StaplerRequest2 staplerRequest, StaplerResponse2 staplerResponse) throws ServletException, IOException {
staplerResponse.setContentType("application/json");
staplerResponse.setStatus(200);
staplerResponse.serveFile(staplerRequest, PluginManagerTest.class.getResource("/plugins/no-wiki-update-center.json"));
}
}
@TestExtension("verifyUploadedPluginFromURLPermission")
public static final class Security3072JpiAction implements RootAction {
@@ -0,0 +1,35 @@
updateCenter.post(
{
"connectionCheckUrl": "https://www.google.com/",
"core": {
"buildDate": "Jun 20, 2026",
"name": "core",
"sha1": "dummy",
"sha256": "dummy",
"size": 1,
"url": "https://updates.jenkins.io/download/war/2.570/jenkins.war",
"version": "2.570"
},
"generationTimestamp": "2026-06-20T00:00:00Z",
"id": "NoWiki",
"deprecations": [],
"plugins": {
"plugin-without-wiki": {
"buildDate": "Jun 20, 2026",
"dependencies": [],
"excerpt": "A plugin without a wiki URL.",
"health": 100,
"name": "plugin-without-wiki",
"popularity": 1,
"releaseTimestamp": "2026-06-20T00:00:00.00Z",
"requiredCore": "2.0",
"sha1": "dummy",
"sha256": "dummy",
"title": "Plugin Without Wiki",
"url": "https://updates.jenkins.io/download/plugins/plugin-without-wiki/1.0/plugin-without-wiki.hpi",
"version": "1.0"
}
},
"updateCenterVersion": "1"
}
);