Skip to content

Migrate from EE 8 to EE 9 #207

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 1 commit into from
Feb 7, 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
8 changes: 4 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>4.88</version>
<version>5.7</version>
<relativePath />
</parent>

Expand Down Expand Up @@ -50,8 +50,8 @@
<properties>
<changelist>999999-SNAPSHOT</changelist>
<!-- https://www.jenkins.io/doc/developer/plugin-development/choosing-jenkins-baseline/ -->
<jenkins.baseline>2.452</jenkins.baseline>
<jenkins.version>${jenkins.baseline}.4</jenkins.version>
<jenkins.baseline>2.479</jenkins.baseline>
<jenkins.version>${jenkins.baseline}.1</jenkins.version>
<jira-rest-client.version>5.2.7</jira-rest-client.version>
<fugue.version>4.7.2</fugue.version>
<gitHubRepo>jenkinsci/${project.artifactId}-plugin</gitHubRepo>
Expand All @@ -64,7 +64,7 @@
<dependency>
<groupId>io.jenkins.tools.bom</groupId>
<artifactId>bom-${jenkins.baseline}.x</artifactId>
<version>3654.v237e4a_f2d8da_</version>
<version>3850.vb_c5319efa_e29</version>
<type>pom</type>
<scope>import</scope>
</dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,11 @@
* @return
*/
private Job initProject() {
if (Stapler.getCurrentRequest() == null) {
if (Stapler.getCurrentRequest2() == null) {

Check warning on line 132 in src/main/java/org/jenkinsci/plugins/JiraTestResultReporter/JiraTestAction.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 132 is only partially covered, one branch is missing
return null;
}

List<Ancestor> ancestors = Stapler.getCurrentRequest().getAncestors();
List<Ancestor> ancestors = Stapler.getCurrentRequest2().getAncestors();

Check warning on line 136 in src/main/java/org/jenkinsci/plugins/JiraTestResultReporter/JiraTestAction.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 136 is not covered by tests
for (Ancestor ancestor : ancestors) {
if (ancestor.getObject() instanceof AbstractProject) {
return (AbstractProject) ancestor.getObject();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
import org.kohsuke.stapler.DataBoundSetter;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerRequest2;
import org.kohsuke.stapler.bind.JavaScriptMethod;
import org.kohsuke.stapler.interceptor.RequirePOST;

Expand Down Expand Up @@ -157,637 +157,637 @@
* @return
*/
private @CheckForNull AbstractProject getJobName() {
StaplerRequest currentRequest = Stapler.getCurrentRequest();
StaplerRequest2 currentRequest = Stapler.getCurrentRequest2();
return currentRequest != null ? currentRequest.findAncestorObject(AbstractProject.class) : null;
}

private boolean pipelineInvocation = false;
private JobConfigMapping.JobConfigEntry jobConfig;

private boolean isPipelineInvocation() {
return pipelineInvocation;
}

private JobConfigMapping.JobConfigEntry getJobConfig() {
return jobConfig;
}

@CheckForNull
public boolean getAdditionalAttachments() {
return jobConfig.getAdditionalAttachments();
}

@DataBoundSetter
public void setAdditionalAttachments(boolean additionalAttachments) {
JiraUtils.log(String.format("Additional attachments field configured as %s", additionalAttachments));
this.jobConfig = new JobConfigMapping.JobConfigEntryBuilder()
.withProjectKey(this.jobConfig.getProjectKey())
.withIssueType(this.jobConfig.getIssueType())
.withAutoRaiseIssues(this.jobConfig.getAutoRaiseIssue())
.withOverrideResolvedIssues(this.jobConfig.getOverrideResolvedIssues())
.withAutoResolveIssues(this.jobConfig.getAutoResolveIssue())
.withAutoUnlinkIssues(this.jobConfig.getAutoUnlinkIssue())
.withAdditionalAttachments(additionalAttachments)
.withConfigs(this.jobConfig.getConfigs())
.build();
}

/**
* Constructor
* @param configs a list with the configured fields
* @param projectKey
* @param issueType
* @param autoRaiseIssue
* @param autoResolveIssue
* @param autoUnlinkIssue
* @param overrideResolvedIssues
*/
@DataBoundConstructor
public JiraTestDataPublisher(
List<AbstractFields> configs,
String projectKey,
String issueType,
boolean autoRaiseIssue,
boolean autoResolveIssue,
boolean autoUnlinkIssue,
boolean overrideResolvedIssues) {

long defaultIssueType;
try {
defaultIssueType = Long.parseLong(issueType);
} catch (NumberFormatException e) {
defaultIssueType = 1L;
}

this.jobConfig = new JobConfigMapping.JobConfigEntryBuilder()
.withProjectKey(projectKey)
.withIssueType(defaultIssueType)
.withAutoRaiseIssues(autoRaiseIssue)
.withOverrideResolvedIssues(overrideResolvedIssues)
.withAutoResolveIssues(autoResolveIssue)
.withAutoUnlinkIssues(autoUnlinkIssue)
.withConfigs(Util.fixNull(configs))
.build();

if (Stapler.getCurrentRequest() != null) {
if (Stapler.getCurrentRequest2() != null) {
// classic job - e.g. Freestyle project, Matrix project, etc.
AbstractProject project = Stapler.getCurrentRequest().findAncestorObject(AbstractProject.class);
AbstractProject project = Stapler.getCurrentRequest2().findAncestorObject(AbstractProject.class);
TestToIssueMapping.getInstance().register(project);
JobConfigMapping.getInstance().saveConfig(project, getJobConfig());
} else {
// pipeline invocation
pipelineInvocation = true;
}
}

/**
* Method invoked for contributing data to this run, see Jenkins documentation for details about arguments
* @param run
* @param workspace
* @param launcher
* @param listener
* @param testResult
* @return a JiraTestData object
* @throws IOException
* @throws InterruptedException
*/
@Override
public TestResultAction.Data contributeTestData(
Run<?, ?> run, @Nonnull FilePath workspace, Launcher launcher, TaskListener listener, TestResult testResult)
throws IOException, InterruptedException {

EnvVars envVars = run.getEnvironment(listener);
Job job = run.getParent();
Job project;
if (job instanceof MatrixConfiguration) {
project = ((MatrixConfiguration) job).getParent();
} else {
project = job;
}

if (isPipelineInvocation()) {
TestToIssueMapping.getInstance().register(project);
JobConfigMapping.getInstance().saveConfig(project, getJobConfig());
}

boolean hasTestData = false;
if (JobConfigMapping.getInstance().getOverrideResolvedIssues(project)) {
hasTestData |= cleanJobCacheFile(listener, job, getTestCaseResults(testResult));
}

if (JobConfigMapping.getInstance().getAutoRaiseIssue(project)) {
if (JobConfigMapping.getInstance().getAdditionalAttachments(project)) {
JiraUtils.log("Obtaining junit-attachments ...");
GetTestDataMethodObject methodObject =
new GetTestDataMethodObject(run, workspace, launcher, listener, testResult);
this.attachments = methodObject.getAttachments();
JiraUtils.log("junit-attachments successfully retrieved");
}
hasTestData |= raiseIssues(listener, project, job, envVars, getTestCaseResults(testResult));
}

if (JobConfigMapping.getInstance().getAutoResolveIssue(project)) {
hasTestData |= resolveIssues(listener, project, job, envVars, getTestCaseResults(testResult));
}

if (JobConfigMapping.getInstance().getAutoUnlinkIssue(project)) {
hasTestData |= unlinkIssuesForPassedTests(listener, project, job, envVars, getTestCaseResults(testResult));
}

if (hasTestData) {
// Workaround to make feasible to use the publisher in parallel executions
if (!reportedTestDataBefore(envVars)) {
JiraTestDataRegistry.getInstance().putJiraTestData(envVars);
return JiraTestDataRegistry.getInstance().getJiraTestData(envVars);
} else {
return null;
}
} else {
return null;
}
}

private boolean reportedTestDataBefore(EnvVars envVars) {
return JiraTestDataRegistry.getInstance().getJiraTestData(envVars) != null;
}

private boolean unlinkIssuesForPassedTests(
TaskListener listener, Job project, Job job, EnvVars envVars, List<CaseResult> testCaseResults) {
boolean unlinked = false;
for (CaseResult test : testCaseResults) {
if (test.isPassed() && TestToIssueMapping.getInstance().getTestIssueKey(job, test.getId()) != null) {
synchronized (test.getId()) {
String issueKey = TestToIssueMapping.getInstance().getTestIssueKey(job, test.getId());
TestToIssueMapping.getInstance().removeTestToIssueMapping(job, test.getId(), issueKey);
unlinked = true;
}
}
}
return unlinked;
}

private boolean resolveIssues(
TaskListener listener, Job project, Job job, EnvVars envVars, List<CaseResult> testCaseResults) {

boolean solved = false;
try {
for (CaseResult test : testCaseResults) {
if (test.isPassed()
&& test.getPreviousResult() != null
&& test.getPreviousResult().isFailed()) {
synchronized (test.getId()) {
for (String issueKey : JiraUtils.searchIssueKeys(job, envVars, test)) {
IssueRestClient issueRestClient =
getDescriptor().getRestClient().getIssueClient();
Issue issue = issueRestClient.getIssue(issueKey).claim();
boolean transitionExecuted = false;
for (Transition transition :
issueRestClient.getTransitions(issue).claim()) {
if (transition.getName().toLowerCase().contains("resolve")) {
issueRestClient.transition(issue, new TransitionInput(transition.getId()));
transitionExecuted = true;
solved = true;
break;
}
}

if (!transitionExecuted) {
listener.getLogger().println("Could not find transition to resolve issue " + issueKey);
}
}
}
}
}
} catch (RestClientException | ResponseTransformationException | UnexpectedResponseException e) {
listener.error("Could not connect properly to Jira server. Please review config details\n");
e.printStackTrace(listener.getLogger());
solved = false;
}
return solved;
}

private boolean cleanJobCacheFile(TaskListener listener, Job job, List<CaseResult> testCaseResults) {
boolean cleaUp = false;
try {
cleaUp = JiraUtils.cleanJobCacheFile(testCaseResults, job);
} catch (RestClientException e) {
listener.error("Could not do the clean up of the JiraIssueJobConfigs.json\n");
e.printStackTrace(listener.getLogger());
throw e;
}
return cleaUp;
}

private boolean raiseIssues(
TaskListener listener, Job project, Job job, EnvVars envVars, List<CaseResult> testCaseResults) {
boolean raised = false;
try {
for (CaseResult test : testCaseResults) {
if (test.isFailed()) {
try {
JiraUtils.createIssue(
job,
project,
envVars,
test,
JiraIssueTrigger.JOB,
getAttachments(test.getClassName(), test.getName()));
raised = true;
} catch (RestClientException e) {
listener.error("Could not create issue for test " + test.getFullDisplayName() + "\n");
e.printStackTrace(listener.getLogger());
throw e;
}
}
}
} catch (RestClientException | ResponseTransformationException | UnexpectedResponseException e) {
listener.error("Could not connect properly to Jira server. Please review config details\n");
e.printStackTrace(listener.getLogger());
raised = false;
}
return raised;
}

private List<CaseResult> getTestCaseResults(TestResult testResult) {
List<CaseResult> results = new ArrayList<CaseResult>();

Collection<PackageResult> packageResults = testResult.getChildren();
for (PackageResult pkgResult : packageResults) {
Collection<ClassResult> classResults = pkgResult.getChildren();
for (ClassResult cr : classResults) {
results.addAll(cr.getChildren());
}
}

return results;
}

/**
* Getter for the Descriptor
* @return singleton instance of the Descriptor
*/
@Override
public JiraTestDataPublisherDescriptor getDescriptor() {
return (JiraTestDataPublisherDescriptor) Jenkins.get().getDescriptorOrDie(getClass());
}

/**
* Getter for the jira url, called from config.jelly to determine if the global configurations were done
* @return
*/
public String getJiraUrl() {
return getDescriptor().getJiraUrl();
}

@Symbol("jiraTestResultReporter")
@Extension
public static class JiraTestDataPublisherDescriptor extends Descriptor<TestDataPublisher> {
/**
* Constructor
* loads the serialized descriptor from the previous run
*/
public JiraTestDataPublisherDescriptor() {
load();
}

public static final String SUMMARY_FIELD_NAME = "summary";
public static final String DESCRIPTION_FIELD_NAME = "description";

private static final String DEFAULT_SUMMARY = "${TEST_FULL_NAME} : ${TEST_ERROR_DETAILS}";
private static final String DEFAULT_DESCRIPTION = "${BUILD_URL}${CRLF}${TEST_STACK_TRACE}";
public static final List<AbstractFields> templates;
public static final StringFields DEFAULT_SUMMARY_FIELD;
public static final StringFields DEFAULT_DESCRIPTION_FIELD;

static {
templates = new ArrayList<AbstractFields>();
DEFAULT_SUMMARY_FIELD = new StringFields(SUMMARY_FIELD_NAME, "${DEFAULT_SUMMARY}");
DEFAULT_DESCRIPTION_FIELD = new StringFields(DESCRIPTION_FIELD_NAME, "${DEFAULT_DESCRIPTION}");
templates.add(DEFAULT_SUMMARY_FIELD);
templates.add(DEFAULT_DESCRIPTION_FIELD);
}

private transient HashMap<String, FullStatus> statuses;
private transient JiraRestClient restClient;
private transient JiraRestClientExtension restClientExtension;
private transient MetadataCache metadataCache = new MetadataCache();
private URI jiraUri = null;
private String username = null;
private Secret password = null;
private boolean useBearerAuth = false;
private String defaultSummary;
private String defaultDescription;

public URI getJiraUri() {
return jiraUri;
}

public String getUsername() {
return username;
}

public Secret getPassword() {
return password;
}

public boolean getUseBearerAuth() {
return useBearerAuth;
}

public String getJiraUrl() {
return jiraUri != null ? jiraUri.toString() : null;
}

public JiraRestClient getRestClient() {
return restClient;
}

/**
* Getter for the summary template
* @return
*/
public String getDefaultSummary() {
return defaultSummary != null && !defaultSummary.equals("") ? defaultSummary : DEFAULT_SUMMARY;
}

/**
* Getter for the description template
* @return
*/
public String getDefaultDescription() {
return defaultDescription != null && !defaultDescription.equals("")
? defaultDescription
: DEFAULT_DESCRIPTION;
}

/**
* Getter for the statuses map, contains information about status category of each status
* @return
*/
public HashMap<String, FullStatus> getStatusesMap() {
return statuses;
}

/**
* Getter for the cache entry
* @param projectKey
* @param issueType
* @return a metadata cache entry
*/
public MetadataCache.CacheEntry getCacheEntry(String projectKey, String issueType) {
return metadataCache.getCacheEntry(projectKey, issueType);
}

/**
* Method for resolving transient objects after deserialization. Called by the JVM.
* See Java documentation for more details.
* @return this object
*/
public Object readResolve() {
if (jiraUri != null && username != null && password != null) {
AsynchronousJiraRestClientFactory factory = new AsynchronousJiraRestClientFactory();
if (useBearerAuth) {
BearerAuthenticationHandler handler = new BearerAuthenticationHandler(password.getPlainText());
restClient = factory.create(jiraUri, handler);

restClientExtension = new JiraRestClientExtension(
jiraUri,
new AsynchronousHttpClientFactory()
.createClient(jiraUri, new BearerAuthenticationHandler(password.getPlainText())));
} else {
restClient = factory.createWithBasicHttpAuthentication(jiraUri, username, password.getPlainText());
restClientExtension = new JiraRestClientExtension(
jiraUri,
new AsynchronousHttpClientFactory()
.createClient(
jiraUri,
new BasicHttpAuthenticationHandler(username, password.getPlainText())));
}
tryCreatingStatusToCategoryMap();
}
return this;
}

/**
* Getter for the display name
* @return
*/
@Override
public String getDisplayName() {
return "JiraTestResultReporter";
}

/**
* Method for obtaining the global configurations (global.jelly), when save/apply is clicked
* @param req current request
* @param json form in json format
* @return
* @throws FormException
*/
@Override
public boolean configure(StaplerRequest req, JSONObject json) throws FormException {
public boolean configure(StaplerRequest2 req, JSONObject json) throws FormException {

try {
jiraUri = new URI(json.getString("jiraUrl"));
} catch (URISyntaxException e) {
JiraUtils.logError("Invalid server URI", e);
}

username = json.getString("username");
password = Secret.fromString(json.getString("password"));
useBearerAuth = json.getBoolean("useBearerAuth");
defaultSummary = json.getString("summary");
defaultDescription = json.getString("description");

if (json.getString("jiraUrl").equals("")
|| json.getString("username").equals("")
|| json.getString("password").equals("")) {
useBearerAuth = false;
restClient = null;
restClientExtension = null;
save();
return true;
}

AsynchronousJiraRestClientFactory factory = new AsynchronousJiraRestClientFactory();
if (useBearerAuth) {
BearerAuthenticationHandler handler = new BearerAuthenticationHandler(password.getPlainText());
restClient = factory.create(jiraUri, handler);

restClientExtension = new JiraRestClientExtension(
jiraUri,
new AsynchronousHttpClientFactory()
.createClient(jiraUri, new BearerAuthenticationHandler(password.getPlainText())));
} else {
restClient = factory.createWithBasicHttpAuthentication(jiraUri, username, password.getPlainText());
restClientExtension = new JiraRestClientExtension(
jiraUri,
new AsynchronousHttpClientFactory()
.createClient(
jiraUri,
new BasicHttpAuthenticationHandler(username, password.getPlainText())));
}
tryCreatingStatusToCategoryMap();
save();
return super.configure(req, json);
}

/**
* method for creating the status category map, if the Jira server knows about categories
*/
private void tryCreatingStatusToCategoryMap() {
try {
Iterable<FullStatus> statuses =
restClientExtension.getStatuses().claim();
HashMap<String, FullStatus> statusHashMap = new HashMap<String, FullStatus>();
for (FullStatus status : statuses) {
statusHashMap.put(status.getName(), status);
}
this.statuses = statusHashMap;
} catch (RestClientException e) {
// status categories not available, either the server doesn't have the dark feature enabled, or
// this version of Jira cannot be queried for this info
JiraUtils.logWarning("Jira server does not support status categories", e);
}
}

/**
* Method for creating a new, configured JiraTestDataPublisher. Override for removing cache entries when
* configuration is finished. Called when save/apply is clicked in the job config page
* @param req current request
* @param json form in json format
* @return
* @throws FormException
*/
@Override
public TestDataPublisher newInstance(StaplerRequest req, JSONObject json) throws FormException {
public TestDataPublisher newInstance(StaplerRequest2 req, JSONObject json) throws FormException {
String projectKey = json.getString("projectKey");
String issueType = json.getString("issueType");
metadataCache.removeCacheEntry(projectKey, issueType);
return super.newInstance(req, json);
}

/**
* Validation for the global configuration, called when Validate Settings is clicked (global.jelly)
* @param jiraUrl
* @param username
* @param password
* @param useBearerAuth
* @return
*/
@RequirePOST
public FormValidation doValidateGlobal(
@QueryParameter String jiraUrl,
@QueryParameter String username,
@QueryParameter String password,
@QueryParameter boolean useBearerAuth) {

Jenkins.get().checkPermission(Jenkins.ADMINISTER);
String serverName;
try {
new URL(jiraUrl);
URI uri = new URI(jiraUrl);
if (uri == null) {
return FormValidation.error("Invalid URL");
}
Secret pass = Secret.fromString(password);
// JIRA does not offer ways to validate username and password, so we try to query some server
// metadata, to see if the configured user is authorized on this server
AsynchronousJiraRestClientFactory factory = new AsynchronousJiraRestClientFactory();
JiraRestClient restClient;
if (useBearerAuth) {
BearerAuthenticationHandler handler = new BearerAuthenticationHandler(pass.getPlainText());
restClient = factory.create(uri, handler);
} else {
restClient = factory.createWithBasicHttpAuthentication(uri, username, pass.getPlainText());
}

MetadataRestClient client = restClient.getMetadataClient();
Promise<ServerInfo> serverInfoPromise = client.getServerInfo();
ServerInfo serverInfo = serverInfoPromise.claim();
serverName = serverInfo.getServerTitle();
} catch (MalformedURLException e) {
return FormValidation.error("Invalid URL");
} catch (URISyntaxException e) {
return FormValidation.error("Invalid URL");
} catch (RestClientException e) {
JiraUtils.logError("ERROR: Unknown error", e);
return FormValidation.error("ERROR " + e.getStatusCode().get());
} catch (Exception e) {
JiraUtils.logError("ERROR: Unknown error", e);
return FormValidation.error("ERROR Unknown: " + e.getMessage());
}

return FormValidation.ok(serverName);
}

/**
* Validation for the project key
* @param projectKey
* @return
*/
public FormValidation doValidateProjectKey(@QueryParameter String projectKey) {
if (projectKey == null || projectKey.length() == 0) {
return FormValidation.error("Invalid Project Key");
}

if (getRestClient() == null) {
return FormValidation.error("No jira site configured");
}

ProjectRestClient projectClient = getRestClient().getProjectClient();
Project project;
try {
project = projectClient.getProject(projectKey).claim();
if (project == null) {
return FormValidation.error("Invalid Project Key");
}
} catch (RestClientException e) {
JiraUtils.logWarning("Invalid Project Key", e);
return FormValidation.error("Invalid Project Key");
}
return FormValidation.ok(project.getName());
}

/**
* Method for filling the issue type select control in the job configuration page
* @param projectKey
* @return
*/
public ListBoxModel doFillIssueTypeItems(@QueryParameter String projectKey) {
ListBoxModel m = new ListBoxModel();
if (projectKey.equals("")) {
return m;
}

ProjectRestClient projectRestClient = getRestClient().getProjectClient();
try {
Promise<Project> projectPromise = projectRestClient.getProject(projectKey);
Project project = projectPromise.claim();
OptionalIterable<IssueType> issueTypes = project.getIssueTypes();

for (IssueType issueType : issueTypes) {
m.add(new ListBoxModel.Option(
issueType.getName(), issueType.getId().toString(), issueType.getName() == "Bug"));
}
} catch (Exception e) {
JiraUtils.logError("ERROR: Unknown error", e);
return m;
}
return m;
}

/**
* Ugly hack (part 2, see config.jelly for part1) for validating the configured values for fields.
* This method will try to create an issue using the configured fields and delete it afterwards.
* @param jsonForm
* @return
* @throws FormException
*/
@JavaScriptMethod
public FormValidation validateFieldConfigs(String jsonForm) throws FormException {
// extracting the configurations for associated with this plugin (we receive the entire form)
StaplerRequest req = Stapler.getCurrentRequest();
StaplerRequest2 req = Stapler.getCurrentRequest2();

Check warning on line 790 in src/main/java/org/jenkinsci/plugins/JiraTestResultReporter/JiraTestDataPublisher.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 160-790 are not covered by tests
JSONObject jsonObject = JSONObject.fromObject(jsonForm);
JSONObject publishers = jsonObject.getJSONObject("publisher");
JSONObject jiraPublisherJSON = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
import hudson.model.Api;
import hudson.model.Item;
import hudson.model.Job;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import jenkins.model.Jenkins;
import org.jenkinsci.plugins.JiraTestResultReporter.TestToIssueMapping;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.StaplerRequest2;
import org.kohsuke.stapler.StaplerResponse2;

/**
* Created by tuicu on 12/08/16.
Expand All @@ -31,7 +31,7 @@ public TestToIssueMappingApi() {
}

@Override
public void doJson(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
public void doJson(StaplerRequest2 req, StaplerResponse2 rsp) throws IOException, ServletException {
String jobName = req.getParameter("job");
JsonElement result;

Expand Down