Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
224bf6c
Update for adding jira site config parameter maxIssuesFromJqlSearch
Hardikrathod01 May 29, 2025
d3b34b9
Update for replacing hard coded value in DescriptorImplTest with Defa…
Hardikrathod01 May 29, 2025
56ba76d
Fix testcase replaceWithFixVersionByRegex
Hardikrathod01 May 29, 2025
4066698
Update for fixing format violations
Hardikrathod01 May 29, 2025
df344f1
- Update for adding maximum allowed value check
May 30, 2025
f330693
Use validation message from messages
May 30, 2025
56e650e
Remove check method for form field validation
May 30, 2025
9c15e78
Apply spotless fix
May 30, 2025
72685e3
Fix test case
May 30, 2025
ea54995
Fix test case and a validation message grammar
May 30, 2025
a83a835
Fix test case because old config will not have maxIssuesFromJqlSearch
May 30, 2025
0ed4a86
Remove parameter maxIssuesFromJqlSearch from doValidate and related p…
May 30, 2025
b97bac5
Implement maximum param value check in setter method
May 30, 2025
6ebfa72
Use variable for comparison of max allowed value
May 30, 2025
e9bd57b
Use ternary operator in setter method
May 30, 2025
3a64256
Remove parameter from old jira configuration
May 30, 2025
358f535
Merge remote-tracking branch 'upstream/master' into issue_662_configu…
May 30, 2025
61cef1e
Resolve conflicts
May 30, 2025
9a07f94
Fix jira session tests
May 30, 2025
bade3ad
Fix test cases because of stubbing problem
May 30, 2025
85750d8
Fix indentation
May 30, 2025
7df98e1
Use Integer instead of int
May 30, 2025
d6823c4
Fix default value not being used when migrating from old config
May 30, 2025
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
19 changes: 10 additions & 9 deletions src/main/java/hudson/plugins/jira/JiraSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@
public class JiraSession {
private static final Logger LOGGER = Logger.getLogger(JiraSession.class.getName());

public static final Integer MAX_ISSUES = 100;

public final JiraRestService service;

/**
Expand All @@ -50,9 +48,12 @@

private final String jiraSiteName;

/* package */ JiraSession(JiraSite site, JiraRestService jiraRestService) {
private final int maxIssuesFromJqlSearch;

/* package */ JiraSession(JiraSite site, JiraRestService jiraRestService, int maxIssuesFromJqlSearch) {
this.service = jiraRestService;
this.jiraSiteName = site.getName();
this.maxIssuesFromJqlSearch = maxIssuesFromJqlSearch;
}

/**
Expand Down Expand Up @@ -131,102 +132,102 @@
* @return issues matching the JQL query
*/
public List<Issue> getIssuesFromJqlSearch(final String jqlSearch) throws TimeoutException {
return service.getIssuesFromJqlSearch(jqlSearch, MAX_ISSUES);
return service.getIssuesFromJqlSearch(jqlSearch, maxIssuesFromJqlSearch);
}

/**
* Get all versions from the given project
*
* @param projectKey The key for the project
* @return An array of versions
*/
public List<ExtendedVersion> getVersions(String projectKey) {
LOGGER.fine("Fetching versions from project: " + projectKey);
return service.getVersions(projectKey);
}

/**
* Get a version by its name
*
* @param projectKey The key for the project
* @param name The version name
* @return A RemoteVersion, or null if not found
*/
public ExtendedVersion getVersionByName(String projectKey, String name) {
LOGGER.fine("Fetching versions from project: " + projectKey);
List<ExtendedVersion> versions = getVersions(projectKey);
if (versions == null) {
return null;
}
for (ExtendedVersion version : versions) {
if (version.getName().equals(name)) {
return version;
}
}
return null;
}

public List<Issue> getIssuesWithFixVersion(String projectKey, String version) throws TimeoutException {
return getIssuesWithFixVersion(projectKey, version, "");
}

public List<Issue> getIssuesWithFixVersion(String projectKey, String version, String filter)
throws TimeoutException {
LOGGER.fine("Fetching versions from project: " + projectKey + " with fixVersion:" + version);
if (isNotEmpty(filter)) {
return service.getIssuesFromJqlSearch(
String.format("project = \"%s\" and fixVersion = \"%s\" and " + filter, projectKey, version),
MAX_ISSUES);
maxIssuesFromJqlSearch);
}
return service.getIssuesFromJqlSearch(
String.format("project = \"%s\" and fixVersion = \"%s\"", projectKey, version), MAX_ISSUES);
String.format("project = \"%s\" and fixVersion = \"%s\"", projectKey, version), maxIssuesFromJqlSearch);
}

