Skip to content

[JENKINS-75344] Fix custom URL name of result action #1970

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/ui-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ jobs:

steps:
- uses: actions/checkout@v4
if: github.event_name == 'push'
- uses: actions/checkout@v4
with:
ref: "${{ github.event.pull_request.merge_commit_sha }}"
if: github.event_name == 'pull_request_target'
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
package io.jenkins.plugins.analysis.core.model;

import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.Collections;

import org.apache.commons.lang3.StringUtils;

import edu.hm.hafner.analysis.Issue;
Expand All @@ -14,6 +9,11 @@
import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.Collections;

import org.kohsuke.stapler.StaplerProxy;
import org.kohsuke.stapler.bind.JavaScriptMethod;
import org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.Whitelisted;
Expand Down Expand Up @@ -164,7 +164,7 @@ public String getDisplayName() {

@Override
public String getUrlName() {
return getLabelProvider().getId();
return StringUtils.defaultIfEmpty(id, getLabelProvider().getId());
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
package io.jenkins.plugins.analysis.core.steps;

import org.apache.commons.lang3.StringUtils;

import edu.hm.hafner.analysis.Severity;
import edu.hm.hafner.util.FilteredLog;
import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
Expand All @@ -9,13 +16,6 @@
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;

import edu.hm.hafner.analysis.Severity;
import edu.hm.hafner.util.FilteredLog;
import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;

import org.kohsuke.stapler.AncestorInPath;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
Expand Down Expand Up @@ -680,12 +680,12 @@ private List<AnalysisResult> record(final Run<?, ?> run, final FilePath workspac
Tool tool = analysisTools.get(0);

var customId = StringUtils.defaultIfBlank(getId(), tool.getActualId());
AnnotatedReport report = new AnnotatedReport(customId);
report.add(scanWithTool(run, workspace, listener, tool), tool.getActualId());

var customName = StringUtils.defaultIfBlank(getName(), tool.getActualName());
var customIcon = StringUtils.defaultIfBlank(getIcon(), tool.getIcon());

AnnotatedReport report = new AnnotatedReport(customId);
report.add(scanWithTool(run, workspace, listener, tool), tool.getActualId());

results.add(publishResult(run, workspace, listener, customName,
report, customName, customIcon, resultHandler));

Expand Down Expand Up @@ -714,9 +714,9 @@ private List<AnalysisResult> record(final Run<?, ?> run, final FilePath workspac
results.add(publishResult(run, workspace, listener, tool.getActualName(),
report, getReportName(tool), tool.getIcon(), resultHandler));
}
}
if (StringUtils.isNotBlank(getId()) || !StringUtils.isNotBlank(getName()) || !StringUtils.isNotBlank(getIcon())) {
logHandler.log("Do not set id, name, or icon for both the tool and the recorder");
if (StringUtils.isNotBlank(getId()) || StringUtils.isNotBlank(getName()) || StringUtils.isNotBlank(getIcon())) {
logHandler.log("Do not set id, name, or icon of recorder when multiple tools are defined");
}
}
}
return results;
Expand Down
5 changes: 5 additions & 0 deletions plugin/src/main/webapp/js/issues-sunburst.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@
color: '#ddd',
borderWidth: 2
},
emphasis: {
itemStyle: {
color: 'inherit'
}
},
label: {
rotate: 'horizontal'
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
package io.jenkins.plugins.analysis.warnings.steps;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import org.eclipse.collections.impl.factory.Lists;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
Expand All @@ -22,6 +11,17 @@
import edu.hm.hafner.analysis.Report;
import edu.hm.hafner.analysis.Severity;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import org.kohsuke.stapler.HttpResponse;
import org.jenkinsci.Symbol;
import org.jenkinsci.plugins.workflow.actions.WarningAction;
Expand Down Expand Up @@ -580,37 +580,64 @@ void shouldFailBuildWhenFailBuildOnErrorsIsSet() {
scheduleBuildAndAssertStatus(job, Result.FAILURE);
}

@Test
void shouldReportResultWithDifferentIdNameAndIconInStep() {
WorkflowJob job = createPipelineWithWorkspaceFilesWithSuffix("emptyFile.txt");
@ParameterizedTest(name = "{index} => Reading JavaDoc warnings from file \"{0}\"")
@ValueSource(strings = {"javadoc.txt", "emptyFile.txt"})
@org.junitpioneer.jupiter.Issue("JENKINS-75344")
void shouldReportResultWithDifferentIdNameAndIconInStep(final String fileName) {
WorkflowJob job = createPipelineWithWorkspaceFilesWithSuffix(fileName);

job.setDefinition(asStage(
"recordIssues id: 'custom-id', name: 'custom-name', icon: 'custom-icon', "
+ "tool: javaDoc(pattern:'**/*issues.txt', reportEncoding:'UTF-8')"));

var action = getResultAction(buildWithResult(job, Result.SUCCESS));
assertThat(action.getUrlName()).isEqualTo("custom-id");
assertThat(action.getId()).isEqualTo("custom-id");
assertThat(action.getDisplayName()).startsWith("custom-name");
assertThat(action.getIconFileName()).isEqualTo("custom-icon");
}

@Test
void shouldReportResultWithDifferentIdNameAndIconInTool() {
WorkflowJob job = createPipelineWithWorkspaceFilesWithSuffix("emptyFile.txt");
@ParameterizedTest(name = "{index} => Reading JavaDoc warnings from file \"{0}\"")
@ValueSource(strings = {"javadoc.txt", "emptyFile.txt"})
@org.junitpioneer.jupiter.Issue("JENKINS-75344")
void shouldReportResultWithDifferentIdNameAndIconInTool(final String fileName) {
WorkflowJob job = createPipelineWithWorkspaceFilesWithSuffix(fileName);

job.setDefinition(asStage(
"recordIssues tool: javaDoc(pattern:'**/*issues.txt', reportEncoding:'UTF-8',"
+ "id: 'custom-id', name: 'custom-name', icon: 'custom-icon')"));

var action = getResultAction(buildWithResult(job, Result.SUCCESS));
assertThat(action.getUrlName()).isEqualTo("custom-id");
assertThat(action.getId()).isEqualTo("custom-id");
assertThat(action.getDisplayName()).startsWith("custom-name");
assertThat(action.getIconFileName()).isEqualTo("custom-icon");
}

@ParameterizedTest(name = "{index} => Reading JavaDoc warnings from file \"{0}\"")
@ValueSource(strings = {"javadoc.txt", "emptyFile.txt"})
@org.junitpioneer.jupiter.Issue("JENKINS-75391")
void shouldShowWarningWhenUsingIdForToolAndRecorder(final String fileName) {
WorkflowJob job = createPipelineWithWorkspaceFilesWithSuffix(fileName);

job.setDefinition(asStage(
"recordIssues id: 'custom-id', name: 'custom-name', icon: 'custom-icon', "
+ "tool: javaDoc(pattern:'**/*issues.txt', reportEncoding:'UTF-8',"
+ "id: 'custom-id', name: 'custom-name', icon: 'custom-icon')"));

var action = getResultAction(buildWithResult(job, Result.SUCCESS));
assertThat(action.getUrlName()).isEqualTo("custom-id");
assertThat(action.getId()).isEqualTo("custom-id");
assertThat(action.getDisplayName()).startsWith("custom-name");
assertThat(action.getIconFileName()).isEqualTo("custom-icon");

assertThat(getConsoleLog(action.getOwner()))
.contains("Do not set id, name, or icon for both the tool and the recorder");
}

/**
* Runs the all Java parsers on three output files: the build should report issues of all tools. The results should
* be aggregated into a new action with the specified ID. Since no name is given the default name is used.
* be aggregated into a new action with the specified ID. Since no name is given, the default name is used.
*/
@Test
void shouldProvideADefaultNameIfNoOneIsGiven() {
Expand Down Expand Up @@ -926,7 +953,7 @@ void shouldLogWarningIfNameIsSetWhenNotAggregating() {
assertThat(ids).containsExactly("groovy-1", "groovy-2");

assertThat(getConsoleLog(build))
.contains("Do not set id, name, or icon for both the tool and the recorder");
.contains("Do not set id, name, or icon of recorder when multiple tools are defined");
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
package io.jenkins.plugins.analysis.warnings;

import java.net.URL;
import java.util.Collection;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
Expand All @@ -15,6 +9,12 @@

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

import java.net.URL;
import java.util.Collection;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.stream.Collectors;

import org.jenkinsci.test.acceptance.po.Build;
import org.jenkinsci.test.acceptance.po.PageObject;

Expand Down Expand Up @@ -217,7 +217,7 @@ public ForensicsTable openForensicsTable() {
* @return the instance of the PageObject to which the link leads to
*/
public <T extends PageObject> T openLinkOnSite(final WebElement element, final Class<T> type) {
String link = element.getAttribute("href");
String link = element.getDomAttribute("href");
T retVal = newInstance(type, injector, url(link));
element.click();
return retVal;
Expand All @@ -229,7 +229,7 @@ public <T extends PageObject> T openLinkOnSite(final WebElement element, final C
* @return the select-element where the user can choose how many rows should be displayed
*/
public Select getLengthSelectElementByActiveTab() {
var element = find(By.xpath(ACTIVE_TAB + "select[contains(@name, 'length')]"));
var element = find(By.xpath(ACTIVE_TAB + "select[@id[starts-with(., 'dt-length')]]"));
return new Select(element);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package io.jenkins.plugins.analysis.warnings;

import org.apache.commons.lang3.StringUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
Expand All @@ -9,10 +13,6 @@
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;

import org.jenkinsci.test.acceptance.po.Build;
import org.jenkinsci.test.acceptance.po.PageObject;

Expand All @@ -34,6 +34,7 @@ public class AnalysisSummary extends PageObject {
private final WebElement infoElement;

private final List<WebElement> results;
private final WebElement summary;

/**
* Creates a new page object representing the analysis summary on the build page of a job.
Expand All @@ -49,7 +50,7 @@ public AnalysisSummary(final Build parent, final String id) {

this.id = id;

WebElement summary = getElement(By.id(id + "-summary"));
summary = getElement(By.id(id + "-summary"));
titleElement = summary.findElement(By.id(id + "-title"));

infoElement = summary.findElement(By.className("fa-image-button"));
Expand All @@ -70,6 +71,15 @@ public String getTitleText() {
return titleElement.getText();
}

/**
* Return the image the summary. Note that not all tools use an image. Symbols are not supported by this method.
*
* @return the image
*/
public String getImage() {
return summary.findElement(by.xpath("../../td/img")).getDomAttribute("src");
}

/**
* Returns the number of new issues.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package io.jenkins.plugins.analysis.warnings;

import java.time.Duration;
import java.util.Collection;
import java.util.List;

import org.junit.Test;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
Expand All @@ -12,6 +8,10 @@

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

import java.time.Duration;
import java.util.Collection;
import java.util.List;

import org.jenkinsci.test.acceptance.junit.WithPlugins;
import org.jenkinsci.test.acceptance.po.Build;
import org.jenkinsci.test.acceptance.po.FreeStyleJob;
Expand All @@ -33,7 +33,7 @@ public class DetailsTabUiTest extends UiTest {
private static final String DETAILS_TAB_RESOURCES = "details_tab_test/";

/**
* When a single warning is being recognized only the issues-tab should be shown.
* When a single warning is being recognized, only the issues-tab should be shown.
*/
@Test
public void shouldPopulateDetailsTabSingleWarning() {
Expand All @@ -56,7 +56,7 @@ public void shouldPopulateDetailsTabSingleWarning() {
}

/**
* When two warnings are being recognized in one file the tabs issues, files and folders should be shown.
* When two warnings are being recognized in one file, then the tabs "issues", "files", and "folders" should be shown.
*/
@Test
public void shouldPopulateDetailsTabMultipleWarnings() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,16 +178,6 @@ private void verifyDetailsTab(final Build build) {
assertThat(resultPage.getPaginationButtons()).hasSize(1);
}

private StringBuilder createReportFilesStep(final WorkflowJob job, final int build) {
String[] fileNames = {"checkstyle-report.xml", "pmd-report.xml", "findbugsXml.xml", "cpd.xml", "Main.java", "pep8Test.txt"};
StringBuilder resourceCopySteps = new StringBuilder();
for (String fileName : fileNames) {
resourceCopySteps.append(job.copyResourceStep(
"/build_status_test/build_0" + build + "/" + fileName).replace("\\", "\\\\"));
}
return resourceCopySteps;
}

@Override
protected IssuesRecorder addAllRecorders(final FreeStyleJob job) {
IssuesRecorder issuesRecorder = super.addAllRecorders(job);
Expand Down
Loading
Loading