From f081d1269ffc43d2b3b140d67d88d19f4e2cfc36 Mon Sep 17 00:00:00 2001 From: preetham-18-developer Date: Sun, 26 Jul 2026 13:11:52 +0530 Subject: [PATCH 1/3] Improve search fallback for single suggestion --- core/src/main/java/hudson/search/Search.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/hudson/search/Search.java b/core/src/main/java/hudson/search/Search.java index 92939e727239..499fc8236666 100644 --- a/core/src/main/java/hudson/search/Search.java +++ b/core/src/main/java/hudson/search/Search.java @@ -117,23 +117,34 @@ private void doIndexImpl(StaplerRequest2 req, StaplerResponse2 rsp) throws IOExc Ancestor a = l.get(i); if (a.getObject() instanceof SearchableModelObject smo) { if (LOGGER.isLoggable(Level.FINE)) { - LOGGER.fine(String.format("smo.displayName=%s, searchName=%s", smo.getDisplayName(), smo.getSearchName())); + LOGGER.fine(String.format( + "smo.displayName=%s, searchName=%s", + smo.getDisplayName(), + smo.getSearchName())); } SearchIndex index = smo.getSearchIndex(); String query = req.getParameter("q"); + if (query != null) { SuggestedItem target = find(index, query, smo); + if (target != null) { - // found rsp.sendRedirect2(req.getContextPath() + target.getUrl()); return; } + + List suggestions = suggest(index, query, smo); + + if (suggestions.size() == 1) { + rsp.sendRedirect2(req.getContextPath() + suggestions.get(0).getUrl()); + return; + } } } } - // no exact match. show the suggestions + // No exact match and no single suggestion. rsp.setStatus(SC_NOT_FOUND); req.getView(this, "search-failed.jelly").forward(req, rsp); } From 4b43c2be3ca3e22e1d5ba7c5d48890663b69c974 Mon Sep 17 00:00:00 2001 From: preetham-18-developer Date: Sun, 26 Jul 2026 14:09:29 +0530 Subject: [PATCH 2/3] Add regression test for single suggestion redirect --- test/src/test/java/hudson/search/SearchTest.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/src/test/java/hudson/search/SearchTest.java b/test/src/test/java/hudson/search/SearchTest.java index 5ded36f56f29..89bf2254465e 100644 --- a/test/src/test/java/hudson/search/SearchTest.java +++ b/test/src/test/java/hudson/search/SearchTest.java @@ -125,6 +125,21 @@ void testSearchByProjectName() throws Exception { assertTrue(contents.contains(String.format("%s - Jenkins", projectName))); } + @Test + void shouldRedirectToSingleSuggestedItem() throws Exception { + FreeStyleProject project = j.createFreeStyleProject("job-config-scroll-test"); + + Page result = j.search("job-config-scroll"); + + assertNotNull(result); + j.assertGoodStatus(result); + + assertEquals( + j.getURL().toString() + project.getUrl(), + result.getUrl().toString() + ); + } + @Issue("JENKINS-24433") @Test void testSearchByProjectNameBehindAFolder() throws Exception { From 142435d1bf00a40a630fbca275934e79780f5374 Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Sun, 2 Aug 2026 05:58:21 -0600 Subject: [PATCH 3/3] Remove differences in spacing It is easier to review the code when the differences that do not change behavior are removed. --- core/src/main/java/hudson/search/Search.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/hudson/search/Search.java b/core/src/main/java/hudson/search/Search.java index 499fc8236666..3ff1aae7161e 100644 --- a/core/src/main/java/hudson/search/Search.java +++ b/core/src/main/java/hudson/search/Search.java @@ -117,19 +117,15 @@ private void doIndexImpl(StaplerRequest2 req, StaplerResponse2 rsp) throws IOExc Ancestor a = l.get(i); if (a.getObject() instanceof SearchableModelObject smo) { if (LOGGER.isLoggable(Level.FINE)) { - LOGGER.fine(String.format( - "smo.displayName=%s, searchName=%s", - smo.getDisplayName(), - smo.getSearchName())); + LOGGER.fine(String.format("smo.displayName=%s, searchName=%s", smo.getDisplayName(), smo.getSearchName())); } SearchIndex index = smo.getSearchIndex(); String query = req.getParameter("q"); - if (query != null) { SuggestedItem target = find(index, query, smo); - if (target != null) { + // found rsp.sendRedirect2(req.getContextPath() + target.getUrl()); return; }