Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 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
17 changes: 9 additions & 8 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 @@ public class JiraSession {

private final String jiraSiteName;

private final int maxIssuesFromJqlSearch;

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

/**
Expand Down Expand Up @@ -131,7 +132,7 @@ public Issue getIssue(String id) {
* @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);
}

/**
Expand Down Expand Up @@ -176,10 +177,10 @@ public List<Issue> getIssuesWithFixVersion(String projectKey, String version, St
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);
}

/**
Expand Down Expand Up @@ -226,7 +227,7 @@ public void migrateIssuesToFixVersion(String projectKey, String version, String
}

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 || issues.isEmpty()) {
return;
}
Expand Down Expand Up @@ -256,7 +257,7 @@ public void replaceFixVersion(String projectKey, String fromVersion, String toVe
}

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 @@ public void addFixVersion(String projectKey, String version, String query) throw
}

LOGGER.fine("Fetching issues with JQL:" + query);
List<Issue> issues = service.getIssuesFromJqlSearch(query, MAX_ISSUES);
List<Issue> issues = service.getIssuesFromJqlSearch(query, maxIssuesFromJqlSearch);
if (issues == null || issues.isEmpty()) {
return;
}
Expand Down
48 changes: 37 additions & 11 deletions src/main/java/hudson/plugins/jira/JiraSite.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
* needed to access this Jira.
* </p>
* <b>When adding new fields do not miss to look at readResolve method!!</b>
*
* @author Kohsuke Kawaguchi
*/
public class JiraSite extends AbstractDescribableImpl<JiraSite> {
Expand All @@ -117,6 +118,8 @@ public class JiraSite extends AbstractDescribableImpl<JiraSite> {

public static final int DEFAULT_THREAD_EXECUTOR_NUMBER = 10;

public static final int MAX_ALLOWED_ISSUES_FROM_JQL = 5000;

/**
* URL of Jira for Jenkins access, like {@code http://jira.codehaus.org/}.
* Mandatory. Normalized to end with '/'
Expand Down Expand Up @@ -150,13 +153,15 @@ public class JiraSite extends AbstractDescribableImpl<JiraSite> {

/**
* User name needed to login. Optional.
*
* @deprecated use credentialsId
*/
@Deprecated
private transient String userName;

/**
* Password needed to login. Optional.
*
* @deprecated use credentialsId
*/
@Deprecated
Expand Down Expand Up @@ -221,12 +226,14 @@ public class JiraSite extends AbstractDescribableImpl<JiraSite> {

/**
* response timeout for jira rest call
*
* @since 3.0.3
*/
private int readTimeout = DEFAULT_READ_TIMEOUT;

/**
* thread pool number
*
* @since 3.0.3
*/
private int threadExecutorNumber = DEFAULT_THREAD_EXECUTOR_NUMBER;
Expand All @@ -238,10 +245,14 @@ public class JiraSite extends AbstractDescribableImpl<JiraSite> {

/**
* To add scm entry change date and time in jira comments.
*
*/
private boolean appendChangeTimestamp;

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

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

/**
Expand Down Expand Up @@ -502,6 +513,7 @@ public boolean getDisableChangelogAnnotations() {
/**
* Sets connect timeout (in seconds).
* If not specified, a default timeout will be used.
*
* @param timeoutSec Timeout in seconds
*/
@DataBoundSetter
Expand All @@ -516,6 +528,7 @@ public int getTimeout() {
/**
* Sets read timeout (in seconds).
* If not specified, a default timeout will be used.
*
* @param readTimeout Timeout in seconds
*/
@DataBoundSetter
Expand Down Expand Up @@ -646,6 +659,17 @@ public void setUpdateJiraIssueForAllStatus(boolean updateJiraIssueForAllStatus)
this.updateJiraIssueForAllStatus = updateJiraIssueForAllStatus;
}

@DataBoundSetter
public void setMaxIssuesFromJqlSearch(int maxIssuesFromJqlSearch) {
this.maxIssuesFromJqlSearch = maxIssuesFromJqlSearch > MAX_ALLOWED_ISSUES_FROM_JQL
? MAX_ALLOWED_ISSUES_FROM_JQL
: maxIssuesFromJqlSearch;
}

public int getMaxIssuesFromJqlSearch() {
return maxIssuesFromJqlSearch;
}

@SuppressWarnings("unused")
protected Object readResolve() throws FormException {
JiraSite jiraSite;
Expand Down Expand Up @@ -683,7 +707,7 @@ protected Object readResolve() throws FormException {
jiraSite.setDisableChangelogAnnotations(disableChangelogAnnotations);
jiraSite.setDateTimePattern(dateTimePattern);
jiraSite.setUseBearerAuth(useBearerAuth);

jiraSite.setMaxIssuesFromJqlSearch(maxIssuesFromJqlSearch);
return jiraSite;
}

Expand Down Expand Up @@ -760,7 +784,8 @@ Lock getProjectUpdateLock() {
/**
* This method only supports credential matching by credentialsId.
* Older methods are not and will not be supported as the credentials should have been migrated already.
* @param item can be <code>null</code> if top level
*
* @param item can be <code>null</code> if top level
* @param uiValidation if <code>true</code> and credentials not found at item level will not go up
*/
private StandardUsernamePasswordCredentials resolveCredentials(Item item, boolean uiValidation) {
Expand Down Expand Up @@ -1132,9 +1157,10 @@ public boolean existsIssue(String id) {

/**
* Returns all versions for the given project key.
* @deprecated use {@link JiraSession#getVersions(String)}
*
* @param projectKey Project Key
* @return A set of JiraVersions
* @deprecated use {@link JiraSession#getVersions(String)}
*/
@Deprecated
public Set<ExtendedVersion> getVersions(String projectKey) {
Expand All @@ -1148,7 +1174,7 @@ public Set<ExtendedVersion> getVersions(String projectKey) {
/**
* Generates release notes for a given version.
*
* @param projectKey the project key
* @param projectKey the project key
* @param versionName the version
* @param filter Additional JQL Filter. Example: status in (Resolved,Closed)
* @return release notes
Expand Down Expand Up @@ -1234,9 +1260,9 @@ public void migrateIssuesToFixVersion(String projectKey, String versionName, Str
/**
* Adds new fix version to issues matching the jql.
*
* @param projectKey the project key
* @param projectKey the project key
* @param versionName the version
* @param query the query
* @param query the query
* @throws TimeoutException if too long
*/
public void addFixVersionToIssue(String projectKey, String versionName, String query) throws TimeoutException {
Expand All @@ -1251,10 +1277,10 @@ public void addFixVersionToIssue(String projectKey, String versionName, String q
* Progresses all issues matching the JQL search, using the given workflow action. Optionally
* adds a comment to the issue(s) at the same time.
*
* @param jqlSearch the query
* @param jqlSearch the query
* @param workflowActionName the workflowActionName
* @param comment the comment
* @param console the console
* @param comment the comment
* @param console the console
* @throws TimeoutException TimeoutException if too long
*/
public boolean progressMatchingIssues(
Expand Down Expand Up @@ -1521,7 +1547,6 @@ public JiraSite build() {
// yes this class hierarchy can be a real big mess...

/**
*
* @param item the Jenkins {@link Item} can be a {@link Job} or {@link Folder}
* @return the parent as {@link ItemGroup} which can be {@link Jenkins} or {@link Folder}
*/
Expand Down Expand Up @@ -1567,6 +1592,7 @@ public static List<JiraSite> getSitesFromFolders(ItemGroup itemGroup) {
/**
* Gets the effective {@link JiraSite} associated with the given project
* and creates automatically jiraSession for each jiraSite found
*
* @return <code>null</code> if no such was found.
*/
@Nullable
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" max="5000" clazz="non-negative-number-required" />
</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>
9 changes: 4 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,7 @@ 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\"", 100);
for (Issue searchResult : searchResults) {
System.out.println("JQL search result: " + searchResult);
}
Expand Down Expand Up @@ -102,8 +101,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.MAX_ALLOWED_ISSUES_FROM_JQL);
long end = System.currentTimeMillis();
System.out.println("time uniq " + (end - start));
}
Expand All @@ -112,7 +111,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.MAX_ALLOWED_ISSUES_FROM_JQL);
long end = System.currentTimeMillis();
System.out.println("time duplicate " + (end - start));
}
Expand Down
8 changes: 3 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,7 @@ 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\"", 100);
for (Issue searchResult : searchResults) {
System.out.println("JQL search result: " + searchResult);
}
Expand Down Expand Up @@ -104,8 +103,7 @@ 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')", 100);
long end = System.currentTimeMillis();
System.out.println("time uniq " + (end - start));
}
Expand All @@ -114,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);
100);
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 @@ -54,7 +54,8 @@ void replaceWithFixVersionByRegex() throws URISyntaxException, TimeoutException
ArrayList<Issue> issues = new ArrayList<>();
issues.add(getIssue("abcXXXXefg", 1L));
issues.add(getIssue("dgcXXXXefg", 2L));
when(service.getIssuesFromJqlSearch(QUERY, JiraSession.MAX_ISSUES)).thenReturn(issues);
when(service.getIssuesFromJqlSearch(QUERY, site.getMaxIssuesFromJqlSearch()))
.thenReturn(issues);

jiraSession.replaceFixVersion(PROJECT_KEY, "/abc.*efg/", TO_VERSION, QUERY);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<threadExecutorNumber>10</threadExecutorNumber>
<dateTimePattern></dateTimePattern>
<appendChangeTimestamp>false</appendChangeTimestamp>
<maxIssuesFromJqlSearch>0</maxIssuesFromJqlSearch>
</hudson.plugins.jira.JiraSite>
</sites>
</hudson.plugins.jira.JiraProjectProperty_-DescriptorImpl>