/**
* Get all issue types
*
* @return An array of issue types
*/
public List<IssueType> getIssueTypes() {
LOGGER.fine("Fetching issue types");
return service.getIssueTypes();
}

/**
* Get all priorities
*
* @return An array of priorities
*/
public List<Priority> getPriorities() {
LOGGER.fine("Fetching priorities");
return service.getPriorities();
}

/**
* Release given version in given project
*/
public void releaseVersion(String projectKey, ExtendedVersion version) {
LOGGER.fine("Releasing version: " + version.getName());
service.releaseVersion(projectKey, version);
}

/**
* Replaces the fix version list of all issues matching the JQL Query with the version specified.
*
* @param projectKey The Jira Project key
* @param version The replacement version
* @param query The JQL Query
*/
public void migrateIssuesToFixVersion(String projectKey, String version, String query) throws TimeoutException {

Version newVersion = getVersionByName(projectKey, version);
if (newVersion == null) {
LOGGER.warning("Version " + version + " was not found");
return;
}

LOGGER.fine("Fetching versions with JQL:" + query);
List<Issue> issues = service.getIssuesFromJqlSearch(query, MAX_ISSUES);
List<Issue> issues = service.getIssuesFromJqlSearch(query, maxIssuesFromJqlSearch);

Check warning on line 230 in src/main/java/hudson/plugins/jira/JiraSession.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 135-230 are not covered by tests
if (issues == null || issues.isEmpty()) {
return;
}
Expand Down Expand Up @@ -256,7 +257,7 @@
}

LOGGER.fine("Fetching versions with JQL:" + query);
List<Issue> issues = service.getIssuesFromJqlSearch(query, MAX_ISSUES);
List<Issue> issues = service.getIssuesFromJqlSearch(query, maxIssuesFromJqlSearch);
if (issues == null) {
return;
}
Expand Down Expand Up @@ -309,7 +310,7 @@
}

LOGGER.fine("Fetching issues with JQL:" + query);
List<Issue> issues = service.getIssuesFromJqlSearch(query, MAX_ISSUES);
List<Issue> issues = service.getIssuesFromJqlSearch(query, maxIssuesFromJqlSearch);

Check warning on line 313 in src/main/java/hudson/plugins/jira/JiraSession.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 313 is not covered by tests
if (issues == null || issues.isEmpty()) {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/hudson/plugins/jira/JiraSessionFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,6 @@ public static JiraSession create(JiraSite jiraSite, URI uri, StandardUsernamePas
jiraSite.getReadTimeout());
}

return new JiraSession(jiraSite, jiraRestService);
return new JiraSession(jiraSite, jiraRestService, jiraSite.getMaxIssuesFromJqlSearch());
}
}
50 changes: 40 additions & 10 deletions src/main/java/hudson/plugins/jira/JiraSite.java
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ public class JiraSite extends AbstractDescribableImpl<JiraSite> {

public static final int DEFAULT_THREAD_EXECUTOR_NUMBER = 10;

public static final int DEFAULT_MAX_ISSUES = 100;

/**
* URL of Jira for Jenkins access, like {@code http://jira.codehaus.org/}.
* Mandatory. Normalized to end with '/'
Expand Down Expand Up @@ -242,6 +244,11 @@ public class JiraSite extends AbstractDescribableImpl<JiraSite> {
*/
private boolean appendChangeTimestamp;

/**
* To allow configurable value of max issues from jql search via jira site global configuration.
*/
private int maxIssuesFromJqlSearch = DEFAULT_MAX_ISSUES;

private int ioThreadCount = Integer.getInteger(JiraSite.class.getName() + ".httpclient.options.ioThreadCount", 2);

/**
Expand Down Expand Up @@ -275,7 +282,8 @@ public JiraSite(
boolean updateJiraIssueForAllStatus,
@CheckForNull String groupVisibility,
@CheckForNull String roleVisibility,
boolean useHTTPAuth) {
boolean useHTTPAuth,
int maxIssuesFromJqlSearch) {
this(
url,
alternativeUrl,
Expand All @@ -289,7 +297,8 @@ public JiraSite(
useHTTPAuth,
DEFAULT_TIMEOUT,
DEFAULT_READ_TIMEOUT,
DEFAULT_THREAD_EXECUTOR_NUMBER);
DEFAULT_THREAD_EXECUTOR_NUMBER,
DEFAULT_MAX_ISSUES);
}

// Deprecate the previous constructor but leave it in place for Java-level compatibility.
Expand Down Expand Up @@ -347,7 +356,8 @@ public JiraSite(
useHTTPAuth,
DEFAULT_TIMEOUT,
DEFAULT_READ_TIMEOUT,
DEFAULT_THREAD_EXECUTOR_NUMBER);
DEFAULT_THREAD_EXECUTOR_NUMBER,
DEFAULT_MAX_ISSUES);
if (credentials != null) {
// we verify the credential really exists otherwise we migrate it
StandardUsernamePasswordCredentials standardUsernamePasswordCredentials =
Expand Down Expand Up @@ -375,7 +385,8 @@ public JiraSite(
boolean useHTTPAuth,
int timeout,
int readTimeout,
int threadExecutorNumber) {
int threadExecutorNumber,
int maxIssuesFromJqlSearch) {
if (url != null) {
url = toURL(url.toExternalForm());
}
Expand All @@ -398,6 +409,7 @@ public JiraSite(
setRoleVisibility(roleVisibility);
this.useHTTPAuth = useHTTPAuth;
this.jiraSession = null;
this.maxIssuesFromJqlSearch = maxIssuesFromJqlSearch;
}

@DataBoundConstructor
Expand All @@ -424,7 +436,8 @@ public JiraSite(
boolean useHTTPAuth,
int timeout,
int readTimeout,
int threadExecutorNumber) {
int threadExecutorNumber,
int maxIssuesFromJqlSearch) {
this(
url,
alternativeUrl,
Expand All @@ -438,7 +451,8 @@ public JiraSite(
useHTTPAuth,
timeout,
readTimeout,
threadExecutorNumber);
threadExecutorNumber,
maxIssuesFromJqlSearch);
}

// Deprecate the previous constructor but leave it in place for Java-level compatibility.
Expand All @@ -457,7 +471,8 @@ public JiraSite(
int timeout,
int readTimeout,
int threadExecutorNumber,
boolean useBearerAuth) {
boolean useBearerAuth,
int maxIssuesFromJqlSearch) {
this(
url,
alternativeUrl,
Expand All @@ -471,7 +486,8 @@ public JiraSite(
useHTTPAuth,
timeout,
readTimeout,
threadExecutorNumber);
threadExecutorNumber,
maxIssuesFromJqlSearch);
this.useBearerAuth = useBearerAuth;
}

Expand Down Expand Up @@ -646,6 +662,15 @@ public void setUpdateJiraIssueForAllStatus(boolean updateJiraIssueForAllStatus)
this.updateJiraIssueForAllStatus = updateJiraIssueForAllStatus;
}

@DataBoundSetter
public void setMaxIssuesFromJqlSearch(int maxIssuesFromJqlSearch) {
this.maxIssuesFromJqlSearch = maxIssuesFromJqlSearch;
}

public int getMaxIssuesFromJqlSearch() {
return maxIssuesFromJqlSearch;
}

@SuppressWarnings("unused")
protected Object readResolve() throws FormException {
JiraSite jiraSite;
Expand Down Expand Up @@ -677,7 +702,8 @@ protected Object readResolve() throws FormException {
useHTTPAuth,
timeout,
readTimeout,
threadExecutorNumber);
threadExecutorNumber,
maxIssuesFromJqlSearch);
}
jiraSite.setAppendChangeTimestamp(appendChangeTimestamp);
jiraSite.setDisableChangelogAnnotations(disableChangelogAnnotations);
Expand Down Expand Up @@ -1350,6 +1376,7 @@ public FormValidation doValidate(
@QueryParameter int readTimeout,
@QueryParameter int threadExecutorNumber,
@QueryParameter boolean useBearerAuth,
@QueryParameter int maxIssuesFromJqlSearch,
@AncestorInPath Item item) {

if (item == null) {
Expand Down Expand Up @@ -1403,6 +1430,7 @@ public FormValidation doValidate(
site.setReadTimeout(readTimeout);
site.setThreadExecutorNumber(threadExecutorNumber);
site.setUseBearerAuth(useBearerAuth);
site.setMaxIssuesFromJqlSearch(maxIssuesFromJqlSearch);
try {
JiraSession session = site.getSession(item, true);
if (session == null) {
Expand Down Expand Up @@ -1451,6 +1479,7 @@ static class Builder {
private String groupVisibility;
private String roleVisibility;
private boolean useHTTPAuth;
private int maxIssuesFromJqlSearch;

public Builder withMainURL(URL mainURL) {
this.mainURL = mainURL;
Expand Down Expand Up @@ -1513,7 +1542,8 @@ public JiraSite build() {
updateJiraIssueForAllStatus,
groupVisibility,
roleVisibility,
useHTTPAuth);
useHTTPAuth,
maxIssuesFromJqlSearch);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@
<f:entry title="${%Jira comments timestamp format}" field="dateTimePattern">
<f:textbox />
</f:entry>
<f:entry title="${%Max Issues From Jql Search}" field="maxIssuesFromJqlSearch">
<f:number default="100" />
</f:entry>
<f:entry>
<f:validateButton title="${%Validate Settings}"
method="validate" with="url,credentialsId,groupVisibility,roleVisibility,useHTTPAuth,alternativeUrl,timeout,readTimeout,threadExecutorNumber,useBearerAuth" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div>
Specifies the maximum number of issues to load from the JQL search query. If this number exceeds the limit configured in Jira, only the maximum allowed by Jira will be retrieved.
</div>
10 changes: 5 additions & 5 deletions src/test/java/JiraTester.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import com.atlassian.jira.rest.client.api.domain.Transition;
import com.atlassian.jira.rest.client.api.domain.User;
import hudson.plugins.jira.JiraRestService;
import hudson.plugins.jira.JiraSession;
import hudson.plugins.jira.JiraSite;
import hudson.plugins.jira.JiraSite.ExtendedAsynchronousJiraRestClientFactory;
import hudson.plugins.jira.extension.ExtendedJiraRestClient;
Expand Down Expand Up @@ -57,7 +56,8 @@ public static void main(String[] args) throws Exception {
// restService.createIssue("TESTPROJECT", "This is a test issue created using Jira jenkins plugin. Please
// ignore it.", "TESTUSER", components1, "test issue from Jira jenkins plugin");

final List<Issue> searchResults = restService.getIssuesFromJqlSearch("project = \"TESTPROJECT\"", 3);
final List<Issue> searchResults =
restService.getIssuesFromJqlSearch("project = \"TESTPROJECT\"", JiraSite.DEFAULT_MAX_ISSUES);
for (Issue searchResult : searchResults) {
System.out.println("JQL search result: " + searchResult);
}
Expand Down Expand Up @@ -102,8 +102,8 @@ public static void main(String[] args) throws Exception {

private static void callUniq(final JiraRestService restService) throws Exception {
long start = System.currentTimeMillis();
List<Issue> issues =
restService.getIssuesFromJqlSearch("key in ('JENKINS-53320','JENKINS-51057')", JiraSession.MAX_ISSUES);
List<Issue> issues = restService.getIssuesFromJqlSearch(
"key in ('JENKINS-53320','JENKINS-51057')", JiraSite.DEFAULT_MAX_ISSUES);
long end = System.currentTimeMillis();
System.out.println("time uniq " + (end - start));
}
Expand All @@ -112,7 +112,7 @@ private static void callDuplicate(final JiraRestService restService) throws Exce
long start = System.currentTimeMillis();
List<Issue> issues = restService.getIssuesFromJqlSearch(
"key in ('JENKINS-53320','JENKINS-53320','JENKINS-53320','JENKINS-53320','JENKINS-53320','JENKINS-51057','JENKINS-51057','JENKINS-51057','JENKINS-51057','JENKINS-51057')",
JiraSession.MAX_ISSUES);
JiraSite.DEFAULT_MAX_ISSUES);
long end = System.currentTimeMillis();
System.out.println("time duplicate " + (end - start));
}
Expand Down
10 changes: 5 additions & 5 deletions src/test/java/JiraTesterBearerAuth.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import com.atlassian.jira.rest.client.api.domain.Transition;
import com.atlassian.jira.rest.client.api.domain.User;
import hudson.plugins.jira.JiraRestService;
import hudson.plugins.jira.JiraSession;
import hudson.plugins.jira.JiraSite;
import hudson.plugins.jira.JiraSite.ExtendedAsynchronousJiraRestClientFactory;
import hudson.plugins.jira.auth.BearerHttpAuthenticationHandler;
Expand Down Expand Up @@ -59,7 +58,8 @@ public static void main(String[] args) throws Exception {
// restService.createIssue("TESTPROJECT", "This is a test issue created using Jira jenkins plugin. Please
// ignore it.", "TESTUSER", components1, "test issue from Jira jenkins plugin");

final List<Issue> searchResults = restService.getIssuesFromJqlSearch("project = \"TESTPROJECT\"", 3);
final List<Issue> searchResults =
restService.getIssuesFromJqlSearch("project = \"TESTPROJECT\"", JiraSite.DEFAULT_MAX_ISSUES);
for (Issue searchResult : searchResults) {
System.out.println("JQL search result: " + searchResult);
}
Expand Down Expand Up @@ -104,8 +104,8 @@ public static void main(String[] args) throws Exception {

private static void callUniq(final JiraRestService restService) throws Exception {
long start = System.currentTimeMillis();
List<Issue> issues =
restService.getIssuesFromJqlSearch("key in ('JENKINS-53320','JENKINS-51057')", JiraSession.MAX_ISSUES);
List<Issue> issues = restService.getIssuesFromJqlSearch(
"key in ('JENKINS-53320','JENKINS-51057')", JiraSite.DEFAULT_MAX_ISSUES);
long end = System.currentTimeMillis();
System.out.println("time uniq " + (end - start));
}
Expand All @@ -114,7 +114,7 @@ private static void callDuplicate(final JiraRestService restService) throws Exce
long start = System.currentTimeMillis();
List<Issue> issues = restService.getIssuesFromJqlSearch(
"key in ('JENKINS-53320','JENKINS-53320','JENKINS-53320','JENKINS-53320','JENKINS-53320','JENKINS-51057','JENKINS-51057','JENKINS-51057','JENKINS-51057','JENKINS-51057')",
JiraSession.MAX_ISSUES);
JiraSite.DEFAULT_MAX_ISSUES);
long end = System.currentTimeMillis();
System.out.println("time duplicate " + (end - start));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public class ChangingWorkflowTest {

@BeforeEach
void setupSpy() {
spySession = spy(new JiraSession(site, restService));
spySession = spy(new JiraSession(site, restService, site.getMaxIssuesFromJqlSearch()));
}

@Test
Expand Down
5 changes: 5 additions & 0 deletions src/test/java/hudson/plugins/jira/DescriptorImplTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ void validateFormConnectionErrors(JenkinsRule r) throws Exception {
JiraSite.DEFAULT_READ_TIMEOUT,
JiraSite.DEFAULT_THREAD_EXECUTOR_NUMBER,
false,
JiraSite.DEFAULT_MAX_ISSUES,
project);

assertEquals(FormValidation.Kind.ERROR, validation.kind);
Expand All @@ -154,6 +155,7 @@ void validateFormConnectionErrors(JenkinsRule r) throws Exception {
JiraSite.DEFAULT_READ_TIMEOUT,
JiraSite.DEFAULT_THREAD_EXECUTOR_NUMBER,
false,
JiraSite.DEFAULT_MAX_ISSUES,
project);
assertEquals(Messages.JiraSite_timeoutMinimunValue("1"), validation.getLocalizedMessage());
assertEquals(FormValidation.Kind.ERROR, validation.kind);
Expand All @@ -170,6 +172,7 @@ void validateFormConnectionErrors(JenkinsRule r) throws Exception {
-1,
JiraSite.DEFAULT_THREAD_EXECUTOR_NUMBER,
false,
JiraSite.DEFAULT_MAX_ISSUES,
project);

assertEquals(Messages.JiraSite_readTimeoutMinimunValue("1"), validation.getMessage());
Expand All @@ -187,6 +190,7 @@ void validateFormConnectionErrors(JenkinsRule r) throws Exception {
JiraSite.DEFAULT_READ_TIMEOUT,
-1,
false,
JiraSite.DEFAULT_MAX_ISSUES,
project);
assertEquals(Messages.JiraSite_threadExecutorMinimunSize("1"), validation.getMessage());
assertEquals(FormValidation.Kind.ERROR, validation.kind);
Expand All @@ -213,6 +217,7 @@ void validateFormConnectionOK(JenkinsRule r) throws Exception {
JiraSite.DEFAULT_READ_TIMEOUT,
JiraSite.DEFAULT_THREAD_EXECUTOR_NUMBER,
false,
JiraSite.DEFAULT_MAX_ISSUES,
project);

verify(builder).build();
Expand Down
Loading